摘要:如何通過(guò)POP3,用Python收取電子郵件。
*寫在前面:為了更好的學(xué)習(xí)python沟堡,博主記錄下自己的學(xué)習(xí)路程。本學(xué)習(xí)筆記基于廖雪峰的Python教程矢空,如有侵權(quán)航罗,請(qǐng)告知?jiǎng)h除。歡迎與博主一起學(xué)習(xí)Pythonヽ( ̄▽ ̄)? *
摘要
本學(xué)習(xí)筆記基于廖雪峰的Python教程屁药。歡迎與博主一起學(xué)習(xí)Pythonヽ( ̄▽ ̄)?
本節(jié)內(nèi)容:如何通過(guò)POP3粥血,用Python收取電子郵件。
目錄
電子郵件
POP3收取郵件
poplib下載郵件
解析郵件
小結(jié)
電子郵件
POP3收取郵件
收取郵件通常用的是POP協(xié)議者祖,目前版本號(hào)為3立莉,俗稱POP3。
我們需要編寫一個(gè)MUA從MDA上收取郵件七问。
我們要用到Python中的兩個(gè)模塊蜓耻,poplib
和email
,分為兩大步驟:
1.用poplib
下載郵件的原始文本
2.用email
解析原始文本械巡,還原郵件刹淌。
當(dāng)然了饶氏,在這之前需要保證我們使用的郵箱已經(jīng)開啟了POP3服務(wù)。
poplib下載郵件
首先引入poplib
模塊:
import poplib
準(zhǔn)備登錄POP3服務(wù)器的相關(guān)信息有勾,包括郵箱地址疹启、密碼和服務(wù)器地址:
email = input('Email:') # 輸入郵箱地址
password = input('Password:') # 輸入密碼
pop3_server = input('POP3_server:') # 輸入POP3服務(wù)器地址
連接POP3服務(wù)器:
server = poplib.POP3(pop3_server)
server.set_debuglevel(1) # 打開調(diào)式信息
print(server.getwelcome().decode('utf-8')) # 打印POP3服務(wù)器歡迎信息
需要注意的是,如果使用的郵箱pop服務(wù)有加密蔼卡,則需要以加密的方法連接服務(wù)器喊崖,像這樣:
server = poplib.POP3_SSL(pop3_server)
進(jìn)行身份認(rèn)證:
server.user(email)
server.pass_(password)
返回郵箱的相關(guān)信息:
print('Messages:%s. Size:%s' % server.stat()) # 返回郵件數(shù)目和占用空間
resp, mails, octets = server.list() # 獲取郵件列表
print(mails) # 打印所有郵件編號(hào)及相應(yīng)的大小
這里stat()
可以獲取郵件總數(shù)目及占用空間。
list()
可以獲取每一封郵件的編號(hào)即占用空間雇逞。
獲取一封郵件:
index = len(mails) # index為郵件總數(shù)目
resp, lines, octets = server.retr(index) # 獲取最新一封郵件的信息
msg_content = b'\r\n'.join(lines).decode('utf-8') # 獲得整個(gè)郵件的原始文本
retr()
可以返回郵件的全部文本荤懂,其中lines
存儲(chǔ)的是文本的每一行內(nèi)容。
接下來(lái)就是解析文本的部分塘砸,后面會(huì)介紹:
msg = Parser().parsestr(msg_content) # 解析郵件原始文本
最后關(guān)閉連接:
server.quit()
解析郵件
解析郵件的過(guò)程與構(gòu)造郵件正好相反节仿。
首先,引入必要的模塊:
from email.parser import Parser # 解析模塊
from email.header import decode_header # 用于獲取頭文件的編碼信息
from email.utils import pasrseaddr # 用于格式化郵件信息
import poplib
由于在解析郵件的過(guò)程中掉蔬,會(huì)遇到編碼問(wèn)題廊宪,需要進(jìn)行相應(yīng)的解碼才能正常顯示。
所以我們需要先定義相關(guān)函數(shù)用以解碼女轿。
針對(duì)郵件的相關(guān)信息箭启,比如Subjict,name等蛉迹,我們定義一個(gè)decode_str
函數(shù):
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = valur.decode(charset) # 如果文本中存在編碼信息册烈,則進(jìn)行相應(yīng)的解碼
return value
針對(duì)郵件的文本內(nèi)容,我們需要檢測(cè)編碼婿禽,否則,非UTF-8
編碼的郵件都無(wú)法正常顯示大猛,我們定義一個(gè)guess_charset
函數(shù):
def guess_charset(msg):
charset = msg.get_charset() # 直接用get_charset()方法獲取編碼
if charset is None: # 如果獲取不到扭倾,則在原始文本中尋找
content_type = msg.get('Content-Type', '').lower()
pos = content_type.find('charset=') # 找'charset='這個(gè)字符串
if pos >=0: # 如果有,則獲取該字符串后面的編碼信息
charset = content_type[pos+8:].strip()
return charset
這里lower()
是把字符串全改為小寫表示挽绩。
strip()
是去除字符串前后的空格字符膛壹。
準(zhǔn)備好編碼的問(wèn)題,就開始正式解析郵件吧唉堪。
把郵件內(nèi)容解析為Message對(duì)象:
msg = Parser().parsestr(msg_content)
由于這個(gè)Message對(duì)象可能嵌套著其他MIMEBase對(duì)象模聋,所以我們要遞歸地打印出Mseeage的層次結(jié)構(gòu):
def print_info(msg, indent=0): # indent用于縮進(jìn)顯示
# 首先打印郵件的發(fā)件人,收件人和主題
if indent == 0:
for header in ['From', 'To', 'Subject']:
value = msg.get(header, '')
if value:
if header == 'Subject': # 解碼主題信息
value = decode_str(value)
else: # 解碼發(fā)件人和收件人信息
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' '* indent, header, value)) #' ' *indent可以打印出2*indent個(gè)空格
# 將組合郵件對(duì)象分離唠亚,
if (msg.is_multipart()):
parts = msg.get_payload() # 拿取msg的子對(duì)象
for n, part in enumerate(parts):
print('%spart %s' % (' ' * indent, n))
print('%s--------------------' % (' ' * indent))
print_info(part,indent + 1)
# 逐一打印郵件對(duì)象
else:
content_type = msg.get_content_type() # 獲取郵件對(duì)象格式
if content_type == 'text/plain' or content_type == 'text/html': # 如果為文本郵件链方,則直接打印
content = msg.get_payload(decode=True)
charset = guess_charset(msg) # 檢測(cè)編碼
if charset:
content = content.decode(charset) # 解碼
print('%sText: %s' % (' ' * indent, content)) # 打印內(nèi)容
else:
print('%sAttachment: %s' % (' ' * indent, content_type)) # 否則為附件,獲取附件信息
整理一下上面的代碼灶搜,就能用來(lái)收取郵件了祟蚀,比如有這樣一封郵件:
我們運(yùn)行上面的代碼工窍,把顯示結(jié)果如下:
+OK QQMail POP3 Server v1.0 Service Ready(QQMail v2.0)
Messages:19. Size:1335886
From: 三貝 <xxxxxx@126.com>
To: xxxxxxxx<xxxxx@qq.com>
Subject: POP3測(cè)試
part 0
--------------------
part 0
--------------------
Text: 你好,正在使用POP3收取郵件前酿。
part 1
--------------------
Text: <div style="line-height:1.7;color:#000000;..."><div>你好患雏,正在使用...
</div></div></span>
part 1
--------------------
Attachment: image/png
從打印的結(jié)構(gòu)我們可以看出,這封郵件是一個(gè)MIMEMultipart
罢维,分為兩部分:
第一部分又是一個(gè)MIMEMultipart
淹仑,這一部分包含一個(gè)純文本格式的MIMEText
和HTML格式的MIMEText
;
第二部分是一個(gè)Image文件肺孵。
小結(jié)
Python用POP3收取電子郵件分兩步:第一匀借,使用poplib
下載郵件原始文本;第二悬槽,使用email
把原始文本解析為Message
對(duì)象怀吻,然后將內(nèi)容展示給用戶。
以上就是本節(jié)的全部?jī)?nèi)容初婆,感謝你的閱讀蓬坡。
下一節(jié)內(nèi)容:數(shù)據(jù)庫(kù)
有任何問(wèn)題與想法,歡迎評(píng)論與吐槽磅叛。
和博主一起學(xué)習(xí)Python吧( ̄▽ ̄)~*