Как быстро отправить письмо сотням тысяч получателей в python, каждый из которых отображается как получатель в заголовке почты?

Я ищу решения для отправки огромного количества писем (сотни тысяч) в Python. У меня есть список получателей (в файле), и я хочу отправить письмо всем им. Я хочу, чтобы каждый из получателей отображался как получатель в заголовке почты, а не как скрытая копия или копия. Что ж, мои решения: отправить отдельное письмо каждому из них, а не письмо всему списку. Я сделал некоторые работы ниже: (я использовал smtplib, threading):

class SendMail(threading.Thread):
  def __init__(self, from, to, subject, message):
     self.from = from
     self.to = to
     self.subject = subject
     self.message = message 
  def run(self):
    try:
                msg = MIMEMultipart('alternative')
                msg['Subject'] = self.subject
                msg['From'] = self.from
                msg['To'] = self.to
                msg.attach(MIMEText(self.message , 'html'))
                server = smtplib.SMTP()              
                server.connect('xxxxx', 25)
                server.login('cxxxxx', 'yyyyyy')                
                server.sendmail(self.from, self.to, msg.as_string())
    except:
          pass

def sendmail():
   f = open('recipients','w')
   from = "[email protected]"
   subject = "hello"
   message = "Hello Hello"
   for line in f.readlines():
      t = SendMail(from, line, subject, message)
      t.run()
   f.close()

Он работает, но очень медленно (около 6 писем в секунду). Поэтому, пожалуйста, помогите мне сделать это быстрее. Или предложите мне другие решения для этой работы. Большое спасибо!


person Nguyễn Thái Sơn    schedule 05.12.2011    source источник
comment
Сотни тысяч писем? Вы один из дем...спамеров?   -  person Blender    schedule 05.12.2011


Ответы (2)


Самым быстрым было бы установить агент передачи почты, такой как Postfix, на свой компьютер и передать все ваши электронные письма на него для доставки с помощью почтового интерфейса /usr/sbin/sendmail. Большинство разумных почтовых серверов могут принимать тысячи почтовых сообщений для доставки в секунду и могут выполнять некоторую конвейерную обработку SMTP для отправки сообщения нескольким получателям в целевом домене за одно соединение, что значительно снижает нагрузку на трафик и повышает пропускную способность сообщений. (Это не повлияет на то, как ваши пользователи увидят ваши электронные письма.)

Большинство почтовых серверов также отлично справляются с временно отключенными серверами, что чрезвычайно важно, поскольку многие сайты используют серые списки. для борьбы со спамом.

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

Кроме того, пул потоков будет ограничивать общее количество активных подключений. Нет смысла создавать 1000 отдельных, но одновременных подключений к одному почтовому серверу. трехстороннее рукопожатие, которое настраивает каждый сеанс, требует в три раза больше времени задержки для вашего сервер для установления сеанса TCP, прежде чем вы сможете отправлять какой-либо SMTP-трафик. Поэтому создайте десять потоков с десятью подключениями и повторно используйте эти подключения для отправки электронных писем. (Даже десять, вероятно, перебор для этого - два или три, вероятно, будут работать лучше. Черт возьми, один поток может быть лучше всего, хотя, если это соединение прервется (ограничения почты для каждого соединения?) вы будет иметь период ничего по сети, пока это соединение не будет восстановлено.)

То, что вы создали сейчас, очень похоже на проблему грозового стада — вы начинаете с сотен или тысяч потоков, но может не хватить памяти, чтобы держать их все в ОЗУ одновременно. Возможно, вы ввели достаточную подкачку, чтобы резко снизить производительность вашей отправляющей системы, где один поток выполнения может полностью уместиться в памяти и работать без остановок для подкачки.

person sarnold    schedule 05.12.2011
comment
Большое спасибо! Раньше я не понимал темы. Я постараюсь понять их глубже. - person Nguyễn Thái Sơn; 06.12.2011

Моя рекомендация (и, безусловно, самая простая) — передать эту работу какой-нибудь третьей стороне и вызывать их библиотеки в своем коде.

MailChimp кажется довольно популярным (вот их api). Они также предлагают щедрый бесплатный план.

SocketLabs — еще один вариант (вот их api). Google должен предоставить вам множество других.

person Burhan Khalid    schedule 05.12.2011