Email messages sent to your app are implemented as HTTP requests. To process incoming email messages, you associate email addresses with script handlers in your app configuration, then include the handlers in your app's code. Incoming email generates HTTP requests, which are passed to the appropriate scripts.
Configuring Your App to Receive Email
When you create a new app, incoming email is disabled by default. To enable the incoming email service, you must modify your
app.yaml file in two ways:
- Add an
inbound_servicessection that enables the incoming email service.
- Add mappings that associate URL-mapped email addresses with script handlers.
To enable the incoming email service, add a short section to your
app.yaml file, like the following:
inbound_services: - mail
You can verify that you have enabled incoming email in your app by going to the Administration Console and checking the Application Settings section. Note that you can only check there to see if the incoming email service is enabled; you must change the
app.yaml file to actually enable or disable the service. If you don't enable incoming email by including this section in your configuration file, incoming email is disabled, and email messages sent to the app are ignored.
Your app can receive email at addresses of the following form:
Email messages are sent to your app as HTTP POST requests using the following URL:
where address is a full email address, including domain name. To handle incoming email in your app, you map email URLs to handlers in the
- url: /_ah/mail/.+ script: handle_incoming_email.app login: admin
In this example, /_ah/mail/.+ matches all email addressed to the app.
If you prefer, you can set up multiple handlers for different email addresses, as in the following example:
- url: /_ah/mail/owner@.*your_app_id\.appspotmail\.com script: handle_owner.app login: admin - url: /_ah/mail/support@.*your_app_id\.appspotmail\.com script: handle_support.app login: admin - url: /_ah/mail/.+ script: handle_catchall.app login: admin
URLs of incoming email messages are matched to this list from first to last, so if an email message URL matches more than one pattern, the first matching handler will be the one executed. This allows you to include a "catchall" handler as the last mapping. The handlers run in the default module (or application version).
Handling Incoming Email
The Python SDK defines
InboundMailHandler, a webapp class for handling incoming email. To use
InboundMailHandler, you subclass it and override the
receive() method. The
receive() method is called with an argument of class
InboundEmailMessage, another class defined by the Python SDK.
InboundMailHandler is in the
google.appengine.ext.webapp.mail_handlers package. You can create an instance of
InboundEmailMessage like this:
import logging import webapp2 from google.appengine.ext.webapp.mail_handlers import InboundMailHandler class LogSenderHandler(InboundMailHandler): def receive(self, mail_message): logging.info("Received a message from: " + mail_message.sender)
Note: Even if you are using the webapp2 framework, you will still need to use the
InboundMailHandler class provided by the old webapp framework. This handler is specific to the App Engine mail service, whereas webapp2 is provided by a third party.
InboundMailHandler contains a
mapping() convenience class method that returns a pair matching all incoming email addresses to the mail
handler (and of course you can call it on any subclass of
InboundMailHandler you code):
app = webapp2.WSGIApplication([LogSenderHandler.mapping()], debug=True)
InboundEmailMessage object (
mail_message in this example) contains the email message. Its
bodies() method returns the bodies within the message. If you call
bodies() without arguments, it returns an iterator that yields HTML bodies first, then plain text bodies. If you want just HTML or just plain text, you can pass an argument to
bodies(), as follows:
plaintext_bodies = mail_message.bodies('text/plain') html_bodies = mail_message.bodies('text/html') for content_type, body in html_bodies: decoded_html = body.decode() # ...
InboundEmailMessage object includes attributes to access other message fields:
subjectcontains the message subject.
senderis the sender's address e.g.
tois a comma-separated list of the message's primary recipients e.g.
"Joe <firstname.lastname@example.org>, Bill <email@example.com>".
cccontains a comma-separated list of the cc recipients e.g.
"Joe <firstname.lastname@example.org>, Bill <email@example.com>".
datereturns the message date.
attachmentsis a list of
Attachmentobjects, possibly empty.
originalis the complete message, including data not exposed by the other fields such as email headers, as a Python email.message.Message.
Once you set up your app to handle incoming email, you can use the development server console to simulate incoming email messages. You can access the development server by going to http://localhost:8000. In the development server, click Inbound Mail on the left side, fill out the form that appears, and click Send Email. You will need to be logged in as an administrator for the app (e.g. by going to http://localhost:8080/_ah/login and being sure to tick "Sign in as administrator"). To learn more, including how to get the development server running, see The Python Development Server.