【问题标题】:SMTP Mail Client PythonSMTP 邮件客户端 Python
【发布时间】:2013-11-02 09:19:07
【问题描述】:

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

【问题讨论】:

  • 你不能使用标准库和/或第三方包中的smtplib吗?
  • 同时,TCP sockets are byte streams, not message streams。每个recv可以从服务器获取半行数据,或者七行半;你不能假设每个人都有一条线。您需要缓冲和解析。或者只是使用makefile 让Python 执行此操作(适用于任何逐行协议,如SMTP),然后使用sendall 而不是send,就完成了。
  • 我们得到了一个基本的骨架代码,一直到 MAIL FROM 命令。之后我们必须填写其余部分。

标签: python syntax smtp


【解决方案1】:

最可能的问题是这个:

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,您可以在其上为您的协议构建消息流。

想象一下,如果你在一个recv 中输入250 mail@mail.com Addr,然后在下一个中输入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% 的时间都可以工作的废话当计算机不太忙时在您的平台上。

【讨论】:

  • 感谢您的收获。我非常感谢您的帮助,但看起来这个骨架代码也来自我们的教科书。我以前从未在 Python 中编程过,所以我只是想让它工作。我已经克服了那个错误,但是现在当我进入“在此处输入消息:”部分时,我在 shell 中收到提示并输入一条消息并按回车键,但随后程序什么也不做。我做了一些谷歌搜索,发现了这个人的视频,我看不出他和我的代码之间有多少差异。 strantalis.wordpress.com/2012/10/14/…
  • @user2946832:Stack Overflow 不是让别人以交互方式调试您的程序、一一解决您遇到的每个问题的好方法。你问为什么你会收到 500 错误,我解释了它,现在你的那部分代码可以工作了。如果您有一个新问题,并且您认为值得就 SO 问题提出问题,请接受此答案,然后提出一个新问题(将每个问题的链接放在另一个问题上)。
  • @user2946832:同时,额外的“.”在教科书里吗?然后去教科书的网站,看看他们是否有“勘误”部分。如果他们这样做了,它应该会告诉你他们发布的代码中的所有错误,以及如何修复它们。
  • @user2946832:无论如何,事实仍然是,您正在尝试向不太了解套接字或 Python 的人学习如何用 Python 编写套接字软件。如果你只是想通过一门课或其他什么,也许没问题。如果你想真正学习,你最好找个地方学习。
猜你喜欢
  • 2014-07-16
  • 1970-01-01
  • 2014-06-21
  • 2020-12-22
  • 2010-12-26
  • 2013-10-31
  • 1970-01-01
  • 2019-05-29
  • 2018-07-15
相关资源
最近更新 更多