Flask知识点串烧(六)--- Flask-Mail

        在WEB程序中发送电子邮件非常简单,借助扩展Flask-Mail或是第三方邮件服务,只需要几行代码就可以发送电子邮件;邮件仅包含几个必要的字段:

使用Flask-Mail发送电子邮件

扩展Flask-Mail包装了Python标准库中的smtplib包,简化了在Flask程序中发送电子邮件的过程。安装及初始化如下:

  • pipenv install flask-mail
  • from flask_mail import Mail
  • mail = Mail(app)

配置Flask-Mail

        Flask-Mail通过连接SMTP服务器来发送邮件,在开始发送邮件前我们需要配置SMTP服务器;在开发和测试阶段我们可以使用邮件服务提供商的SMTP服务器;

  • Flask-Mail的常用配置:
    • MAIL_SERVER 用于发送邮件的SMTP服务器,默认为localhost;
    • MAIL_PORT 发信端口,默认为25
    • MAIL_USE_TLS 是否使用STARTTLS,默认为False;
    • MAIL_USE_SSL 是否使用SSL/TLS,默认为False;
    • MAIL_USERNAME 发信服务器的用户名;
    • MAIL_PASSWORD 发信服务器的密码;
    • MAIL_DEFAULT_SENDER 默认的发信人;
  • 对发送的邮件进行加密可以避免邮件在发送过程中被第三方截获和篡改。SSL和TLS是2种常用的电子邮件安全协议。TLS继承了SSL,并在SSL的基础上做了一些改进。根据加密方式的不同,端口也要相应改变:
    • SSL/TLS加密:MAIL_USE_SSL=True MAIL_PORT=465
    • STARTTLS加密:MAIL_USE_TLS=True MAIL_PORT=587
    • 当不对邮件加密时,邮件服务器的端口使用默认的25端口;
    • 常用SMTP服务提供商配置
      提供商 发信服务器 MAIL_USERNAME MAIL_PASSWORD 额外操作
      Gmail smtp.gmail.com 邮箱地址 邮箱密码 另外需要开启"Allow less secure apps",在本地设置vpn代理
      QQ邮箱 smtp.qq.com 邮箱地址 授权码 需要开启SMPT服务并获取授权码
      新浪邮箱 smtp.sina.com 邮箱地址 邮箱密码 需要开启SMTP服务
      163邮箱 smtp.163.com 邮箱地址 授权码 需要开启SMTP服务器并设置授权码
      Outlook/Hotmail smtp.live.com或smtp.office365.com 邮箱地址 邮箱密码
    • 对于需要发送大量邮件的事务性邮件任务,更好的选择是使用自己配置的SMTP服务器或是使用类似SendGrid等事物邮件服务提供商;
    • 在实例化Mail类时,Flask-Mail会获取配置以创建一个用于发信的对象,所以确保在实例化Mail之前加载配置;
    • 邮箱账户和密码属于敏感信息,所以设置为从环境变量中获取。另外,生产环境中,我们通常会使用不同的邮箱服务器地址,所以发信服务器也从环境变量中获取;
    • 发信人MAIL_DEFAULT_SENDER由一个2元元组组成,即(姓名,邮箱地址)。需要注意,使用邮件服务提供商提供的SMTP服务器发信时,发信人字符串中的邮件地址必须和邮箱地址相同,可以直接用MAIL_USERNAME的值构建发信人地址;Flask-Mail会把这个元组转换为标准的发信人格式;设置默认发信人后,在发信时就不需要再指定发信人;
  • 构建邮件数据
    • from flask-mail import Message
    • 通过Message类的构造方法中的subject/recipients/body关键字传入参数,其中recipients为一个包含电子邮件地址的列表;
    • 收信人字符串可以添加收信人姓名,也可以只使用邮箱地址:'MiaLi<[email protected]>' 或 '[email protected]'
    • Message类的构造方法还支持其它参数来定义邮件首部其它字段,具体可以参考Flask-Mail文档或源码;
  • 发送邮件
    • 通过对mail对象调用send()方法,传入我们在上面构建的邮件对象即可发送邮件;
    • mail.send(message) ;
  • 提供HTML正文
    • 一封邮件的正文可以是纯文本(text/plian)也可以是HTML格式(text/html)的正文。处于更全面的考虑,应该即包含纯文本又包含HTML格式的正文;
    • 在收件人的邮件系统比较古老时,无法读取HTML格式的邮件,则会读取纯文本格式的正文;
    • 大多数主流浏览器客户端都对HTML邮件有着各种各样的限制,对于HTML邮件正文的编写,有如下最佳实践:
      • 使用Tabel布局,而不是Div布局;
      • 使用行内样式定义;
      • 尽量使用比较基础的CSS属性,避免使用快捷属性(background)、定位属性(float,position);
      • 邮件正文的宽度不应超过600px;
      • 避免使用JS代码;
      • 避免使用图片背景;
      • 在Flask-Mail中,我们可以使用Mesage类实例来构建邮件。和纯文本正文类似,HTML正文可以在实例化时传入html参数指定,或是通过message.html属性指定;
    • 使用Jinjia2模板组织正文
      • 为了同时支持纯文本和HTML格式的邮件正文,每一类邮件我们都需要分别创建HTML和纯文本格式模板;
      • message.html和message.body属性都通过render_template渲染;
      • 当邮件中需要加入URL时(比如链接和图片),注意要生成完整的外部URL,而不是内部URL。这可以通过url_for()函数中将关键字_external设为True实现;
      • 大多数程序都需要发送多种不同类型的邮件,我们可以使用模板继承技术来为所有邮件创建一个包含基本样式的基模板;

异步发送邮件

       当程序正在使用SMTP方式发送邮件时,发信的操作会阻断“请求-响应”循环,知道发信结束后,视图函数才会返回响应。这在客户端会造成几秒的延迟,为了避免延迟,我们可以将发信操作放入后台线程异步执行;

  • 因为Flask-Mail的send()方法内部的逻辑中使用了current_app变量,而这个变量只在激活的程序上下文中才存在,在后台线程中发送邮件时,并没有程序上下文存在。为了正常实现发信功能,需要传入程序实例app作为参数,并调用app.app_context()手动激活程序上下文;
  • 在生产环境下,我们应该使用异步任务队列处理工具来处理这类任务,比如Celery;
发布了132 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Geroge_lmx/article/details/104222116