Python отправляет электронную почту слишком медленно - PullRequest
1 голос
/ 08 ноября 2011

У меня есть скрипт ниже, который я использую, чтобы самому сказать 10 сообщений <-> сам.Тем не менее, я заметил, что Python действительно требует времени, чтобы сделать это.В прошлом году мне понадобилась система для отправки около 200 электронных писем с вложениями и текстом, и я реализовал ее с помощью msmtp + bash.Насколько я помню, это было намного быстрее.

Перемещение цикла while внутри (вокруг функции smtp_serv.sendmail (отправитель, получатель, msg) дает аналогичные результаты).

Я что-то делаюнеправильно?Конечно, он не может быть медленнее, чем bash + msmtp (и я только отправляю сообщение «привет», без вложений).

#! /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 ]

3 голосов
/ 09 ноября 2011

В этом сценарии настройка 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())
2 голосов
/ 08 ноября 2011

Вы открываете соединение с SMTP-сервером, а затем закрываете его для каждого электронного письма.Было бы более эффективно сохранять соединение открытым при отправке всех электронных писем.

1 голос
/ 25 января 2018

Может быть, это очень поздно, но я думаю, что это актуально. Недавно у меня возникла та же проблема, и я, обыскав вокруг, понял, что вызов для подключения к SMTP-серверу может занять очень много времени из-за проблем с разрешением доменного имени, поскольку SMTP-сервер выполняет обратный поиск для проверки подключающегося клиента.

В моем случае этот звонок занимал около 1 минуты!:

s = smtplib.SMTP(smtp_server)

Решение заключалось в том, чтобы исправить разрешение доменного имени на коробке Linux. После этого соединение стало очень быстрым.

Надеюсь, что это может помочь.

1 голос
/ 08 ноября 2011

Реальный ответ здесь - «профиль, код!». Время, сколько времени занимают разные части кода, чтобы вы знали, на что тратится большая часть времени. Таким образом, вы получите реальный ответ без догадок.

Тем не менее, я предполагаю, что именно звонки на smtp_serv.verify(recipient) могут быть медленными. Причины могут заключаться в том, что серверу иногда требуется запрашивать информацию у других SMTP-серверов или что он ограничивает эти операции, чтобы спаммеры не использовали их массово для сбора адресов электронной почты.

Также попробуйте пропинговать SMTP-сервер. Если пинг-понг занимает значительное время, я ожидаю, что отправка каждого электронного письма займет, по крайней мере, так долго.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...