我正在尝试使用替换aiosmtpd
的新smtpd
库创建一个开放的SMTP中继。下面的程序实例化一个传递到邮件控制器的Proxy
处理程序,后者在后台启动。然后使用连接到中继的标准smtplib
客户端创建一条消息。
一切都很好,直到客户端和中继之间的SMTP会话以永不离开中继的消息结束。中继从不回复250 OK\r\n
和ctrl+c
表示sendmail
正在等待回复。
有什么想法吗?脚本缺少什么吗?
修改:mail.example.com
只是一个示例服务器。使用smtpd DebuggingServer
执行脚本时,relay = aiosmtpd.handlers.Proxy("localhost", 1025)
不会打印任何内容。
$ python3.6 -m smtpd -n -c DebuggingServer -d localhost:1025
DebuggingServer started at Fri Apr 7 18:41:09 2017
Local addr: ('localhost', 1025)
Remote addr:('localhost', 25)
...nothing printed out...
脚本:
from aiosmtpd.handlers import Debugging, Proxy
from aiosmtpd.controller import Controller
from smtplib import SMTP
# relay = aiosmtpd.handlers.Debugging()
relay = aiosmtpd.handlers.Proxy("localhost", 1025)
# relay = aiosmtpd.handlers.Proxy("mail.example.com", 25)
controller = Controller(relay)
controller.start()
print(controller, controller.hostname, controller.port)
input("ready... press enter to continue")
print("creating SMTP with debug")
client = SMTP()
client.set_debuglevel(1)
print("connecting to the SMTP server")
client.connect(controller.hostname, controller.port)
print("sending message")
client.sendmail('alice@example.com',
['bob@example.com'], """\
From: Alice <alice@example.com>
To: Bob <bob@example.com>
Subject: Title
Body.
""")
print("stopping controller")
controller.stop()
print("checking if controller really stopped")
client.connect(controller.hostname, controller.port)
以下是脚本的输出:
$ python3.6 relay.py
<aiosmtpd.controller.Controller object at 0x10199f710> ::0 8025
ready... press enter to continue
creating SMTP with debug
connecting to the SMTP server
connect: ('::0', 8025)
connect: to ('::0', 8025) None
reply: b'220 localhost Python SMTP 1.0a4\r\n'
reply: retcode (220); Msg: b'localhost Python SMTP 1.0a4'
connect: b'localhost Python SMTP 1.0a4'
sending message
send: 'ehlo localhost\r\n'
reply: b'250-localhost\r\n'
reply: b'250-SIZE 33554432\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250 HELP\r\n'
reply: retcode (250); Msg: b'localhost\nSIZE 33554432\n8BITMIME\nHELP'
send: 'mail FROM:<alice@example.com> size=85\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'rcpt TO:<bob@example.com>\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'data\r\n'
reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
data: (354, b'End data with <CR><LF>.<CR><LF>')
send: b'From: Alice <alice@example.com>\r\nTo: Bob <bob@example.com>\r\nSubject: Title\r\n\r\nBody.\r\n.\r\n'
...nothing happens at this point...
^CTraceback (most recent call last):
File "relay.py", line 49, in <module>
""")
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 881, in sendmail
(code, resp) = self.data(msg)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 568, in data
(code, msg) = self.getreply()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 386, in getreply
line = self.file.readline(_MAXLINE + 1)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
KeyboardInterrupt
为了比较,这是使用调试处理程序的输出:
$ python3.6 relay.py
<aiosmtpd.controller.Controller object at 0x10189f710> ::0 8025
ready... press enter to continue
creating SMTP with debug
connecting to the SMTP server
connect: ('::0', 8025)
connect: to ('::0', 8025) None
reply: b'220 localhost Python SMTP 1.0a4\r\n'
reply: retcode (220); Msg: b'localhost Python SMTP 1.0a4'
connect: b'localhost Python SMTP 1.0a4'
sending message
send: 'ehlo localhost\r\n'
reply: b'250-localhost\r\n'
reply: b'250-SIZE 33554432\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250 HELP\r\n'
reply: retcode (250); Msg: b'localhost\nSIZE 33554432\n8BITMIME\nHELP'
send: 'mail FROM:<alice@example.com> size=85\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'rcpt TO:<bob@example.com>\r\n'
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
send: 'data\r\n'
reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
data: (354, b'End data with <CR><LF>.<CR><LF>')
send: b'From: Alice <alice@example.com>\r\nTo: Bob <bob@example.com>\r\nSubject: Title\r\n\r\nBody.\r\n.\r\n'
---------- MESSAGE FOLLOWS ----------
mail options: ['SIZE=85']
rcpt options: []
From: Alice <alice@example.com>
To: Bob <bob@example.com>
Subject: Title
X-Peer: ('::1', 64397, 0, 0)
Body.
------------ END MESSAGE ------------
reply: b'250 OK\r\n'
reply: retcode (250); Msg: b'OK'
data: (250, b'OK')
stopping controller
checking if controller really stopped
connect: ('::0', 8025)
connect: to ('::0', 8025) None
Traceback (most recent call last):
File "relay.py", line 51, in <module>
client.connect(controller.hostname, controller.port)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 335, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 306, in _get_socket
self.source_address)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 722, in create_connection
raise err
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 713, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 61] Connection refused
答案 0 :(得分:1)
编辑:aiosmtpd 1.0b1中的错误已为fixed,因此升级应解决此问题。
在aiosmtpd 1.0a4中,Proxy.handle_DATA
中的未捕获异常(使用data
作为str而不是字节)会导致asyncio任务停止,但异常永远不会传播。
如果升级到1.0a5,您将正确打印异常:&#34;错误:(TypeError)不能在字节对象上使用字符串模式&#34;。问题是从1.0a5开始,aiosmtpd中的Proxy
被设计用于在decode_data=True
对象上设置aiosmtpd.smtp.SMTP
的Controller子类,但默认情况下,decode_data=False
导致错误。 (在我看来,Proxy
应更改为与decode_data=False
一起使用,因此我已打开PR #74。)
因此,要在aiosmtpd 1.0a4或1.0a5中使用Proxy,您需要复制并使用UTF8Controller
中的aiosmtpd/tests/test_handlers.py
子类。我用1.0a4和1.0a5测试了以下脚本:
from aiosmtpd.handlers import Debugging, Proxy
from aiosmtpd.controller import Controller
from aiosmtpd.smtp import SMTP as SMTPServer
from smtplib import SMTP as SMTPClient
class UTF8Controller(Controller):
def factory(self):
return SMTPServer(self.handler, decode_data=True)
# relay = Debugging()
relay = Proxy("localhost", 1025)
# relay = Proxy("mail.example.com", 25)
controller = UTF8Controller(relay)
controller.start()
print(controller, controller.hostname, controller.port)
input("ready... press enter to continue")
print("creating SMTP with debug")
client = SMTPClient()
client.set_debuglevel(1)
print("connecting to the SMTP server")
client.connect(controller.hostname, controller.port)
print("sending message")
client.sendmail('alice@example.com',
['bob@example.com'], """\
From: Alice <alice@example.com>
To: Bob <bob@example.com>
Subject: Title
Body.
""")
print("stopping controller")
controller.stop()
print("checking if controller really stopped")
client.connect(controller.hostname, controller.port)