我必须在类里面用 Python 编写一个 SMTP 邮件客户端,并且卡在作业的第一部分。经过许多麻烦后,我已经走到这一步(目前使用免费可移植 SMTP 服务器,但稍后需要为 gmail 使用 SSL 或 TLS)。下面是我的代码。当它到达代码的 RCPT TO 部分时,我收到 500 语法错误。谁能帮忙?
from socket import *
msg = "\r\n I love computer networks!"
endmsg = "\r\n.\r\n"
# Choose a mail server
mailServer = 'localhost'
mailPort = 25
# Create socket called clientSocket and establish a TCP connection with mailserver
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((mailServer, mailPort))
recv = clientSocket.recv(1024)
print 'test'
print recv
if recv[:3] != '220':
print '220 reply not received from server.'
# Send HELLO command and print server response.
helloCommand = 'HELO Alice\r\n';
clientSocket.send(helloCommand)
recv1 = clientSocket.recv(1024)
print recv1
if recv1[:3] != '250':
print '250 reply not received from server.'
# Send MAIL FROM command and print server response.
#command = "STARTTLS\r\n"
#clientSocket.send(command)
#recva = clientSocket.recv(1024)
#print(recva)
mailfromCommand = 'MAIL FROM: <mail@mail.com>\r\n.'
clientSocket.send(mailfromCommand)
recv1 = clientSocket.recv(1024)
print(recv1)
if recv1[:3] != '250':
print('mail from 250 reply not received from server.')
# Send RCPT TO command and print server response.
rcpttoCommand = 'RCPT TO: <myemail@gmail.com>\r\n'
clientSocket.send(rcpttoCommand)
recv1 = clientSocket.recv(1024)
print(recv1)
if recv1[:3] != '250':
print('rcpt to 250 reply not received from server.')
# Send DATA command and print server response
dataCommand = 'Data'
print(dataCommand)
clientSocket.send(dataCommand)
recv1 = clientSocket.recv(1024)
print(recv1)
if recv1[:3] != '250':
print('data 250 reply not received from server.')
# Send message data.
message = raw_input('Enter Message Here: ')
# Fill in end# Message ends with a single period.
mailMessageEnd = '\r\n.\r\n'
clientSocket.send(message + mailMessageEnd)
recv1 = clientSocket.recv(1024)
print(recv1)
if recv1[:3] != '250':
print('end msg 250 reply not received from server.')
# Send QUIT command and get server response.
quitCommand = 'Quit\r\n'
print(quitCommand)
clientSocket.send(quitCommand)
recv1 = clientSocket.recv(1024)
print(recv1)
if recv1[:3] != '250':
print('quit 250 reply not received from server.')
pass
if __name__ == '__main__':
main()
结果:
test
220 localhost
250 Hello localhost
250 mail@mail.com Address Okay
RCPT TO: <myemail@gmail.com>
500 Syntax Error
rcpt to 250 reply not received from server.
Data
请您参考如下方法:
最有可能的问题是这个:
mailfromCommand = 'MAIL FROM: <mail@mail.com>\r\n.'
注意到最后多出来的 . 了吗?所以,您发送给服务器的最终结果是:
MAIL FROM: <mail@mail.com>
.RCPT TO: <myemail@gmail.com>
而.RCPT是语法错误。
但是,代码中还有另外两个非常严重的问题。
首先是不能保证 send发送你给它的所有数据。这就是它返回实际发送的字节数的原因。因此,您很可能最终将其作为命令的一部分发送。
这个问题很容易解决:只需使用 sendall 而不是 send。
第二个是不能保证每个recv 都会得到一行数据。它可能在一个 recv 中得到 6 个字符,然后在下一个中得到 19 行。 TCP sockets are byte streams, not message streams ,您可以在其之上为您的协议(protocol)构建消息流。
想象一下,如果您在一次 recv 中获得 250 mail@mail.com Addr,然后 ess OK\r\n250 myemail@gmail.com 会发生什么地址OK\r\n在下。您将检查第二个是否以 250 开头,发现不是,然后失败。
这个问题一般来说不是那么容易解决——通常你必须缓冲和解析消息,这意味着要么写一个生成器,要么完全重新组织你的代码。
但是对于像 SMTP 这样的逐行协议(protocol),这很简单:只需使用 makefile ,它返回一个文件对象,您可以对其进行迭代或调用 readline,它会神奇地为您处理缓冲。
看起来所有这三个错误显然都在您的老师给您的代码中。更不用说 helloCommand = 'HELO Alice\r\n' 末尾的分号之类的东西(对于实际上不懂 Python 的人编写的代码来说,这是一个危险信号)。您可能想阅读 Socket Programming HOWTO ,或者更好的是,一个更完整的教程(谷歌希望能为你找到)这样你就可以学习如何实际编写工作程序而不是废话,当计算机不太忙时,几乎 99% 的时间都可以在你平台上的本地主机上工作.
