【Python入門】41.電子郵件之 POP3收取郵件
摘要:如何通過POP3,用Python收取電子郵件。
寫在前面:為了更好的學習python,博主記錄下自己的學習路程。本學習筆記基於廖雪峰的Python教程,如有侵權,請告知刪除。歡迎與博主一起學習Pythonヽ( ̄▽ ̄)ノ
摘要 本學習筆記基於廖雪峰的Python教程。歡迎與博主一起學習Pythonヽ( ̄▽ ̄)ノ 本節內容:如何通過POP3,用Python收取電子郵件。
目錄
電子郵件
POP3收取郵件
收取郵件通常用的是POP協議,目前版本號為3,俗稱POP3。
我們需要編寫一個MUA從MDA上收取郵件。
我們要用到Python中的兩個模組,poplib
email
,分為兩大步驟:
1.用poplib
下載郵件的原始文字
2.用email
解析原始文字,還原郵件。
當然了,在這之前需要保證我們使用的郵箱已經開啟了POP3服務。
poplib下載郵件
首先引入poplib
模組:
import poplib
準備登入POP3伺服器的相關資訊,包括郵箱地址、密碼和伺服器地址:
email = input('Email:') # 輸入郵箱地址
password = input('Password:') # 輸入密碼
pop3_server = input('POP3_server:' ) # 輸入POP3伺服器地址
連線POP3伺服器:
server = poplib.POP3(pop3_server)
server.set_debuglevel(1) # 開啟調式資訊
print(server.getwelcome().decode('utf-8')) # 列印POP3伺服器歡迎資訊
需要注意的是,如果使用的郵箱pop服務有加密,則需要以加密的方法連線伺服器,像這樣:
server = poplib.POP3_SSL(pop3_server)
進行身份認證:
server.user(email)
server .pass_(password)
返回郵箱的相關資訊:
print('Messages:%s. Size:%s' % server.stat()) # 返回郵件數目和佔用空間
resp, mails, octets = server.list() # 獲取郵件列表
print(mails) # 列印所有郵件編號及相應的大小
這裡stat()
可以獲取郵件總數目及佔用空間。
list()
可以獲取每一封郵件的編號即佔用空間。
獲取一封郵件:
index = len(mails) # index為郵件總數目
resp, lines, octets = server.retr(index) # 獲取最新一封郵件的資訊
msg_content = b'\r\n'.join(lines).decode('utf-8') # 獲得整個郵件的原始文字
retr()
可以返回郵件的全部文字,其中lines
儲存的是文字的每一行內容。
接下來就是解析文字的部分,後面會介紹:
msg = Parser().parsestr(msg_content) # 解析郵件原始文字
最後關閉連線:
server.quit()
解析郵件
解析郵件的過程與構造郵件正好相反。
首先,引入必要的模組:
from email.parser import Parser # 解析模組
from email.header import decode_header # 用於獲取標頭檔案的編碼資訊
from email.utils import pasrseaddr # 用於格式化郵件資訊
import poplib
由於在解析郵件的過程中,會遇到編碼問題,需要進行相應的解碼才能正常顯示。
所以我們需要先定義相關函式用以解碼。
針對郵件的相關資訊,比如Subjict,name等,我們定義一個decode_str
函式:
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = valur.decode(charset) # 如果文字中存在編碼資訊,則進行相應的解碼
return value
針對郵件的文字內容,我們需要檢測編碼,否則,非UTF-8
編碼的郵件都無法正常顯示,我們定義一個guess_charset
函式:
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='這個字串
if pos >=0: # 如果有,則獲取該字串後面的編碼資訊
charset = content_type[pos+8:].strip()
return charset
這裡lower()
是把字串全改為小寫表示。
strip()
是去除字串前後的空格字元。
準備好編碼的問題,就開始正式解析郵件吧。
把郵件內容解析為Message物件:
msg = Parser().parsestr(msg_content)
由於這個Message物件可能巢狀著其他MIMEBase物件,所以我們要遞迴地打印出Mseeage的層次結構:
def print_info(msg, indent=0): # indent用於縮排顯示
# 首先列印郵件的發件人,收件人和主題
if indent == 0:
for header in ['From', 'To', 'Subject']:
value = msg.get(header, '')
if value:
if header == 'Subject': # 解碼主題資訊
value = decode_str(value)
else: # 解碼發件人和收件人資訊
hdr, addr = parseaddr(value)
name = decode_str(hdr)
value = u'%s <%s>' % (name, addr)
print('%s%s: %s' % (' '* indent, header, value)) #' ' *indent可以打印出2*indent個空格
# 將組合郵件物件分離,
if (msg.is_multipart()):
parts = msg.get_payload() # 拿取msg的子物件
for n, part in enumerate(parts):
print('%spart %s' % (' ' * indent, n))
print('%s--------------------' % (' ' * indent))
print_info(part,indent + 1)
# 逐一列印郵件物件
else:
content_type = msg.get_content_type() # 獲取郵件物件格式
if content_type == 'text/plain' or content_type == 'text/html': # 如果為文字郵件,則直接列印
content = msg.get_payload(decode=True)
charset = guess_charset(msg) # 檢測編碼
if charset:
content = content.decode(charset) # 解碼
print('%sText: %s' % (' ' * indent, content)) # 列印內容
else:
print('%sAttachment: %s' % (' ' * indent, content_type)) # 否則為附件,獲取附件資訊
整理一下上面的程式碼,就能用來收取郵件了,比如有這樣一封郵件:
我們執行上面的程式碼,把顯示結果如下:
+OK QQMail POP3 Server v1.0 Service Ready(QQMail v2.0)
Messages:19. Size:1335886
From: 三貝 <[email protected]126.com>
To: xxxxxxxx<[email protected]>
Subject: POP3測試
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
從列印的結構我們可以看出,這封郵件是一個MIMEMultipart
,分為兩部分:
第一部分又是一個MIMEMultipart
,這一部分包含一個純文字格式的MIMEText
和HTML格式的MIMEText
;
第二部分是一個Image檔案。
小結
Python用POP3收取電子郵件分兩步:第一,使用poplib
下載郵件原始文字;第二,使用email
把原始文字解析為Message
物件,然後將內容展示給使用者。
以上就是本節的全部內容,感謝你的閱讀。
下一節內容:資料庫
有任何問題與想法,歡迎評論與吐槽。
和博主一起學習Python吧( ̄▽ ̄)~*