代码之家  ›  专栏  ›  技术社区  ›  josh3736

测试大容量SMTP电子邮件发送代码的最佳方法?

  •  6
  • josh3736  · 技术社区  · 15 年前

    (是的,收件人需要电子邮件。不,我没有发垃圾邮件。是的,我对CAN-SPAM很满意。是的,我知道 sending email from code sucks .) 许多电子邮件是事务性的(响应用户操作生成的);有些是批量的(基本上是邮件合并)。

    我不想依赖外部SMTP服务器(在其他考虑因素中,一想到必须检查邮箱中的跳出邮件并尝试解析它们,我就感觉很不好。)

    我的设计相当简单。事务性消息和批量消息都被生成并插入到DB表中。此表包含电子邮件信封和内容,以及尝试次数和重试日期。

    该服务运行几个工作线程,这些线程一次获取20行并循环遍历每一行。使用 Simple DNS Plus 库中,我获取收件人域的MX记录,然后使用 System.Net.Mail.SmtpClient Send() 成功后,我可以将电子邮件出列。如果它暂时失败,我可以增加尝试次数,并设置一个适当的重试日期后。如果它永久失败,我可以出列并处理失败。

    最近我发现ISP阻塞了与上的25端口的连接,这甚至加剧了我的小规模测试困难 任何 我的ISP的SMTP服务器以外的服务器(在生产中,这个东西当然会在一个适当的服务器上,在那里端口25不会被阻塞。这并不能帮助我从我的开发人员机器上进行测试。)

    1. 我应该如何开始测试我的代码?
    2. SmtpClient.Send() 会失败吗?列举了六种例外情况; SmtpException SmtpFailedRecipientsException 似乎是最相关的。

    更新: Marc B's answer 指出我基本上是在创建自己的SMTP服务器。他提出了一个正确的观点,即我正在重新发明轮子,因此我的理由是不使用“实际的”轮子(后缀等):

    1. 电子邮件具有不同的发送优先级(尽管这与信封的大小无关) X-Priority ). 批量电子邮件的优先级较低;事务性很高(任何电子邮件或电子邮件组可以进一步配置为具有任意优先级。)我需要能够暂停发送低优先级的电子邮件,以便可以先发送高优先级的电子邮件(为了实现这一点,工作线程只需在每次获得另外20个优先级最高的项目时从队列中选取它们。)

      Google search 显示Postfix并不真正支持优先级; Sendmail

    2. 我需要能够显示一个爆炸(批量电子邮件组)发送过程的进度给我的用户。如果我只是把我所有的邮件都交给了一个外部服务器,我就不知道实际的传递过程有多远了。

    3. 我对分析跳出消息犹豫不决,因为每个MTA的跳出消息都是不同的。Sendmail和Exchange不同 [...] . 另外,我检查收件箱的频率是多少?如果跳出消息本身没有传递呢?

    4. 我不太担心爆炸中途失败。

      如果我们说的是灾难性的失败(应用程序终止未处理的异常、电源故障等等):由于工作线程在成功传递每个电子邮件时都会将其从数据库中排出队列,因此我可以知道谁收到了blast,谁没有收到。此外,当服务在失败后重置时,它只是在队列中保留的位置重新开始。

      如果我们说的是局部故障(a ,DNS失败,等等):我只是记录失败,增加电子邮件的尝试计数器,然后稍后再试(这基本上就是SMTP规范所要求的 n

    5. 我希望滚动我自己的路线将最终允许我得到电子邮件的速度比如果我不得不依赖一个外部SMTP服务器。如果服务器不在我的控制之下,我就不得不担心速率限制;即使是这样,它仍然是一个瓶颈。我所采用的多线程体系结构意味着我可以并行连接到多个远程服务器,从而减少交付所需的总时间 n

    2 回复  |  直到 8 年前
        1
  •  2
  •   Marc B    15 年前

    假设你有两台服务器可用。一个是发送者,一个是接收者。你可以用一长串假域名在这两个域名上设置DNS(甚至只是主机文件)。就这两个服务器而言,这些域是完全有效的,因为本地DNS服务器对它们具有权威性,但就网络的其余部分而言,这些域是完全无效的。只需确保解析器在DNS之前检查主机文件。

    当然,考虑到您必须测试所有这些条件,您基本上是在创建自己的SMTP服务器,所以为什么不首先使用实际的服务器呢?我猜,对跳出消息进行一些基本的解析所需的工作将远远少于必须拿出代码块来处理postfix/sendmail/exim/等的所有故障模式。。。他们自己已经处理得很好了。

    尤其是当你认为你的发送代码从一开始就必须是完美的时候。如果一封邮件在一段时间内失败了,而只有一半的收件人收到了邮件,那么你所处的困境将远远大于几百封或几千封邮件的反弹。或者更糟的是,以多种不同的方式出现故障(有些服务器无法访问,有些因流量过大而将您列为灰色,等等……)。然而,bounce将愉快地坐在传入队列中,直到您手动处理它们,或者修补bounce解析器来处理它们。

        2
  •  1
  •   petrosmm Saeed Neamati    5 年前

    searching around Papercut 我在几台额外的机器上躺着。然后用测试地址填充数据库 *@[test-machine-*.local]

    虽然这确实工作得很好,我测试了25个发送线程,它看起来像我压倒了四台电脑运行剪纸。几百次发送尝试都经历了TCP连接失败;这些消息被正确地重新设置为稍后发送(最终确实到达)。然而,在25000封测试邮件中,大约有500封干脆就消失了——把每台测试机上Papercut文件夹中的*.eml文件加起来,只得到了约24500封。

    现在我想知道丢失的邮件是由于我的代码中的问题,还是剪纸丢弃了它在SMTP中报告为 250 OK .