本页面介绍如何将 Mail API(一种旧版捆绑服务)与标准环境中的 Python 运行时搭配使用。您的应用可以通过 Python 版 App Engine 服务 SDK 访问捆绑服务。
概览
在 Python 中,邮件处理功能包含在 google.appengine.api.mail
模块中。这与 Python 2 不同,在 Python 2 中,mail_handlers
模块由 webapp 提供。适用于 Python 的邮件 API 可用于接收电子邮件和退信通知。
使用邮件 API
当电子邮件作为 HTTP POST 请求中的请求正文发送时,您的应用会收到邮件。为了让应用处理传入的电子邮件,应用需要将网址与路径 /_ah/mail/[ADDRESS]
进行匹配。路径的 [ADDRESS]
部分通常是带有后缀 @<Cloud-Project-ID>.appspotmail.com
的电子邮件地址。以此格式发送到应用的电子邮件将路由到函数。
Python 不需要应用在 app.yaml
文件中指定处理程序脚本,因此您可以移除 app.yaml
中的所有 handler
部分。
您的 app.yaml
文件应保留以下行:
inbound_services:
- mail
- mail_bounce
发送邮件
升级到 Python 时,您无需更改应用的配置。用于发送邮件的行为、功能和设置说明保持不变。如需了解详情,请参阅以下指南:
接收邮件
要接收邮件,您需要导入 google.appengine.api.mail
模块并使用 InboundEmailMessage
类来表示电子邮件。该类需要实例化才能从传入的 HTTP 请求中检索电子邮件内容。
以前,在 Python 2 中,应用可以通过替换 webapp 处理程序 InboundEmailHandler
中的 receive()
方法来访问 InboundEmailMessage
类。在 Python 中不需要如此操作;相反,应用需要实例化新对象。
Web 框架
使用 Python 网络框架时,InboundEmailMessage
构造函数会接收 HTTP 请求正文的字节。您可以使用多种方法在 Python 中创建 InboundEmailMessage
对象。以下是 Flask 和 Djago 应用的示例:
Python 3 (Flask)
在 Flask 中,request.get_data()
提供请求字节数。
Python 3 (Django)
在 Django 中,request.body
提供 HTTP 请求正文的字节。
如需查看本指南中的完整代码示例,请参阅 GitHub。
其他与 WSGI 兼容的框架
对于其他与 WSGI 兼容的框架,我们建议使用与 Flask 和 Django 示例相同的方法来创建 InboundEmailMessage
。当 HTTP 请求正文的字节直接可用时,此方法有效。
没有网络框架的 WSGI 应用
如果您的应用是不使用网络框架的 WSGI 应用,则 HTTP 请求正文的字节可能无法直接可用。如果 HTTP 请求正文的字节直接可用,我们建议您使用 Python 网络框架。
在 Python 中,为 InboundEmailMessage
定义了一个名为 from_environ
的 factory 方法。此方法是一个将 WSGI environ
字典作为输入的类方法,可用于任何 WSGI 应用。
在以下示例中,请注意如何将 environ
作为输入来获取 mail_message
:
Python 3(WSGI 应用)
接收退信通知
退信通知是来自电子邮件系统的自动邮件,表示应用的邮件递送出现问题。要处理退信通知,您的应用需要将传入的网址路径与 /_ah/bounce
路径相匹配。
与 InboundEmailMessage
类似,可通过替换 webapp 处理程序 BounceNotificationHandler
中的 receive()
方法来访问 Python 2 的 BounceNotification
类。
在 Python 中,应用需要实例化 BounceNotification
对象,该对象可以通过多种方式创建,具体取决于所使用的 Python 网络框架。
Web 框架
BounceNotification
对象使用通过调用 post_vars.get(key)
检索的值进行初始化。
使用 Python 网络框架(如 Flask 或 Django)时,BounceNotification
构造函数采用名为 post_vars
的字典,其中包含表单数据的 POST 请求。要检索数据,需要在输入对象上定义 get()
方法。key
是 BounceNotification
可以从中读取和检索的输入值列表,可以是以下任何一种:
original-to, original-cc, original-bcc, original-subject, original-text, notification-from, notification-to, notification-cc, notification-bcc, notification-subject, notification-text, raw-message
在大多数网络框架中,此数据以多字典形式在请求对象中提供。其中大多数类型都可以转换为由字符串键控的字典。
对于除 raw-message
之外的所有键,该值可以是任何值。通常,该值可以是单个值(如字符串),也可以是值列表(如 {'to': ['bob@example.com', 'alice@example.com']}
)。所有字段的默认值都是空字符串。这些值将填充 original
和 notification
属性。
对于 raw-message
键,该值必须是 EmailMessage
构造函数的有效输入。它可以是单个值,也可以是单个值列表。raw-message
键用于初始化对象的 original_raw_message
属性。
Python 2 (webapp2)
class LogBounceHandler(BounceNotificationHandler):
def receive(self, bounce_message):
logging.info('Received bounce post ... [%s]', self.request)
logging.info('Bounce original: %s', bounce_message.original)
logging.info('Bounce notification: %s', bounce_message.notification)
Python 3 (Flask)
在 Flask 中,类型为 werkzeug.datastructures.MultiDict
的 request.form
提供 POST 变量。但是,即使键存在多个值,此类型的 get()
方法也只会返回一个值。
为了获取与键对应的所有值,应用需要调用 dict(request.form.lists())
,这会生成一个字典,其中每个值都是一个列表。
Python 3 (Django)
在 Django 中,类型为 django.http.QueryDict
的 request.POST
提供 POST 变量。但是,即使键存在多个值,此类型的 get()
方法也只会返回一个值。
为了获取与键对应的所有值,应用需要调用 dict(request.POST.lists())
,这会生成一个字典,其中每个值都是一个列表。
没有网络框架的 WSGI 应用
如果您的应用是不使用网络框架的 WSGI 应用,则 HTTP POST 请求的表单变量可能无法在字典中直接可用。
在 Python 中,为 BounceNotification
定义了一个名为 from_environ
的 factory 方法。此方法是一个将 WSGI environ
字典作为输入的类方法,可用于任何 WSGI 应用。
在以下示例中,请注意如何将 environ
作为输入来获取 bounce_message
:
Python 3
代码示例
如需查看本指南中的完整代码示例,请参阅 GitHub。