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

1.系统功能设计

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

2.系统功能流程图

3.系统功能实现测试

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

流程如下:

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

图3

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

2.验证身份

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

图4

3.邮件传送

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

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

# 选择一个邮件服务

mailServer = "smtp.qq.com"

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

fromAddress = "2485947593@qq.com"

toAddress = "3050387300@qq.com"

图5

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

4.连接释放

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

图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 = "2485947593@qq.com"
toAddress = "3050387300@qq.com"
# 发送方,验证信息,由于邮箱输入信息会使用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——参数格式错误

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要让客户端运行 Python 代码,可以使用 Python 的 `exec()` 函数将代码字符串作为参数传递给它。同时,需要使用 Python 的 `socket` 模块实现网络通信。 以下是一个简单的客户端-服务器程序,其中客户端可以将要运行的 Python 代码字符串发送给服务器,服务器会执行代码并将结果返回给客户端: 服务器端代码: ```python import socket HOST = '' # 服务器 IP 地址 PORT = 8888 # 服务器端口号 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen(1) print('Server started...') def execute_code(code): # 执行代码并返回结果 try: exec(code) return 'Execution succeeded.' except Exception as e: return 'Execution failed: ' + str(e) while True: conn, addr = s.accept() print('Connected by', addr) while True: data = conn.recv(1024) if not data: break code = data.decode() result = execute_code(code) conn.sendall(result.encode()) conn.close() ``` 客户端代码: ```python import socket HOST = 'localhost' # 服务器 IP 地址 PORT = 8888 # 服务器端口号 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) code = ''' print('Hello, world!') ''' s.sendall(code.encode()) while True: data = s.recv(1024) if not data: break result = data.decode() print(result) s.close() ``` 在客户端代码中,将要运行的 Python 代码字符串存储在 `code` 变量中,并将其编码为字节串后发送给服务器。然后,客户端等待服务器返回执行结果,并将其解码为字符串后打印出来。 这只是一个简单的示例程序,实际应用中需要考虑更多的安全性和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古镇口听海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值