使用asp.net发送超过20,000封电子邮件

8
我正在编写一个应用程序,需要向从我们的数据库中选择的学生发送大量电子邮件(每封电子邮件都将个性化,包括他们的姓名、课程等信息...因此需要逐一发送)。
我可以通过 SmtpClient 进行循环发送,但我担心由于发送数量过多,最终会遇到超时问题或者线程被杀死,因为机器资源不足。
目前,我只是在寻找更好的处理方法的建议,或者如果循环使用 SmtpClient 是可行的解决方案,如何处理以防止出现上述问题。
Web 服务是否是更好的替代方案?
请给予建议,谢谢。

你需要使用一些第三方工具。 - anishMarokey
2
您无需使用第三方工具。 - Josh Stodola
5个回答

11
我的建议是批量处理邮件。不要尝试运行ASP.NET代码来创建20K封电子邮件并将它们发送出去,否则您可能会遇到超时和性能问题。相反,填充一个包含收件人、主题和正文的表格,并从Windows服务开始批处理过程。这样,您的代码将以可以管理延迟的方式执行,而不是让网页等待请求返回。

这种方法听起来很有前途。我已经将电子邮件保存在一个表中了。抱歉问一个新手问题,但是我该如何调用这个Windows服务来启动电子邮件的发送,同样,我应该如何从Windows服务向客户端报告哪些电子邮件已成功发送,哪些失败了? - Kyle
你不需要调用Windows服务,只需让它运行。该服务可以设计为检查你的表格并查看是否有工作要做。如果有未发送的电子邮件,则将它们批量处理并发送。基本上,该服务应该被设计为每5分钟查询一次该表。(注意,在该表上应该放置一个布尔标志,表示是否已发送,并为了性能考虑,对该布尔标志进行索引。)现在,当查询所有未发送的项目时,如果计数大于1,则服务开始发送电子邮件。至于向客户端报告返回,可以参考其他方式。 - John Hartsock
我的最后一条评论被切断了。 至于向客户报告,您可以在网页上显示您的日志,说明是否已发送电子邮件。此显示应分为两个视图:已发送和未发送。(要小心,因为这可能会导致20,000条记录的长时间加载)。 - John Hartsock
关于Windows服务还有一个快速问题。我该如何分割它,以便不会一次性尝试发送20k+封电子邮件?我认为除非我按照其他人在这里建议的方式进行“分块”处理,否则最终可能会遇到相同或类似的问题... - Kyle
你的问题很快就能得到解决,因为这个设计非常优美。因为你只是在排队电子邮件,所以可以调整服务每5分钟运行一次的查询,选择“SELECT Top 100 * FROM MyMailTable where notsent = true”。这样,每隔5分钟或你创建的任何时间间隔,服务就会发送100封电子邮件。 - John Hartsock

6

首先,这并不是什么大事,我已经处理了五万封以上的电子邮件。

让电子邮件写入一个文件夹-目录中。然后使用您可以安装的本地SMTP服务,将其指向文件夹作为接收目录。这至少可以确保在此时您有一个良好的缓冲区(即您可以完成asp.net端,而此时电子邮件未被发送)。


首先,我们遇到的问题是所有学生都使用一个“第三方”电子邮件(都使用相同的电子邮件),该电子邮件已将我们的交换服务器列入“可接受发件人”。不幸的是,我无法访问交换服务器以告诉它从这个“文件夹”获取电子邮件...这完全取决于我们基础设施的责任。我也无法访问将Web服务器添加为我们第三方电子邮件(其中包含所有电子邮件地址)上的“可接受发件人”,因此无法在那里使用它作为SMTP服务器。如果我创建了一个Web服务来处理通过我们的交换发送电子邮件...是否可行? - Kyle
实际上问题出在哪里?认真地说……本地 SMTP 服务可以配置为 (a) 使用 Exchange 服务器作为中继,(b) 使用用户名和密码进行身份验证,就像您使用普通的 SMTP 服务一样。 - TomTom
你的回答并没有提供任何解决方案,反而只是在问更多问题。你真的期望这20000个用户都使用同一个电子邮件提供商吗?你的回答表明你在发送此类电子邮件方面没有经验。 - Helen Neely
1
@Helen - 这很愚蠢。抱歉。使用中继的电子邮件服务器将像任何其他服务器一样通过一个服务器发送所有电子邮件。这就是它的工作原理。他对所有20,000封电子邮件都有相同的发件人,而电子邮件服务器会找出要发送到哪里。如果你不知道电子邮件的工作原理,Helen,我建议你先了解基础知识,而不是发表愚蠢的评论。任何电子邮件服务器(在这种情况下是交换服务器)都能找出要发送电子邮件的位置。 - TomTom
是的,这就是我们的做法,使用SmtpClient的PickupDirectory功能。目录会被命名为GUID的电子邮件填满。然后将它们复制到Exchange正在使用的“真实”接收目录中(我们使用临时目录以防生成过程半途失败,我们不小心发送了一些电子邮件,并可以删除并重新启动),然后Exchange将其吸收——不必担心超载,Exchange足够聪明,只会一次性吸收少量电子邮件(尽管这是可配置的)。 - Nicholas Piasecki

2
使用SQL Server自带的Database Mail工具怎么样呢?你仍然可以使用asp.net,但是邮件将由SQL Server发送,你只需要调用存储过程并让SQL Server处理即可。
我不建议使用批量选项,因为除非你付出很多努力,否则不会有任何优化或队列功能。
Database Mail工具也提供了队列和优先级选项。如果出现问题,电子邮件将被重新排队并稍后发送,但其他邮件仍将继续发送。
在SQL Server 2008中,它被称为Database Mail,在早期版本中被称为SQL Mail。
欲了解更多信息,请参阅以下链接:

那个东西简直糟糕,本来就不应该出现在SQL Server中。 - TomTom
2
请忽略TomTom - 他生来就是醉汉!你看过他的其他评论吗? - Helen Neely
我可以同意,一个邮件发送程序可能不应该是数据库服务器的一部分,但事实仍然如此。这对于提问者来说可能是一个好的解决方案。 - Steven

0
你可以使用JavaScript定时器请求发送邮件的脚本,以便将邮件分成小块发送,避免超时。然后从浏览器中调用该脚本。还可以添加进度条、身份验证等功能。

0
你不需要一个网络服务,而是需要一种将电子邮件批量排队的方法(可能是在数据库中创建一个“Email_Queue”表)。然后,在服务器上运行的Windows服务可以按照先进先出的原则逐个读取队列中的邮件,并以合理的块大小发送到SMTPClient,处理完项目后从队列中删除。您可能需要运行一些测量来确定邮件服务器的块大小和延迟时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接