起源
就是通信的一個發展,懶得打字了省略了,以後再查吧
管理程序
一些讓郵件普及的郵件公司
MUA(MailUserAgent)郵件用戶代理
MTA(MailTransferAgent)郵件傳輸代理
MDA(MailDeliveryAgent)郵件投遞代理
流程
MUT->MTA
qq MTA->...........................->sina MTA
sina MTA->.........................->sina MDA
sina MDA->MUA(FoxMail/outlook)郵件下載到本地電腦
編寫程序
發送 MUA->MTA 協議
接收 MTA->MDA 協議
准備工作
注冊郵箱
第三方郵箱進行設置
進入設置中心
取得授權碼
案例07發送純文本郵件‘
import smtplib
from email.mime.text import MIMEText
#MIMEText的主要參數有3個
#1。郵件內容
#2。MIME子類型,在這裡用plain代表text格式的文件
#3.郵件的編碼格式
msg = MIMEText('這是一封文本格式的郵件','plain','utf-8')
#發送email的地址,需要更改為對應的郵件地址
from_addr = '[email protected]'
#授權密碼,大多數的郵箱在使用第三方軟件時,都需要驗證密鑰,這裡不是指郵箱的密碼
from_pwd = 'XXXXXXXXXXX'
#收件人
to_addr = '[email protected]'
#輸入smtplib服務器地址
#此處根據不同的郵件服務商有不同的值
#現在基本任何一家郵件服務商在開啟第三方郵件的時候都需要開啟服務
#TX QQ郵箱的smtplib地址時smtplib.qq.com
smtp_srv = 'smtplib.qq.com'
try:
srv = smtplib.SNTP_SSL(smtp_srv.encode(),465) #這裡的465時QQ郵箱的端口
#登陸郵箱,任何的郵箱在使用之前都必須的登陸
srv.login(from_addr,from_pwd)
#發送郵件
#三參數,發送地址,接受的地址(必須時list格式),發送內容時字符串格式
srv.sendmail(from_addr,[to_addr],msg.as_String())
srv.quit()
except Exception as e:
print(e)
Python for mail
SMTP協議負責發送郵件
使用Email模塊構建郵件-純文本案例V07
HTML格式郵件發送
准備HTML代碼作為內容
把郵件的subtype設為html
發送
案列V08
import smtplib
from email.mime.text import MIMEText
#MIMEText的主要的三個參數
#1。郵件內容
#2。MIME子類型的格式 這裡時HTML所以是html
#3.郵件的編碼格式
msg_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>這是一封HTML格式的郵件</h1>
</body>
</html>
"""
#發送郵件的地址
from_addr = '[email protected]'
#發送郵件的密碼
from_pwd = 'XXXXXXXXXXx'
#收件人
to_addr = '[email protected]'
#輸入SMTP服務器地址
smtp_srv = 'smtp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
#登陸郵箱
srv.login(from_addr,from_pwd)
#發送郵件
srv.sendemail = (from_addr,[to_addr],msg_content.as_toString())
srv.quit()
except Exception as e:
print(e)
發送帶附件的郵件
可以看作有一個文本郵件和一個附件的合體
需要使用MIMEltaipart格式構建
添加一個MIMEBase或者MEME text作為附件
案列V09
import smtplib
from email.mime.text import MIMEText
from email.mime.text import MIMEBase,MIMMultipart #構建基礎郵件時使用
mail_mul = MIMEMulipart()
#構建郵件正文
main_text = MIMEText("這是郵件的正文",'plain','utf-8')
#把構建的正文附加到郵件中
mail_mul.attach(mail_text)
#構建附件,需要從本地讀入
#打開一個本地文件
with open('a.txt','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-Dispostion'] = 'attachment;filename="a.txt"'
#添加MIMEMultipation
mail_mul.attach(m)
#發送郵件
from_addr = '[email protected]'
from_pwd = 'XXXXXXXXx'
to_addr = '[email protected],com'
smtp_srv = 'sntp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
#登陸郵箱
srv.load(from_addr,from_pwd)
srv.sendmail(from_addr,[to_addr],mail_mul.as_string())
srv.quit()
except Exception as e:
print(e)
添加郵件頭,抄送等信息
mail['From'] 表示發送者的信息,包括姓名和郵件
mail['To'] 表示接收者信息,包括姓名和郵件地址
mail['Subject']表示摘要或者主題信息
案例V10
同時支持html和text格式
構建一個MIMEMultipart格式的郵件
MIMEMultipart的subtype設置成alterbalive
添加html 文件和text文件
import smtplib
from email.mime.text import MIMEText
from email,mime.multipart import MIMEMUltipart
#構建一個MIMEMultipart郵件
msg = MIMEMultapart('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("這是文本格式的郵件",'plain','utf-8')
msg.attach(msg_text)
from_addr = '[email protected]'
from_pwd = 'XXXXX'
to_addr = "[email protected]"
smtp_srv = 'smtp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
srv.login(from_addr,from_pwd)
srv_sendmail(from_addr,[to_addr],msg.as_tostring())
srv.quit()
except Exception as e:
print(e)
使用smtplib模塊發送郵件
POP3協議接受郵件
本質上講是從MDA到MTA的一個過程
從MDA下載下來的是一個完整的郵件結構體,需要解析才能的帶每個具有
步驟:
1.用poplib下載郵件結構體原始內容
1.准備相應的內容(郵件的內容,密碼。pop3實例)
2.身份驗證
3.一般會先得到郵箱內郵件的整體列表
4.根據相應的序號,得到某一封信的數據流
5.利用解析函數進行解析出相應的郵件結構體
2.emai解析郵件的具體內容
案例V12
#導入相關的包
#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 = '[email protected]'
#郵箱的授權碼
pwd = 'pwd'
#pop3的服務器地址 默認端口995
pop3_srv = 'pop.qq.com'
#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返回所有的郵件編號列表
#malis返回所有郵件編號列表
rsp,mails,octets = srv.list()
#可以查看返回mails列表類似
print(mails)
#獲取最新一封郵件,注意,郵件的索引號從1開始,最新的郵件索引號最高
index = len(mails)
#retr 負責返回一個具體索引號的一封信的內容,此內容不具有可讀性
#lines 存儲郵件的最高原始文本的每一行
rsp,lines,octets = srv.retr(index)
#獲取整個郵件的原始文本
msg_count = b'\r\n'.join(lines).decode('utf8')
#解析出郵件的整個結構體
#參數時解碼後的郵件整體
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字段,則內容的大概是‘我的郵箱<[email protected]>’這種格式
else:
hdr,addr = parseaddr(value)
name = decodeStr(hdr)
#最終的返回類型如“我的郵箱是<[email protected]>”
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 = gussCharset(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 value
def gussCharset(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:
#如果包含charset,則內容為charset=XXX
charset = content_type[pos+8:].strip()
return charset
if __name__ == '__main__':
#得到郵件的原始內容
msg = getMsg()
print(msg)
#精確解析郵件的內容
parseMsg(msg,0)