【问题标题】:Python smtplib sometimes fails sendingPython smtplib 有时发送失败
【发布时间】:2012-12-14 10:37:39
【问题描述】:

我用 Python 编写了一个简单的“POP3S to Secure SMTP over TLS”MRA 脚本(见下文)。

它工作正常,但有时它在尝试通过 SMTP 发送时返回“连接意外关闭”。再次运行脚本将成功传递该消息。

请给我一些建议,为什么它有时会无法传递消息,但在下一次运行时它会成功传递此消息!?

#! /usr/bin/env python

import poplib
import email

def forward_pop3_smtp( smtp_credentials, pop3_credentials, forward_address):
    pop3_server = pop3_credentials[0]
    pop3_port = pop3_credentials[1]
    pop3_user = pop3_credentials[2]
    pop3_password = pop3_credentials[3]

    message_recipient = forward_address

    server = poplib.POP3_SSL( pop3_server, pop3_port)
    server.user( pop3_user)
    server.pass_( pop3_password)

    for messages_iterator in range( len( server.list()[1])):
        message_list = server.retr( messages_iterator + 1)[1]

        message_string = ''
        for message_line in message_list:
            message_string += message_line + '\n'

        message_message = email.message_from_string( message_string)
        message_message_as_string = message_message.as_string()
        message_sender = message_message[ 'From']
        print( 'message_sender = ' + message_sender)

        smtp_return = send_smtp( smtp_credentials, message_sender, message_recipient, message_message_as_string)
        print( 'smtp_return = ' + str(smtp_return))
        if smtp_return == 0:
            print( 'Deleting message ' + message_message[ 'Subject'] + ':\n')
            return_delete = server.dele( messages_iterator + 1)
            print( 'return_delete = \n' + str(return_delete))
            print( '\n')
    server.quit()

def send_smtp( smtp_credentials, message_sender, message_recipient, message_message_as_string):
    smtp_server = smtp_credentials[0]
    smtp_port = smtp_credentials[1]
    smtp_user = smtp_credentials[2]
    smtp_password = smtp_credentials[3]

    import smtplib
    exception = 0
    try:
        server = smtplib.SMTP( smtp_server)
        server.starttls()
        server.login( smtp_user, smtp_password)
        smtp_sendmail_return = server.sendmail( message_sender, message_recipient, message_message_as_string)
        server.quit()
    except Exception, e:
        exception = 'SMTP Exception:\n' + str( e) + '\n' + str( smtp_sendmail_return)
    return exception

if __name__ == '__main_':
    print( 'This module needs to be imported!\n')
    quit()

【问题讨论】:

  • 你能访问服务器端的日志吗?它可能有正当理由放弃它会在日志中提到的连接。此外,您能否看到网络级别的情况(例如tcpdump)?此外 - 与您的问题没有直接关系的事情 - 我建议重新提出异常,而不是返回。
  • 09:05:21 EHLO - 250 09:05:21 STARTTLS - 220 09:05:21 STARTTLS - 220 09:05:21 EHLO - 250 09:05:21 邮件 - 250 09: 05:21 RCPT - 250 09:05:21 数据 - 250 09:05:21 退出 - 240 09:05:21 EHLO - 250 09:05:21 STARTTLS - 220 09:05:21 STARTTLS - 220 09:05: 22 EHLO - 250 09:05:22 邮件 - 250 09:05:22 RCPT - 250 09:05:22 数据 - 250 09:05:22 退出 - 240 09:05:40 EHLO - 250 09:05:40 STARTTLS - 220 09:05:40 STARTTLS - 220 09:05:40 EHLO - 250 09:05:40 邮件 - 250 09:05:40 RCPT - 250 09:05:40 数据 - 250 09:05:40 退出 - 240
  • @gertvdijk:谢谢!日志中似乎没有任何用处。重新升起的意思是,执行被打断了,对吧?这种情况有什么好处?
  • (offtopic) 重新引发可以在调用您的函数的其他代码中捕获异常,从而使您的代码更“可重用”。您可以使用这些异常记录并执行操作,但在我看来,未能完成函数的主要任务并有效隐藏异常并不是一个好习惯。
  • @gertvdijk:再次感谢!午饭后我会试着理解你的解释。我意识到有一个 SMTP 反垃圾邮件过滤器(SOPHOS PureMessage)以某种方式集成,并将检查这些日志。

标签: python smtp smtplib


【解决方案1】:

为 TLS 使用端口 587。我没有看到脚本使用 smtp_port

使用喜欢,

server = smtplib.SMTP( smtp_server, int(smtp_port)

对于安全 SMTP(SMTP + SSL),使用 smtplib.SMTP_SSL

【讨论】:

  • StartTLS != TLS。可以在端口 25 上启动连接,然后要求使用 TLS 提升连接。见Wikipedia: STARTTLS。此外,它没有解释为什么它一次有效,而下一次无效。
  • 我的 python 代码在 25 日连接并使用 StartTLS 时会挂起并抛出与 netfirms smtp 服务器的连接错误。
  • 那么这是您的 MTA 失败或某种“功能”,例如灰名单。 RFC 3207 对此非常清楚:25 端口没问题。
  • 我不明白RFC 2476 的意思:端口 587 保留用于本文档中指定的电子邮件消息提交。在此端口上接收到的消息被定义为提交。使用的协议是 ESMTP [SMTP-MTA, ESMTP],附加的限制在这里指定。
猜你喜欢
  • 2020-01-10
  • 2013-02-04
  • 1970-01-01
  • 2017-04-02
  • 2014-01-31
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 2010-10-07
相关资源
最近更新 更多