Python TCP Socket中SMTP请求被拒,但Telnet可正常运行的原因与解决
邮件验证器SMTP连接问题排查与修复
问题现象
用Python TCP Socket调试SMTP功能时收到错误响应:
554 smtp6.server.rpi.edu ESMTP not accepting messages 250 smtp6.server.rpi.edu Hello [IP Address Redacted], pleased to meet you 550 5.0.0 Command rejected 550 5.0.0 Command rejected
但用Telnet操作时完全正常:
250 smtp4.server.rpi.edu Hello [REDACTED IP], pleased to meet you MAIL FROM: <> 250 2.1.0 <>... Sender ok RCPT TO: <[Address]> 250 2.1.5 <[Address]>... Recipient ok QUIT 221 2.0.0 smtp4.server.rpi.edu closing connection
原Python代码如下:
import socket; data = [ "HELO www", "MAIL FROM: <>", "RCPT TO: <[Address]>" ]; miniSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); miniSock.connect(("mail.rpi.edu", 25)); for i in data: miniSock.send(bytes("" + i + "\r\n", 'utf-8')); res = miniSock.recv(5000); print(str(res, "utf-8"));
问题原因
- 违反SMTP协议交互顺序:Socket连接成功后,服务器会先发送一条
220开头的初始问候报文,但你的代码直接发送HELO命令,完全忽略了这一步,导致服务器无法正确解析后续指令,返回拒绝错误。 - 负载均衡节点差异:
mail.rpi.edu是负载均衡域名,会分配到不同的SMTP节点(比如报错的smtp6和Telnet成功的smtp4),部分节点对协议顺序的校验更严格,放大了这个问题。
修复方案
修改代码先接收服务器的初始问候,同时改用现代SMTP标准的EHLO命令替代HELO,主动发送QUIT关闭连接。
修复后的代码:
import socket def main(): target_server = "mail.rpi.edu" target_port = 25 commands = [ "EHLO localhost", "MAIL FROM: <>", "RCPT TO: <[Address]>", "QUIT" ] # 建立Socket连接 miniSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) miniSock.connect((target_server, target_port)) # 先接收服务器的初始问候响应 initial_response = miniSock.recv(5000).decode('utf-8') print("初始响应:", initial_response) # 逐个发送命令并接收返回 for cmd in commands: miniSock.send(f"{cmd}\r\n".encode('utf-8')) response = miniSock.recv(5000).decode('utf-8') print(f"\n命令: {cmd}") print("响应:", response) # 关闭连接 miniSock.close() if __name__ == "__main__": main()
关键修复点说明
- 接收初始问候:连接成功后先读取服务器的
220响应,确保后续命令在正确的协议阶段发送。 - EHLO替代HELO:
EHLO是SMTP标准命令,会触发服务器返回扩展功能支持,兼容性远好于老旧的HELO。 - 主动发送QUIT:符合SMTP会话的完整流程,避免服务器侧出现半开连接。
- 代码优化:去掉不必要的分号,用函数封装提升可读性,使用f-string简化字符串拼接。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

