有没有办法防止SMTP连接超时? smtplib,python

时间:2018-03-09 23:32:01

标签: python email timeout smtplib

我有一个我需要无限期运行的脚本。该脚本将通过电子邮件向我发送每日完成的某些步骤的确认。我正在尝试使用smtplib。

初始连接已设置好,以便在脚本启动时使用getpass输入我的登录名(写入脚本)和密码。我不想将我的密码写入脚本,甚至不能通过脚本在配置文件中引用。因此,我想在启动时输入密码并保持smtp连接。

根据脚本中的要求重新连接到smtp连接将无法完全脱离脚本并使其无限期运行。

我目前使用的示例代码如下所示:

import smtplib
import getpass

smtpObj = smtplib.SMTP('smtp.gmail.com',587)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login('myemail@gmail.com',password = getpass.getpass('Enter Password: '))

然后我输入密码,输出为:

(235, b'2.7.0 Accepted')

所以一切正常。

问题是,脚本需要暂停几分钟到几天的任何时间,具体取决于时间。这是使用带有时间条件的while循环实现的,直到调用send函数的某个时间:

smtpObj.sendmail('myemail@gmail.com','recipient@gmail.com','This is a test')

然而,在约20/30分钟之后,似乎(即如果暂停足够)。然后smptObj.sendmail调用将因超时错误而失败。

具体错误如下:

SMTPSenderRefused: (451, b'4.4.2 Timeout - closing connection. l22sm2469172wre.52 - gsmtp', 'myemail@gmail.com')

到目前为止,我尝试了以下内容:

使用以下超时参数化实例化连接对象:

smtpObj = smtplib.SMTP('smtp.gmail.com',587,timeout=None)
smtpObj = smtplib.SMTP('smtp.gmail.com',587,timeout=86400)

这些似乎都不会妨碍“超时”。连接(即同样的问题仍然存在)。

我也尝试过这篇文章中建议的解决方法:

How can I hold a SMTP connection open with smtplib and Python?

然而,这也没有奏效!

我确实想尝试避免每次我想要发送电子邮件时必须重新连接的解决方案,因为我只想手动输入一次连接的密码,而不是写它直接或间接地进入脚本。

肯定有办法解决超时问题!如果有人可以在这里提供帮助,请告诉我!但是,如果你认为更明显的'在脚本需要发送电子邮件之前重新连接的解决方案是更好的方法,请告诉我。

谢谢!...

1 个答案:

答案 0 :(得分:2)

如果您不想在脚本中包含敏感凭据,则应使用env vars。

从终端shell(在python之外):

<div class="text-center">
    <div class="btn-group">
        <a href="#" class="btn btn-primary">text 1</a>
        <a href="#" class="btn btn-outline-primary">text 2</a>
    </div>
</div>

所以要在你的代码中利用它......

$ EXPORT secretVariable=mySecretValue
$ echo $secretVariable
$ mySecretValue
$

通过这样做,您不必手动输入密码。除此之外,试图让空闲的SMTP连接一次打开几天并不是很实际,只需要实现一个try / except结构。

>>> import os
>>> myPW = os.getenv('secretVariable')
>>> myPW
'mySecretVal'
>>>

import smtplib import os def smtp_connect(): # Instantiate a connection object... password = os.getenv('secretVariable') smtpObj = smtplib.SMTP('smtp.gmail.com',587) smtpObj.ehlo() smtpObj.starttls() smtpObj.login('myemail@gmail.com',password=password) return smtpObj def smtp_operations(): try: # SMTP lib operations... smtpObj.sendmail('myemail@gmail.com','recipient@gmail.com','This is a test') # SMTP lib operations... except Exception: # replace this with the appropriate SMTPLib exception # Overwrite the stale connection object with a new one # Then, re-attempt the smtp_operations() method (now that you have a fresh connection object instantiated). smtpObj = smtp_connect() smtp_operations() smtpObj = smtp_connect() smtp_operations() 替换为当您有过时连接时引发的实际SMTP except Exception时,您确定自己没有捕获不会发生的异常属于陈旧的连接。

因此,使用Exception,脚本将尝试执行SMTP操作。如果连接是陈旧的,它将实例化一个新的连接对象,然后尝试用新连接对象重新执行它。