Ricezione di email

I messaggi email vengono inviati alla tua app come richieste HTTP. Per elaborare i messaggi email in arrivo, devi associare gli indirizzi email ai servlet nella configurazione dell'applicazione, quindi includere il codice servlet con la tua app. L'email in arrivo genera richieste HTTP che vengono passate ai servlet appropriati per la gestione.

Configurazione dell'applicazione per la ricezione di email

Quando crei una nuova applicazione, la posta in arrivo è disattivata per impostazione predefinita. Se non abiliti esplicitamente i messaggi email in arrivo inviati alla tua app, vengono ignorati.

Per abilitare il servizio email in arrivo, modifica i file di configurazione appengine-web.xml e web.xml:

Attivazione dell'email in appengine-web.xml

Modifica appengine-web.xml aggiungendo una sezione inbound-services che abilita il servizio email in arrivo:

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

I messaggi email vengono inviati alla tua app come richieste POST HTTP utilizzando il seguente URL:

/_ah/mail/<ADDRESS>

dove <ADDRESS> è un indirizzo email completo, incluso il nome di dominio. Tieni presente che, anche se il deployment dell'app è stato eseguito su un dominio personalizzato, l'app non può ricevere email inviate agli indirizzi di quel dominio.

Attivazione dell'email in web.xml

Modifica web.xml mappando gli URL email ai servlet:

<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>

Negli snippet riportati sopra, /_ah/mail/* corrisponde a tutte le email indirizzate all'app. I servlet di posta vengono eseguiti nella versione attualmente pubblicata della tua app in App Engine.

Invio dei messaggi in arrivo basato su pattern

Se la tua app utilizza la corrispondenza di pattern, valuta la possibilità di utilizzare un approccio basato su filtri basato sui seguenti snippet di codice.

Gestore di calcestruzzo

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;
  }
}

Il gestore concreto sopra indicato è registrato utilizzando il seguente snippet in web.xml:

<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>

Tieni presente che le istruzioni security-constraint non sono possibili per i filtri; i criteri di sicurezza sul gestore dovranno essere introdotti in altro modo.

Gestore di estratti conto

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;
  }
}

Gestione delle email in arrivo

L'API JavaMail include la classe MimeMessage, che puoi utilizzare per analizzare i messaggi email in arrivo. MimeMessage ha un costruttore che accetta una sessione java.io.InputStream e una sessione JavaMail, che può avere una configurazione vuota.

Crea un'istanza MimeMessage come questa:

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) {
      // ...
    }
    // ...
  }
}

Puoi quindi utilizzare vari metodi per analizzare l'oggetto message:

  • Chiama getFrom() per restituire il mittente del messaggio.
  • Richiama getContentType() per estrarre il tipo di contenuti del messaggio. Il metodo getContent() restituisce un oggetto che implementa l'interfaccia Multipart.
  • Chiama getCount() per determinare il numero di parti
  • Chiama getBodyPart(int index) per restituire una determinata parte del corpo.

Dopo aver configurato l'app per la gestione delle email in arrivo, puoi utilizzare la console del server di sviluppo per simulare le email in arrivo. Per scoprire di più, incluse informazioni sull'avvio del server di sviluppo, consulta Il server di sviluppo Java. Dopo aver avviato l'applicazione nel server di sviluppo locale, puoi accedervi visitando l'URL http://localhost:8888/_ah/admin/, sostituendo il valore 8888 con la porta in uso, se non usi quella predefinita per il server di sviluppo locale.

Nel server di sviluppo, fai clic su Posta in entrata a sinistra, compila il modulo visualizzato e fai clic su Invia email.