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"]],["最后更新时间 (UTC):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."]]