3

我必须用 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
4

1 回答 1

2

最可能的问题是这个:

mailfromCommand = 'MAIL FROM: <mail@mail.com>\r\n.'

注意到最后的额外内容.了吗?因此,您向服务器发送的内容最终是:

MAIL FROM: <mail@mail.com>
.RCPT TO: <myemail@gmail.com>

并且.RCPT是语法错误。


但是,代码中还有另外两个非常严重的问题。

首先是无法保证send发送您提供的所有数据。这就是为什么它返回实际发送的字节数。因此,您很容易最终将其作为命令的一部分发送。

这个解决起来很简单:只需使用sendall而不是send.


第二个是不能保证每个recv人都能得到准确的一行数据。它可能在一个中包含 6 个字符recv,然后在下一个中包含 19 行。TCP 套接字是字节流,而不是消息流,您可以在其之上为您的协议构建消息流。

想象一下,如果你进入250 mail@mail.com Addr一个recv,然后ess OK\r\n250 myemail@gmail.com Address OK\r\n进入下一个,会发生什么。您将检查第二个是否以 开头250,发现不是,然后失败。

这个问题一般来说解决起来并不容易——通常你必须缓冲和解析消息,这意味着要么编写一个生成器,要么完全重新组织你的代码。

但是对于像 SMTP 这样的逐行协议,这很容易:只需使用makefile,它会返回一个文件对象,您可以对其进行迭代或调用readline,它会神奇地为您处理缓冲。


看起来这三个错误显然都在你老师给你的代码中。更不用说末尾的分号之类的东西了helloCommand = 'HELO Alice\r\n'(对于实际上并不了解 Python 的人编写的代码,这是一个危险信号)。您可能想阅读Socket Programming HOWTO,或者,更好的是,更完整的教程(希望 Google 可以为您找到),以便您学习如何实际编写工作程序,而不是在 localhost 上几乎 99% 的时间都可以工作的废话当计算机不太忙时在您的平台上。

于 2013-11-02T00:56:32.440 回答