首页 > 解决方案 > ConnectionResetError: [WinError 10054] 现有连接被远程主机 (SMTP) 强行关闭

问题描述

我正在尝试使用 SMTP 套接字从一个 gmail 帐户向另一个帐户发送一封测试电子邮件。我已允许来自我的客户 gmail 帐户的不安全访问。

在登录阶段,代码在这里中断:

#Send username as Base64 encoded string
username = (username + '\r\n').encode()
command = base64.b64encode(username)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

我收到 10054 错误消息,并尝试使用 wireshark 分解发生的事情,但我并不真正了解发生了什么。它似乎是基于 google smtp 服务器的服务器端加密。我是套接字编程的新手,感谢您的耐心等待!

其余代码:

from socket import *
import time
import base64

print("")

username = input("Enter your mail.com username : ")
password = input("Enter your mail.com password : ")
rec = input("\nEnter the recipient's email address : ")
name = input("\nEnter your name : ")
subject = input("\nEnter the subject for your mail : \n")

message = ["SMTP client is awesome \r\n", "123456789 \r\n","Networking is cool. \r\n"]

print("")

endmsg = "\r\n.\r\n"

# Choose a mail server (e.g. Google mail server) and call it mailserver
mailserver = "smtp.gmail.com"
mailserverPort = 587

# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((mailserver, mailserverPort))

resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send EHLO (for Extended SMTP) command and print server response.
heloCommand = 'EHLO 127.0.0.1 \r\n'
print('C: ' + heloCommand)
clientSocket.send(heloCommand.encode())
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Authentication start mail server client
command = 'STARTTLS \r\n'
print('C: ' + command)
clientSocket.send(command.encode())
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Authentication required for the mail.com server I'm using
command = 'AUTH LOGIN \r\n'
print('C: ' + command)
clientSocket.send(command.encode())
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send username as Base64 encoded string
username = (username + '\r\n').encode()
command = base64.b64encode(username)
#print('C: ' + command.decode())
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send password as Base64 encoded string
password = (password + '\r\n').encode()
command = base64.b64encode(password)
print('C: ' + command)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send MAIL FROM command and print server response.
command = "MAIL FROM: <" + username + ">\r\n"
print('C: ' + command)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send RCPT TO command and print(server resp.decode()onse.
command = "RCPT TO: <" + rec + ">\r\n"
print('C: ' + command)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send DATA command and print server response.
command = "DATA\r\n"
print('C: ' + command)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

# Send message headers
# Gmail does not accept mail without headers to prevent spam
command = 'From: ' + name + ' <' + username + '>' + '\r\n'
print('C: ' + command)
clientSocket.send(command)
command = 'To: ' + rec + '\r\n'
print('C: ' + command)
clientSocket.send(command)
command = 'Date: ' + time.asctime( time.localtime(time.time()) ) + '\r\n'
print('C: ' + command)
clientSocket.send(command)
command = 'Subject: ' + subject + '\r\n'
print('C: ' + command)
clientSocket.send(command)

# Send message data.
clientSocket.send('\r\n')
for msg in message:
    print('C: ' + msg)
    clientSocket.send(msg)

# Message ends with a single period.
print('C: ' + endmsg)
clientSocket.send(endmsg)

# Send QUIT command and get server resp.decode()onse.
command = "QUIT\r\n"
print('C: ' + command)
clientSocket.send(command)
resp = clientSocket.recv(1024)
print('S: ' + resp.decode())

标签: pythonsocketsnetworkingsmtp

解决方案


STARTTLS命令请求启动 SSL/TLS 加密会话。但是您的代码中根本没有 SSL/TLS 逻辑。如果服务器回复成功STARTTLS,则您的客户端必须启动并完成成功的 SSL/TLS 握手,然后才能发送任何进一步的 SMTP 命令。SSL/TLS 会话要求对这些命令(及其响应)进行加密。

由于您没有遵守协议,您将被强制断开连接。所以要么不要使用STARTTLS(在这种情况下,你AUTH可能会失败),或者在你的套接字上正确实施 SSL/TLS。

顺便说一句,您不应该启用对您的 Gmail 帐户的“不安全访问”。让Gmail 创建一个特定于应用程序的密码并使用它来代替您的真实密码。


推荐阅读