初學Python3,做一個email的例子,雖然知道做的很渣渣,還是分享一下吧
POP3協議
POP3全稱Post Official Protocol3,即郵局協議的第三個版本,它規定了怎樣將個人計算機連接到Internet的郵件服務器和下載電子郵件的電子協議,它是因特網電子協議的第一個離線標准,POP3允許用戶從服務器上將郵件存儲到本地主機(個人計算機),同時刪除保存在郵件服務器上的郵件,而POP3服務器則是遵循POP3協議的郵件服務器,用來接收電子郵件。
Python3支持POP3的模塊是poplib:建立連接(初始化POP3時進行)、用戶名/密碼認證、獲取郵件信息/下載郵件/刪除郵件等處理、退出並更新處理。
POP3的協議模型及處理是非常直觀的,獲取到郵件以后的解析消息才是major problem!
代碼如下
import poplib
import sys
from importlib import reload
from email.parser import Parser
from email.parser import BytesParser
from email.header import decode_header
from email.utils import parseaddr
import email.iterators
# 解析消息頭中的字符串
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# 將郵件附件或內容保存至文件
# 即郵件中的附件數據寫入附件文件
def savefile(filename, data, path):
try:
filepath = path + filename
print( ' Save as: ' + filepath)
f = open(filepath, ' wb ')
except:
print(filepath + ' open failed ')
# f.close()
else:
f.write(data)
f.close()
# 獲取郵件的字符編碼,首先在message中尋找編碼,如果沒有,就在header的Content-Type中尋找
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get( ' Content-Type ', '').lower()
pos = content_type.find( ' charset= ')
if pos >= 0:
charset = content_type[pos+8:].strip()
return charset
# 解析郵件的函數,首先打印收件人、發件人、標題
# 然后調用message的walk循環處理郵件中的每一個子對象(包括文本、html、附件一次或多次)
# 郵件頭屬性中的filename存在則該子對象是附件,對附件名稱進行編碼並將附件下載到指定目錄
# 由於網絡上傳輸的郵件都是編碼以后的格式,需要在get_payload的時候指定decode=True來轉換成可輸出的編碼
# 如果郵件是text或者html格式,打印格式並輸出轉碼以后的子對象內容
def print_info(msg):
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(addr)
value = name + ' < ' + addr + ' > '
print(header + ' : ' + value)
for part in msg.walk():
filename = part.get_filename()
content_type = part.get_content_type()
charset = guess_charset(part)
if filename:
filename = decode_str(filename)
data = part.get_payload(decode = True)
if filename != None or filename != '':
print( ' Accessory: ' + filename)
savefile(filename, data, mypath)
else:
email_content_type = ''
content = ''
if content_type == ' text/plain ':
email_content_type = ' text '
elif content_type == ' text/html ':
email_content_type = ' html '
if charset:
content = part.get_payload(decode=True).decode(charset)
print(email_content_type + ' ' + content)
email = ' email_name@163.com '
password = ' email_passwd '
pop3_server = ' pop.163.com '
mypath = ' D://email/ '
server = poplib.POP3(pop3_server, 110)
# print(server.getwelcome())
server.user(email)
server.pass_(password)
print( ' Message: %s. Size: %s ' % server.stat())
resp, mails, objects = server.list()
# print(mails)
index = len(mails)
# 取出某一個郵件的全部信息
resp, lines, octets = server.retr(index)
# 郵件取出的信息是bytes,轉換成Parser支持的str
lists = []
for e in lines:
lists.append(e.decode())
msg_content = ' \r\n '.join(lists)
msg = Parser().parsestr(msg_content)
print_info(msg)
# server.dele(index)
# 提交操作信息並退出
server.quit()
import sys
from importlib import reload
from email.parser import Parser
from email.parser import BytesParser
from email.header import decode_header
from email.utils import parseaddr
import email.iterators
# 解析消息頭中的字符串
def decode_str(s):
value, charset = decode_header(s)[0]
if charset:
value = value.decode(charset)
return value
# 將郵件附件或內容保存至文件
# 即郵件中的附件數據寫入附件文件
def savefile(filename, data, path):
try:
filepath = path + filename
print( ' Save as: ' + filepath)
f = open(filepath, ' wb ')
except:
print(filepath + ' open failed ')
# f.close()
else:
f.write(data)
f.close()
# 獲取郵件的字符編碼,首先在message中尋找編碼,如果沒有,就在header的Content-Type中尋找
def guess_charset(msg):
charset = msg.get_charset()
if charset is None:
content_type = msg.get( ' Content-Type ', '').lower()
pos = content_type.find( ' charset= ')
if pos >= 0:
charset = content_type[pos+8:].strip()
return charset
# 解析郵件的函數,首先打印收件人、發件人、標題
# 然后調用message的walk循環處理郵件中的每一個子對象(包括文本、html、附件一次或多次)
# 郵件頭屬性中的filename存在則該子對象是附件,對附件名稱進行編碼並將附件下載到指定目錄
# 由於網絡上傳輸的郵件都是編碼以后的格式,需要在get_payload的時候指定decode=True來轉換成可輸出的編碼
# 如果郵件是text或者html格式,打印格式並輸出轉碼以后的子對象內容
def print_info(msg):
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(addr)
value = name + ' < ' + addr + ' > '
print(header + ' : ' + value)
for part in msg.walk():
filename = part.get_filename()
content_type = part.get_content_type()
charset = guess_charset(part)
if filename:
filename = decode_str(filename)
data = part.get_payload(decode = True)
if filename != None or filename != '':
print( ' Accessory: ' + filename)
savefile(filename, data, mypath)
else:
email_content_type = ''
content = ''
if content_type == ' text/plain ':
email_content_type = ' text '
elif content_type == ' text/html ':
email_content_type = ' html '
if charset:
content = part.get_payload(decode=True).decode(charset)
print(email_content_type + ' ' + content)
email = ' email_name@163.com '
password = ' email_passwd '
pop3_server = ' pop.163.com '
mypath = ' D://email/ '
server = poplib.POP3(pop3_server, 110)
# print(server.getwelcome())
server.user(email)
server.pass_(password)
print( ' Message: %s. Size: %s ' % server.stat())
resp, mails, objects = server.list()
# print(mails)
index = len(mails)
# 取出某一個郵件的全部信息
resp, lines, octets = server.retr(index)
# 郵件取出的信息是bytes,轉換成Parser支持的str
lists = []
for e in lines:
lists.append(e.decode())
msg_content = ' \r\n '.join(lists)
msg = Parser().parsestr(msg_content)
print_info(msg)
# server.dele(index)
# 提交操作信息並退出
server.quit()