欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

在Python的Flask框架下收發電子郵件的教程

系統 1758 0

?簡述

在大多數此類教程中都會不遺余力的介紹如何使用數據庫。今天我們對數據庫暫且不表,而是來關注另一個在web應用中很重要的特性:如何推送郵件給用戶。

在某個輕量級應用中我們可能會添加一個如下的郵件服務功能:當用戶有了新的粉絲后,我們發送一封郵件通知用戶。有很多方法可以實現這個特性,而我們希望提供出一種可復用的通用框架來處理。
?
Flask-Mail介紹

對于我們來說是幸運的,現在已經有很多外部插件來處理郵件,雖說不能百分百按照我們的想法去處理,但已經相當接近了。?

在虛擬環境中安裝 Flask-Mail是相當簡單的。Windows以外的用戶可以利用以下命令來安裝:
?

            
flask/bin/pip install flask-mail

          

Windows用戶的安裝稍有不同,因為Flask-Mail所使用的一些模塊不能再Windows系統上運行,你可以使用以下命令:?
?

            
flask\Scripts\pip install --no-deps lamson chardet flask-mail

          

配置:

回想一下前文中單元測試部分的案例,我們通過添加配置支持了一個這樣的功能:當應用的某個版本測試出錯時可以郵件通知我們。從這個例子就可以看出如何配置使用郵件支持。

再次提醒大家,我們需要設置兩個方面的內容:

  • ??? 郵件服務器信息
  • ??? 用戶郵箱地址

如下正是前文中所用到的配置

?

            
# email server
MAIL_SERVER = 'your.mailserver.com'
MAIL_PORT = 25
MAIL_USE_TLS = False
MAIL_USE_SSL = False
MAIL_USERNAME = 'you'
MAIL_PASSWORD = 'your-password'
 
# administrator list
ADMINS = ['you@example.com']

          

其中并沒有設置切實可用的郵件服務器和郵箱。現在我們通過一個例子來看如何使用gmail郵箱賬戶來發送郵件:

?

            
# email server
MAIL_SERVER = 'smtp.googlemail.com'
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_USERNAME = 'your-gmail-username'
MAIL_PASSWORD = 'your-gmail-password'
 
# administrator list
ADMINS = ['your-gmail-username@gmail.com']

          

另外我們也可以初始化一個Mail對象來連接SMTP郵件服務器,發送郵件:
?

            
from flask.ext.mail import Mail
mail = Mail(app)

          


發個郵件試試!

為了了解flask-mail如何工作的,我們可以從命令行發一封郵件看看。進入python shell并執行如下的腳本:
?

            
>>> from flask.ext.mail import Message
>>> from app import mail
>>> from config import ADMINS
>>> msg = Message('test subject', sender = ADMINS[0], recipients = ADMINS)
>>> msg.body = 'text body'
>>> msg.html = '
            
              HTML
            
             body'
>>> mail.send(msg)

          

上面這段代碼會根據inconfig.py中配置的郵箱地址列表,以首個郵箱作為發件人給所有郵箱發送一封郵件。郵件內容會以文本和html兩種格式呈現,而你能看到哪種格式取決于你的郵件客戶端。

多么簡單小巧!你完全可以現在就把它集成到你的應用中。


郵件框架

我們現在可以編寫一個幫助函數來發送郵件。這是以上測試中一個通用版的測試。我們把這個函數放進一個新的原文件中用作郵件支持(fileapp/emails.py):
?

            
from flask.ext.mail import Message
from app import mail
 
def send_email(subject, sender, recipients, text_body, html_body):
 msg = Message(subject, sender, recipients)
 msg.body = text_body
 msg.html = html_body
 mail.send(msg)

          

Flask-Mail的郵件支持超出了我們目前的使用范圍,像密件抄送和附件的功能并不會在此應用中得以使用。

Follower 提醒

現在,我們已經有了發郵件的基本框架,我們可以寫發送follower提醒的函數了 (fileapp/emails.py):
?

            
from flask import render_template
from config import ADMINS
 
def follower_notification(followed, follower):
 send_email("[microblog] %s is now following you!" % follower.nickname,
  ADMINS[0],
  [followed.email],
  render_template("follower_email.txt",
   user = followed, follower = follower),
  render_template("follower_email.html",
   user = followed, follower = follower))

          

你在這里找到任何驚喜了嗎?我們的老朋友render_template函數有一次出現了。

如果你還記得,我們使用這個函數在views渲染模版. 就像在views里寫html不好一樣,使用郵件模版是理想的選擇。我們要可能的將邏輯和表現分開,所以email模版也會和其它試圖模版一起放到在模版文件夾里.


所以,我們需要為follower提醒郵件寫純文本和網頁版的郵件模版,下面這個是純文本的版本 (fileapp/templates/follower_email.txt):
?

            
Dear {{user.nickname}},
 
{{follower.nickname}} is now a follower. Click on the following link to visit {{follower.nickname}}'s profile page:
 
{{url_for("user", nickname = follower.nickname, _external = True)}}
 
Regards,
 
The microblog admin

          

下面這個是網頁版的郵件,效果會更好(fileapp/templates/follower_email.html):
?

            

Dear {{user.nickname}},

{{follower.nickname}} is now a follower.

{{follower.nickname}}
{{follower.about_me}}

Regards,

The microblog admin

注解:模版中的url_for函數的 _external = True 參數的意義.默認情況下,url_for 函數生成url是相對我們的域名的。例如,url_for("index")函數返回值是/index, 但是,發郵件是我們想要http://localhost:5000/index這種url,email中是沒有域上下文的,所以,我們必須強制生成帶域名的url,_external argument就是干這個工作的。


最后一步是處理“follow”過程,即觸發郵件提醒時的視圖函數,(fileapp/views.py):
?

            
from emails import follower_notification
 
@app.route('/follow/
            
              ')
@login_required
def follow(nickname):
 user = User.query.filter_by(nickname = nickname).first()
 # ...
 follower_notification(user, g.user)
 return redirect(url_for('user', nickname = nickname))

            
          

現在你可以創建兩個用戶(如果還沒有用戶的話)嘗試著用讓一個用戶follow另一個用戶,理解郵件提醒是怎樣工作的。

就是這樣嗎?我們做完了嗎?

我們可能心底里很興奮完成了這項工作并且把郵件提醒功能同未完成列表里刪除。

但是,如果你現在測試下應用,你會發現當你單擊follow鏈接的時候,頁面會2到3秒才會響應,瀏覽器才會刷新,這在之前是沒有的。?
?
發生了什么?

問題是,Flask-Mail 使用同步模式發送電子郵件。 從電子郵件發送開始,直到電子郵件交付后,給瀏覽器發回其響應,在整個過程中,Web服務器會一直阻塞。如果我們試圖發送電子郵件到一個服務器是緩慢的,甚至更糟糕的,暫時處于脫機狀態,你能想象會發生什么嗎?很不好。

這是一個可怕的限制,發送電子郵件應該是后臺任務且不會干擾Web服務器,讓我們看看我們如何能夠解決這個問題。

Python中執行異步調用

我們想send_email 函數發完郵件后立即返回,需要讓發郵件移動到后臺進程來異步執行。

事實上python已經對異步任務提供了支持,但實際上,還可以用其他的方式,比如線程和多進程模塊也可以實現異步任務。

每當我們需要發郵件的時候,啟動一個線程來處理,比啟動一個全新的進程節省資源。所以,讓我們將mail.send(msg)調用放到另一個線程中。(fileapp/emails.py):
?

            
from threading import Thread
 
def send_async_email(msg):
 mail.send(msg)
 
def send_email(subject, sender, recipients, text_body, html_body):
 msg = Message(subject, sender = sender, recipients = recipients)
 msg.body = text_body
 msg.html = html_body
 thr = threading.Thread(target = send_async_email, args = [msg])
 thr.start()

          

如果你測試‘follow‘函數,現在你會發現瀏覽器在發送郵件之前會刷新。

所以,我們已經實現了異步發送,但是,如果未來在別的需要異步功能的地方難道我們還需要在實現一遍嗎?

過程都是一樣的,這樣就會在每一種情況下都有重復代碼,這樣非常不好。


我們可以通過 decorator改進代碼。使用裝飾器的代碼是這樣的:?
?

            
from decorators import async
 
@async
def send_async_email(msg):
 mail.send(msg)
 
def send_email(subject, sender, recipients, text_body, html_body):
 msg = Message(subject, sender = sender, recipients = recipients)
 msg.body = text_body
 msg.html = html_body
 send_async_email(msg)

          

更好了,對不對?

實現這種方式的代碼實際上很簡單,創建一個新源文件(fileapp/decorators.py):
?

            
from threading import Thread
 
def async(f):
 def wrapper(*args, **kwargs):
  thr = Thread(target = f, args = args, kwargs = kwargs)
  thr.start()
 return wrapper

          

現在我們對異步任務創建了個有用的框架(framework), 我們可以說已經完成了!?

僅僅作為一個練習,讓我們思考一下為什么這個方法會看上去使用了進程而不是線程。我們并不想每當我們需要發送一封郵件時就有一個進程被啟動,所以我們能夠使用thePoolclass而不用themultiprocessingmodule。這個類會創建指定數量的進程(這些都是主進程的子進程),并且這些子進程會通過theapply_asyncmethod送到進程池,等待接受任務去工作。這可能對于一個繁忙的網站會是一個有趣的途徑,但是我們目前仍將維持現在線程的方式。
?
最后的話
這個 updatedmicroblogapplication 的源代碼如下:

下載 microblog-0.11.zip 。


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色橹橹欧美在线观看视频高清免费 | 毛片免费一区二区三区 | 日韩欧美国产网站 | 日韩欧美亚洲综合久久99e | 亚洲一区二区三区首页 | 精品视频一区二区观看 | 成人精品一区二区 | 国产精品第一区 | 最新欧美精品一区二区三区 | 国产九九精品视频 | 日韩成人av在线 | 小明永久免费 | 大陆黄色网| 青草国产视频 | 色黄视频在线观看 | 国产专区欧美 | 日韩无毛 | 高清国产一区二区三区四区五区 | 一级片免费在线播放 | 精品久久久久久久 | avtom影院 首页亚洲 | 国产精品欧美一区二区三区 | 九九热热九九 | 日本一区二区在线视频 | 欧美精品一区二区三区四区 | 国产精品人妻无码久久久郑州 | 国产福利视频在线 | 一区二区三区视频在线观看 | 久久伊人精品 | 国产合集福利视频在线视频 | 亚洲一区二区三区在线 | 精品AV综合一区二区三区 | 午夜影院恐怖电影免费看 | 日韩中文字幕免费在线观看 | 欧美黄色片一级 | 日本高清无吗 | a在线观看免费 | 久久99综合国产精品亚洲首页 | 久草精品视频在线观看 | 国产在线欧美精品中文一区 | 日本高清视频www夜色资源网 |