猴哥讲故事

用故事的方式学习技术

Flask-mail测试和遇到的问题

导语

今天在尝试 Flask-Mail 发送邮件的过程中,遇到一个小问题导致发送邮件失败,查到了半天问题,真是被自己蠢到了。
这里针对这个问题的前因后果做一个整理分享给大家,避免大家踩同样的坑。

安装 Flask-Mail

这里建议利用 virtualenv 来创建隔离的环境来测试发送邮件,关于 virtualenv相关的介绍和使用可以参考如下连接

Centos下pyenv安装python多版本-增强版

Centos下python纯净虚拟环境

安装并验证 Flask-Mail

pip install flask-mail

root@pts/1 $ python
Python 2.7.5 (default, Nov  3 2016, 17:08:21) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import flask_mail
>>> print flask_mail.__version__
0.9.1
>>> 

Flask-Mail 说明

参考 flask-mail 官方文档 需要注意一下配置

Configuring Flask-Mail
Flask-Mail is configured through the standard Flask config API. These are the available options (each is explained later in the documentation):

MAIL_SERVER : default ‘localhost’
MAIL_PORT : default 25
MAIL_USE_TLS : default False
MAIL_USE_SSL : default False
MAIL_DEBUG : default app.debug
MAIL_USERNAME : default None
MAIL_PASSWORD : default None
MAIL_DEFAULT_SENDER : default None
MAIL_MAX_EMAILS : default None
MAIL_SUPPRESS_SEND : default app.testing
MAIL_ASCII_ATTACHMENTS : default False

这里尤其注意下面两个参数吧

MAIL_USE_TLS : default False
MAIL_USE_SSL : default False

关于 TLS 和 SSL 的说明可以参考 聊聊HTTPS和SSL/TLS协议

遇到问题

参考网上flask web开发中实例设置 MAIL_USE_TLS=True ,考虑google email可能被墙的原因,在实际中自己的 MAIL_SERVER='smtp.exmail.qq.com'
但是测试过程中不报错,就直接卡死不动,以为是防火墙的问题,也修改了云端的防火墙开启了465端口,还是不能发信。

思考…

MAIL_SERVER/MAIL_USERNAME/MAIL_PASSWORD可能是没有错,端口的话腾讯企业邮箱smtp开发的端口是465,那就剩下这个协议的问题了…

登陆网页端设置中查看,呃… 怎么不是TSL协议,而是SSL协议,如下图

exmail-smtp-protocol

那么TLS是google mail的设置了吗?赶紧登陆 google mail去看看

google-mail-smtp-protocol

还真是…

修改配置为:

app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USE_TLS'] = False ## 默认就是 false, 加上警示自己

再次测试发送邮件成功,如下图

flask-send-mail

实际脚本

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
33
34
35
36
37
38
39
40
41
42
43
44
45
root@pts/1 $ cat flask-sendmail.py
#!/usr/bin/env python
#coding: utf-8

from flask import Flask, request
from flask_script import Manager,Shell
from flask_mail import Mail,Message
from threading import Thread
import os

app = Flask(__name__)

app.config['DEBUG'] = True


app.config['MAIL_SERVER'] = 'smtp.exmail.qq.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')

manager = Manager(app)
mail = Mail(app)

## 异步发送邮件
def send_async_email(app,msg):
with app.app_context():
mail.send(msg)

@app.route('/')
def index():
msg = Message(subject='Email test by flask-email',sender="liuc1@xxx.com",recipients=['liuc1@xxx.com','xxxxxxx@qq.com'])
msg.body = 'hello 刘超'
msg.html = '<b>测试Flask发送邮件<b>'

thread = Thread(target=send_async_email,args=[app,msg])
thread.start()

# mail.send(msg)

return '<h1>邮件发送成功</h1>'

if __name__ == '__main__':
manager.run()

邮件内容会以文本和html两种格式呈现,而你能看到哪种格式取决于你的邮件客户端

flask-mail相关错误总结

没有开启POP3/SMTP服务

smtplib.SMTPAuthenticationError: (454, 'Authentication failed, please open smtp flag first!')

密码错误

QQ邮箱 开启POP3/SMTP服务 之后需要一个独立的邮箱密码

smtplib.SMTPAuthenticationError: (535, 'Authentication failed')

开启 TLS

smtplib.SMTPServerDisconnected: Connection unexpectedly closed


公众号: DailyJobOps
DailyJobOps