用python定時發送郵件
2020/12/24 Hongmin
Python 3.6.3 |Anaconda custom (64-bit)|
關鍵詞:python郵件發送;定時
一、 用python實作郵件發送
用程式實作郵件收發的三個角色:
MUA (mail user agent, 郵件用戶代理)
MTA (mail transfer agent, 郵件傳輸代理)
MDA (mail delivery agent, 郵件投遞代理)
發郵件:MUA → MTA【使用SMTP協議】
收郵件:MUA ← MDA 【使用POP3/IMAP4協議】
Python對SMTP的支持有smtplib和email兩個模塊,email負責構造郵件,smtplib負責發送郵件
電子郵件訊息由headers(標題)和payloads(有效負載, 也稱為內容)組成,headers是RFC 5322或RFC
6532風格的欄位名和值,欄位名和值用冒號分隔,冒號既不是欄位名的一部分也不是欄位值的一部分,payloads可以是一個簡單的文本訊息,或者一個二進制物件,或者一個結構化的子訊息序列,每個子訊息都有自己的頭部集和有效負載,后一種型別的payloads由MIME型別的訊息來指示,例如multipart/**或message/rfc822*,
——19.1.1. email.message: Representing an email message
(一)用到的模塊
【1. email】
(1) email.mime: Python檔案中對mime的介紹
email.mime.text.MIMEText(_text, _subtype=‘plain’, _charset=None, *, policy=compat32)
類MIMEText用來生成一個主要型別為text的MIME物件,
(2) email.utils.parseaddr(address)
email.utils.formataddr((name_encoded_by_Header, address))
寫郵件的時候,Email的地址可以有兩種寫法,一種寫法是:xxx@qq.com,另一種寫法是:name<xxx@qq.com>,用前者寫法,在郵箱中就會顯示為xxx<xxx@qq.com>;用后者,就會顯示為name<xxx@qq.com>,更為清晰、專業,
有的時候,用前者寫法也會顯示name,是因為對方郵箱中保存了這個地址,類似于對方手機中保存了手機號和姓名而parseaddr函式就是將str “name<xxx@qq.com>”轉換成一個tuple,
In[48]: a = parseaddr('name<xxx@126.com>')
In[49]: a
Out[49]: ('name', 'xxx@126.com')
In[50]: type(a)
Out[50]: tuple
In[53]: name, addr = parseaddr('boy<xxx@126.com>')
In[54]: name
Out[54]: 'boy'
In[55]: addr
Out[55]: 'xxx@126.com'
決議出name和address后,需要用formataddr()函式將其變為標準的email地址,
標準的email地址格式為’name <address>’,因此formataddr()與parseaddr()相反,會將tuple轉換成str,
注意:formataddr()接收的name需要經Header()進行編碼處理后才行,【注1】
from email.header import Header
In[67]: name, addr = parseaddr('boy<xxx@126.com>')
In[68]: a = formataddr((name, addr)) # 將name直接傳入
In[69]: b = formataddr((Header(name, 'utf-8').encode(), addr)) # 將name用Header()編碼處理后傳入
In[70]: a
Out[70]: 'boy <xxx@126.com>'
In[71]: b
Out[71]: '=?utf-8?q?boy?= <xxx@126.com>' #下文msg[’From‘]和msg['To']只識別這種格式
構建郵件正文:
from email.mime.text import MIMEText
from email.header import Header
from email.utils import parseaddr, formataddr
# 撰寫一個進行地址決議、生成標準地址格式的函式
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), addr))
# 設定郵件內容
msg = MIMEText('This is an email for testing.', 'plain', 'utf-8')
# 設定郵件收發件人名稱、主題等
'''
收發件人名稱、主題,不是通過SMTP發送給MTA的,而是包含在發送給MTA的文本中(msg),
'''
msg['From'] = _format_addr('發件人名 <%s>' % '發件人郵箱'
msg['To'] = _format_addr('收件人名 <%s>' % '收件人郵箱' #msg['From']和msg['To']直接使用formataddr后的字串,如果有多個這樣的字串地址,用逗號(,)分開,
msg['Subject'] = Header('TEST', 'utf-8').encode() # 此處,主題也經過了Header的編碼處理
純文本郵件:MIMEText(‘文本’, ‘plain’, ‘utf-8’)
HTML郵件:MIMEText(‘HTML字串’, ‘html’, ‘utf-8’)
【2. smtplib】
在使用email構建好郵件正文后,用smtplib來發送郵件,
smtplib模塊定義了一個SMTP客戶端會話物件,可以使用該物件向任何具有SMTP或ESMTP偵聽程式守護行程的Internet機器發送郵件,有關SMTP和ESMTP操作的詳細資訊,請參考RFC 821 (Simple Mail Transfer Protocol)和RFC 1869 (SMTP服務擴展),
——21.17. smtplib — SMTP protocol client
smtplib.SMTP()函式,設定服務器地址和埠號
smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)
常用郵箱的服務器(SMTP/POP3)地址和埠總結
163.com:
POP3服務器地址:pop.163.com(埠:110)
SMTP服務器地址:smtp.163.com(埠:25)
126郵箱:
POP3服務器地址:pop.126.com(埠:110)
SMTP服務器地址:smtp.126.com(埠:25)
139郵箱:
POP3服務器地址:POP.139.com(埠:110)
SMTP服務器地址:SMTP.139.com(埠:25)
QQ郵箱:
POP3服務器地址:pop.qq.com(埠:110)
SMTP服務器地址:smtp.qq.com (埠:25)
QQ企業郵箱 :
POP3服務器地址:pop.exmail.qq.com (SSL啟用 埠:995)
SMTP服務器地址:smtp.exmail.qq.com(SSL啟用 埠:587/465)
gmail(google.com) :
POP3服務器地址:pop.gmail.com(SSL啟用 埠:995)
SMTP服務器地址:smtp.gmail.com(SSL啟用 埠:587)
Foxmail:
POP3服務器地址:POP.foxmail.com(埠:110)
SMTP服務器地址:SMTP.foxmail.com(埠:25)
sina.com:
POP3服務器地址:pop3.sina.com.cn(埠:110)
SMTP服務器地址:smtp.sina.com.cn(埠:25)
——常用郵箱的服務器(SMTP/POP3)地址和埠總結
設定發送引數:
from_addr = 'xxx@126.com'
password = 'GJZDZMUF' # 密碼或郵箱授權碼
to_addr = 'xxx@foxmail.com'
smtp_server = 'smtp.126.com'
server = smtplib.SMTP(smtp_server, 25) # 設定服務器和埠號
server.set_debuglevel(1) # 列印出和SMTP服務器互動的所有資訊,如果沒有這一陳述句,將不列印任何資訊
server.login(from_addr, password) # 進行登錄
server.sendmail(from_addr, [to_addr], msg.as_string())
# 1. msg.as_string()把MIMEText物件變成str(包含utf-8編碼資訊和Base64編碼)
# 2. [to_addr]表示可以有多個收件人,多個收件人,傳入list,當然,也可以在前面to_addr處直接用list進行賦值,那么此處就不是傳入[to_addr],而是傳入to_addr了
server.quit()
二、定時
待續,
三、遇到的錯誤
【注1】實際操作時,如果傳入未被Header編碼處理的name,發送郵件時暫未發現報錯(英文與中文皆是),因此此處待進一步驗證,
參考資料:
SMTP發送郵件
從Python email模塊理解郵件生命周期及MIME
python:利用smtplib模塊發送郵件詳解
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/240537.html
標籤:python
上一篇:Python入門
