我正在寻找用Python发送大量邮件(数十万)的解决方案。我有一个收件人列表(在一个文件中),我想发送邮件给所有人。我希望每个收件人都显示为邮件标题中的接收者,而不是密件抄送或cc。好吧,我的解决方案:向每个邮件发送一个单独的邮件,而不是邮件发送到所有列表。我在下面做了一些工作:(我使用 smtplib ,线程):
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 = "me@mail.test"
subject = "hello"
message = "Hello Hello"
for line in f.readlines():
t = SendMail(from, line, subject, message)
t.run()
f.close()
它工作但很慢(约6邮件/秒)。所以请帮助我加快速度。或者建议我做另外一个解决方案。非常感谢你!
答案 0 :(得分:5)
最快的方法是在您的计算机上安装Postfix等邮件传输代理,并将所有电子邮件发送给它,以便使用/usr/sbin/sendmail
邮件界面进行传递。大多数合理的邮件服务器每秒可以接受数千封邮件进行传递,并且可以执行一些SMTP流水线操作,以便在单个连接中向目标域上的多个收件人发送邮件,从而大大减少流量开销并提高邮件吞吐量。 (这不会影响用户查看电子邮件的方式。)
大多数邮件服务器也可以非常好地暂时关闭服务器,这非常重要,因为许多网站使用greylisting来打击垃圾邮件。
但是,如果你真的想通过Python中的网络连接联系SMTP服务器,那么使用thread pool发送线程来获取队列中的地址是一个非常好的主意,创建并发送电子邮件,然后返回队列以获取另一个服务地址。您当前的代码为每个邮件传递创建并销毁新线程。线程需要时间来创建并花费时间来销毁,所有这些开销都是为邮件服务所花费的时间。
此外,线程池将限制活动连接的总数。创建1000个单独但同时连接到单个邮件服务器是没有意义的。设置每个会话的three-way handshakes占用服务器延迟的三倍,以便在您发送任何SMTP流量之前建立TCP会话。因此,创建十个具有十个连接的线程,并重用这些连接来发送电子邮件。 (即使十个也可能是矫枉过正 - 两个或三个可能会更好。哎呀,一个线程可能是最好的,但如果连接断开(每个连接邮件限制?)你在重新建立连接之前,会有一段时间通过网络发送 nothing 。)
您现在创建的内容与thundering herd problem非常相似 - 您启动了数百或数千个线程,但可能没有足够的内存来将它们全部保存在RAM中。您可能已经引入了足够的交换来大幅降低发送系统的性能,其中单个执行线程可能完全适合内存并且可以在不停止交换的情况下运行。
答案 1 :(得分:1)
我的建议(到目前为止最简单)是将这项工作卸载给某些第三方并在您的代码中调用它们的库。
MailChimp似乎很受欢迎(这是他们的api)。他们还提供慷慨的免费计划。
SocketLabs是另一种选择(这是他们的api)。谷歌应该为你提供大量其他的。