python模塊smtplib學(xué)習(xí)
python的smtplib提供了一種很方便的途徑發(fā)送電子郵件。它對smtp協(xié)議進(jìn)行了簡單的封裝。
smtp協(xié)議的基本命令包括:
HELO 向服務(wù)器標(biāo)識用戶身份
MAIL 初始化郵件傳輸 mail from:
RCPT 標(biāo)識單個(gè)的郵件接收人;常在MAIL命令后面,可有多個(gè)rcpt to:
DATA 在單個(gè)或多個(gè)RCPT命令后,表示所有的郵件接收人已標(biāo)識,并初始化數(shù)據(jù)傳輸,以.結(jié)束
VRFY 用于驗(yàn)證指定的用戶/郵箱是否存在;由于安全方面的原因,服務(wù)器常禁止此命令
EXPN 驗(yàn)證給定的郵箱列表是否存在,擴(kuò)充郵箱列表,也常被禁用
HELP 查詢服務(wù)器支持什么命令
NOOP 無操作,服務(wù)器應(yīng)響應(yīng)OK
QUIT 結(jié)束會話
RSET 重置會話,當(dāng)前傳輸被取消
MAIL FROM 指定發(fā)送者地址
RCPT TO 指明的接收者地址
一般smtp會話有兩種方式,一種是郵件直接投遞,就是說,比如你要發(fā)郵件給zzz@163.com,那就直接連接163.com的郵件服務(wù)器,把信投給zzz@163.com; 另一種是驗(yàn)證過后的發(fā)信,它的過程是,比如你要發(fā)郵件給zzz@163.com,你不是直接投到163.com,而是通過自己在sina.com的另一個(gè)郵箱來發(fā)。這樣就要先連接sina.com的smtp服務(wù)器,然后認(rèn)證,之后在把要發(fā)到163.com的信件投到sina.com上,sina.com會幫你把信投遞到163.com。
第一種方式的命令流程基本是這樣:
1. helo
2. mail from
3. rcpt to
4. data
5. quit
但是第一種發(fā)送方式一般有限制的,就是rcpt to指定的這個(gè)郵件接收者必須在這個(gè)服務(wù)器上存在,否則是不會接收的。 先看看代碼:
#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# smtp會話過程中的mail from地址
from_addr = "asfgysg@zxsdf.com"
# smtp會話過程中的rcpt to地址
to_addr = "zhaoweikid@163.com"
# 信件內(nèi)容
msg = "test mail"
svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會話過程中會有輸出信息
svr.set_debuglevel(1)
# helo命令,docmd方法包括了獲取對方服務(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是有反垃圾郵件功能的,想上面的這種投遞郵件的方法不一定能通過反垃圾郵件系統(tǒng)的檢測的。所以一般不推薦個(gè)人這樣發(fā)送。
第二種有點(diǎn)不一樣:
1.ehlo
2.auth login
3.mail from
4.rcpt to
5.data
6.quit
相對于第一種來說,多了一個(gè)認(rèn)證過程,就是auth login這個(gè)過程。
#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64
# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# 郵件用戶名
username = "xxxxxx@163.com"
# 密碼
password = "xxxxxxx"
# smtp會話過程中的mail from地址
from_addr = "xxxxxx@163.com"
# smtp會話過程中的rcpt to地址
to_addr = "yyyyyy@163.com"
# 信件內(nèi)容
msg = "my test mail"
svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會話過程中會有輸出信息
svr.set_debuglevel(1)
# ehlo命令,docmd方法包括了獲取對方服務(wù)器返回信息
svr.docmd("EHLO server")
# auth login 命令
svr.docmd("AUTH LOGIN")
# 發(fā)送用戶名,是base64編碼過的,用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()
上面說的是最普通的情況,但是不能忽略的是現(xiàn)在好多企業(yè)郵件是支持安全郵件的,就是通過SSL發(fā)送的郵件,這個(gè)怎么發(fā)呢?SMTP對SSL安全郵件的支持有兩種方案,一種老的是專門開啟一個(gè)465端口來接收ssl郵件,另一種更新的做法是在標(biāo)準(zhǔn)的25端口的smtp上增加一個(gè)starttls的命令來支持。
看看第一種怎么辦:
#-*- 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()
這里我是從原來的smtplib.SMTP派生出了新的SMTP_SSL類,它專門來處理ssl連接。我這里測試的192.168.2.10是我自己的測試服務(wù)器.
第二種是新增加了starttls的命令,這個(gè)很簡單,smtplib里就有這個(gè)方法,叫smtplib.starttls()。當(dāng)然,不是所有的郵件系統(tǒng)都支持安全郵件的,這個(gè)需要從ehlo的返回值里來確認(rèn),如果里面有starttls,才表示支持。相對于發(fā)送普通郵件的第二種方法來說,只需要新增加一行代碼就可以了:
#-*- encoding: gb2312 -*-
import os, sys, string
import smtplib
import base64
# 郵件服務(wù)器地址
mailserver = "smtp.163.com"
# 郵件用戶名
username = "xxxxxx@163.com"
# 密碼
password = "xxxxxxx"
# smtp會話過程中的mail from地址
from_addr = "xxxxxx@163.com"
# smtp會話過程中的rcpt to地址
to_addr = "yyyyyy@163.com"
# 信件內(nèi)容
msg = "my test mail"
svr = smtplib.SMTP(mailserver)
# 設(shè)置為調(diào)試模式,就是在會話過程中會有輸出信息
svr.set_debuglevel(1)
# ehlo命令,docmd方法包括了獲取對方服務(wù)器返回信息,如果支持安全郵件,返回值里會有starttls提示
svr.docmd("EHLO server")
svr.starttls() # <------ 這行就是新加的支持安全郵件的代碼!
# auth login 命令
svr.docmd("AUTH LOGIN")
# 發(fā)送用戶名,是base64編碼過的,用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)格說來,是應(yīng)該判斷一下返回的代碼的,在smtp協(xié)議中,只有返回代碼是2xx或者3xx才能繼續(xù)下一步,返回4xx或5xx的,都是出錯(cuò)了。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python3使用smtplib實(shí)現(xiàn)發(fā)送郵件功能
- python模塊smtplib實(shí)現(xiàn)純文本郵件發(fā)送功能
- python郵件發(fā)送smtplib使用詳解
- Python smtplib實(shí)現(xiàn)發(fā)送郵件功能
- python smtplib模塊實(shí)現(xiàn)發(fā)送郵件帶附件sendmail
- python smtplib模塊自動收發(fā)郵件功能(二)
- python中使用smtplib和email模塊發(fā)送郵件實(shí)例
- Python httplib,smtplib使用方法
- Python使用smtplib模塊發(fā)送電子郵件的流程詳解
- python3模塊smtplib實(shí)現(xiàn)發(fā)送郵件功能
相關(guān)文章
Python re.sub 反向引用的實(shí)現(xiàn)
反向引用指的是在指定替換結(jié)果的過程中,可以引用原始字符串中的匹配到內(nèi)容,本文主要介紹了反向引用的設(shè)置方法,感興趣的可以了解一下2021-07-07
python encrypt 實(shí)現(xiàn)AES加密的實(shí)例詳解
在本篇文章里小編給大家分享的是關(guān)于python encrypt 實(shí)現(xiàn)AES加密的實(shí)例內(nèi)容,有興趣的朋友們可以參考下。2020-02-02
Python中不同數(shù)據(jù)對象的空值校驗(yàn)的方法小結(jié)
Python中有多種數(shù)據(jù)對象,每種都有其特定的空值表示方法和校驗(yàn)方式,本文將深入探討這些空值校驗(yàn)的方法,有需要的小伙伴可以參考一下2024-04-04
利用python和ffmpeg 批量將其他圖片轉(zhuǎn)換為.yuv格式的方法
今天小編就為大家分享一篇利用python和ffmpeg 批量將其他圖片轉(zhuǎn)換為.yuv格式的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-01-01
Python中matplotlib庫安裝失敗的經(jīng)驗(yàn)總結(jié)(附pycharm配置anaconda)
最近根據(jù)領(lǐng)導(dǎo)布置的學(xué)習(xí)任務(wù),開始學(xué)習(xí)python中的matplotlib,朋友告訴我這個(gè)很簡單,然而剛踏入安裝的門檻,就遇到了安裝不成功的問題,下面這篇文章主要給大家介紹了關(guān)于Python中matplotlib庫安裝失敗的經(jīng)驗(yàn)總結(jié),需要的朋友可以參考下2022-08-08
使用python3 實(shí)現(xiàn)插入數(shù)據(jù)到mysql
今天小編就為大家分享一篇使用python3 實(shí)現(xiàn)插入數(shù)據(jù)到mysql,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03

