最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python smtplib模塊發(fā)送SSL/TLS安全郵件實(shí)例

 更新時(shí)間:2015年04月08日 12:00:21   投稿:junjie  
這篇文章主要介紹了python smtplib模塊發(fā)送SSL/TLS安全郵件實(shí)例,本文講解了二種發(fā)送方式,需要的朋友可以參考下

python的smtplib提供了一種很方便的途徑發(fā)送電子郵件。它對(duì)smtp協(xié)議進(jìn)行了簡(jiǎn)單的封裝。

smtp協(xié)議的基本命令包括:

HELO 向服務(wù)器標(biāo)識(shí)用戶身份
MAIL 初始化郵件傳輸 mail from:
RCPT 標(biāo)識(shí)單個(gè)的郵件接收人;常在MAIL命令后面,可有多個(gè)rcpt to:
DATA 在單個(gè)或多個(gè)RCPT命令后,表示所有的郵件接收人已標(biāo)識(shí),并初始化數(shù)據(jù)傳輸,以.結(jié)束
VRFY 用于驗(yàn)證指定的用戶/郵箱是否存在;由于安全方面的原因,服務(wù)器常禁止此命令
EXPN 驗(yàn)證給定的郵箱列表是否存在,擴(kuò)充郵箱列表,也常被禁用
HELP 查詢服務(wù)器支持什么命令
NOOP 無(wú)操作,服務(wù)器應(yīng)響應(yīng)OK
QUIT 結(jié)束會(huì)話
RSET 重置會(huì)話,當(dāng)前傳輸被取消
MAIL FROM 指定發(fā)送者地址
RCPT TO 指明的接收者地址

一般smtp會(huì)話有兩種方式,一種是郵件直接投遞,就是說(shuō),比如你要發(fā)郵件給zzz@163.com,那就直接連接163.com的郵件服務(wù)器,把信投給zzz@163.com; 另一種是驗(yàn)證過(guò)后的發(fā)信,它的過(guò)程是,比如你要發(fā)郵件給zzz@163.com,你不是直接投到163.com,而是通過(guò)自己在sina.com的另一個(gè)郵箱來(lái)發(fā)。這樣就要先連接sina.com的smtp服務(wù)器,然后認(rèn)證,之后在把要發(fā)到163.com的信件投到sina.com上,sina.com會(huì)幫你把信投遞到163.com。

第一種方式的命令流程基本是這樣:
1. helo
2. mail from
3. rcpt to
4. data
5. quit

但是第一種發(fā)送方式一般有限制的,就是rcpt to指定的這個(gè)郵件接收者必須在這個(gè)服務(wù)器上存在,否則是不會(huì)接收的。 先看看代碼:

復(fù)制代碼 代碼如下:

#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib

# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# smtp會(huì)話過(guò)程中的mail from地址
from_addr = "asfgysg@zxsdf.com"
# smtp會(huì)話過(guò)程中的rcpt to地址
to_addr = "zhaoweikid@163.com"
# 信件內(nèi)容
msg = "test mail"

svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會(huì)話過(guò)程中會(huì)有輸出信息
svr.set_debuglevel(1)
# helo命令,docmd方法包括了獲取對(duì)方服務(wù)器返回信息
svr.docmd("HELO server")
# mail from, 發(fā)送郵件發(fā)送者
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to, 郵件接收者
svr.docmd("RCPT TO: <%s>" % to_addr)
# data命令,開始發(fā)送數(shù)據(jù)
svr.docmd("DATA")
# 發(fā)送正文數(shù)據(jù)
svr.send(msg)
# 比如以 . 作為正文發(fā)送結(jié)束的標(biāo)記,用send發(fā)送的,所以要用getreply獲取返回信息
svr.send(" . ")
svr.getreply()
# 發(fā)送結(jié)束,退出
svr.quit()

注意的是,163.com是有反垃圾郵件功能的,想上面的這種投遞郵件的方法不一定能通過(guò)反垃圾郵件系統(tǒng)的檢測(cè)的。所以一般不推薦個(gè)人這樣發(fā)送。

 第二種有點(diǎn)不一樣:

1.ehlo
2.auth login
3.mail from
4.rcpt to
5.data
6.quit

相對(duì)于第一種來(lái)說(shuō),多了一個(gè)認(rèn)證過(guò)程,就是auth login這個(gè)過(guò)程。

復(fù)制代碼 代碼如下:

#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64

# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# 郵件用戶名
username = "xxxxxx@163.com"
# 密碼
password = "xxxxxxx"
# smtp會(huì)話過(guò)程中的mail from地址
from_addr = "xxxxxx@163.com"
# smtp會(huì)話過(guò)程中的rcpt to地址
to_addr = "yyyyyy@163.com"
# 信件內(nèi)容
msg = "my test mail"

svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會(huì)話過(guò)程中會(huì)有輸出信息
svr.set_debuglevel(1)
# ehlo命令,docmd方法包括了獲取對(duì)方服務(wù)器返回信息
svr.docmd("EHLO server")
# auth login 命令
svr.docmd("AUTH LOGIN")
# 發(fā)送用戶名,是base64編碼過(guò)的,用send發(fā)送的,所以要用getreply獲取返回信息
svr.send(base64.encodestring(username))
svr.getreply()
# 發(fā)送密碼
svr.send(base64.encodestring(password))
svr.getreply()
# mail from, 發(fā)送郵件發(fā)送者
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to, 郵件接收者
svr.docmd("RCPT TO: <%s>" % to_addr)
# data命令,開始發(fā)送數(shù)據(jù)
svr.docmd("DATA")
# 發(fā)送正文數(shù)據(jù)
svr.send(msg)
# 比如以 . 作為正文發(fā)送結(jié)束的標(biāo)記
svr.send(" . ")
svr.getreply()
# 發(fā)送結(jié)束,退出
svr.quit()

   
上面說(shuō)的是最普通的情況,但是不能忽略的是現(xiàn)在好多企業(yè)郵件是支持安全郵件的,就是通過(guò)SSL發(fā)送的郵件,這個(gè)怎么發(fā)呢?SMTP對(duì)SSL安全郵件的支持有兩種方案,一種老的是專門開啟一個(gè)465端口來(lái)接收ssl郵件,另一種更新的做法是在標(biāo)準(zhǔn)的25端口的smtp上增加一個(gè)starttls的命令來(lái)支持。

看看第一種怎么辦:

復(fù)制代碼 代碼如下:

#-*- encoding: gb2312 -*-
import os, sys, string, socket
import smtplib


class SMTP_SSL (smtplib.SMTP):
    def __init__(self, host='', port=465, local_hostname=None, key=None, cert=None):
        self.cert = cert
        self.key = key
        smtplib.SMTP.__init__(self, host, port, local_hostname)
       
    def connect(self, host='localhost', port=465):
        if not port and (host.find(':') == host.rfind(':')):
            i = host.rfind(':')
            if i >= 0:
                host, port = host[:i], host[i+1:]
                try: port = int(port)
                except ValueError:
                    raise socket.error, "nonnumeric port"
        if not port: port = 654
        if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)
        msg = "getaddrinfo returns an empty list"
        self.sock = None
        for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
            af, socktype, proto, canonname, sa = res
            try:
                self.sock = socket.socket(af, socktype, proto)
                if self.debuglevel > 0: print>>stderr, 'connect:', (host, port)
                self.sock.connect(sa)
                # 新增加的創(chuàng)建ssl連接
                sslobj = socket.ssl(self.sock, self.key, self.cert)
            except socket.error, msg:
                if self.debuglevel > 0:
                    print>>stderr, 'connect fail:', (host, port)
                if self.sock:
                    self.sock.close()
                self.sock = None
                continue
            break
        if not self.sock:
            raise socket.error, msg

        # 設(shè)置ssl
        self.sock = smtplib.SSLFakeSocket(self.sock, sslobj)
        self.file = smtplib.SSLFakeFile(sslobj);

        (code, msg) = self.getreply()
        if self.debuglevel > 0: print>>stderr, "connect:", msg
        return (code, msg)
       
if __name__ == '__main__':
    smtp = SMTP_SSL('192.168.2.10')
    smtp.set_debuglevel(1)
    smtp.sendmail("zzz@xxx.com", "zhaowei@zhaowei.com", "xxxxxxxxxxxxxxxxx")
    smtp.quit()

   

這里我是從原來(lái)的smtplib.SMTP派生出了新的SMTP_SSL類,它專門來(lái)處理ssl連接。我這里測(cè)試的192.168.2.10是我自己的測(cè)試服務(wù)器.

第二種是新增加了starttls的命令,這個(gè)很簡(jiǎn)單,smtplib里就有這個(gè)方法,叫smtplib.starttls()。當(dāng)然,不是所有的郵件系統(tǒng)都支持安全郵件的,這個(gè)需要從ehlo的返回值里來(lái)確認(rèn),如果里面有starttls,才表示支持。相對(duì)于發(fā)送普通郵件的第二種方法來(lái)說(shuō),只需要新增加一行代碼就可以了:

復(fù)制代碼 代碼如下:

#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64

# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# 郵件用戶名
username = "xxxxxx@163.com"
# 密碼
password = "xxxxxxx"
# smtp會(huì)話過(guò)程中的mail from地址
from_addr = "xxxxxx@163.com"
# smtp會(huì)話過(guò)程中的rcpt to地址
to_addr = "yyyyyy@163.com"
# 信件內(nèi)容
msg = "my test mail"

svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會(huì)話過(guò)程中會(huì)有輸出信息
svr.set_debuglevel(1)
# ehlo命令,docmd方法包括了獲取對(duì)方服務(wù)器返回信息,如果支持安全郵件,返回值里會(huì)有starttls提示
svr.docmd("EHLO server")
svr.starttls()  # <------ 這行就是新加的支持安全郵件的代碼!
# auth login 命令
svr.docmd("AUTH LOGIN")
# 發(fā)送用戶名,是base64編碼過(guò)的,用send發(fā)送的,所以要用getreply獲取返回信息
svr.send(base64.encodestring(username))
svr.getreply()
# 發(fā)送密碼
svr.send(base64.encodestring(password))
svr.getreply()
# mail from, 發(fā)送郵件發(fā)送者
svr.docmd("MAIL FROM: <%s>" % from_addr)
# rcpt to, 郵件接收者
svr.docmd("RCPT TO: <%s>" % to_addr)
# data命令,開始發(fā)送數(shù)據(jù)
svr.docmd("DATA")
# 發(fā)送正文數(shù)據(jù)
svr.send(msg)
# 比如以 . 作為正文發(fā)送結(jié)束的標(biāo)記
svr.send(" . ")
svr.getreply()
# 發(fā)送結(jié)束,退出
svr.quit()


注意: 以上的代碼為了方便我都沒有判斷返回值,嚴(yán)格說(shuō)來(lái),是應(yīng)該判斷一下返回的代碼的,在smtp協(xié)議中,只有返回代碼是2xx或者3xx才能繼續(xù)下一步,返回4xx或5xx的,都是出錯(cuò)了。

相關(guān)文章

  • YOLOv5改進(jìn)系列之增加小目標(biāo)檢測(cè)層

    YOLOv5改進(jìn)系列之增加小目標(biāo)檢測(cè)層

    yolov5出來(lái)已經(jīng)很長(zhǎng)時(shí)間了,所以有關(guān)yolov5的一些詳細(xì)介紹在這里就不一一介紹了,下面這篇文章主要給大家介紹了關(guān)于YOLOv5改進(jìn)系列之增加小目標(biāo)檢測(cè)層的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • Python中實(shí)現(xiàn)WebSocket的示例詳解

    Python中實(shí)現(xiàn)WebSocket的示例詳解

    WebSocket 是一種計(jì)算機(jī)通信協(xié)議,它為客戶端和服務(wù)器之間的雙向通信提供了一個(gè)全雙工的通道,本篇文章將詳解 Python 中如何實(shí)現(xiàn) WebSocket,感興趣的可以了解下
    2025-03-03
  • Python屬性私有化詳解

    Python屬性私有化詳解

    私有化是為了實(shí)現(xiàn)更好的封裝形式。能隱藏屬性,不被隨意修改。以前置雙下劃線__屬性/方法名定義,但是結(jié)尾不能是雙下劃線。如果不讓某些屬性在類外部被隨意更改,可設(shè)置成私有屬性。在類定義的內(nèi)部可以訪問(wèn)
    2023-02-02
  • 修改python plot折線圖的坐標(biāo)軸刻度方法

    修改python plot折線圖的坐標(biāo)軸刻度方法

    今天小編就為大家分享一篇修改python plot折線圖的坐標(biāo)軸刻度方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • pygame中blit()參數(shù)的使用及臟矩形動(dòng)畫形成的說(shuō)明

    pygame中blit()參數(shù)的使用及臟矩形動(dòng)畫形成的說(shuō)明

    這篇文章主要介紹了pygame中blit()參數(shù)的使用及臟矩形動(dòng)畫形成的說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • python復(fù)制文件代碼實(shí)現(xiàn)

    python復(fù)制文件代碼實(shí)現(xiàn)

    最近在備份手機(jī)上的照片的時(shí)候,純手工操作覺得有些麻煩,就想寫個(gè)腳本自動(dòng)進(jìn)行。因?yàn)閭浞莸臅r(shí)候有些照片以前備份過(guò)了,所以需要有個(gè)判重操作,看下面的實(shí)現(xiàn)代碼
    2013-12-12
  • Flask緩存靜態(tài)文件的具體方法

    Flask緩存靜態(tài)文件的具體方法

    在本篇文章中小編給大家整理的是一篇關(guān)于Flask緩存靜態(tài)文件的具體方法,有需要的朋友們可以參考下。
    2020-08-08
  • 使用Python畫出小人發(fā)射愛心的代碼

    使用Python畫出小人發(fā)射愛心的代碼

    今天小編就為大家分享一篇使用Python畫出小人發(fā)射愛心的代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • python使用xlrd模塊讀寫Excel文件的方法

    python使用xlrd模塊讀寫Excel文件的方法

    這篇文章主要介紹了python使用xlrd模塊讀寫Excel文件的方法,較為詳細(xì)的分析了xlrd模塊的安裝、使用與操作Excel文件的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • Python判斷變量是否已經(jīng)定義的方法

    Python判斷變量是否已經(jīng)定義的方法

    這篇文章主要介紹了Python判斷變量是否已經(jīng)定義的方法,非常實(shí)用的方法,需要的朋友可以參考下
    2014-08-08

最新評(píng)論

稻城县| 罗平县| 木里| 板桥市| 新营市| 湘潭市| 新兴县| 铅山县| 潢川县| 遂溪县| 疏附县| 黄石市| 巨鹿县| 石阡县| 镇雄县| 嘉兴市| 克山县| 马鞍山市| 九江县| 晋宁县| 共和县| 乐昌市| 天峻县| 麻阳| 卢氏县| 东阳市| 郧西县| 股票| 宽甸| 汝阳县| 会泽县| 楚雄市| 紫阳县| 合水县| 调兵山市| 竹山县| 鄱阳县| 锦州市| 宕昌县| 渝北区| 柳州市|