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-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选项,指定线程数就可以了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值