使用Python調用郵件服務器發送郵件,使用的協議是SMTP(Simple Mail Transfer Protocol),下圖為使用TCP/IP基於SMTP發送郵件的過程示意圖:

SMTP協議工作原理:
SMTP工作在兩種情況下:一是電子郵件從用戶端傳輸到服務器:二是從某一個MTA(Message Transfer Agent)傳輸到另一個MTA。SMTP也是請求/響應協議,命令和響應都是基於NVT ASCII文本,並以CR和LF符結束。響應包括一個表示返回狀態的三位數字代碼。SMTP在TCP協議25號端口監聽連續請求。
SMTP連接和發送過程
Python使用SMTP發送郵件
在python中,發送郵件主要包括email 和smtplib,其中email 實現郵件構造,smtplib實現郵件發送。在smtplib庫中,主要主要用smtplib.SMTP()類,用於連接SMTP服務器,發送郵件。SMTP類中常用方法如
| 方法 |
描述 |
| SMTP.set_debuglevel(level) | 設置輸出debug調試信息,默認不輸出 |
| SMTP.docmd(cmd[, argstring]) | 發送一個命令到SMTP服務器 |
| SMTP.connect([host[, port]]) | 連接到指定的SMTP服務器 |
| SMTP.helo([hostname]) | 使用helo指令向SMTP服務器確認你的身份 |
| SMTP.ehlo(hostname) | 使用ehlo指令像ESMTP(SMTP擴展)確認你的身份 |
| SMTP.ehlo_or_helo_if_needed() | 如果在以前的會話連接中沒有提供ehlo或者helo指令,這個方法會調用ehlo()或helo() |
| SMTP.has_extn(name) | 判斷指定名稱是否在SMTP服務器上 |
| SMTP.verify(address) | 判斷郵件地址是否在SMTP服務器上 |
| SMTP.starttls([keyfile[, certfile]]) | 使SMTP連接運行在TLS模式,所有的SMTP指令都會被加密 |
| SMTP.login(user, password) | 登錄SMTP服務器 |
| SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) | 發送郵件 from_addr:郵件發件人 to_addrs:郵件收件人 msg:發送消息 |
| SMTP.quit() | 關閉SMTP會話 |
| SMTP.close() | 關閉SMTP服務器連接 |
python中通過SMTP發送郵件主要包括以下幾個步驟(以qq郵箱為例):
1. 開通郵箱SMTP服務,獲取郵箱授權碼,郵箱SMTP開通路徑:郵箱設置/賬戶/POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務

2. 編輯郵件內容,主要包括三部分內容:信封,首部和正文;其中信封包括發送郵箱,接收郵箱等;
3. 初始化配置信息,調用SMTP發送郵件
代碼實現如下所示,其中python版本為3.7:
1 import smtplib
2 import email.utils
3 from email.mime.text import MIMEText
4
5 class Msg():
6 def __init__(self):
7 pass
8
9 @staticmethod
10 def creat_msg():
11 # Creat mail information
12 msg = MIMEText('Come on', 'plain', 'utf-8')
13 msg['From'] = email.utils.formataddr(('Author', 'xxxxxxxxxx@qq.com'))
14 msg['To'] = email.utils.formataddr(('Recipient', 'xxxxxxxxx@163.com'))
15 msg['Subject'] = email.utils.formataddr(('Subject', 'Good good study, day day up!'))
16
17 return msg
18
19 class EmailServer():
20 def __init__(self):
21 pass
22
23 @staticmethod
24 def config_server():
25 # Configure mailbox
26 config = dict()
27 config['send_email']= 'xxxxxxxxxx@qq.com'
28 config['passwd'] = 'xxxxxxxxxx'
29 config['smtp_server'] = 'smtp.qq.com'
30 config['target_email'] = 'xxxxxxxxxx@163.com'
31 return config
32
33 def send_email(self):
34 # Use smtp to send email to the target mailbox
35 msg = Msg.creat_msg()
36 config = self.config_server()
37
38 server = smtplib.SMTP()
39 server.connect(host=config['smtp_server'], port=25)
40 server.login(user=config['send_email'], password=config['passwd'])
41 server.set_debuglevel(True)
42
43 try:
44 server.sendmail(config['send_email'],
45 [config['target_email']],
46 msg.as_string())
47 finally:
48 server.quit()
49
50 if __name__ == '__main__':
51 emailServer = EmailServer()
52 emailServer.send_email()
發送郵件過程跟蹤如下:

經過測試,從QQ郵箱向163郵箱可正常發送郵件,從163郵箱發送到QQ郵箱則會進入垃圾箱,翻閱了不少資料,目前還沒有解決如何擺脫垃圾箱的困擾,如有知道的朋友,可在評論區解惑,不甚感謝~
參考文獻:
(1)https://blog.51cto.com/lizhenliang/1875330
(2)TCP/IP詳解卷1:協議
