Réception d'e-mails

Les e-mails sont envoyés à votre application en tant que requêtes HTTP. Pour traiter les e-mails entrants, vous devez associer des adresses électroniques à des servlets dans la configuration de votre application, puis inclure le code des servlets dans votre application. Un e-mail entrant génère des requêtes HTTP qui sont transmises aux servlets appropriés pour être traitées.

Configurer votre application pour recevoir des e-mails

Lorsque vous créez une application, le traitement des e-mails entrants est désactivé par défaut. Si vous n'activez pas explicitement cette fonctionnalité dans votre application, les e-mails entrants sont ignorés.

Pour activer le service de traitement des e-mails entrants, modifiez les fichiers de configuration appengine-web.xml et web.xml :

Activer le traitement des e-mails dans appengine-web.xml

Modifiez appengine-web.xml en ajoutant une section inbound-services qui active le service de courrier électronique entrant :

Java 8

<inbound-services>
  <!-- Used to handle incoming mail. -->
  <service>mail</service>
  <!-- Used to handle bounced mail notifications. -->
  <service>mail_bounce</service>
</inbound-services>

Java 7

<inbound-services>
  <!-- Used to handle incoming mail. -->
  <service>mail</service>
  <!-- Used to handle bounced mail notifications. -->
  <service>mail_bounce</service>
</inbound-services>

Les e-mails sont envoyés à votre application en tant que requêtes HTTP POST à l'aide de l'URL suivante :

/_ah/mail/<ADDRESS>

<ADDRESS> est une adresse e-mail complète, incluant le nom de domaine. Notez que, même si votre application est déployée sur un domaine personnalisé, vous ne pouvez pas recevoir de messages envoyés aux adresses de ce domaine.

Activer le traitement des e-mails dans le fichier web.xml

Modifiez le fichier web.xml en mappant les URL de messagerie sur des servlets :

Java 8

<servlet>
  <servlet-name>mailhandler</servlet-name>
  <servlet-class>com.example.appengine.mail.MailHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>mailhandler</servlet-name>
  <url-pattern>/_ah/mail/*</url-pattern>
</servlet-mapping>
<security-constraint>
  <web-resource-collection>
    <web-resource-name>mail</web-resource-name>
    <url-pattern>/_ah/mail/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>admin</role-name>
  </auth-constraint>
</security-constraint>

Java 7

<servlet>
  <servlet-name>mailhandler</servlet-name>
  <servlet-class>com.example.appengine.mail.MailHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>mailhandler</servlet-name>
  <url-pattern>/_ah/mail/*</url-pattern>
</servlet-mapping>
<security-constraint>
  <web-resource-collection>
    <web-resource-name>mail</web-resource-name>
    <url-pattern>/_ah/mail/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>admin</role-name>
  </auth-constraint>
</security-constraint>

Dans les extraits ci-dessus, /_ah/mail/* correspond à tous les e-mails adressés à l'application. Les servlets de messagerie s'exécutent dans la version active de votre application dans App Engine.

Distribution des messages entrants basée sur un motif

Si votre application utilise un filtrage par motif, vous pouvez envisager d'utiliser une approche basée sur le filtrage, inspirée des extraits de code suivants.

Gestionnaire concret

Java 8

public class HandleDiscussionEmail extends MailHandlerBase {

  private static final Logger log = Logger.getLogger(HandleDiscussionEmail.class.getName());
  public HandleDiscussionEmail() { super("discuss-(.*)@(.*)"); }

  @Override
  protected boolean processMessage(HttpServletRequest req, HttpServletResponse res)
    throws ServletException
  {
    log.info("Received e-mail sent to discuss list.");
    MimeMessage msg = getMessageFromRequest(req);
    Matcher match = getMatcherFromRequest(req);
    // ...
    return true;
  }
}

Java 7

public class HandleDiscussionEmail extends MailHandlerBase {

  private static final Logger log = Logger.getLogger(HandleDiscussionEmail.class.getName());

  public HandleDiscussionEmail() {
    super("discuss-(.*)@(.*)");
  }

  @Override
  protected boolean processMessage(
      HttpServletRequest req, HttpServletResponse res) throws ServletException {
    log.info("Received e-mail sent to discuss list.");
    MimeMessage msg = getMessageFromRequest(req);
    Matcher match = getMatcherFromRequest(req);
    // ...
    return true;
  }
}

Le gestionnaire concret présenté ci-dessus est enregistré dans web.xml au moyen de l'extrait de code suivant :

Java 8

<filter>
  <filter-name>HandleDiscussionEmail</filter-name>
  <filter-class>com.example.appengine.mail.HandleDiscussionEmail</filter-class>
</filter>
<filter-mapping>
  <filter-name>HandleDiscussionEmail</filter-name>
  <url-pattern>/_ah/mail/*</url-pattern>
</filter-mapping>

Java 7

<filter>
  <filter-name>HandleDiscussionEmail</filter-name>
  <filter-class>com.example.appengine.mail.HandleDiscussionEmail</filter-class>
</filter>
<filter-mapping>
  <filter-name>HandleDiscussionEmail</filter-name>
  <url-pattern>/_ah/mail/*</url-pattern>
</filter-mapping>

Notez qu'il n'est pas possible d'utiliser les directives security-constraint sur les filtres. Les règles de sécurité du gestionnaire devront être appliquées d’une autre manière.

Gestionnaire abstrait

Java 8

public abstract class MailHandlerBase implements Filter {

  private Pattern pattern = null;

  protected MailHandlerBase(String pattern) {
    if (pattern == null || pattern.trim().length() == 0)
    {
      throw new IllegalArgumentException("Expected non-empty regular expression");
    }
    this.pattern = Pattern.compile("/_ah/mail/"+pattern);
  }

  @Override public void init(FilterConfig config) throws ServletException { }

  @Override public void destroy() { }

  /**
   * Process the message. A message will only be passed to this method
   * if the servletPath of the message (typically the recipient for
   * appengine) satisfies the pattern passed to the constructor. If
   * the implementation returns false, control is passed
   * to the next filter in the chain. If the implementation returns
   * true, the filter chain is terminated.
   *
   * The Matcher for the pattern can be retrieved via
   * getMatcherFromRequest (e.g. if groups are used in the pattern).
   */
  protected abstract boolean processMessage(HttpServletRequest req, HttpServletResponse res) throws ServletException;

  @Override
  public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain)
      throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) sreq;
    HttpServletResponse res = (HttpServletResponse) sres;

    MimeMessage message = getMessageFromRequest(req);
    Matcher m = applyPattern(req);

    if (m != null && processMessage(req, res)) {
      return;
    }

    chain.doFilter(req, res); // Try the next one

  }

  private Matcher applyPattern(HttpServletRequest req) {
    Matcher m = pattern.matcher(req.getServletPath());
    if (!m.matches()) m = null;

    req.setAttribute("matcher", m);
    return m;
  }

  protected Matcher getMatcherFromRequest(ServletRequest req) {
    return (Matcher) req.getAttribute("matcher");
  }

  protected MimeMessage getMessageFromRequest(ServletRequest req) throws ServletException {
    MimeMessage message = (MimeMessage) req.getAttribute("mimeMessage");
    if (message == null) {
      try {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        message = new MimeMessage(session, req.getInputStream());
        req.setAttribute("mimeMessage", message);

      } catch (MessagingException e) {
        throw new ServletException("Error processing inbound message", e);
      } catch (IOException e) {
        throw new ServletException("Error processing inbound message", e);
      }
    }
    return message;
  }
}

Java 7

public abstract class MailHandlerBase implements Filter {

  private Pattern pattern = null;

  protected MailHandlerBase(String pattern) {
    if (pattern == null || pattern.trim().length() == 0) {
      throw new IllegalArgumentException("Expected non-empty regular expression");
    }
    this.pattern = Pattern.compile("/_ah/mail/" + pattern);
  }

  @Override public void init(FilterConfig config) throws ServletException { }

  @Override public void destroy() { }

  /**
   * Process the message. A message will only be passed to this method
   * if the servletPath of the message (typically the recipient for
   * appengine) satisfies the pattern passed to the constructor. If
   * the implementation returns false, control is passed
   * to the next filter in the chain. If the implementation returns
   * true, the filter chain is terminated.
   *
   * The Matcher for the pattern can be retrieved via
   * getMatcherFromRequest (e.g. if groups are used in the pattern).
   */
  protected abstract boolean processMessage(
      HttpServletRequest req, HttpServletResponse res) throws ServletException;

  @Override
  public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain)
      throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) sreq;
    HttpServletResponse res = (HttpServletResponse) sres;

    MimeMessage message = getMessageFromRequest(req);
    Matcher m = applyPattern(req);

    if (m != null && processMessage(req, res)) {
      return;
    }

    chain.doFilter(req, res); // Try the next one

  }

  private Matcher applyPattern(HttpServletRequest req) {
    Matcher m = pattern.matcher(req.getServletPath());
    if (!m.matches()) {
      m = null;
    }

    req.setAttribute("matcher", m);
    return m;
  }

  protected Matcher getMatcherFromRequest(ServletRequest req) {
    return (Matcher) req.getAttribute("matcher");
  }

  protected MimeMessage getMessageFromRequest(ServletRequest req) throws ServletException {
    MimeMessage message = (MimeMessage) req.getAttribute("mimeMessage");
    if (message == null) {
      try {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        message = new MimeMessage(session, req.getInputStream());
        req.setAttribute("mimeMessage", message);

      } catch (MessagingException e) {
        throw new ServletException("Error processing inbound message", e);
      } catch (IOException e) {
        throw new ServletException("Error processing inbound message", e);
      }
    }
    return message;
  }
}

Gérer les e-mails reçus

L'API JavaMail inclut la classe MimeMessage, que vous pouvez utiliser pour analyser les e-mails entrants. MimeMessage possède un constructeur acceptant un objet java.io.InputStream et une session JavaMail, qui peuvent avoir une configuration vide.

Vous créez une instance de MimeMessage comme illustré ci-dessous :

Java 8

import java.io.IOException;
import java.util.logging.Logger;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MailHandlerServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(MailHandlerServlet.class.getName());

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);
    try {
      MimeMessage message = new MimeMessage(session, req.getInputStream());
      log.info("Received mail message.");
    } catch (MessagingException e) {
      // ...
    }
    // ...
  }
}

Java 7


import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MailHandlerServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(MailHandlerServlet.class.getName());

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);
    try {
      MimeMessage message = new MimeMessage(session, req.getInputStream());
      log.info("Received mail message.");
    } catch (MessagingException e) {
      // ...
    }
    // ...
  }
}

Vous pouvez ensuite faire appel à différentes méthodes pour analyser l'objet message :

  • Appelez getFrom() pour obtenir l'expéditeur du message.
  • Appelez getContentType() pour extraire le type de contenu du message. La méthode getContent() renvoie un objet qui met en œuvre l'interface Multipart.
  • Appelez getCount() pour déterminer le nombre de parties.
  • Appelez getBodyPart(int index) pour renvoyer une partie spécifique du corps.

Une fois que vous avez configuré votre application pour gérer les e-mails entrants, vous pouvez utiliser la console du serveur de développement pour simuler l'arrivée de courriers. Pour en savoir plus, en particulier sur le lancement du serveur de développement, consultez la section dédiée au Serveur de développement Java. Après avoir démarré votre application sur le serveur de développement local, vous pouvez y accéder au moyen de l’URL http://localhost:8888/_ah/admin/, en remplaçant la valeur 8888 par le port que vous avez choisi (si vous n’utilisez pas le port par défaut du serveur de développement local).

Sur le serveur de développement, cliquez sur Inbound Mail (Courrier entrant) dans la partie gauche, remplissez le formulaire qui s'affiche, puis cliquez sur Send Email (Envoyer un e-mail).

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Environnement standard App Engine pour Java 8