如何使用smtplib和Python保持SMTP连接开启?

3

我需要检查SMTP服务器的超时时间,但我的套接字只是关闭了。我做错了什么?以下是我的测试代码:

#!/usr/bin/python
import smtplib
import time
import datetime
import socket
socket.setdefaulttimeout(1800)


now = time.time()
server = smtplib.SMTP()
server.set_debuglevel(1)
server.connect('mx.foo.bar','25')
(code,resp) = server.docmd('NOOP')
then = time.time()

print then-now

希望这个能够奏效。


你为什么想要这样做?你连接,发送邮件,然后断开连接。如果你不使用它,为什么要保持连接处于打开状态呢? - Jerry Coffin
我正在尝试检查RFC合规性。建议使用Python,而不是C语言,因为它更易于使用。 - leto
3个回答

10

嗯,我还没有找到使用smtplib保持smtp连接开放的方法。

但是,如果您想重复使用连接而不关闭(是的,打开连接需要时间,大约2-3秒钟),您可以先测试连接。为此,请发送NOOP命令并测试状态是否等于250。如果不是,则可以打开连接并发送邮件。您可以选择在完成之前不退出()连接。

import smtplib

def create_conn():
    conn = smtplib.SMTP('smtp.gmail.com', 587)
    ...
    return conn

def is_connected(conn):
    try:
        status = conn.noop()[0]
    except:  # smtplib.SMTPServerDisconnected
        status = -1
    return True if status == 250 else False

1
@Ethan- 有道理! - trex
1
@trex 谢谢。它非常好用,我已经成功地使用了2年多,没有任何问题。 - Ethan
这是一个阻塞方法。它有超时吗? - Minh Hoàng
1
这个很好用。在你的create_conn函数中创建一个全局变量smtp_connection并检查is_connected(smtp_connection),它将重复使用相同的连接直到关闭或超时。 - Ruchit Patel

1

你确定你已经断开连接了吗?当我使用上述代码对一个 postfix 服务器进行操作时,我得到了以下结果:

connect: ('server', '25')
connect: ('ip.address', 25)
reply: '220 server ESMTP Postfix\r\n'
reply: retcode (220); Msg: nserver ESMTP Postfix
connect: server ESMTP Postfix
send: 'NOOP\r\n'
reply: '250 2.0.0 Ok\r\n'
reply: retcode (250); Msg: 2.0.0 Ok
0.0531799793243

Docmd不会阻塞,服务器响应后程序退出。因此,当程序退出时我会断开连接。

如果我打开Python命令行并执行:

>> import smtplib
>> server = smtplib.SMTP()
>> server.connect('server')
>> server.docmd('NOOP')
(250, '2.0.0 Ok')
>> ## let it sit for 5 minutes
>> server.docmd('NOOP')
(421, '4.4.2 server Error: timeout exceeded')

我的日志证实了这一点:

Oct 20 10:45:35 [postfix/smtpd] connect from unknown[ip.address]
Oct 20 10:50:10 [postfix/smtpd] timeout after NOOP from unknown[ip.address]

0

请检查您的邮件服务器设置 - 它们可能会中断连接。


我检查了每个MTA,都发生了这种情况。它们收到命令后返回220,然后连接就关闭了。使用telnet我在5分钟后会超时。 - leto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接