Flask项目:使用Flask-Mail + uwsgi的邮件发送

自己写了一个个人主页,准备部署到阿里云上,环境是

Flask + Nginx + MySQL + uwsgi + CentOS6.8

有一个(也是唯一一个^_^)需要后台处理的业务就是邮件发送,使用Flask-Mail来完成。

Flask-Mail 扩展提供了一个简单的接口,可以在 Flask 应用中设置 SMTP, 使得可以在视图以及脚本中发送邮件信息。

开启163邮箱的SMTP服务

我使用的是163邮箱的SMTP服务,首先需要先开启该服务并获得授权码。在163邮箱的“设置-POP3/SMTP/IMAP”中可以开启服务:
Flask项目:使用Flask-Mail + uwsgi的邮件发送_第1张图片
在“设置-客户端授权密码”中可以获得授权码,具体可能需要用到手机验证:
Flask项目:使用Flask-Mail + uwsgi的邮件发送_第2张图片

安装Flask-Mail

pip install Flask-Mail

配置Flask-Mail

配置项 默认值 功能
MAIL_SERVER localhost   邮箱服务器
MAIL_PORT   25  端口
MAIL_USE_TLS    False   是否使用TLS
MAIL_USE_SSL    False   是否使用SSL
MAIL_DEBUG  app.debug   是否为DEBUG模式,打印调试消息
MAIL_SUPPRESS_SEND  app.testing 设置是否真的发送邮件,True不发送
MAIL_USERNAME   None    用户名,填邮箱
MAIL_PASSWORD   None    密码,填授权码
MAIL_DEFAULT_SENDER None    默认发送者,填邮箱
MAIL_MAX_EMAILS None    一次连接中的发送邮件的上限
MAIL_ASCII_ATTACHMENTS  False   如果 MAIL_ASCII_ATTACHMENTS 设置成 True 的话,文件名将会转换成 ASCII 的。一般用于添加附件。

邮件是通过一个Mail实例进行管理的:

from flask import Flask
from flask_mail import Mail, Message

app = Flask(__name__)
...
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER') or '你的邮箱服务器'
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') or '你的邮箱'
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') or '你的邮箱授权码'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:dzd123@localhost/flask'
...

# 创建实例
mail = Mail(app)

发送邮件

首先要创建发送邮件的内容Message实例:

from flask-mail import Message
msg = Message(subject=subject, recipients=[to], sender=app.config['MAIL_USERNAME'])

其中,subject为主题,recipients为接收方,可以设置一个或多个收件人,也可以后续添加,sender为发送方,如果设置了”MAIL_DEFAULT_SENDER”,就不必再填写发件人,因为默认情况下会使用配置项的发送人。
邮件内容可以包括主体以及/或者HTML:

msg.html = 'Email: ' + message[0] + '
Message: '
+ message[1] msg.body = 'Email: ' + message[0] + 'Message: ' + message[1]

最后,发送邮件的时候请使用Flask应用设置的Mail实例:

mail.send(msg)

完整例子

from flask import Flask, render_template, request, flash, redirect, url_for, current_app
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_mail import Mail, Message
from threading import Thread
import os
from flask_migrate import Migrate, MigrateCommand
from datetime import datetime

base_dir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)

app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') or 'idandan'
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER') or '你的邮箱服务器'
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') or '你的邮箱'
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') or '你的邮箱授权码'
app.config['MAIL_PORT'] = 465  # 设置邮箱端口为465,默认为25,由于阿里云禁止了25端口,所以需要修改
app.config['MAIL_USE_SSL'] = True  # 163邮箱需要开启SSL
#database_uri = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite')
#app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:dzd123@localhost/你的数据库名'

# 创建实例
mail = Mail(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)


# 数据库模型类
class MessageModel(db.Model):
    __tablename__ = 'message'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))
    email = db.Column(db.String(64))
    message = db.Column(db.Text)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow())


# 发送邮件
def send_mail(to, subject, message, **kwargs):
    msg = Message(subject=subject, recipients=[to], sender=app.config['MAIL_USERNAME'])
    msg.html = 'Email: ' + message[0] + '
Message: '
+ message[1] msg.body = 'Email: ' + message[0] + 'Message: ' + message[1] mail.send(msg) return 'ok' # 视图处理路由 @app.route('/send/', methods=['GET', 'POST']) def send(): if request.method == 'POST': # 接收form表单中传递过来的数据 name = request.form.get('name') email = request.form.get('email') message = request.form.get('message') # 写入数据库 record = MessageModel(name=name, email=email, message=message) db.session.add(record) db.session.commit() # 发送邮件 send_mail('收件人邮箱', name, [email, message]) flash('Email send successfully') return redirect(url_for('index')) return render_template('index.html') @app.route('/') def index(): return render_template('index.html') if __name__ == '__main__': manager.run()

开始使用了异步发送,但是由于使用的是uwsgi,似乎由于GIL的原因,禁止了uwsgi的多线程(不确定是不是),所以导致邮件一直发送不出去,测试了很久,将异步发送去掉了以后就成功了,同学们也可以测试一下。另外,在初始化MySQL时,报了”ModuleNotFoundError: No module named ‘MySQLdb’
“的错误,这个只要在配置”SQLALCHEMY_DATABASE_URI”的时候,加上一个”pymysql”就可以了,详细可以见No module named ‘MySQLdb’


分割线
终于找到不能异步发送邮件的原因了,uwsgi默认时单线程的,每次都是结束后才能给服务器发送成功,在后台启动文件”uwsgi.ini”中添加threads选项,指定线程数就可以了

你可能感兴趣的:(PythonFlask学习,Flask-Mail,mysql,uwsgi,nginx,邮件发送)