收取郵件有兩種協議,POP3和IMAP,POP3相對於IMAP功能較少無法對郵件進行更深層次的操作,因此本文使用IMAP協議收取郵件。python提供了很多收郵件的模塊,本文使用imaplib來接收郵件。
前提
需要在郵件箱的設置中打開允許IMAP,不同郵件開啟全方式不同,具體開啟方式自行百度。(本文使用outlook,默認開啟)
難點
獲得郵件不難,難點是如何解析郵件的內容,由於郵件內容的編碼是不固定的,因此編碼格式的選擇影響着解析郵件內容的正確性
代碼
import imaplib , email , os
imapserver = 'outlook.office365.com'
emailuser = "bill@outlook.com"
emailpasswd = "billpasswd"
attachementdir=r"d:\a" #附件存放的位置
conn = imaplib.IMAP4_SSL(imapserver)
conn.login(emailuser,emailpasswd)
conn.list() #列出郵箱中所有的列表,如:收件箱、垃圾箱、草稿箱。。。
conn.select('INBOX') #選擇收件箱(默認)
result , dataid = conn.uid ( 'search' , None , "ALL" )
mailidlist = dataid[0].split () #轉成標准列表,獲得所有郵件的ID
# 解析郵件內容
def get_body(msg):
if msg.is_multipart ():
return get_body ( msg.get_payload ( 0 ) )
else:
return msg.get_payload ( None , decode=True )
#search('FROM','abc@outlook.com',conn) 根據輸入的條件查找特定的郵件
def search(key,value,conn):
result , data = conn.search(None,key,'"()"'.format(value))
return data
#獲取附件
def get_attachements(msg):
for part in msg.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
if bool(filename):
filepath = os.path.join(attachementdir,filename)
with open(filepath,'wb') as f:
f.write(part.get_payload(decode=True))
for id in mailidlist:
result , data = conn.fetch ( id , '(RFC822)' ) # 通過郵件id獲取郵件
e = email.message_from_bytes ( data[0][1] )
subject = email.header.make_header ( email.header.decode_header ( e['SUBJECT'] ) )
mail_from = email.header.make_header ( email.header.decode_header ( e['From'] ) )
print("郵件的subject是%s" % subject)
print("郵件的發件人是%s" % mail_from)
body = str ( get_body ( e ) , encoding='utf-8' ) # utf-8 gb2312 GB18030解析中文日文英文
print("郵件內容是%s" % body)
conn.logout()
【問題】
一般utf-8可以解決大部分的郵件編碼格式,若不能解析請使用其他編碼。
【待改進】
email模塊有一個獲取郵件編碼的方法,暫時未能找到
使用email提供的方法獲取郵件編碼,變可以解決所有郵件解析的問題
