flask使用Flask-Mail实现邮件发送

Flask-Mail可以实现邮件的发送,并且可以和 Flask 集成,让我们更方便地实现此功能。

1、安装

使用pip安装:

$ pip install Flask-Mail

或下载源码安装:

$ git clone https://github.com/mattupstate/flask-mail.git
$ cd flask-mail
$ python setup.py install

2、发送邮件

Flask-Mail 连接到简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP) 服务器,并把邮件交给这个服务器发送。这里以QQ邮箱为例,介绍如何简单地发送邮件。在此之前,我们需要知道QQ邮箱的服务器地址和端口是什么

# -*- coding: utf-8 -*-
from flask import Flask
from flask_mail import Mail, Message
import os
app = Flask(__name__)
app.config['MAIL_SERVER'] = 'smtp.qq.com'  # 邮件服务器地址
app.config['MAIL_PORT'] = 25               # 邮件服务器端口
app.config['MAIL_USE_TLS'] = True          # 启用 TLS
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') or 'me@example.com'
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') or '123456'
mail = Mail(app)
@app.route('/')
def index():msg = Message('Hi', sender='me@example.com', recipients=['he@example.com'])msg.html = '<b>Hello Web</b>'# msg.body = 'The first email!'mail.send(msg)return '<h1>OK!</h1>'
if __name__ == '__main__':app.run(host='127.0.0.1', debug=True)

在发送前,需要先设置用户名和密码,当然你也可以直接写在文件里,如果是从环境变量读取,可以这么做:

$ export MAIL_USERNAME='me@example.com'
$ export MAIL_PASSWORD='123456'

将上面的sender和recipients改一下,就可以进行测试了。

从上面的代码,我们可以知道,使用 Flask-Mail 发送邮件主要有以下几个步骤:

  • 配置 app 对象的邮件服务器地址,端口,用户名和密码等
  • 创建一个 Mail 的实例:mail = Mail(app)
  • 创建一个 Message 消息实例,有三个参数:邮件标题、发送者和接收者
  • 创建邮件内容,如果是 HTML 格式,则使用msg.html,如果是纯文本格式,则使用msg.body
  • 最后调用mail.send(msg)发送消息

Flask-Mail 配置项
Flask-Mail 使用标准的 Flask 配置 API 进行配置,下面是一些常用的配置项:
在这里插入图片描述

3、异步发送邮件

使用上面的方式发送邮件,会发现页面卡顿了几秒才出现消息,这是因为我们使用了同步的方式。为了避免发送邮件过程中出现的延迟,我们把发送邮件的任务移到后台线程中,代码如下:

# -*- coding: utf-8 -*-
from flask import Flask
from flask_mail import Mail, Message
from threading import Thread
import os
app = Flask(__name__)
app.config['MAIL_SERVER'] = 'smtp.qq.com'
app.config['MAIL_PORT'] = 25
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') or 'smtp.example.com'
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') or '123456'
mail = Mail(app)
def send_async_email(app, msg):with app.app_context():mail.send(msg)
@app.route('/sync')
def send_email():msg = Message('Hi', sender='me@example.com', recipients=['he@example.com'])msg.html = '<b>send email asynchronously</b>'thr = Thread(target=send_async_email, args=[app, msg])thr.start()return 'send successfully'
if __name__ == '__main__':app.run(host='127.0.0.1', debug=True)

在上面,我们创建了一个线程,执行的任务是send_async_email,该任务的实现涉及一个问题:

很多 Flask 扩展都假设已经存在激活的程序上下文和请求上下文。Flask-Mail 中的send()函数使用 current_app,因此必须激活程序上下文。不过,在不同线程中执行mail.send()函数时,程序上下文要使用 app.app_context()人工创建。

4、带附件的邮件

有时候,我们发邮件的时候需要添加附件,比如文档和图片等,这也很简单,代码如下:

# -*- coding: utf-8 -*-
from flask import Flask
from flask_mail import Mail, Message
import os
app = Flask(__name__)
app.config['MAIL_SERVER'] = 'smtp.qq.com'  # 邮件服务器地址
app.config['MAIL_PORT'] = 25               # 邮件服务器端口
app.config['MAIL_USE_TLS'] = True          # 启用 TLS
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME') or 'me@example.com'
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD') or '123456'
mail = Mail(app)
@app.route('/attach')
def add_attchments():msg = Message('Hi', sender='me@example.com', recipients=['other@example.com'])msg.html = '<b>Hello Web</b>'with app.open_resource("/Users/Admin/Documents/pixel-example.jpg") as fp:msg.attach("photo.jpg", "image/jpeg", fp.read())mail.send(msg)return '<h1>OK!</h1>'
if __name__ == '__main__':app.run(host='127.0.0.1', debug=True)

上面的代码中,我们通过app.open_resource(path_of_attachment)打开了本机的某张图片,然后通过msg.attach()方法将附件内容添加到 Message 对象。msg.attach()方法的第一个参数是附件的文件名,第二个参数是文件内容的MIME (Multipurpose Internet Mail Extensions)类型,第三个参数是文件内容。

5、批量发送

在某些情况下,我们需要批量发送邮件,比如给网站的所有注册用户发送改密码的邮件,这时为了避免每次发邮件时都要创建和关闭跟服务器的连接,我们的代码需要做一些调整,类似如下:

with mail.connect() as conn:for user in users:subject = "hello, %s" % user.namemsg = Message(recipients=[user.email], body='...', subject=subject)conn.send(msg)

上面的工作方式,使得应用与电子邮件服务器保持连接,一直到所有邮件已经发送完毕。某些邮件服务器会限制一次连接中的发送邮件的上限,这样的话,你可以配置MAIL_MAX_EMAILS。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/99660.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ClickHouse配置Hdfs存储数据

文章目录 背景配置单机配置HA高可用Hdfs集群性能测试统计trait最多的10个trait term统计性状xxx minValue > 500 0000的数量结论 参考文档 背景 由于公司初始使用Hadoop这一套&#xff0c;所以希望ClickHouse也能使用Hdfs作为存储 看了下ClickHouse的文档&#xff0c;拿Hdf…

HyperDock 1.8.0.10(Dock优化工具)

HyperDock 是一款为 macOS 设计的实用工具&#xff0c;它提供了许多方便快捷的功能&#xff0c;使您能够更高效地管理和操作应用程序窗口。 首先&#xff0c;HyperDock 提供了类似于 Windows 7 的任务栏预览功能。当您将鼠标悬停在应用程序图标上时&#xff0c;会显示该应用程…

flutter 上传图片并裁剪

1.首先在pubspec.yaml文件中新增依赖pub.dev image_picker: ^0.8.75 image_cropper: ^4.0.1 2.在Android的AndroidManifest.xml文件里面添加权限 <activityandroid:name"com.yalantis.ucrop.UCropActivity"android:screenOrientation"portrait"andro…

Spring-mvc的参数传递与常用注解的解答及页面的跳转方式---综合案例

目录 一.slf4j--日志 二.常用注解 2.1.RequestMapping 2.2.RequestParam 2.3.RequestBody 2.4.PathVariable 三.参数的传递 3.1 基础类型 3.2 复杂类型 3.3 RequestParam 3.4 PathVariable 3.5 RequestBody 3.6 增删改查 四.返回值 4.1 void 返回值 4.2 String 返…

Elsaticsearch倒排索引

搜索引擎应该具有什么要求&#xff1f; 查询快 高效的压缩算法 快速的编码和解码速度 结果准确 BM25 TF-IDF 检索结果丰富 召回率 面向海量数据&#xff0c;如何达到搜索引擎级别的查询效率&#xff1f; 索引 帮助快速检索以数据结构为载体以文件形式落地 倒排…

手把手教你写一个简单的ioc容器

Ioc IOC&#xff08;控制反转&#xff09; 就是 依赖倒置原则的一种代码设计思路。就是把原先在代码里面需要实现的对象创建、对象之间的依赖&#xff0c;反转给容器来帮忙实现。 Spring IOC容器通过xml,注解等其它方式配置类及类之间的依赖关系&#xff0c;完成了对象的创建和…

微服务-gateway基本使用

文章目录 一、前言二、gateway网关1、什么是微服务网关&#xff1f;2、微服务架构下网关的重要性2.1、没有网关2.2、有网关 3、gateway的功能4、gateway实战4.1、依赖配置4.2、添加网关配置4.3、添加网关启动类4.4、查看项目是否启动成功4.5、验证路由配置是否正确 三、总结 一…

报错:axios发送的所有请求都是404

axios发送的所有请求都是404 一、问题二、分析三、解决一、问题 对后台发送数据请求接口,在 Swagger 上是可以请求到的 但是通过 Ajax 发送请求就会报 404 Swagger 上调用如下 项目接口请求如下

react16之前diff算法的理解和总结

此篇文章所讨论的是 React 16 以前的 Diff 算法。而 React 16 启用了全新的架构 Fiber&#xff0c;相应的 Diff 算法也有所改变&#xff0c;本片不详细讨论Fiber。 fiber架构是为了支持react进行可中断渲染&#xff0c;降低卡顿&#xff0c;提升流畅度。 react16之前的版本&…

二、C#—第一个c#程序(2)

&#x1f33b;&#x1f33b; 目录 一、编写第一个C#程序1.1 使用Visual Studio创建c#程序的步骤1.2 编写第一个程序“Hello Word”1.3 c#程序的基本结构1.3.1 c#中的命名空间1.3.2 c#中的类1.3.3 c#中的程序启动器——Main方法1.3.4 c#中的标识符1.3.5 c#中的关键字1.3.6 c#中的…

Java-HashMap中put()方法是如何实现的,内含详细流程图

文章目录 Java中的HashMap什么是HashMap&#xff1f;对比其他Map中put()方法HashMap中put()方法使用示例 HashMap中put()源码解析手绘流程图实现原理源码探究&#xff08;JDK 1.8&#xff09; 设计put()的意义总结 Java中的HashMap 什么是HashMap&#xff1f; HashMap是Java中…

linux并发服务器 —— 多进程并发 - 进程间的通信及实践(五)

进程间的通信 进程是一个独立的资源分配单元&#xff0c;不能在一个进程中直接访问另一个进程的资源&#xff1b; 进程间通信&#xff08;IPC&#xff09;的目的&#xff1a; 1. 数据传输 - A进程发送数据给B进程 2. 通知事件 - eg. 进程终止通知父进程 3. 资源共享 - 多个…