Skip to main content
 首页 » 编程设计

python之SMTP 邮件客户端 Python

2024年11月01日35yxwkf

我必须在类里面用 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% 的时间都可以在你平台上的本地主机上工作.