之前也写过python smtplib发送邮件 ,其是基于smtpmlib模块写的应用,这里是想利用flask写一个简单的API ,具体的应用场景是,假如一个局域网环境中,只有一台主机可以上外网外发邮件。其他主机不可以上外网。该主机启动一个flask API邮件外发服务,其他主机需要发送告警邮件时,就可以通过调用该主机的邮件服务外发告警信息。该功能的实现准备分两篇走,第一篇先讲下fask-mail模块,第二篇来具体实现该需求。

一、flask-mail 模块介绍

其初还准备参考之前的smtplib,通过flask调用该程序外出,不过flask对应的邮件扩展有现成的模块有:flask-mail 、flask.ext.mail、flask-sendmail 。这里使用flask-mail 实现。Flask-Mail 提供了一个简单的接口,让我们可以方便的在 Flask 应用中使用 SMTP协议 发送邮件。

二、flask-mail 模块的安装与使用

1、安装

1pip install Flask-Mail 或
2easy_install Flask-Mail

查看该模块的源码会发现,其最终还是调用的smtplib模块来实现的。

2、配置

Flask-Mail 使用 Flask 标准的配置 API 进行配置。下面是所有的配置选项:

 1MAIL_SERVER : 默认为 '127.0.0.1'
 2MAIL_PORT : 默认为 25
 3MAIL_USE_TLS : 默认为 False
 4MAIL_USE_SSL : 默认为 False
 5MAIL_DEBUG : 默认为 app.debug
 6MAIL_USERNAME : 默认为 None
 7MAIL_PASSWORD : 默认为 None
 8MAIL_DEFAULT_SENDER : 默认为 None
 9MAIL_MAX_EMAILS : 默认为 None
10MAIL_SUPPRESS_SEND : 默认为 app.testing
11MAIL_ASCII_ATTACHMENTS : 默认为 False

具体的参数我们可以查看源码

3、初始化

这个在官方的文档中也进行了说明,有两种方法。

方法1:

使用传入到 Mail 实例中的应用程序的配置项进行邮件发送:

1from flask import Flask
2from flask_mail import Mail
3app = Flask(__name__)
4mail = Mail(app)

方法2:

使用 Flask 的 current_app 中的配置项进行邮件发送,如果我们有多个 不同配置的应用程序 则使用此种方式比较方便:

1mail = Mail()
2app = Flask(__name__)
3mail.init_app(app)

三、利用flask-mail 发送邮件

发送详解

发送之前我们需要先构建一个 Message 对象,如下:

1from flask_mail import Message
2msg = Message("Hello Flask", sender="[email protected]",  recipients=["[email protected]"])

我们也可以同时指定多个收件人:

1msg.recipients = ["[email protected]", "[email protected]"]
2msg.add_recipient("[email protected]")

如果我们配置了 MAIL_DEFAULT_SENDER 字段,就可以不再设置 sender ,这个时候会使用 MAIL_DEFAULT_SENDER 中指定的发件人,像这样:

1msg = Message("Hello Flask", recipients=["[email protected]"])

如果我们希望在收件列表中显示一个名字(string),可以通过一个二元祖来指定:

1msg = Message("Hello", sender=("itybku", "[email protected]"))

同时, 我们还可以指定下面两个字段:

1msg.body = "this is body string"
2msg.html = "<h2>this is html message"</h2>

最后就是发送:

1mail.send(msg)

发送完毕后,与邮件服务器的链接就会关闭。

发送大量邮件

如果我们一次发送大量的邮件,可以通过下面的方式发送:

1with mail.connect() as conn:
2    for user in users:
3        message = '...'
4        subject = "hello, %s" % user.name
5        msg = Message(recipients=[user.email],
6                      body=message,
7                      subject=subject)
8        conn.send(msg)

与电子邮件服务器的连接会一直保持直到所有的邮件都已经发送完毕才会断开。注意大量发送的时候,还可以设置MAIL_MAX_EMAILS变量 。

Some mail servers set a limit on the number of emails sent in a single connection. You can set the max amount of emails to send before reconnecting by specifying theMAIL_MAX_EMAILS setting.

添加附件

1with app.open_resource("image.png") as fp:
2    msg.attach("image.png", "image/png", fp.read())

不使用SSL示例

 1# coding: utf-8
 2from flask import Flask
 3from flask_mail import Mail, Message
 4app = Flask(__name__)
 5app.config['MAIL_SERVER'] = 'smtp.163.com'
 6app.config['MAIL_PORT'] = 25
 7app.config['MAIL_USE_SSL'] = False
 8app.config['MAIL_USERNAME'] = '[email protected]'
 9app.config['MAIL_PASSWORD'] = 'password'
10app.config['MAIL_DEFAULT_SENDER'] = '[email protected]'
11mail = Mail(app)
12@app.route("/")
13def index():
14        msg = Message('这是一封测试邮件Header', recipients=['[email protected]'])
15        msg.body = "This is the email body"
16        msg.html = 'hello api'
17        mail.send(msg)
18        return "Sent"
19if __name__ == "__main__":
20    app.run(host="0.0.0.0",port=5000,debug=True)
21    #app.run()
22            

使用SSL示例(带附件)

 1#!/usr/bin/env python
 2# coding:utf-8
 3from flask import Flask
 4from flask_mail import Mail, Message
 5app = Flask(__name__)
 6app.config['MAIL_SERVER'] = 'smtp.qq.com'
 7app.config['MAIL_PORT'] = 465
 8app.config['MAIL_USE_SSL'] = True
 9app.config['MAIL_USERNAME'] = '[email protected]'
10app.config['MAIL_PASSWORD'] = '********'
11app.config['MAIL_DEFAULT_SENDER'] = '[email protected]'
12mail = Mail(app)
13@app.route('/mail')
14def welcome():
15    msg = Message('这是一封测试邮件Header', recipients=['itybku@139'])
16    msg.body = '这是一封测试邮件 bodyer'
17    msg.html = '这是一封测试邮件 htmler'
18    image = 'image_.运维之路jpg'
19    with app.open_resource(image) as fp:
20        msg.attach(image, 'image/jpg', fp.read())
21    mail.send(msg)
22    return 'Hello world!'
23if __name__ == '__main__':
24    app.run(debug=tuple)

注,QQ邮箱使用SMTP、IMAP等协议需要配置,打开 QQ邮箱 > 设置 > POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 > 生成授权码。

参考页面:http://www.pythondoc.com/flask-mail/