Flask扩展系列:Mail

Posted 编程派

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask扩展系列:Mail相关的知识,希望对你有一定的参考价值。

文 | 思诚之道

来源:http://www.bjhee.com/flask-ext2.html

继续介绍 Flask 常用的扩展,很多站点都需要发送邮件功能,比如用户注册成功邮件,用户重置密码邮件。你可以使用 Python 的 smtplib来发邮件,不过 Flask 有个第三方扩展 Flask-Mail,可以更方便的实现此功能。这里我们就来介绍下这个 Flask-Mail。

系列文章

  • Flask 扩展系列(一)–Restful

安装和启用

建议通过 pip 安装,简单方便:

 
   
   
 
  1. $ pip install Flask-Mail

我们可以采用下面的方法初始化一个 Mail 的实例:

 
   
   
 
  1. from flask import Flask

  2. from flask_mail import Mail

  3.  

  4. app = Flask(__name__)

  5. mail = Mail(app)

同其他扩展一样,最后一行实例化代码也可以写成下面的方式:

 
   
   
 
  1. ...

  2. mail = Mail()

  3. mail.init_app(app)

这样的写法在应用工厂模式下经常会用到。

发送邮件

我们来看一段发送 Hello World 邮件的代码:

 
   
   
 
  1. from flask import Flask

  2. from flask_mail import Mail, Message

  3.  

  4. app = Flask(__name__)

  5. app.config.update(

  6.     MAIL_SERVER='smtp.example.com',

  7.     MAIL_USERNAME='bjhee',

  8.     MAIL_PASSWORD='example'

  9. )

  10.  

  11. mail = Mail(app)

  12.  

  13. @app.route('/mail')

  14. def send_mail():

  15.     msg = Message('Hello',

  16.                   sender=('Billy.J.Hee', 'bjhee@example.com'),

  17.                   recipients=['you@example.com'])

  18.     msg.html = '<h1>Hello World</h1>'

  19.     mail.send(msg)

  20.     return 'Successful'

  21.  

  22. if __name__ == '__main__':

  23.     app.run(host='0.0.0.0', debug=True)

Message 对象的属性,可以在初始化时当作参数(key=value) 传入,也可以在初始化后赋值。比如我们可以这样定义收件人:

 
   
   
 
  1.     msg.recipients=['you@example.com']

由于收件人可以多个,我们也可以通过"add_recipient()"方法添加收件人:

 
   
   
 
  1.     msg.add_recipient('he@example.com')

 
   
   
 
  1.     msg.sender='bjhee@example.com'

另外,上例中的邮件体是 HTML 格式,如果是 Plain Text 格式的话,你可以这样写:

 
   
   
 
  1.     msg.body = 'Hello World'

配置参数

Flask-Mail 扩展可以在 Flask 应用配置项中配置其参数,上例中我们已经看到了 SMTP 服务器,用户名和密码的配置项,这里列举一些常用的:

配置项 功能
MAIL_SERVER SMTP邮件服务器地址,默认为localhost
MAIL_PORT SMTP邮件服务器端口,默认为25
MAIL_USERNAME 邮件服务器用户名
MAIL_PASSWORD 邮件服务器密码
MAIL_DEFAULT_SENDER 默认发件人,如果Message对象里没指定发件人,就采用默认发件人
MAIL_USE_TLS 是否启用TLS,默认为False
MAIL_USE_SSL 是否启用SSL,默认为False
MAIL_MAX_EMAILS 邮件批量发送个数上限,默认为没有上限
MAIL_ASCII_ATTACHMENTS 将附件的文件名强制转换为ASCII字符,避免在某些情况下出现乱码,默认为False
MAIL_SUPPRESS_SEND 调用”Mail.send()”方法后,邮件不会真的被发送,在测试环境中使用,默认为False

批量发送

如果一次需要发送大量邮件,建议采用下面的方式:

 
   
   
 
  1. @app.route('/batch')

  2. def send_batch():

  3.     with mail.connect() as conn:

  4.         for user in users:

  5.             msg = Message(subject='Hello, %s' % user['name'],

  6.                           body='Welcome, %s' % user['name'],

  7.                           recipients=[user['email']])

  8.             conn.send(msg)

  9.  

  10.     return 'Successful'

这样应用同邮件服务器的连接"mail.connect()"会一直保持到所有邮件发送完毕,也就是退出 with 语句后再关闭,避免多次创建关闭连接的开销。批量发送邮件个数上限由配置项"MAILMAXEMAILS"决定。

邮件带附件

回到第一个发送邮件的例子,让我们在 Hello World 邮件中加上附件:

 
   
   
 
  1. @app.route('/mail')

  2. def send_mail():

  3.     msg = Message('Hello',

  4.                   sender=('Billy.J.Hee', 'bjhee@example.com'),

  5.                   recipients=['you@example.com'])

  6.     msg.html = '<h1>Hello World</h1>'

  7.  

  8.     # Add Attachment

  9.     with app.open_resource('blank.docx') as fp:

  10.         msg.attach('blank.docx', 'application/msword', fp.read())

  11.  

  12.     mail.send(msg)

  13.     return 'Successful'

上面的代码中,我们通过"app.open_resource()"方法打开了本地当前目录下的"blank.docx"文件,然后通过"Message.attach()"方法将其附到消息对象中即可。"Message.attach()"方法的第一个参数指定了附件上的文件名,第二个参数指定了文件内容的 MIME 类型,第三个参数就是文件内容。

如果大家不知道要附上的文件 MIME 类型是什么,可以查下 MIME 参考手册。

email_dispatched 信号

Flask-Mail 扩展还提供了一个信号"email_dispatched",当邮件被调度时,该信号就会被发出。如果大家忘了什么是信号,可以参考 进阶系列的第二篇。开发者可以通过这个信号来确定邮件是否被发送成功。当然,发送成功不代表被接收成功。

 
   
   
 
  1. from flask_mail import email_dispatched

  2.  

  3. def log_mail_sent(message, app):

  4.     print 'Message "%s" is sent successfully' % (message.subject)

  5.  

  6. email_dispatched.connect(log_mail_sent)

另外,在跑测试时我们不希望邮件真的被发出去,此时可以将 Flask 应用的配置项"TESTING"设成 True,或者将 Flask-Mail 扩展的配置项"MAILSUPPRESSSEND"设成 True。这样,调用"Mail.send()"方法后,邮件不会被发出,但是你依然可以接收到"email_dispatched"信号。

本篇中的示例参考了 Flask-Mail 的官方文档和 Flask-Mail 的源码。本篇的示例代码可以在这里下载。


题图:pexels,CC0 授权。

点击阅读原文,查看更多 Python 教程和资源。

以上是关于Flask扩展系列:Mail的主要内容,如果未能解决你的问题,请参考以下文章

Flask 扩展 Mail

使用flask-mail扩展发送邮件

Flask之邮件扩展

flask-mail的使用

Flask Web 开发学习稿

FlaskFlask与SMTP协议邮件扩展