背景知識
- 了解 SMTP協(xié)議詳解以及工作過程
重點了解“SMTP的連接和發(fā)送過程”和“SMTP常用的命令” - copy官方給的python代碼框架
1)梳理邏輯(摘自SMTP的連接和發(fā)送過程):
(a)建立TCP連接(使用Socket)
(b)客戶端發(fā)送HELO/EHLO命令以標識發(fā)件人自己的身份缸兔, 接受 服務(wù)器端響應(yīng)蚓挤;
(c)客戶端發(fā)送AUTH LOGIN登錄請求允坚,接著發(fā)送用戶名和密碼;
(d)客戶端發(fā)送RCPT命令胎食,以標識該電子郵件的計劃接收人,可以有多個RCPT行肴颊;
(e)協(xié)商結(jié)束奸例,發(fā)送郵件,用命令DATA發(fā)送
(f)以.表示結(jié)束輸入內(nèi)容一起發(fā)送出去
(g)結(jié)束此次發(fā)送赡模,用QUIT命令退出
2)每個命令都以\r\n
結(jié)尾田炭,特定格式命令:
HELO
:HELO <domain> <CRLF>
RCPT TO
:<forward-path> <CRLF>——<forward-path>
3)選擇郵箱服務(wù)器
gmail還要翻墻,棄用(? 漓柑。?)
我是使用網(wǎng)易郵箱作為郵箱服務(wù)器教硫,公司郵箱作為目標賬戶叨吮。
網(wǎng)易郵箱需要提前進行一些設(shè)置,開啟STMP功能瞬矩,方法如下:
- 登錄郵箱 -- 設(shè)置 -- 進入POP3/SMTP/IMAP界面茶鉴,可以看最下面提示有SMTP服務(wù)器:
smtp.163.com
- 勾選 IMAP/SMTP服務(wù),會彈出提示設(shè)置授權(quán)碼
- 進入設(shè)置授權(quán)碼丧鸯,開啟服務(wù)蛤铜,這里需要手機號碼驗證(如果你和我一樣,關(guān)聯(lián)的手機號碼已經(jīng)不知道丟哪里了丛肢,可以換一個綁定當前手機的網(wǎng)易郵箱围肥,(^ ^)),總之蜂怎,設(shè)置好授權(quán)碼后穆刻,這個授權(quán)碼就是代碼里的
password
下面是最終代碼展示:
from socket import *
import base64
msg = 'I love computer networks!'
endmsg = '\r\n.\r\n'
# 郵件服務(wù)器,端口 25
mailserver = 'smtp.163.com'
fromaddr = 'z****@163.com' # 填寫自己的郵箱
toaddr = 'z***@***.com' # 填寫目標郵箱
username = 'z****@163.com'
password = 'a*****6' # 網(wǎng)易郵箱授權(quán)碼
# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((mailserver, 25))
recv = clientSocket.recv(1024).decode()
print(recv)
if recv[:3] != '220':
print('220 reply not received from server.')
# Send HELO command and print server response.
heloCommand = 'HELO Alice\r\n'
clientSocket.send(heloCommand.encode())
recv1 = clientSocket.recv(1024).decode()
print(recv1)
if recv1[:3] != '250':
print('250 reply not received from server.')
# send AUTH LOGIN command
base64_str = ('\x00' + username + '\x00' + password).encode()
base64_str = base64.b64encode(base64_str)
authCommand = 'AUTH PLAIN '.encode() + base64_str + '\r\n'.encode()
clientSocket.send(authCommand)
recv_auth = clientSocket.recv(1024)
print(recv_auth.decode())
# Send MAIL FROM command and print server response.
mailCommand = 'MAIL FROM: <' + fromaddr + '>\r\n'
clientSocket.send(mailCommand.encode())
recv_from = clientSocket.recv(1024).decode()
print(recv_from)
if recv_from[:3] != '250':
print('250 reply not received from server.')
# Send RCPT TO command and print server response.
rcptCommand = 'RCPT TO: <' + toaddr + '>\r\n'
clientSocket.send(rcptCommand.encode())
recv_rcpt = clientSocket.recv(1024).decode()
print(recv_rcpt)
if recv_rcpt[:3] != '250':
print('250 reply not received from server.')
# Send DATA command and print server response.
clientSocket.send('DATA\r\n'.encode())
recv_data = clientSocket.recv(1024).decode()
print(recv_data)
if (recv_data[:3] != '354'):
print('354 reply not received from server')
# Send message data.
send_msg = 'from: ' + fromaddr + '\r\n'
send_msg += 'to: ' + toaddr + '\r\n'
send_msg += 'subject: ' + msg + '\r\n'
send_msg += 'content-type: text/plain\t\n'
send_msg += '\r\n' + msg
clientSocket.send(send_msg.encode())
# Message ends with a single period.
clientSocket.send(endmsg.encode())
recv = clientSocket.recv(1024).decode()
print(recv)
if (recv[:3] != '250'):
print('250 reply not received from server')
# Send QUIT command and get server response.
clientSocket.send('QUIT\r\n'.encode())
# close
clientSocket.close()
結(jié)果:
bb.png