Python之Mail编程(电子邮件编程)
生活随笔
收集整理的這篇文章主要介紹了
Python之Mail编程(电子邮件编程)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
電子郵件的歷史起源
- 1969 Leonard K. 教授發給同時的 “LO”
- 1971 美國國防部自主的阿帕網(Arpanet)的通訊機制
- 通訊地址里用@,?
- 1987年中國的第一份電子郵件 ?“Across the Great Wall we can reach every corner in the world"
管理程序
- Euroda使郵件普及?
- Netscape,outlook,forxmail后來居上
- Hotmal使用瀏覽器發送郵件i
參考資料
- ?[官網](https://docs.python.org/3/library/email.mime.html)
郵件工作流程
- MUA(MailUserAgent)郵件用戶代理
- MTA(MailTransferAgent)郵件傳輸代理
- MDA(MailDeliveryAgent)郵件投遞代理
- 流程
編寫程序
- 發送: ?MUA->MTA with SMTP:SimpleMailTransferProtocal,包含MTA->MTA
- 接受: ?MDA->MUA with POP3 and IMAP:PostOfficeProtocal v3 and ?InternetMessageAccessProtocal v4
? ??
準備工作
- 注冊郵箱(以qq郵箱為例)
- 第三方郵箱需要特殊設置, 以qq郵箱為例
- 進入設置中心
- 取得授權碼
? ? ? ??
Python for mail
1.SMTP協議負責發送郵件
- 使用email模塊構建郵件
- 純文本郵件
- 案例見下方代碼
- HTML格式郵件發送
- 準備HTML代碼作為內容
- ?把郵件的subtpye設為html
- 發送
- 案例見下方代碼
- 發送帶附件的郵件
- 可以把郵件看作是一個文本郵件和一個附件的合體
- 一封郵件如果涉及多個部分,需要使用MIMEMultipart格式構建
- 添加一個MIMEText正文
- 添加一個MIMEBase或者MEMEText作為附件
- 案例見下方代碼
- 添加郵件頭, 抄送等信息
- mail["From"] 表示發送著信息,包括姓名和郵件
- mail["To"] ?表示接收者信息,包括姓名和郵件地址
- mail["Subject"] 表示摘要或者主題信息
- 案例見下方代碼
- 同時支持html和text格式
- 構建一個MIMEMultipart格式郵件
- MIMEMultipart的subtype設置成alternative格式
- 添加HTML和text郵件
- 案例見下方代碼
- 使用smtplib模塊發送郵件
2.POP3協議接受郵件?
- 本質上是MDA到MUA的一個過程
- 從 MDA下載下來的是一個完整的郵件結構體,需要解析才能得到每個具體可讀的內容
- 步驟:
? ? ? ? ? ? 1. 用poplib下載郵件結構體原始內容
? ? ? ? ? ? ? ? 1. 準備相應的內容(郵件地址,密碼,POP3實例)
? ? ? ? ? ? ? ? 2. 身份認證
? ? ? ? ? ? ? ? 3. 一般會先得到郵箱內郵件的整體列表
? ? ? ? ? ? ? ? 4. 根據相應序號,得到某一封信的數據流
? ? ? ? ? ? ? ? 5. 利用解析函數進行解析出相應的郵件結構體
? ? ? ? ? ? 2. 用email解析郵件的具體內容
- 案例見下方代碼
使用email模塊構建郵件案例:
# 導入相應的包 import smtplib from email.mime.text import MIMEText # MIMEText三個主要參數 # 1. 郵件內容 # 2. MIME子類型,在此案例我們用plain表示text類型 # 3. 郵件編碼格式msg = MIMEText("Hello, i am beijing tulingxueyuan ", "plain", "utf-8")# 發送email地址,此處地址直接使用我的qq有偶像,密碼一般需要臨時輸入,此處偷懶 from_addr = "1366798119@qq.com" # 此處密碼是經過申請設置后的授權碼,不是不是不是你的qq郵箱密碼 from_pwd = "hjpovygcxmrshhcj"# 收件人信息 # 此處使用qq郵箱,我給自己發送 to_addr = "1366798119@qq.com"# 輸入SMTP服務器地址 # 此處根據不同的郵件服務商有不同的值, # 現在基本任何一家郵件服務商,如果采用第三方收發郵件,都需要開啟授權選項 # 騰訊qq郵箱所的smtp地址是 smtp.qq.comsmtp_srv = "smtp.qq.com"try:# 兩個參數# 第一個是服務器地址,但一定是bytes格式,所以需要編碼# 第二個參數是服務器的接受訪問端口srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) #SMTP協議默認端口25#登錄郵箱發送srv.login(from_addr, from_pwd)# 發送郵件# 三個參數# 1. 發送地址# 2. 接受地址,必須是list形式# 3. 發送內容,作為字符串發送srv.sendmail(from_addr, [to_addr], msg.as_string())srv.quit() except Exception as e:print(e)HTML格式郵件發送案例:
from email.mime.text import MIMETextmail_content = """<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><h1> 這是一封HTML格式郵件</h1></body></html>"""msg = MIMEText(mail_content, "html", "utf-8")# 構建發送者地址和登錄信息 from_addr = "1366798119@qq.com" from_pwd = "hjpovygcxmrshhcj"# 構建郵件接受者信息 to_addr = "1366798119@qq.com"smtp_srv = "smtp.qq.com"try:import smtplibsrv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)srv.login(from_addr, from_pwd)srv.sendmail(from_addr, [to_addr], msg.as_string())srv.quit()except Exception as e:print(e)發送帶附件的郵件案例:
from email.mime.text import MIMEText #構建附件使用 from email.mime.multipart import MIMEBase, MIMEMultipart # 構建基礎郵件使用mail_mul = MIMEMultipart() # 構建郵件正文 mail_text = MIMEText("Hello, i am liudana", "plain", "utf-8") # 把構建好的郵件正文附加入郵件中 mail_mul.attach(mail_text)# 構建附加 # 構建附件,需要從本地讀入附件 # 打開一個本地文件 # 以rb格式打開 with open("02.html", "rb") as f:s = f.read()# 設置附件的MIME和文件名m = MIMEText(s, 'base64', "utf-8")m["Content-Type"] = "application/octet-stream"# 需要注意,# 1. attachment后分好為英文狀態# 2. filename 后面需要用引號包裹,注意與外面引號錯開m["Content-Disposition"] = "attachment; filename='02.html'"# 添加到MIMEMultipartmail_mul.attach(m)# 發送email地址,此處地址直接使用我的qq有偶像,密碼一般需要臨時輸入,此處偷懶 from_addr = "1366798119@qq.com" # 此處密碼是經過申請設置后的授權碼,不是不是不是你的qq郵箱密碼 from_pwd = "hjpovygcxmrshhcj"# 收件人信息 # 此處使用qq郵箱,我給自己發送 to_addr = "1366798119@qq.com"# 輸入SMTP服務器地址 # 此處根據不同的郵件服務商有不同的值, # 現在基本任何一家郵件服務商,如果采用第三方收發郵件,都需要開啟授權選項 # 騰訊qq郵箱所的smtp地址是 smtp.qq.comsmtp_srv = "smtp.qq.com"try:import smtplibsrv = smtplib.SMTP_SSL(smtp_srv.encode(), 465) #SMTP協議默認端口25#登錄郵箱發送srv.login(from_addr, from_pwd)# 發送郵件# 三個參數# 1. 發送地址# 2. 接受地址,必須是list形式# 3. 發送內容,作為字符串發送srv.sendmail(from_addr, [to_addr], mail_mul.as_string())srv.quit() except Exception as e:print(e)添加郵件頭, 抄送等信息案例:
from email.mime.text import MIMEText from email.header import Headermsg = MIMEText("Hello wold", "plain", "utf-8") # 下面代碼故意寫錯,說明,所謂的發送者的地址,只是從一個Header的第一個參數作為字符串構建的內容 # 用utf8編碼是因為很可能內容包含非英文字符 header_from = Header("從圖靈學院郵箱發出去的<TuLingXueYuan@qq.cn>", "utf-8") msg['From'] = header_from# 填寫接受者信息 header_to = Header("去王曉靜的地方<wangxiaojing@sina.com>", 'utf-8') msg['To'] = header_toheader_sub = Header("這是圖靈學院的主題", 'utf-8') msg['Subject'] = header_sub# 構建發送者地址和登錄信息 from_addr = "1366798119@qq.com" from_pwd = "hjpovygcxmrshhcj"# 構建郵件接受者信息 to_addr = "1366798119@qq.com"smtp_srv = "smtp.qq.com"try:import smtplibsrv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)srv.login(from_addr, from_pwd)srv.sendmail(from_addr, [to_addr], msg.as_string())srv.quit()except Exception as e:print(e)同時支持html和text格式案例:
from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart# 構建一個MIMEMultipart郵件 msg = MIMEMultipart("alternative")# 構建一個HTML郵件內容 html_content = """<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><h1> 這是一封HTML格式郵件</h1></body></html>""" # msg_html = MIMEText(html_content, "html", "utf-8") msg.attach(msg_html)msg_text = MIMEText("just text content", "plain", "utf-8") msg.attach(msg_text)# 發送email地址,此處地址直接使用我的qq郵箱,密碼臨時輸入 from_addr = "1366798119@qq.com" #from_pwd = input('163郵箱密碼: ') from_pwd = "hjpovygcxmrshhcj"# 收件人信息: # 此處使用我注冊的163郵箱 to_addr = "1366798119@qq.com"# 輸入SMTP服務器地址: # 此地址根據每隔郵件服務商有不同的值,這個是發信郵件服務商的smtp地址 # 我用的是qq郵箱發送,此處應該填寫騰訊qq郵箱的smtp值,即smtp.163.com, # 需要開啟授權碼, smtp_srv = "smtp.qq.com"try:import smtplib# 加密傳輸#server = smtplib.SMTP_SSL(smtp_srv.encode(), 465) # SMTP協議默認端口是25# qq郵箱要求使用 TLS加密傳輸server = smtplib.SMTP(smtp_srv.encode(), 25) # SMTP協議默認端口是25server.starttls()# 設置調試級別# 通過設置調試等級,可以清楚的看到發送郵件的交互步驟server.set_debuglevel(1)# 登錄發送郵箱server.login(from_addr, from_pwd)server.sendmail(from_addr, [to_addr], msg.as_string())server.quit() except Exception as e:print(e)POP3協議接受郵件案例:
# 導入相關包 # poplib負責從MDA到MUA下載 import poplib# 以下包負責相關郵件結構解析 from email.parser import Parser from email.header import decode_header from email.utils import parseaddr# 得到郵件的原始內容 # 這個過程主要負責從MDA到MUA的下載并使用Parse粗略解析 def getMsg():# 準備相應的信息email = "1366798119@qq.com"# 郵箱的授權碼pwd = "hjpovygcxmrshhcj"# pop3服務器地址pop3_srv = "pop.qq.com" # 端口995# ssl代表是安全通道srv = poplib.POP3_SSL(pop3_srv)# user代表email地址srv.user(email)# pass_代表密碼srv.pass_(pwd)# 以下操作根據具體業務具體使用# stat返回郵件數量和占用空間# 注意stat返回一個tuple格式msgs, counts = srv.stat()print("Messages: {0}, Size: {1}".format(msgs, counts))# list返回所有郵件編號列表# mails是所有郵件編號列表rsp, mails, octets = srv.list()# 可以查看返回的mails列表類似[b'1 82923', b'2 2184', ...]print(mails)# 獲取最新一封郵件,注意,郵件索引號是從1開始, 最新代表索引號最高index = len(mails)# retr負責返回一個具體索引號的一封信的內容,此內容不具有可讀性# lines 存儲郵件的最原始文本的每一行rsp, lines, octets = srv.retr(index)# 獲得整個郵件的原始文本msg_count = b'\r\n'.join(lines).decode("utf-8")# 解析出郵件整個結構體# 參數是解碼后的郵件整體msg = Parser().parsestr(msg_count)#關閉鏈接srv.quit()return msg# 詳細解析得到的郵件內容 # msg代表是郵件的原始內容 # idnent代表的是郵件嵌套的層級 def parseMsg(msg, indent=0):'''1. 郵件完全可能是有嵌套格式2. 郵件只有一個From,To,Subject之類的信息:param msg::param indent: 描述郵件里面有幾個郵件MIMEXXX類型的內容,展示的時候進行相應縮進:return:'''# 想辦法提取出頭部信息# 只有在第一層的郵件中才會有相關內容,# 此內容只有一個if indent == 0:for header in ['From', "To", 'Subject']:# 使用get可以避免如果沒有相關關鍵字報錯的可能性# 如果沒有 關鍵字”From“, 我們使用 msg["From"]會報錯value = msg.get(header, '')if value:# Subject中的內容直接解碼就可以,他是字符串類型if header == 'Subject':value = decodeStr(value)# 如果是From和To字段,則內容大概是 "我的郵箱<xxxxx@qq.com>“這種格式else:hdr, addr = parseaddr(value)name = decodeStr(hdr)# 最終返回形如 "我的郵箱<xxx@qq.com>的格式value = "{0}<{1}>".format(name, addr)print("{0}, {1}: {2}".format(indent, header, value))# 下面代碼關注郵件內容本身# 郵件內容中,有可能是multipart類型,也有可能是普通郵件類型# 下面的解析使用遞歸方式if (msg.is_multipart()):# 如果是multipart類型,則調用遞歸解析# 得到多部分郵件的一個基礎郵件部分parts = msg.get_payload()# enumerate 函數是內置函數# 作用是將一個列表,此處是parts,生成一個有索引和parts原內容構成的新的列表# 例如 enumerate(['a', 'b', 'c']) 結果是: [(1,'a'), (2, 'b'), (3, 'c')]for n,part in enumerate(parts):# 一個字符串乘以一個數字的意思是對這個字符串進行n倍擴展# 比如 ”aa" * 2 -> "aaaa"print("{0}spart: {1}".format(' '*indent, n))parseMsg(part, indent+1)else: # 基礎類型# get_content_type是系統提供函數,得到內容類型content_type = msg.get_content_type()# text/plain 或者 text/html是固定值if content_type == 'text/plain' or content_type == 'text/html':content = msg.get_payload(decode=True)charset = guessCharset(msg)if charset:content = content.decode(charset)print("{0}Text: {1}".format(indent, content))else: #不是文本內容,則應該是附件print('{0}Attachment: {1}'.format(indent, content_type))def decodeStr(s):'''s代表一封郵件中From,To,Subject中的任一項對s進行解碼,解碼是編碼的逆過程:param s::return:'''value, charset = decode_header(s)[0]# charset完全可能為空if charset:# 如果指定編碼,則用指定編碼格式進行解碼value = value.decode(charset)return valuedef guessCharset(msg):'''猜測郵件的編碼格式:param msg::return:'''# 調用現成的函數charset = msg.get_charset()if charset is None:# 找到內容類型,并轉換成小寫content_type = msg.get("Content-Type", "").lower()pos = content_type.find("charset=")if pos >= 0:# 如果包含chraset,則內容形如 charset=xxxxcharset = content_type[pos+8:].strip()return charsetif __name__ == "__main__":# 得到郵件的原始內容msg = getMsg()print(msg)# 精確解析郵件內容parseMsg(msg, 0)?
總結
以上是生活随笔為你收集整理的Python之Mail编程(电子邮件编程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue3使用vant4-showToas
- 下一篇: 2019年8月计算机语言排行,2019程