Python发送电子邮件太慢了

时间:2011-11-08 18:12:40

标签: python performance email smtp

我有下面的脚本,我用它自己发送10条消息< - >我自己。但是,我注意到Python真的需要一段时间才能做到这一点。去年我需要一个系统来发送大约200封带有附件和文本的电子邮件,我用msmtp + bash实现了它。据我记得它快得多。

在内部移动while循环(在smtp_serv.sendmail(sender,recepient,msg)函数周围产生类似的结果)。

我做错了吗?当然它不能比bash + msmtp慢(而且我只发送'hi'消息,没有附件)。

#! /usr/bin/python3.1

def sendmail(recepient,  msg):

    import smtplib

    # Parameters
    sender = 'login@gmail.com'
    password = 'password'
    smtpStr = 'smtp.gmail.com'
    smtpPort = 587
    # /Parameters

    smtp_serv = smtplib.SMTP(smtpStr, smtpPort)
    smtp_serv.ehlo_or_helo_if_needed()
    smtp_serv.starttls()
    smtp_serv.ehlo()

    recepientExists = smtp_serv.verify(recepient)
    if recepientExists[0] == 250:
        smtp_serv.login(sender, password)
        try:
            smtp_serv.sendmail(sender, recepient, msg)
        except smtplib.SMTPException:
            print(recepientExists[1])
    else:
        print('Error',   recepientExists[0], ':',  recepientExists[1])

    smtp_serv.quit()

for in in range(10):
    sendmail('receiver@gmail.com',  'hi')

4 个答案:

答案 0 :(得分:3)

在此脚本中,设置SMTP连接(5秒)所需的时间比发送电子邮件(1秒)多五倍,因此设置单个连接并发送多封电子邮件而不是创建电子邮件是有意义的每次连接:

#!/usr/bin/env python3
import smtplib    
from contextlib import contextmanager
from datetime   import datetime
from email.mime.text import MIMEText
from netrc      import netrc
from timeit     import default_timer as timer

@contextmanager
def logined(sender, password, smtp_host='smtp.gmail.com', smtp_port=587):
    start = timer(); smtp_serv = smtplib.SMTP(smtp_host, smtp_port, timeout=10)
    try: # make smtp server and login
        smtp_serv.ehlo_or_helo_if_needed()
        smtp_serv.starttls()
        smtp_serv.ehlo()
        print('smtp setup took (%.2f seconds passed)' % (timer()-start,))
        start = timer(); smtp_serv.login(sender, password)
        print('login took %.2f seconds' % (timer()-start,))
        start = timer(); yield smtp_serv
    finally:
        print('Operations with smtp_serv took %.2f seconds' % (timer()-start,))
        start = timer(); smtp_serv.quit()
        print('Quiting took %.2f seconds' % (timer()-start,))

smtp_host = 'smtp.gmail.com'
login, _, password = netrc().authenticators(smtp_host)
with logined(login, password, smtp_host) as smtp_serv:
    for i in range(10):
        msg = MIMEText('#%d timestamp %s' % (i, datetime.utcnow()))
        msg['Subject'] = 'test #%d' % i
        msg['From'] = login
        msg['To'] = login
        smtp_serv.send_message(msg) 

输出

smtp setup took (5.43 seconds passed)
login took 0.40 seconds
Operations with smtp_serv took 9.84 seconds
Quiting took 0.05 seconds

如果您的Python版本没有.send_message(),那么您可以使用:

smtp_serv.sendmail(from, to, msg.as_string())

答案 1 :(得分:2)

您正在打开与SMTP服务器的连接,然后为每封电子邮件关闭它。在发送所有电子邮件时保持连接打开会更有效。

答案 2 :(得分:1)

这里真正的答案是“简介代码!”。时间代码的不同部分需要多长时间,以便您知道大部分时间花在哪里。这样你就可以在没有猜测的情况下得到真正的答案。

不过,我的猜测是,对smtp_serv.verify(recipient)的调用可能是缓慢的。原因可能是服务器有时需要向其他SMTP服务器询问信息,或者它会对这些操作进行限制,以避免垃圾邮件发送者大量使用它们来收集电子邮件地址。

另外,尝试ping SMTP服务器。如果乒乓球占用大量时间,我希望发送每封电子邮件至少需要很长时间。

答案 3 :(得分:1)

也许这来得很晚,但我认为这与此事有关。 我最近遇到了同样的问题,并通过搜索来实现,由于域名解析问题,连接SMTP服务器的呼叫可能非常耗时,因为SMTP服务器执行反向查找以验证连接客户端。

在我的情况下,此通话大约需要1分钟!:

s = smtplib.SMTP(smtp_server)

解决方法是在Linux机器上修复域名解析。在那之后,连接变得非常快。

希望这可能会有所帮助。