publicclassHandleDiscussionEmailextendsMailHandlerBase{privatestaticfinalLoggerlog=Logger.getLogger(HandleDiscussionEmail.class.getName());publicHandleDiscussionEmail(){super("discuss-(.*)@(.*)");}@OverrideprotectedbooleanprocessMessage(HttpServletRequestreq,HttpServletResponseres)throwsServletException{log.info("Received e-mail sent to discuss list.");MimeMessagemsg=getMessageFromRequest(req);Matchermatch=getMatcherFromRequest(req);// ...returntrue;}}
publicabstractclassMailHandlerBaseimplementsFilter{privatePatternpattern=null;protectedMailHandlerBase(Stringpattern){if(pattern==null||pattern.trim().length()==0){thrownewIllegalArgumentException("Expected non-empty regular expression");}this.pattern=Pattern.compile("/_ah/mail/"+pattern);}@Overridepublicvoidinit(FilterConfigconfig)throwsServletException{}@Overridepublicvoiddestroy(){}/** * 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). */protectedabstractbooleanprocessMessage(HttpServletRequestreq,HttpServletResponseres)throwsServletException;@OverridepublicvoiddoFilter(ServletRequestsreq,ServletResponsesres,FilterChainchain)throwsIOException,ServletException{HttpServletRequestreq=(HttpServletRequest)sreq;HttpServletResponseres=(HttpServletResponse)sres;MimeMessagemessage=getMessageFromRequest(req);Matcherm=applyPattern(req);if(m!=null && processMessage(req,res)){return;}chain.doFilter(req,res);// Try the next one}privateMatcherapplyPattern(HttpServletRequestreq){Matcherm=pattern.matcher(req.getServletPath());if(!m.matches())m=null;req.setAttribute("matcher",m);returnm;}protectedMatchergetMatcherFromRequest(ServletRequestreq){return(Matcher)req.getAttribute("matcher");}protectedMimeMessagegetMessageFromRequest(ServletRequestreq)throwsServletException{MimeMessagemessage=(MimeMessage)req.getAttribute("mimeMessage");if(message==null){try{Propertiesprops=newProperties();Sessionsession=Session.getDefaultInstance(props,null);message=newMimeMessage(session,req.getInputStream());req.setAttribute("mimeMessage",message);}catch(MessagingExceptione){thrownewServletException("Error processing inbound message",e);}catch(IOExceptione){thrownewServletException("Error processing inbound message",e);}}returnmessage;}}
處理傳入電子郵件
JavaMail API 包含 MimeMessage 類別,可用於剖析收到的電子郵件。MimeMessage 所含的建構函式可以接受 java.io.InputStream 和 JavaMail 工作階段,其中設定可保持空白。
建立類似這樣的 MimeMessage 執行個體:
importjava.io.IOException;importjava.util.logging.Logger;importjava.util.Properties;importjavax.mail.MessagingException;importjavax.mail.Session;importjavax.mail.internet.MimeMessage;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;publicclassMailHandlerServletextendsHttpServlet{privatestaticfinalLoggerlog=Logger.getLogger(MailHandlerServlet.class.getName());@OverridepublicvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsIOException{Propertiesprops=newProperties();Sessionsession=Session.getDefaultInstance(props,null);try{MimeMessagemessage=newMimeMessage(session,req.getInputStream());log.info("Received mail message.");}catch(MessagingExceptione){// ...}// ...}}
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["難以理解","hardToUnderstand","thumb-down"],["資訊或程式碼範例有誤","incorrectInformationOrSampleCode","thumb-down"],["缺少我需要的資訊/範例","missingTheInformationSamplesINeed","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-09-04 (世界標準時間)。"],[[["\u003cp\u003eIncoming emails are received by your application as HTTP POST requests, routed to specific servlets based on the email address.\u003c/p\u003e\n"],["\u003cp\u003eTo receive emails, you must enable the incoming email service in your \u003ccode\u003eappengine-web.xml\u003c/code\u003e file, and map email URLs to servlets in \u003ccode\u003eweb.xml\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eEmail URLs follow the format \u003ccode\u003e/_ah/mail/<ADDRESS>\u003c/code\u003e, and your application can use servlets or filters to handle incoming mail at these URLs.\u003c/p\u003e\n"],["\u003cp\u003eThe JavaMail API's \u003ccode\u003eMimeMessage\u003c/code\u003e class is used to parse and process the content of incoming email messages, which is available through the request's input stream.\u003c/p\u003e\n"],["\u003cp\u003eThe local development server allows you to simulate incoming emails via its console at the url: \u003ca href=\"http://localhost:8888/_ah/admin/\"\u003ehttp://localhost:8888/_ah/admin/\u003c/a\u003e.\u003c/p\u003e\n"]]],[],null,["# Receiving Email\n\nEmail messages are sent to your app as HTTP requests. To process\nincoming email messages, you must associate email addresses with servlets in your\napplication configuration, and then include the servlet code with your app. The\nincoming email generates HTTP requests that are passed to the appropriate\nservlets for handling.\n\n\n| This API is supported for first-generation runtimes and can be used when [upgrading to corresponding second-generation runtimes](/appengine/docs/standard/\n| java-gen2\n|\n| /services/access). If you are updating to the App Engine Java 11/17 runtime, refer to the [migration guide](/appengine/migration-center/standard/migrate-to-second-gen/java-differences) to learn about your migration options for legacy bundled services.\n\n\u003cbr /\u003e\n\nConfiguring your application to receive email\n---------------------------------------------\n\nWhen you create a new application, incoming email is disabled by default. If\nyou don't explicitly enable incoming email messages sent to your app are ignored.\n\nTo enable the incoming email service, modify the `appengine-web.xml` and\n`web.xml` configuration files:\n\n### Enabling email in appengine-web.xml\n\nModify `appengine-web.xml` by adding an `inbound-services` section that\nenables the incoming email service: \n\n \u003cinbound-services\u003e\n \u003c!-- Used to handle incoming mail. --\u003e\n \u003cservice\u003email\u003c/service\u003e\n \u003c!-- Used to handle bounced mail notifications. --\u003e\n \u003cservice\u003email_bounce\u003c/service\u003e\n \u003c/inbound-services\u003e\n\nEmail messages are sent to your app as HTTP POST requests using the following URL: \n\n /_ah/mail/\u003cADDRESS\u003e\n\nwhere `\u003cADDRESS\u003e` is a full email address, including domain name. Note that even\nif your app is deployed on a custom domain, your app can't receive email sent to\naddresses in that domain.\n\nEnabling email in web.xml\n-------------------------\n\nModify `web.xml` by mapping email URLs to servlets: \n\n \u003cservlet\u003e\n \u003cservlet-name\u003emailhandler\u003c/servlet-name\u003e\n \u003cservlet-class\u003ecom.example.appengine.mail.MailHandlerServlet\u003c/servlet-class\u003e\n \u003c/servlet\u003e\n \u003cservlet-mapping\u003e\n \u003cservlet-name\u003emailhandler\u003c/servlet-name\u003e\n \u003curl-pattern\u003e/_ah/mail/*\u003c/url-pattern\u003e\n \u003c/servlet-mapping\u003e\n \u003csecurity-constraint\u003e\n \u003cweb-resource-collection\u003e\n \u003cweb-resource-name\u003email\u003c/web-resource-name\u003e\n \u003curl-pattern\u003e/_ah/mail/*\u003c/url-pattern\u003e\n \u003c/web-resource-collection\u003e\n \u003cauth-constraint\u003e\n \u003crole-name\u003eadmin\u003c/role-name\u003e\n \u003c/auth-constraint\u003e\n \u003c/security-constraint\u003e\n\nIn the above snippets, `/_ah/mail/*` matches all email addressed to the app.\nMail servlets run in the currently serving version of your app in App Engine.\n\n### Pattern-based dispatching of incoming messages\n\nIf your app uses pattern matching, consider using a filter-based approach based\non the following code snippets.\n\n#### Concrete handler\n\n public class HandleDiscussionEmail extends MailHandlerBase {\n\n private static final Logger log = Logger.getLogger(HandleDiscussionEmail.class.getName());\n public HandleDiscussionEmail() { super(\"discuss-(.*)@(.*)\"); }\n\n @Override\n protected boolean processMessage(HttpServletRequest req, HttpServletResponse res)\n throws ServletException\n {\n log.info(\"Received e-mail sent to discuss list.\");\n MimeMessage msg = getMessageFromRequest(req);\n Matcher match = getMatcherFromRequest(req);\n // ...\n return true;\n }\n }\n\nThe above concrete handler is registered using the following snippet in\n`web.xml`: \n\n \u003cfilter\u003e\n \u003cfilter-name\u003eHandleDiscussionEmail\u003c/filter-name\u003e\n \u003cfilter-class\u003ecom.example.appengine.mail.HandleDiscussionEmail\u003c/filter-class\u003e\n \u003c/filter\u003e\n \u003cfilter-mapping\u003e\n \u003cfilter-name\u003eHandleDiscussionEmail\u003c/filter-name\u003e\n \u003curl-pattern\u003e/_ah/mail/*\u003c/url-pattern\u003e\n \u003c/filter-mapping\u003e\n\nNote that `security-constraint` directives are not possible on filters;\nsecurity policies on the handler will have to be introduced some other way.\n\n#### Abstract handler\n\n public abstract class MailHandlerBase implements Filter {\n\n private Pattern pattern = null;\n\n protected MailHandlerBase(String pattern) {\n if (pattern == null || pattern.trim().length() == 0)\n {\n throw new IllegalArgumentException(\"Expected non-empty regular expression\");\n }\n this.pattern = Pattern.compile(\"/_ah/mail/\"+pattern);\n }\n\n @Override public void init(FilterConfig config) throws ServletException { }\n\n @Override public void destroy() { }\n\n /**\n * Process the message. A message will only be passed to this method\n * if the servletPath of the message (typically the recipient for\n * appengine) satisfies the pattern passed to the constructor. If\n * the implementation returns false, control is passed\n * to the next filter in the chain. If the implementation returns\n * true, the filter chain is terminated.\n *\n * The Matcher for the pattern can be retrieved via\n * getMatcherFromRequest (e.g. if groups are used in the pattern).\n */\n protected abstract boolean processMessage(HttpServletRequest req, HttpServletResponse res) throws ServletException;\n\n @Override\n public void doFilter(ServletRequest sreq, ServletResponse sres, FilterChain chain)\n throws IOException, ServletException {\n\n HttpServletRequest req = (HttpServletRequest) sreq;\n HttpServletResponse res = (HttpServletResponse) sres;\n\n MimeMessage message = getMessageFromRequest(req);\n Matcher m = applyPattern(req);\n\n if (m != null && processMessage(req, res)) {\n return;\n }\n\n chain.doFilter(req, res); // Try the next one\n\n }\n\n private Matcher applyPattern(HttpServletRequest req) {\n Matcher m = pattern.matcher(req.getServletPath());\n if (!m.matches()) m = null;\n\n req.setAttribute(\"matcher\", m);\n return m;\n }\n\n protected Matcher getMatcherFromRequest(ServletRequest req) {\n return (Matcher) req.getAttribute(\"matcher\");\n }\n\n protected MimeMessage getMessageFromRequest(ServletRequest req) throws ServletException {\n MimeMessage message = (MimeMessage) req.getAttribute(\"mimeMessage\");\n if (message == null) {\n try {\n Properties props = new Properties();\n Session session = Session.getDefaultInstance(props, null);\n message = new MimeMessage(session, req.getInputStream());\n req.setAttribute(\"mimeMessage\", message);\n\n } catch (MessagingException e) {\n throw new ServletException(\"Error processing inbound message\", e);\n } catch (IOException e) {\n throw new ServletException(\"Error processing inbound message\", e);\n }\n }\n return message;\n }\n }\n\nHandling incoming email\n-----------------------\n\nThe JavaMail API includes the `MimeMessage` class which you can use to parse\nincoming email messages. `MimeMessage` has a constructor that accepts a\n`java.io.InputStream` and a JavaMail session, which can have an empty\nconfiguration.\n\nCreate a `MimeMessage` instance like this: \n\n import java.io.IOException;\n import java.util.logging.Logger;\n import java.util.Properties;\n\n import javax.mail.MessagingException;\n import javax.mail.Session;\n import javax.mail.internet.MimeMessage;\n\n import javax.servlet.http.HttpServlet;\n import javax.servlet.http.HttpServletRequest;\n import javax.servlet.http.HttpServletResponse;\n\n public class MailHandlerServlet extends HttpServlet {\n\n private static final Logger log = Logger.getLogger(MailHandlerServlet.class.getName());\n\n @Override\n public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {\n Properties props = new Properties();\n Session session = Session.getDefaultInstance(props, null);\n try {\n MimeMessage message = new MimeMessage(session, req.getInputStream());\n log.info(\"Received mail message.\");\n } catch (MessagingException e) {\n // ...\n }\n // ...\n }\n }\n\nYou can then use various methods to parse the `message` object:\n\n- Call `getFrom()` to return the sender of the message.\n- Call `getContentType()` to extract the message content type. The `getContent()` method returns an object that implements the `Multipart` interface.\n- Call `getCount()` to determine the number of parts\n- Call `getBodyPart(int index)` to return a particular body part.\n\nAfter you set up your app to handle incoming email, you can use the development\nserver console to simulate incoming email messages. To learn more, including how\nto start the development server, see\n[The Java\nDevelopment Server](/appengine/docs/legacy/standard/java/tools/using-local-server). After you start your application in the local\ndevelopment server, you can access your application by visiting the URL\n\u003chttp://localhost:8888/_ah/admin/\u003e,\nreplacing the value 8888 with whatever port you are using if you don't use the\ndefault port for the local development server.\n\nIn the development server, click Inbound Mail on the left side, fill out the\nform that appears, and click Send Email."]]