最近編寫自動化郵件監控時,因爲公司的郵箱是outlook
, 自動化有兩種方式, 這邊記錄一下已被以後使用html
發件人 —> MUA
-> MTA
-> 若干個MTA
- MDA
<- MUA
<- 收件人python
發件人經過電子郵件軟件
MUA
將郵件傳輸給本電子郵件的@163.com
則會傳遞給網易的服務器MTA
,再由服務提供商投遞到對方的服務器MDA
存儲,若是郵件的接收方是@sina.com
則投遞到新浪的服務器MDA
上, 若是對方要收取郵件, 則須要經過MUA
從對應的MDA
中提取郵件.編程
郵件的內容其實都存在
MUA
上, 即從電子郵箱軟件看到的內容. 操做電子郵件軟件的郵件就是直接操做MUA
上的內容.windows
名詞 | 釋義 |
---|---|
MUA |
Mail User Agent , 電子郵件軟件, 好比outlook 、foxmail |
MTA |
Mail Transfer Agent , 郵件傳輸代理,即Email 服務提供商,好比網易、新浪 |
MDA |
Mail Delivery Agent , 郵件投遞代理, 即服務提供商的服務器 |
有了以上的概念, 那麼收發郵件的本質就是:安全
MUA
把郵件發送到MTA
. 此時使用的協議就是SMTP
協議.MUA
從MDA
上收郵件.在郵件客戶端在發送郵件時會先配置SMTP
服務器, 也就是須要發到哪一個MTA
上. 若是此時你用的是@163.com
,則只能發也必須發到網易的MTA
, 新浪的MTA
是不服務網易的用戶的. 爲了驗證你是網易的用戶, 所以SMTP
服務器要求提供郵件地址和郵件口令.服務器
協議名 | 釋義 |
---|---|
MIME |
多用途互聯網郵件擴展類型。是設定某種擴展名的文件用一種應用程序來打開的方式類型 |
SMTP |
Simple Mail Transfer Protocol , 郵件發送協議,創建在FTP文件傳輸服務上的一種郵件服務. |
POP |
Post Office Protocol , 目前的版本是3, 俗稱POP3 ; 郵件接收協議, 本協議主要用於支持使用客戶端遠程管理在服務器上的電子郵件。 |
IMAP |
Internet Message Access Protocol , 目前版本是4, 交互郵件訪問協議, 它的主要做用是郵件客戶端能夠經過這種協議從郵件服務器上獲取郵件的信息,下載郵件, 直接操做MDA 上存儲的郵件,好比從收件箱一道垃圾箱. |
## pop協議
import poplib ## python內置庫
## 郵件解析
from email.parser import Parser ## 解析郵件原始文本
from email.header import decode_header
from email.utils import parseaddr
## smtp協議
import smtplib
## 郵件構造
from email.mime.text import MIMEText
複製代碼
pop3
協議收取的不是一個能夠閱讀的郵件自己, 而是郵件的原始文本, 須要使用
## 基礎配置
email_address = 'xxx@outlook.com'
email_password = 'xxxx'
pop_server_host = 'partner.outlook.cn' ## 公司級(office365)的連接地址, 我的申請的可能不一樣
pop_server_port = 995 ## 端口
## 登陸郵件
### 連接pop服務器
email_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10)
email_server = poplib.POP3(host=pop_server_host, port=pop_server_port, timeout=10)
### 驗證郵箱是否存在
email_server.user(email_address)
### 驗證郵件密碼是否正確
email_server.pass_(email_password)
複製代碼
## 返回郵件數量和佔用空間
email_server.stat()
## 返回郵件編號
resp, mails, octets = email_server.list()
## 返回郵件數量
index = len(mails)
## 獲取特定序號郵件, 索引從1開始
resp, lines, octets = email_server.retr(index) ## lines 儲存郵件原始文本全部信息.
## 獲取郵件原始文本
email_content = b'\r\n'.join(lines).decode('utf-8')
## 解析郵件文本
## 解析爲`Message`對象, 此時對象自己多是一個`MIMEMultipart`對象, 即包含嵌套的其餘`MIME`對象, 嵌套可能還不止一層.
content = Parser().parsestr(email_content)
複製代碼
## 刪除郵件
## 經過郵件索引號直接從服務器刪除郵件.
email_server.dele(index)
## 關閉鏈接
email_server.quit()
複製代碼
MIME
(Multipurpose Internet Mail Extensions
): 描述消息內容類型的因特網標準, 能包含文本、圖像、音頻、視頻以及其餘應用程序專用的數據ui
MIME參考手冊: www.w3school.com.cn/media/media…編碼
類型/子類型 | 擴展名 |
---|---|
application/pdf |
pdf |
image/jpeg |
jpe /jpg /jpeg |
## Suject解析
## 郵件的Subject或者Email中包含的名字都是通過編碼後的str, 要正常顯示, 就必須decode.
def decode_str(s):
value, charset = decode_header(s)[0] ## decode_header()返回的是一個list, 抄送多人時會返回多個元素. 能夠用索引選擇對應元素.
if charset: ## charset是獲得的編碼類型
value = value.decode(charset)
return value
## 獲得對應元素好比說收件人、發件人的原始文本值
for header in ['From','To','Subject']
content = content.get(header,'')
## Subject解析
value = decode_str(value) ## 此時header = 'Subject'
複製代碼
## From、To解析 發件人、收件人解析
hdr, addr = parseaddr(value) ## 此時header in ('From','To')
name = decode_str(hdr)
複製代碼
## 郵件正文解析
## 郵件文本也是str,須要檢測編碼,不然非utf-8編碼的郵件沒法正常顯示
## 編碼確認
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
## 正文解析
content_type = content.get_content_type()
if content_type = 'text/plain' or content_type = 'text/html':
content_email = content.get_payload(decode=True)
charset = guess_charset(content)
if charset:
content_email = content_email.decode(content)
複製代碼
Python
對SMTP
支持有smtplib
和email
兩個模塊,email
負責構建郵件,smtplib
負責發送郵件.spa
## 基礎數據
### 發件人 密碼 收件人 服務器
from_addr = 'xxx@163.com'
password = 'xxxx'
to_addr = 'xxx@outlook.com'
smtp_server = 'smtp.163.com'
## 構建基礎文件
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name,'utf-8').encode(), addr))
msg = MIMEText('hello, send by Python...','plain','utf-8')
msg['From'] = _format_addr('name <%s>' % from_addr)
msg['To'] = _format_addr('name <%s>' % to_addr)
msg['Subject'] = Header('來自SMTP的問候...','utf-8').encode()
## 郵件發送
server = smtplib.SMTP(smtp_server,25) # SMTP協議默認端口是25, 25端口是明文傳輸 若是要SSL安全鏈接 則須要: server.starttls()
server.ser_debuglevek(1) ## 打印初和SMTP服務器交互的全部信息
server.login(from_addr,password)
server.sendmail(from_addr, [to_addr], msg.as_string()) ## 郵件正文是一個`str` as_string()把MIMEText對象變成`str`.
server.quit()
複製代碼
配置用法的核心是經過pywin32
(python for windows
)庫調用本地outlook
配置(office
提供基於COM
接口的編程)進行郵件讀取, 但會存在一個問題讀取配置須要受權, 受權方法一是會喚起受權窗口進行短期臨時受權, 二是經過後臺配置進行永久受權.
## pip install pywin32
import win32com
複製代碼
## 啓動outlook進程
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") ## Dispatch派遣 即調用Outlook.Application.
## 獲取配置中全部帳號
accounts = win32com.client.Dispatch("Outlook.Application").Session.Accounts
## 獲取一級目錄
inbox = outlook.Folders(account.DeliveryStore.DisplayName)
folders = inbox.Folders
複製代碼