L’envoi d’un email est simple avec le framework Web Play! Framework.
Vous pouvez envoyer un email directement en une ligne :

Mail.send("sender@express-board.fr","candidat@hotmail.fr","Subject","Test de message");

Cependant la façon la plus pratique est d’utiliser une partie du framework et des entités. Lorsque vous vous inscrivez comme candidat sur mon site express-board.fr, vous recevez un email afin de vous souhaiter la bienvenue. Voyons comment cela fonctionne.

Dans le répertoire appsnotifiers j’ai créé une classe Mails qui étend la classe Mailer de Play!

package notifiers;

import models.*;
import play.*;
import play.mvc.*;

import java.util.*;

public class Mails extends Mailer {

    public static void welcome(User user) {
        setSubject("Bienvenue sur eXpress Board");
        addRecipient(user.email);
        setFrom("contact@express-board.fr");
        send(user);
    }

}

La méthode welcome reçoit en argument une entité User et appelle la méthode send de Mailer. Celle-ci recherche alors un template HTML et un template TXT afin d’envoyer l’email. Il suffit donc de créer 2 fichiers portant exactement le même nom que la méthode dans le répertoire viewsMails.

Voici le fichier viewsMailswelcome.txt pour l’envoi en text/plain de l’email :

Bienvenue sur eXpress Board !
=============================

Votre compte a été activé.

Votre nom d'utilisateur est votre adresse email : ${user.email}
Votre mot de passe : ${user.password}

En cas de soucis techniques, n'hésitez pas à nous contacter par email : contact@express-board.fr

A bientôt !

L'équipe eXpress Board

Comme vous pouvez le constater, je peux utiliser le moteur Groovy de Play! pour récupérer et afficher l’email et le mot de passe de l’utilisateur. La syntaxe ${…} n’est que du Groovy, le meilleur langage de script pour la plate-forme Java.

Voici le fichier viewsMailswelcome.html :

<table width="650" align="center" style="font-size: 14px;" cellpadding="0" cellspacing="0">
    <tr id="topshadow">
        <td height="10" width="10" background="http://www.express-board.fr/public/images/email/shadow_tl.gif" bgcolor="#ffffff"></td> 
        <td height="10" background="http://www.express-board.fr/public/images/email/shadow_top.gif" bgcolor="#ffffff"> </td>
        <td height="10" width="10" background="http://www.express-board.fr/public/images/email/shadow_tr.gif" bgcolor="#ffffff"> </td>
    </tr>

    <tr id="header">
        <td width="10" background="http://www.express-board.fr/public/images/email/shadow_left.gif" bgcolor="#ffffff" rowspan="2"></td>
        <td height="102" background="http://www.express-board.fr/public/images/email/header_bg.gif" bgcolor="#e6f1fb" align="center">
            <table width="95%"><tr><td align="left"><img src="http://www.express-board.fr/public/images/email/email_logo.gif" /></td></tr></table>
        </td>
        <td width="10" background="http://www.express-board.fr/public/images/email/shadow_right.gif" bgcolor="#ffffff" rowspan="2"> </td>
    </tr>

    <tr id="content">
        <td bgcolor="#f4faff" align="center">
            <table width="95%" cellpadding="30">
                <tr>
                    <td align="left">
                        <font face="Lucida Grande, Segoe UI, Arial, Verdana, Lucida Sans Unicode, Tahoma, Sans Serif">
<h3>Bienvenue sur l'eXpress-Board !</h3>

<p>Votre compte a été activé.</p>
<hr>
<p>Votre nom d'utilisateur est votre adresse email : ${user.email}</p>
<p>Votre mot de passe : ${user.password}</p>
<hr>
<p>Vous pouvez maintenant <a href="http://www.express-board.fr/administration/login">vous authentifier</a> et poster votre première annonce ! </p>
<p>En cas de soucis techniques, n'hésitez pas à nous contacter par email : contact@express-board.fr</p>

<br/>
<br/>
A bientôt !
<br/>
<br/>
<br/>
<br/>
L'équipe express-Board<br/><br/>
P.S. Suivez-nous sur notre compte <a href="http://twitter.com/expressboard">Twitter</a>
                        </font>
                    </td>
                </tr>
            </table>
        </td>
    </tr>

    <tr id="bottomshadow">
        <td height="10" width="10" background="http://www.express-board.fr/public/images/email/shadow_bl.gif" bgcolor="#ffffff"></td>
        <td height="10" background="http://www.express-board.fr/public/images/email/shadow_bottom.gif" bgcolor="#ffffff"> </td>
        <td height="10" width="10" background="http://www.express-board.fr/public/images/email/shadow_br.gif" bgcolor="#ffffff"> </td>
    </tr>

    <tr id="copyright">
        <td></td>
        <td align="right">
            <span style="font-size: 12px; color: #888;"> © 2010 eXpress-Board.fr par Innoteria SARL</span>
        </td>
        <td></td>
    </tr>
</table>

Lorsque vous envoyez des emails au format HTML, il faut que les URLs des images soient absolues. Sans quoi, les navigateurs ou les lecteurs de mails refusent de les charger.

Et comment envoyer cet email ?

Voici un exemple de méthode. Un formulaire permet de saisir le nom, l’email et un texte de présentation. Au passage, notez comment Play! permet de gérer les arguments obligatoires d’un formulaire et de valider le champ email. Il y a différentes façons de faire, je vous proposerai un article séparé pour vous en parler.


     public static void saveNewUser(@Required String fullname, 
                                                     @Required String email,
                                                     @MaxSize(message = "Le contenu du champ présentation est trop long", value = 1000) String presentation) {
      
        validation.email(email).message("Email invalide, merci de saisir un email correct pour continuer.");
       
        if (validation.hasErrors()) {
            params.flash(); // add http parameters to the flash scope
            render("/Administration/createAccount.html");
            return;
        }
 
        // verification si user existe deja..
        ... 
        ...

        // creation de l'utilisateur
        User user = new User();
        user.email = email;
        user.fullname = fullname;
        user.presentation = presentation.trim();

        user.password = RandomStringUtils.randomAlphanumeric(9);
        user.active = Boolean.TRUE;
        user.validateAndSave();

        // Envoi de l'email 
        Mails.welcome(user);
 
       render(user);
    }
 

Configuration d’un compte Gmail

Pour l’eXpress-Board, j’ai fait simple : j’utilise une boite email hébergé sur Gandi.net. J’ai ensuite configuré mon compte GMail afin de l’autoriser à aller chercher les emails via POP/IMAP sur ce serveur. Et le tour est joué… je reçois mes emails de l’express-board sur ma boite GMail.

Pour configurer un compte Gandi avec Play! afin de pouvoir envoyer un email, voici ma configuration (avec le mot de passe modifié bien entendu)

%playapps.application.mode=prod
%playapps.db=mysql:play:play@play
%playapps.mail.smtp.host=mail.gandi.net
%playapps.mail.smtp.user=contact@express-board.fr
%playapps.mail.smtp.pass=MOT DE PASSE EN CLAIR
%playapps.mail.smtp.channel=ssl
%playapps.mail.smtp.port=465
%playapps.mail.debug=false

J’utilise l’hébergement PlayApps.net, la plateforme de cloud de Zenexity. C’est l’hébergeur du site l’express-board. Cela fonctionne vraiment bien, c’est gratuit pour l’instant, et j’en suis vraiment très content.

Allez, à vous de jouer maintenant !

Update

Suite aux 2 remarques de Benoit et Tartur, je précise quelques points qui peuvent surprendre lorsque l’on découvre Play! L’entité User n’a pas attributs statiques. Il n’y a pas d’encapsulation, les propriétés sont publiques tout simplement.

package models;

import javax.persistence.*;

import org.hibernate.annotations.GenericGenerator;
import play.db.jpa.*;
import play.data.validation.*;

import java.util.List;

@Entity
public class User extends Model {
    @Email
    @Required
    public String email;

    @Required
    public String password;

    @Lob
    @MaxSize(1000)
    public String presentation;

    public Boolean active;

    public User() {
    }

    public static User connect(String email, String password) {
        return find("byEmailAndPassword", email, password).first();
    }

    public static User findByEmail(String email) {
        return find("byEmail", email).first();
    }

    @Override
    public String toString() {
        return fullname;
    }

    public static List findAllActives() {
        return find("active", Boolean.TRUE).fetch();
    }

}

La classe User étend Model, une classe de base de Play! Celle-ci me fournit quelques services. Elle étend elle-même la classe JPASupport de Play, qui donne un ensemble de méthode type crud directement à mon entité. C’est une approche différente de ce que l’on voit classiquement en Java. Bien entendu vous pouvez écrire du code JPA classique, mettre des services et des DAO, cela fonctionne aussi. Mais j’apprécie de gagner du temps en utilisant ce système de Play! qui est plutôt bien pensé.

9 réflexions sur « Play! Framework : envoyer un email »

  1. Article très intéressant, comme d’habitude.

    N’étant pas encore familier de Play!, je trouve le fonctionnement de la classe Mails curieuse…

    Raisonnement Javaïste pas encore habitué à Play! : la méthode « welcome » est statique et appelle des setters (de la classe mère), qui sont donc à priori eux aussi statiques. Du coup, si plusieurs utilisateurs s’enregistrent exactement en même temps (ça serait vraimant pas de chance, mais imaginons…), n’y-a-t’il pas un risque de d’envoyer un mail à la mauvaise personne en environnement multi-threads ?

  2. @Benoit : Dans la classe play.mvc.Mailer, tu as une Hashmap de String et Object qui est stockée dans une ThreadLocal. C’est le moyen de s’assurer qu’en effet, tu ne reçois pas le mail destiné à ton voisin.

    Concernant la classe User, j’ai complété l’article afin de montrer la tête qu’elle a. Il n’y a pas d’attributs static.

    Nicolas

  3. Merci pour toutes ces précisions ! C’est très enrichissant (et ça donne de plus en plus envie de se mettre à Play! : dès que j’aurai un moment de libre, je mets ça en tête de ma TODO)

  4. J’ai été voir la plateform de cloud il y à juste 10 minutes. C’est pas gratuit (ça démarre à 10 €).
    C’est dommage si on veut essayer pour voir ce que ça donne.
    merci pour l’article.
    Meissa

  5. Je passe de temps en temps lire le touilleur et c’est plutôt agréable de voir des gens partager.

    Je vais donc essayer de rester dans cet esprit en indiquant que pour les mails et les images, on n’est pas obligés de mettre le lien absolu vers les images.
    On peut – avec les content-id – embarquer directement les images dans le mail (cf ici avec les commons apache).

    Après, il faut bien sur que le client mail accepte les content-id … :p

    Merci Nicolas et continue comme ça !! 🙂

  6. @meissa : en fait c’est gratuit pour l’instant. Les prix sont précisés à titre indicatif. Les équipes de Zenexity acceptent les projets un par un. Il faut donc que tu proposes un projet solide, et ils te laissent alors tester librement la plateforme.

Les commentaires sont fermés.