本文主要介绍,如何使用 Flask-Mail 发送邮件。

Flask-Mail 连接到简单邮件传输协议(SMTP)服务器,并把邮件交给这个服务器发送。如果不进行配置,Flask-Mail 会连接 localhost 上的端口 25,无需验证即可发送邮件。

安装 Flask-Mail

1
pip install flask-mail

Flask-Mail 发送邮件

以 163 邮箱账户为例,发送电子邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from flask import Flask,render_template
from flask.ext.mail import Mail,Message
import os
app = Flask(__name__)
#下面是SMTP服务器配置
app.config['MAIL_SERVER'] = 'smtp.163.com' #电子邮件服务器的主机名或IP地址
app.config['MAIL_PORT'] = '25' #电子邮件服务器的端口
app.config['MAIL_USE_TLS'] = True #启用传输层安全
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') #邮件账户用户名
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') #邮件账户的密码
mail = Mail(app)
@app.route('/')
def index():
msg = Message('主题',sender=os.environ.get('MAIL_USERNAME'),recipients=['test@test.com'])
msg.body = '文本 body'
msg.html = '<b>HTML</b> body'
mail.send(msg)
return '<h1>邮件发送成功</h1>'
if __name__ == '__main__':
app.run(debug=True)

上面的注释已经写的很明确了,其中邮件账户用户名和邮件账户密码已经存储到环境变量中,如何设置?我使用的命令行工具是 Mac OS X 下的 bash ,比如你设置的用户名为 test@test.com 密码为:test

在命令行中输入:

1
2
export MAIL_USERNAME = 'test@test.com'
export MAIL_PASSWORD = 'test'

异步发送邮件

由于上面发送邮件比较慢,我们可以在异步线程中发送邮件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from flask import Flask,render_template
from flask.ext.mail import Mail,Message
import os
from threading import Thread
app = Flask(__name__)
app.config['MAIL_SERVER'] = 'smtp.163.com'
app.config['MAIL_PORT'] = '25'
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')
mail = Mail(app)
def send_async_email(app,msg):
with app.app_context():
mail.send(msg)
@app.route('/')
def index():
msg = Message('主题',sender=os.environ.get('MAIL_USERNAME'),recipients=['test@test.com'])
msg.body = '文本 body'
msg.html = '<b>HTML</b> body'
thread = Thread(target=send_async_email,args=[app,msg])
thread.start()
return '<h1>邮件发送成功</h1>'
if __name__ == '__main__':
app.run(debug=True)

我们改动了一些代码,我们创建了个线程 thread,我们执行的方法是send_async_email ,需要注意的是很多 Flask 扩展都假设已经存在激活的程序上下文和请求上下文。Flask-Mail 中的 send() 函数使用 current_app,因此必须激活程序上下文,但是在异步线程中执行 mail.send() 函数时,程序上下文要使用app.app_context() 人工创建。

现在再运行程序,会发现程序流畅多了。但是程序要发送大量电子邮件时,使用专门发送电子邮件的作业要比给每封邮件都新创建一个线程更合适。例如,我们可以把执行send_async_email() 函数的操作发给 Celery 任务队列。