socket通信原理?10分钟掌握python socket实现邮件客户端吧!

1.系统功能设计

创建一个向任何接收方发送电子邮件的简单邮件客户。你的客户将必须与邮件服务器(如谷歌的电子邮件服务器)创建一个TCP连接,使用SMTP协议与该邮件服务器进行交谈,经该邮件服务器向某接收方(如你的朋友)发送一个电子邮件报文,最后关闭与该邮件服务器的TCP连接。

2.系统功能流程图

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第1张图片

3.系统功能实现测试

系统实现一个SMTP客户端,使用QQ邮箱作为发件人,向指定的QQ邮箱发送一封邮件。SMTP协议即简单邮件传输协议,允许用户按照标准发送/接收邮件。

流程如下:

1.建立TCP连接并域服务器交互

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第2张图片

图3

如图3所示qq邮件服务器建立连接,域名"smtp.qq.com",SMTP默认端口号25。建立连接后服务器将返回状态码220;与服务器的交互:发送"HELO"命令,开始与服务器的交互,服务器将返回状态码250(请求动作正确完成)。

2.验证身份

发送"AUTH LOGIN"命令,开始验证身份,服务器将返回状态码334(服务器等待用户输入验证信息)。发送经过base64编码的用户名,服务器等待用户输入验证信息,将返回状态码334。发送经过base64编码的密码(不是登录密码,而是开启SMTP时的授权码),用户验证成功,服务器将返回状态码235如图4所示。

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第3张图片

图4

3.邮件传送

msg = "\r\n I love computer networks!"

endMsg = "\r\n.\r\n"

# 选择一个邮件服务

mailServer = "smtp.qq.com"

# 发送方地址和接收方地址,from 和 to

fromAddress = "[email protected]"

toAddress = "[email protected]"

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第4张图片

图5

连接建立并且验证成功后,就可开始传送邮件。邮件的传送从MAIL FROM命令开始,MAIL 命令后面有发件人的地址。MAIL FROM: [email protected]。若SMTP服务器已准备好接收邮件,则回答250 OK。接着SMTP客户端发送一个或多个RCPT (收件人recipient的缩写)命令,格式为RCPT TO: <[email protected]>。每发送一个 RCPT命令,都应有相应的信息从SMTP服务器返回。正常情况下,SMTP服务器回复信息是354 Start mail input; end with . 。表示回车换行。此时SMTP客户端就可开始传送邮件内容,并用. (两个回车,中间一个点)表示邮件内容的结束。

4.连接释放

邮件发送完毕后,SMTP客户应发送QUIT命令。SMTP服务器返回的信息是221 (服务关闭),表示SMTP同意释放TCP连接。邮件传送的全部过程就此结束。同时,我们还可以登陆邮箱,查看邮件收发情况如图6、7所示

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第5张图片

图6

socket通信原理?10分钟掌握python socket实现邮件客户端吧!_第6张图片

图7

 4.源码

# SMTPClient.py
from socket import *
msg = "\r\n I love computer networks!"
endMsg = "\r\n.\r\n"
# 选择一个邮件服务
mailServer = "smtp.qq.com"
# 发送方地址和接收方地址,from 和 to
fromAddress = "[email protected]"
toAddress = "[email protected]"
# 发送方,验证信息,由于邮箱输入信息会使用base64编码,因此需要进行编码
username = "MjQ4NTk0NzU5M0BxcS5jb20="  # 输入自己的用户名对应的编码
password = "ZHRobnlvZmVyZGZsZWFpYg=="  # 此处不是自己的密码,而是开启SMTP服务时对应的授权码dthnyoferdfleaib

# 创建客户端套接字并建立连接
serverPort = 25  # SMTP使用25号端口
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((mailServer, serverPort))  # connect只能接收一个参数
# 从客户套接字中接收信息
recv = clientSocket.recv(1024).decode()
print(recv)
if '220' != recv[:3]:
print('220 reply not received from server.')

# 发送 HELO 命令并且打印服务端回复
# 开始与服务器的交互,服务器将返回状态码250,说明请求动作正确完成
heloCommand = 'HELO Alice\r\n'
clientSocket.send(heloCommand.encode())  # 随时注意对信息编码和解码
recv1 = clientSocket.recv(1024).decode()
print(recv1)
if '250' != recv1[:3]:
print('250 reply not received from server.')

# 发送"AUTH LOGIN"命令,验证身份.服务器将返回状态码334(服务器等待用户输入验证信息)
clientSocket.sendall('AUTH LOGIN\r\n'.encode())
recv2 = clientSocket.recv(1024).decode()
print(recv2)
if '334' != recv2[:3]:
print('334 reply not received from server.')

# 发送验证信息
clientSocket.sendall((username + '\r\n').encode())
recvName = clientSocket.recv(1024).decode()
print(recvName)
if '334' != recvName[:3]:
    print('334 reply not received from server')
clientSocket.sendall((password + '\r\n').encode())
recvPass = clientSocket.recv(1024).decode()
print(recvPass)

# 如果用户验证成功,服务器将返回状态码235
if '235' != recvPass[:3]:
    print('235 reply not received from server')
# TCP连接建立好之后,通过用户验证就可以开始发送邮件。邮件的传送从MAIL命令开始,MAIL命令后面附上发件人的地址。
# 发送 MAIL FROM 命令,并包含发件人邮箱地址
clientSocket.sendall(('MAIL FROM: <' + fromAddress + '>\r\n').encode())
recvFrom = clientSocket.recv(1024).decode()
print(recvFrom)
if '250' != recvFrom[:3]:
print('250 reply not received from server')

# 接着SMTP客户端发送一个或多个RCPT (收件人recipient的缩写)命令,格式为RCPT TO: <收件人地址>。
# 发送 RCPT TO 命令,并包含收件人邮箱地址,返回状态码 250
clientSocket.sendall(('RCPT TO: <' + toAddress + '>\r\n').encode())
recvTo = clientSocket.recv(1024).decode()  # 注意UDP使用sendto,recvfrom
print(recvTo)
if '250' != recvTo[:3]:
print('250 reply not received from server')

# 发送 DATA 命令,表示即将发送邮件内容。服务器将返回状态码354(开始邮件输入,以"."结束)
clientSocket.send('DATA\r\n'.encode())
recvData = clientSocket.recv(1024).decode()
print(recvData)
if '354' != recvData[:3]:
print('354 reply not received from server')

# 编辑邮件信息,发送数据
subject = "I love computer networks!"
contentType = "text/plain"
message = 'from:' + fromAddress + '\r\n'
message += 'to:' + toAddress + '\r\n'
message += 'subject:' + subject + '\r\n'
message += 'Content-Type:' + contentType + '\t\n'
message += '\r\n' + msg
clientSocket.sendall(message.encode())

# 以"."结束。请求成功返回 250
clientSocket.sendall(endMsg.encode())
recvEnd = clientSocket.recv(1024).decode()
print(recvEnd)
if '250' != recvEnd[:3]:
print('250 reply not received from server')

# 发送"QUIT"命令,断开和邮件服务器的连接
clientSocket.sendall('QUIT\r\n'.encode())
clientSocket.close()

附:了解SMTP协议(简单邮件传输协议)常见命令和响应

命令:

HELO——发送端的主机信息

MAIL FROM——发件人

RCPT TO—— 收件人,可以有多个

DATA——邮件主体内容

QUIT——断开连接

VRFY—— 需要对收件人名字进行验证

EXPN——需要扩展的邮件发送清单

HELP——命令名

响应:

220——服务器就绪

221——服务关闭

421——服务器未就绪,关闭传输信道

250——要求的邮件操作完成

501——参数格式错误

你可能感兴趣的:(信息与通信,websocket,python,计算机网络)