欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在Python的Flask框架下收發(fā)電子郵件的教程

 更新時(shí)間:2015年04月21日 09:01:38   投稿:goldensun  
這篇文章主要介紹了在Python的Flask框架下收發(fā)電子郵件的教程,主要用到了Flask中的Flask-mail工具,需要的朋友可以參考下

 簡(jiǎn)述

在大多數(shù)此類教程中都會(huì)不遺余力的介紹如何使用數(shù)據(jù)庫(kù)。今天我們對(duì)數(shù)據(jù)庫(kù)暫且不表,而是來(lái)關(guān)注另一個(gè)在web應(yīng)用中很重要的特性:如何推送郵件給用戶。

在某個(gè)輕量級(jí)應(yīng)用中我們可能會(huì)添加一個(gè)如下的郵件服務(wù)功能:當(dāng)用戶有了新的粉絲后,我們發(fā)送一封郵件通知用戶。有很多方法可以實(shí)現(xiàn)這個(gè)特性,而我們希望提供出一種可復(fù)用的通用框架來(lái)處理。
 
Flask-Mail介紹

對(duì)于我們來(lái)說(shuō)是幸運(yùn)的,現(xiàn)在已經(jīng)有很多外部插件來(lái)處理郵件,雖說(shuō)不能百分百按照我們的想法去處理,但已經(jīng)相當(dāng)接近了。 

在虛擬環(huán)境中安裝 Flask-Mail是相當(dāng)簡(jiǎn)單的。Windows以外的用戶可以利用以下命令來(lái)安裝:
 

flask/bin/pip install flask-mail

Windows用戶的安裝稍有不同,因?yàn)镕lask-Mail所使用的一些模塊不能再Windows系統(tǒng)上運(yùn)行,你可以使用以下命令: 
 

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

配置:

回想一下前文中單元測(cè)試部分的案例,我們通過(guò)添加配置支持了一個(gè)這樣的功能:當(dāng)應(yīng)用的某個(gè)版本測(cè)試出錯(cuò)時(shí)可以郵件通知我們。從這個(gè)例子就可以看出如何配置使用郵件支持。

再次提醒大家,我們需要設(shè)置兩個(gè)方面的內(nèi)容:

  •     郵件服務(wù)器信息
  •     用戶郵箱地址

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

 

# 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']

其中并沒(méi)有設(shè)置切實(shí)可用的郵件服務(wù)器和郵箱?,F(xiàn)在我們通過(guò)一個(gè)例子來(lái)看如何使用gmail郵箱賬戶來(lái)發(fā)送郵件:

 

# 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']

另外我們也可以初始化一個(gè)Mail對(duì)象來(lái)連接SMTP郵件服務(wù)器,發(fā)送郵件:
 

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


發(fā)個(gè)郵件試試!

為了了解flask-mail如何工作的,我們可以從命令行發(fā)一封郵件看看。進(jìn)入python shell并執(zhí)行如下的腳本:
 

>>> 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 = '<b>HTML</b> body'
>>> mail.send(msg)

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

多么簡(jiǎn)單小巧!你完全可以現(xiàn)在就把它集成到你的應(yīng)用中。


郵件框架

我們現(xiàn)在可以編寫一個(gè)幫助函數(shù)來(lái)發(fā)送郵件。這是以上測(cè)試中一個(gè)通用版的測(cè)試。我們把這個(gè)函數(shù)放進(jìn)一個(gè)新的原文件中用作郵件支持(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的郵件支持超出了我們目前的使用范圍,像密件抄送和附件的功能并不會(huì)在此應(yīng)用中得以使用。

Follower 提醒

現(xiàn)在,我們已經(jīng)有了發(fā)郵件的基本框架,我們可以寫發(fā)送follower提醒的函數(shù)了 (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函數(shù)有一次出現(xiàn)了。

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


所以,我們需要為follower提醒郵件寫純文本和網(wǎng)頁(yè)版的郵件模版,下面這個(gè)是純文本的版本 (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

下面這個(gè)是網(wǎng)頁(yè)版的郵件,效果會(huì)更好(fileapp/templates/follower_email.html):
 

<p>Dear {{user.nickname}},</p>
<p><a href="{{url_for("user", nickname = follower.nickname, _external = True)}}">{{follower.nickname}}</a> is now a follower.</p>
<table>
 <tr valign="top">
  <td><img src="{{follower.avatar(50)}}"></td>
  <td>
   <a href="{{url_for('user', nickname = follower.nickname, _external = True)}}">{{follower.nickname}}</a><br />
   {{follower.about_me}}
  </td>
 </tr>
</table>
<p>Regards,</p>
<p>The <code>microblog</code> admin</p>

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


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

from emails import follower_notification
 
@app.route('/follow/<nickname>')
@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))

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

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

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

但是,如果你現(xiàn)在測(cè)試下應(yīng)用,你會(huì)發(fā)現(xiàn)當(dāng)你單擊follow鏈接的時(shí)候,頁(yè)面會(huì)2到3秒才會(huì)響應(yīng),瀏覽器才會(huì)刷新,這在之前是沒(méi)有的。 
 
發(fā)生了什么?

問(wèn)題是,F(xiàn)lask-Mail 使用同步模式發(fā)送電子郵件。 從電子郵件發(fā)送開(kāi)始,直到電子郵件交付后,給瀏覽器發(fā)回其響應(yīng),在整個(gè)過(guò)程中,Web服務(wù)器會(huì)一直阻塞。如果我們?cè)噲D發(fā)送電子郵件到一個(gè)服務(wù)器是緩慢的,甚至更糟糕的,暫時(shí)處于脫機(jī)狀態(tài),你能想象會(huì)發(fā)生什么嗎?很不好。

這是一個(gè)可怕的限制,發(fā)送電子郵件應(yīng)該是后臺(tái)任務(wù)且不會(huì)干擾Web服務(wù)器,讓我們看看我們?nèi)绾文軌蚪鉀Q這個(gè)問(wèn)題。

Python中執(zhí)行異步調(diào)用

我們想send_email 函數(shù)發(fā)完郵件后立即返回,需要讓發(fā)郵件移動(dòng)到后臺(tái)進(jìn)程來(lái)異步執(zhí)行。

事實(shí)上python已經(jīng)對(duì)異步任務(wù)提供了支持,但實(shí)際上,還可以用其他的方式,比如線程和多進(jìn)程模塊也可以實(shí)現(xiàn)異步任務(wù)。

每當(dāng)我們需要發(fā)郵件的時(shí)候,啟動(dòng)一個(gè)線程來(lái)處理,比啟動(dòng)一個(gè)全新的進(jìn)程節(jié)省資源。所以,讓我們將mail.send(msg)調(diào)用放到另一個(gè)線程中。(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()

如果你測(cè)試‘follow‘函數(shù),現(xiàn)在你會(huì)發(fā)現(xiàn)瀏覽器在發(fā)送郵件之前會(huì)刷新。

所以,我們已經(jīng)實(shí)現(xiàn)了異步發(fā)送,但是,如果未來(lái)在別的需要異步功能的地方難道我們還需要在實(shí)現(xiàn)一遍嗎?

過(guò)程都是一樣的,這樣就會(huì)在每一種情況下都有重復(fù)代碼,這樣非常不好。


我們可以通過(guò) decorator改進(jìn)代碼。使用裝飾器的代碼是這樣的: 
 

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)

更好了,對(duì)不對(duì)?

實(shí)現(xiàn)這種方式的代碼實(shí)際上很簡(jiǎn)單,創(chuàng)建一個(gè)新源文件(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

現(xiàn)在我們對(duì)異步任務(wù)創(chuàng)建了個(gè)有用的框架(framework), 我們可以說(shuō)已經(jīng)完成了! 

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

下載 microblog-0.11.zip 。

相關(guān)文章

  • Python StringIO及BytesIO包使用方法解析

    Python StringIO及BytesIO包使用方法解析

    這篇文章主要介紹了Python StringIO及BytesIO包使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Python Django 后臺(tái)管理之后臺(tái)模型屬性詳解

    Python Django 后臺(tái)管理之后臺(tái)模型屬性詳解

    這篇文章主要介紹了Python Django 后臺(tái)管理之后臺(tái)模型屬性,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Python使用matplotlib繪制Logistic曲線操作示例

    Python使用matplotlib繪制Logistic曲線操作示例

    這篇文章主要介紹了Python使用matplotlib繪制Logistic曲線操作,結(jié)合實(shí)例形式詳細(xì)分析了Python基于matplotlib庫(kù)繪制Logistic曲線相關(guān)步驟與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-11-11
  • Python三百行代碼實(shí)現(xiàn)飛機(jī)大戰(zhàn)

    Python三百行代碼實(shí)現(xiàn)飛機(jī)大戰(zhàn)

    飛機(jī)大戰(zhàn)想必大家可能玩過(guò)微信的這款小游戲,給我的感覺(jué)是這款游戲怎么可以做得這么好呢,操作簡(jiǎn)單,容易上手,簡(jiǎn)直是“老少皆宜”啊,既然這款游戲這么棒,能否自己動(dòng)手用 Python 來(lái)實(shí)現(xiàn)呢?事實(shí)證明是可以的
    2022-09-09
  • Python全棧之作用域和閉包

    Python全棧之作用域和閉包

    這篇文章主要為大家介紹了Python作用域和閉包,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • python計(jì)算一個(gè)序列的平均值的方法

    python計(jì)算一個(gè)序列的平均值的方法

    這篇文章主要介紹了python計(jì)算一個(gè)序列的平均值的方法,涉及Python遞歸遍歷與數(shù)學(xué)計(jì)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 詳解Python的Django框架中manage命令的使用與擴(kuò)展

    詳解Python的Django框架中manage命令的使用與擴(kuò)展

    這篇文章主要介紹了Python的Django框架中manage命令的使用與擴(kuò)展,manage.py使得用戶借助manage命令在命令行中能實(shí)現(xiàn)諸多簡(jiǎn)便的操作,需要的朋友可以參考下
    2016-04-04
  • window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程

    window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程

    這篇文章主要介紹了window7下的python2.7版本和python3.5版本的opencv-python安裝過(guò)程,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Python算法的時(shí)間復(fù)雜度和空間復(fù)雜度(實(shí)例解析)

    Python算法的時(shí)間復(fù)雜度和空間復(fù)雜度(實(shí)例解析)

    算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度,簡(jiǎn)單而講時(shí)間復(fù)雜度指的是語(yǔ)句執(zhí)行次數(shù),空間復(fù)雜度指的是算法所占的存儲(chǔ)空間,本文通過(guò)代碼給大家介紹Python算法的時(shí)間復(fù)雜度和空間復(fù)雜度問(wèn)題,感興趣的朋友一起看看吧
    2019-11-11
  • Python 2.7中文顯示與處理方法

    Python 2.7中文顯示與處理方法

    今天小編就為大家分享一篇Python 2.7中文顯示與處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07

最新評(píng)論