当使用Twilio SendGrid发送邮件时,有时你希望能够跟踪这些邮件的状态,比如收件人何时打开邮件或报告为垃圾邮件。这是通过使用事件Webhooks实现的。让我们来看看如何使用Python和Flask来跟踪你所发送的邮件的状态。
先决条件和依赖性
在继续前进之前,请确保你具备以下条件:
- 在你的机器上安装了Python 3
- 一个免费的SendGrid账户
- 一个用于测试这个项目的电子邮件地址
- 一个你将接收电子邮件的域名。为了本文的目的,我将使用yourdomainhere.com。你将需要用你自己的域名来替换它。
在编写代码之前,你需要安装一些依赖项:
- 用于发送电子邮件的SendGrid Python库
- Flask,作为接收HTTP请求的网络框架
确保你创建并激活一个虚拟环境,然后用以下命令安装这些东西:
pip install sendgrid==6.9.6 Flask==1.1.2
注册SendGrid并创建一个API密钥
在创建SendGrid账户时,为了本教程的目的,你可以选择免费层。一旦你有一个账户,你需要创建一个API密钥,如该截图所示。你可以随心所欲地命名它,但一旦它被创建,请确保在继续前进之前保存它

保存这个 API 密钥的一个好方法是把它设置为一个环境变量,你可以从你的 Python 代码中访问它,以避免在你的代码中直接写入它。将SENDGRID_API_KEY 环境变量的值设置为你的SendGrid账户的API密钥。不过在其他地方记下它仍然没有坏处,因为你无法再次查看它。如果你需要帮助设置环境变量,这里有一个有用的教程。我们将在后面使用这个API密钥。
用Python发送电子邮件
在能够跟踪电子邮件的状态之前,我们需要实际发送一个。让我们写一些快速代码来发送一封包含火星车拍摄的照片的电子邮件。创建一个名为mars_email.py 的文件,并在其中添加以下代码:
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
def send_mars_email(from_email, to_email, img_url):
message = Mail(
from_email=from_email,
to_emails=to_email,
subject='Here is your Mars Rover picture',
html_content='<strong>Check out this Mars pic</strong><br><br>'
f'<img src="{img_url}"></img><br><br>'
f'<a href="{img_url}">Here is a link to the Mars Pic</a>')
sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
response = sg.send(message)
print(response.status_code, response.body, response.headers)
send_mars_email('from@example.com', 'to@example.com', 'https://mars.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01000/opgs/edr/fcam/FLB_486265257EDR_F0481570FHAZ00323M_.JPG')
这段代码包含一个发送包含图片的电子邮件的函数,以及一些在底部调用该函数发送以下图片的独立代码。

用你想使用的电子邮件地址替换from@example.com 和to@example.com 。用终端命令python mars_email.py ,运行这段代码,你应该会收到一封带有那张火星车照片的电子邮件。
为事件Webhook创建一个Flask应用程序
下一步是编写一些Python代码,创建一个网络应用程序,以便在你发送的电子邮件发生交付事件或参与事件时接收HTTP请求。创建一个名为app.py 的文件,并在其中添加以下代码:
from flask import Flask, request
app = Flask(__name__)
@app.route('/event', methods=['POST'])
def event_webhook():
event = request.json[0]['event']
if event == 'delivered':
print('Your email has been delivered!')
elif event == 'open':
print('Your email has been opened.')
elif event == 'click':
print('The link in your email has been clicked.')
elif event == 'spamreport':
print('The recipient has marked your email as spam.')
return '200'
if __name__ == '__main__':
app.run(debug=True)
这段代码将接收来自Twilio SendGrid的HTTP请求,并根据发生的事件打印不同的语句,例如用户点击邮件中的一个链接。在python app.py 或flask run 中运行代码,并将其放在app.py 所在的同一目录中。这将在你的机器的5000端口上运行一个Flask服务器。现在,我们需要一个可公开访问的URL来为SendGrid提供事件Webhook。
配置事件Webhook
我们将使用一个叫做ngrok的工具来创建一个公共URL,SendGrid可以用它来转发请求到我们本地运行的应用程序。
如果你还没有,在你的系统上安装ngrok。随着Python代码的运行,打开第二个终端窗口,启动ngrok,如下所示:
ngrok http 5000
这就是告诉 ngrok 从公共互联网创建一个 "隧道",进入我们本地机器的 5000 端口,Flask 应用程序正在那里监听请求。输出应该是这样的。

带着这个URL,前往你的SendGrid仪表盘中的邮件设置页面,并点击 "事件Webhook",如下面的截图所示。

通过复制和粘贴你的ngrok URL来配置事件Webhook,并将/event ,这是你希望HTTP请求被发送到的Flask应用上的路由。在这个例子中,我勾选了 "已送达"、"已打开"、"已点击 "和 "垃圾邮件报告 "事件,但你可以选择与你相关的事件。

在点击保存之前,不要忘记点击事件Webhook状态的 "ENABLED"!
测试它
现在你有一个Flask应用程序在ngrok URL后面运行,并且配置了SendGrid Event Webhook以向该URL发送请求,你可以在另一个终端窗口中再次运行你的代码mars_email.py ,以看到你的交付和参与事件被记录在屏幕上。

尝试不同的事情,如点击邮件中的链接,或将其报告为垃圾邮件,以看到更多的事件记录在屏幕上。从这里,你可以改变代码,以适应你的特定用例的需要。
如果你的网络服务器没有返回2xx响应类型,SendGrid将重试一个POST请求,直到他们收到一个2xx响应或最长时间过期。所有的事件都会在事件发生后的24小时内以递增的间隔重试。请注意,这个时间限制是一个滚动的24小时,这意味着新的失败的事件将获得自己的24小时重试期。
我迫不及待地想看到你在未来用Twilio SendGrid建立什么。