您的位置:首页 > 大数据 > 人工智能

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

2018-01-06 21:56 477 查看
自己写了一个个人主页,准备部署到阿里云上,环境是

Flask + Nginx + MySQL + uwsgi + CentOS6.8


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

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

开启163邮箱的SMTP服务

我使用的是163邮箱的SMTP服务,首先需要先开启该服务并获得授权码。在163邮箱的“设置-POP3/SMTP/IMAP”中可以开启服务:



在“设置-客户端授权密码”中可以获得授权码,具体可能需要用到手机验证:



安装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] + '<br>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] + '<br>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选项,指定线程数就可以了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息