使用PHP发送大量电子邮件

54

我目前在写一篇音乐博客。管理员每隔2-3天发布一篇新文章。管理员发布文章后,将立即向约5000个订阅者发送大量电子邮件。

实现大规模邮件功能的最佳方法是什么?

以下函数是否有效?

function massmail() 
{
  $content = '...';
  foreach ($recipients as $r) {
    $_content = $content . '<img src="http://xxx/trackOpenRate.php?id='.$r.'">';
    mail($r, 'subject', $_content);
  }
}

另一个问题:如果所有5000个订阅用户都在使用Yahoo Mail,Yahoo会把它视为DDOS攻击并阻止我的SMTP服务器的IP地址吗?


是的,但我想对于5000个收件人来说效果不太好。 - Matthew Scharley
如果我使用PHP mail()函数发送5000封电子邮件,但所有邮件都在BCC中,而不是通过mail()循环发送,会发生什么?这样做可以吗? - user345602
9
由于数千封BCC邮件将进入邮件头部,因此您将会遇到以下致命错误(我自己也遇到了):php-server postfix/sendmail[26573]: fatal: mailer@mydomain.com(33): unable to extract recipients: message header length exceeds safety limit - YOMorales
11个回答

49
首先,使用PHP自带的mail()函数并不是一个最佳的解决方案。它很容易被标记为垃圾邮件,并且你需要设置头部来确保你正确地发送HTML邮件。至于代码片段是否能正常工作,它确实可以,但我怀疑你是否能正确地在其中插入HTML代码,除非你指定额外的头部
我建议你看一下SwiftMailer,它支持HTML,支持不同的mime类型和SMTP身份验证(这样更不容易将你的邮件标记为垃圾邮件)。

10
根据您对邮件服务器的掌控程度,您可能还希望进行一些延迟/定时发送。如果您一次发送数百封邮件,一些目标服务器可能会阻止您。此外,您可能希望保留有关每个已发送电子邮件状态的详细日志记录。建议您拥有100多个测试电子邮件账户(您自己的测试账户),并使用不同内容逐步进行测试。 - Mercer Traieste

39
我会将所有电子邮件插入到数据库中(类似于队列),然后像你在代码中所做的那样逐个处理它们(如果你想使用swiftmailer或phpmailer等,也可以这样做)。
每发送一封邮件后,更新数据库记录发送日期/时间。
通过首先将它们放入数据库中,您可以获得:
1. 发送给谁的记录 2. 如果您的脚本超时或失败并且您必须再次运行它,则不会向同一组人发送相同的电子邮件。 3. 您可以从cron作业运行发送进程并按批处理,以便您的邮件服务器不受压倒,并跟踪已发送的内容。
请记住如何自动处理被退回的电子邮件或无效的电子邮件,以便可以将其自动从列表中删除。
如果您发送了这么多电子邮件,您肯定会收到一些反弹邮件。

18
这只是建议,不是答案:使用专门的邮件列表软件会更好。mailman 是一个常用的例子,但像 mlmmj 这样简单的东西可能已经足够了。发送大量邮件实际上比看起来要困难得多。你不仅需要发送邮件,还需要跟踪“死”地址,以避免你的邮件或更糟糕的是你的邮件服务器被标记为垃圾邮件。你必须处理人们取消订阅的情况,原因也差不多。
你可以自己实现这些功能,但特别是反弹处理是困难且无法得到回报的工作。使用邮件列表管理器将使事情变得容易得多。
至于如何使你的邮件对雅虎有吸引力,则完全是另一回事。尽管有缺点,他们似乎非常看重SPF和 DomainKey。你可能需要实施它们,并需要与你的邮件服务器管理员合作。

谢谢你的建议,Michiel。我想给预订了我管理的网站的客户发送大约4000封电子邮件。使用服务有很多好处,当我查看将这些订阅者添加到我的客户Mailchimp帐户(一个月)的费用时,增加了约30美元。比手动操作更经济实惠。 - Jason

15

您可以考虑使用CRON来进行此类操作。一次性发送大量邮件肯定不好,可能会被检测为垃圾邮件、DDoS攻击或导致服务器崩溃等问题。

因此,使用CRON可能是个很好的解决方案,一次发送100封邮件,然后等待几分钟,再发送下一个100封邮件,以此类推。


14
在从CRON运行PHP脚本时,由于您是从命令行运行PHP,因此没有php超时限制。这意味着,您可以在代码中放置一个sleep命令,计数发送的100封电子邮件后再休眠(some_time),而无需每隔几分钟设置一个CRON,脚本将会继续运行。 - Martin
2
对@Martin的陈述进行一点补充: http://www.php.net/manual/en/features.commandline.differences.php - YOMorales

11

不要使用标准的PHP工具将电子邮件发送给5000人。你会在几秒钟内被大多数ISP封禁,甚至都不知道。你应该使用邮件列表软件或者电子邮件服务提供商来完成这个任务。


2
这可能是真的,但如果你每小时保持邮件在100封以下,大多数ISP就不会给你太多麻烦;但是一旦你滥用他们的网络,那么你就会遭到惩罚!只要确保你的标题符合标准,不要滥用网络,你就会安全。 - Conrad

8
为什么不使用phplist呢?它也是基于PHP Mailer构建的,许多行业领导者都在使用它。我自己已经用过几次向我的客户发送大量邮件。 phplist的好处是您可以在域级别和时间限制级别上控制您的消息。

我们还使用了一些内部捕获系统将用户群推送到邮件列表中,然后设置cron条目每天触发一个特定的邮件。可能性是无限的,这就是开源的精彩之处!


你是不是指的是 www.phplist.org 而不是 .com? - sridesmet

4

3
此外,还要看一下PHPmailer类。 PHPMailer

如果我没弄错的话,SwiftMailer不是建立在PHPMailer之上的吗? - Extrakun
3
PHPMailer 已被很多东西所依赖,PHPList 也是其中之一。 - Elitmiar

1

你可以使用 SwiftMailer 来实现此功能。通过使用批处理。

<?php
    $message = Swift_Message::newInstance()
      ->setSubject('Let\'s get together today.')
      ->setFrom(array('myfrom@domain.com' => 'From Me'))
      ->setBody('Here is the message itself')
      ->addPart('<b>Test message being sent!!</b>', 'text/html');

    $data = mysql_query('SELECT first, last, email FROM users WHERE is_active=1') or die(mysql_error());
    while($row = mysql_fetch_assoc($data))
    {
       $message->addTo($row['email'], $row['first'] . ' ' . $row['last']);
    }

    $message->batchSend();
?>

0

我已经使用 Lotus NotusPHP 完成了它。

如果您可以访问邮件服务器或者您可以向邮件服务器管理员请求一些东西,那么这个解决方案就可以使用:

1)在邮件服务器中创建一个组:销售部门

2)将您需要加入该组的帐户分配给该

3)为该组分配一个互联网地址:salesdept@DOMAIN.com

4)使用邮件函数创建您的 PHP 脚本:

$to = "salesdept@DOMAIN.com";
mail($to, $subject, $message, $headers);



这对我来说很有效,组内所有的账户都收到了邮件。

祝你好运。


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