如何在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 = "me@mail.test"
subject = "hello"
message = "Hello Hello"
for line in f.readlines():
t = SendMail(from, line, subject, message)
t.run()
f.close()
这个方法可以用,但速度很慢(大约每秒6封邮件)。所以请帮我想办法让它快一点。或者给我推荐其他方法来完成这个任务。非常感谢!
2 个回答
我建议你(这也是最简单的方法)把这项工作交给一些第三方服务,然后在你的代码中调用他们的库。
MailChimp 看起来很受欢迎(这是他们的 API)。他们还提供了一个非常慷慨的免费计划。
SocketLabs 也是一个不错的选择(这是他们的 API)。你可以在谷歌上找到很多其他的选择。
最快的方式是在你的机器上安装一个邮件传输代理,比如Postfix,然后把所有的邮件交给它来发送,使用/usr/sbin/sendmail
这个邮件接口。大多数合理的邮件服务器每秒可以处理成千上万封邮件,并且可能会进行一些SMTP管道处理,这样可以在一次连接中把邮件发送给同一个域的多个收件人,这样可以大大减少网络流量,提高邮件发送的效率。(这不会影响用户看到的邮件内容。)
大多数邮件服务器也能很好地处理临时宕机的服务器,这一点非常重要,因为许多网站使用灰名单来对抗垃圾邮件。
不过,如果你真的想在Python中通过网络连接联系SMTP服务器,使用一个线程池来发送邮件是个不错的主意。这个线程池会从队列中取出地址,创建并发送邮件,然后再回到队列中处理下一个地址。你现在的代码是为每封邮件都创建和销毁一个新线程。创建和销毁线程需要时间,这些时间本可以用来处理你的邮件。
此外,线程池还会限制活跃连接的总数。没有必要同时为一个邮件服务器创建1000个独立的连接。每次建立连接时需要进行三次握手,这个过程会消耗三倍的延迟时间才能建立TCP连接,然后才能发送任何SMTP流量。所以,创建十个线程并用这十个连接来发送邮件是个好主意。(其实十个可能有点多,两三个就可能更合适。甚至一个线程可能是最好的选择,不过如果这个连接断了(每个连接的邮件限制?),你就会有一段时间无法发送任何邮件,直到重新建立连接。)
你现在创建的情况很像雷鸣群体问题——你启动了数百或数千个线程,但可能没有足够的内存同时保持它们在RAM中运行。这样可能会导致频繁的内存交换,严重降低你的发送系统的性能,而单个线程执行时可能完全在内存中运行,不会因为交换而停顿。