Flask擴展 -- flask-mail
電子郵件是最常用的通信方式之一。雖然Python標準庫中的smtplib包可用在Flask程序中發送電子郵件,但包裝了smtplib的Flask-Mail擴展能更好的和Flask集成。
1.安裝Flask-Mail
1.1使用pip安裝
pip install flask-mail
1.2 下載源碼安裝
git clone https://github.com/mattupstate/flask-mail.git cd flask-mail python setup.py install
2.flask-mail初始化
from flask import Flask from flask_mail importMail, Message app = Flask(__name__) mail = Mail(app)
3.Flask-Mail 配置
3.1 Flask-Mail常用配置項
Flask-Mail通過標準的Flask配置API進行配置,這些常用的配置項如下:
配置 | 默認值 | 說明 |
MAIL_SERVER | localhost | 電子郵件服務器的主機名或IP地址 |
MAIL_PORT | 25 | 電子郵件服務器的端口 |
MAIL_USE_TLS | False | 啟用傳輸層安全(Transport Layer Security,TLS)協議 |
MAIL_USE_SSL | Flase | 啟用安全套接層(Secure Sockets Layer,SSL)協議 |
MAIL_USERNAME | None | 郵件賬戶的用戶名 |
MAIL_PASSWORD | None | 郵件賬戶的密碼 |
MAIL_DEFAULT_SENDER | None | 默認發件人,如果Message對象裏沒指定發件人,就采用默認發件人 |
MAIL_MAX_EMAILS | None | 郵件批量發送個數上限,默認為沒有上限 |
MAIL_SUPPRESS_SEND | app.testing | 調用“Mail.send()”方法後,郵件不會真的被發送,在測試環境中使用,默認為False |
MAIL_ASCII_ATTACHMENTS | Flase | 將附件的文件名強制轉換為ASCII字符,避免在某些情況下出現亂碼 |
3.2 常見的SMTP郵箱服務配置
(1)配置QQ郵箱服務器
MAIL_SERVER = ‘smtp.qq.com‘, MAIL_PROT = 25, MAIL_USE_TLS = True, MAIL_USE_SSL = False, MAIL_USERNAME = "", MAIL_PASSWORD = "",
QQ郵箱的配置方式如下:
開啟了授權之後,就會彈出生成授權碼頁面:
註意:
a.qq郵箱的服務器地址為smtp.qq.com;
b.郵箱服務的端口為25或者465都可以;
c.TLS,SSL的選擇很多人發不出去郵件的關鍵之一,這裏QQ郵箱選擇TLS;
d.賬號和密碼需要特別註意,這裏的賬號是自己的QQ郵箱賬號,密碼不是QQ郵箱密碼,而是生成的授權碼;
(2)其他郵箱後續補充
4. 簡單功能實現
下面舉例說明flask-email擴展是如何實現簡單郵件發送的:
from flask import Flask from flask_mail import Mail, Message
app = Flask(__name__) app.config.update( MAIL_SERVER=‘smtp.qq.com‘, MAIL_PROT=465, MAIL_USE_TLS=True, MAIL_USE_SSL=False, MAIL_USERNAME="[email protected]", MAIL_PASSWORD="****************", ) mail = Mail(app) @app.route(‘/‘) def index(): # sender 發送方,recipients 郵件接收方列表 msg = Message("Hi!This is a test ",sender=‘xxxxxxxxxxxxxx@qq.com‘, recipients=[‘[email protected]‘]) # msg.body 郵件正文 msg.body = "This is a first email" mail.send(msg) print("Mail sent") return ‘send successfully‘
if __name__ == "__main__": app.run(debug=True)
如果想發送信息,首先需要創建一個Message實例:
msg = Message("Hello",sender="[email protected]",recipients=["[email protected]"])
當然,我們也可以單獨添加郵件接收對象:
msg.recipients = ["[email protected]"] msg.add_recipient("[email protected]")
在配置參數的時候,如果我們設置了MAIL_DEFAULT_SENDER參數,在後面創建message實例時不需要清楚指明郵件發送方,此時程序會自動獲取默認配置:
msg = Message("Hello",recipients=["[email protected]"])
5.異步發送郵件
使用上面的方式發送郵件,會發現頁面卡頓了幾秒才出現消息,這是因為我們使用了同步的方式。為了避免發送郵件過程中出現的延遲,我們把發送郵件的任務移到後臺線程中。代碼如下:
# -*- 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 ‘[email protected]‘ app.config[‘MAIL_PASSWORD‘] = os.environ.get(‘MAIL_PASSWORD‘) or ‘*********‘ 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=‘[email protected]‘, recipients=[‘[email protected]‘]) 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(debug=True)
在上面,我們創建了一個線程,執行的任務是send_async_email
,該任務的實現涉及一個問題:
很多 Flask 擴展都假設已經存在激活的程序上下文和請求上下文。Flask-Mail 中的 send()
函數使用 current_app
,因此必須激活程序上下文。不過,在不同線程中執行 mail.send()
函數時,程序上下文要使用 app.app_context()
人工創建。
6.帶附件的郵件
有時候,我們發郵件的時候需要添加附件,比如文檔和圖片等,這也很簡單,代碼如下:
# -*- 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 app.config[‘MAIL_USERNAME‘] = os.environ.get(‘MAIL_USERNAME‘) or ‘[email protected]‘ app.config[‘MAIL_PASSWORD‘] = os.environ.get(‘MAIL_PASSWORD‘) or ‘**********‘ mail = Mail(app) @app.route(‘/attach‘) def add_attchments(): msg = Message(‘A photo‘, sender=‘[email protected]‘, recipients=[‘[email protected]‘]) msg.html = ‘<b>A beautiful photo!</b>‘ with app.open_resource("1111.jpg") as fp: msg.attach("photo.jpg", "image/jpeg", fp.read()) mail.send(msg) return ‘<h1>OK!</h1>‘ if __name__ == ‘__main__‘: app.run(debug=True)
上面的代碼中,我們通過 app.open_resource(path_of_attachment)
打開了本機的某張圖片,然後通過msg.attach()
方法將附件內容添加到 Message 對象。msg.attach()
方法的第一個參數是附件的文件名,第二個參數是文件內容的 MIME (Multipurpose Internet Mail Extensions)
類型,第三個參數是文件內容。
7.批量發送
在某些情況下,我們需要批量發送郵件,比如給網站的所有註冊用戶發送改密碼的郵件,這時為了避免每次發郵件時都要創建和關閉跟服務器的連接,我們的代碼需要做一些調整,類似如下:
with mail.connect() as conn: for user in users: subject = "hello, %s" % user.name msg = Message(recipients=[user.email], body=‘...‘, subject=subject) conn.send(msg)
上面的工作方式,使得應用與電子郵件服務器保持連接,一直到所有郵件已經發送完畢。某些郵件服務器會限制一次連接中的發送郵件的上限,這樣的話,你可以配置 MAIL_MAX_EMAILS
。
Flask擴展 -- flask-mail