python:发送邮件,在""内部失败块

时间:2015-01-10 23:04:31

标签: email python-3.x gmail raspberry-pi with-statement

我想知道为什么这段代码

test = smtplib.SMTP('smtp.gmail.com', 587)
test.ehlo()
test.starttls()
test.ehlo()
test.login('address','passw')
test.sendmail(sender, recipients, composed)
test.close()

有效,但写得像这样

with smtplib.SMTP('smtp.gmail.com', 587) as s:
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login('address','passw')
    s.sendmail(sender, recipients, composed)
    s.close()

它失败并显示消息

Unable to send the email. Error:  <class 'AttributeError'>
Traceback (most recent call last):
  File "py_script.py", line 100, in <module>
    with smtplib.SMTP('smtp.gmail.com', 587) as s:
AttributeError: __exit__

为什么会这样? (覆盆子pi上的python3) THX

1 个答案:

答案 0 :(得分:5)

您没有使用Python 3.3或更高版本。在您的Python版本中,smtplib.SMTP()不是上下文管理器,不能在with语句中使用。

直接导致回溯,因为没有__exit__ method,这是对上下文管理器的要求。

来自smptlib.SMTP() documentation

  

在版本3.3中更改:添加了对with语句的支持。

您可以使用@contextlib.contextmanager

将对象包装在上下文管理器中
from contextlib import contextmanager
from smtplib import SMTPResponseException, SMTPServerDisconnected

@contextmanager
def quitting_smtp_cm(smtp):
    try:
        yield smtp
    finally:
        try:
            code, message = smtp.docmd("QUIT")
            if code != 221:
                raise SMTPResponseException(code, message)
        except SMTPServerDisconnected:
            pass
        finally:
            smtp.close()

这使用与Python 3.3中添加的相同的退出行为。像这样使用它:

with quitting_smtp_cm(smtplib.SMTP('smtp.gmail.com', 587)) as s:
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login('address','passw')
    s.sendmail(sender, recipients, composed)

请注意,它会为您关闭连接。