Menerima Email

Pesan email dikirim ke aplikasi Anda sebagai permintaan HTTP. Untuk memproses pesan email masuk, Anda harus mengaitkan alamat email dengan servlet dalam konfigurasi aplikasi, lalu menyertakan kode servlet dengan aplikasi tersebut. Email masuk menghasilkan permintaan HTTP yang diteruskan ke servlet yang sesuai untuk ditangani.

Mengonfigurasi aplikasi Anda untuk menerima email

Ketika Anda membuat aplikasi baru, email masuk dinonaktifkan secara default. Jika Anda tidak secara eksplisit mengaktifkan pesan email masuk yang dikirim ke aplikasi Anda akan diabaikan.

Untuk mengaktifkan layanan email masuk, ubah file konfigurasi appengine-web.xml dan web.xml:

Mengaktifkan email di appengine-web.xml

Ubah appengine-web.xml dengan menambahkan bagian inbound-services yang mengaktifkan layanan email masuk:

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

Pesan email dikirim ke aplikasi Anda sebagai permintaan POST HTTP menggunakan URL berikut:

/_ah/mail/<ADDRESS>

dengan <ADDRESS> adalah alamat email lengkap, termasuk nama domain. Perlu diperhatikan bahwa meskipun aplikasi Anda di-deploy di domain kustom, aplikasi Anda tidak dapat menerima email yang dikirim ke alamat di domain tersebut.

Mengaktifkan email di web.xml

Ubah web.xml dengan memetakan URL email ke 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>

Dalam cuplikan di atas, /_ah/mail/* cocok dengan semua email yang dialamatkan ke aplikasi. Servlet email berjalan dalam versi aplikasi yang saat ini ditayangkan di App Engine.

Pengiriman pesan masuk berbasis pola

Jika aplikasi Anda menggunakan pencocokan pola, pertimbangkan untuk menggunakan pendekatan berbasis filter berdasarkan cuplikan kode berikut.

Pengendali konkret

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

Pengendali konkret di atas didaftarkan menggunakan cuplikan berikut di 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>

Perhatikan bahwa perintah security-constraint tidak dimungkinkan pada filter; kebijakan keamanan pada pengendali harus diperkenalkan dengan cara lain.

Pengendali abstrak

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

Menangani email masuk

JavaMail API menyertakan class MimeMessage yang dapat Anda gunakan untuk mengurai pesan email masuk. MimeMessage memiliki konstruktor yang menerima java.io.InputStream dan sesi JavaMail, yang dapat memiliki konfigurasi kosong.

Buat instance MimeMessage seperti ini:

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

Anda kemudian dapat menggunakan berbagai metode untuk mengurai objek message:

  • Panggil getFrom() untuk mengembalikan pengirim pesan.
  • Panggil getContentType() untuk mengekstrak jenis konten pesan. Metode getContent() menampilkan objek yang menerapkan antarmuka Multipart.
  • Panggil getCount() untuk menentukan jumlah bagian
  • Panggil getBodyPart(int index) untuk menampilkan bagian isi tertentu.

Setelah menyiapkan aplikasi untuk menangani email masuk, Anda dapat menggunakan konsol server pengembangan untuk menyimulasikan pesan email masuk. Untuk mempelajari lebih lanjut, termasuk cara memulai server pengembangan, lihat Server Pengembangan Java. Setelah memulai aplikasi di server pengembangan lokal, Anda dapat mengakses aplikasi dengan mengunjungi URL http://localhost:8888/_ah/admin/, yang menggantikan nilai 8888 dengan port apa pun yang Anda gunakan jika Anda tidak menggunakan port default untuk server pengembangan lokal.

Di server pengembangan, klik Email Masuk di sisi kiri, isi formulir yang muncul, dan klik Send Email.