【问题标题】:Send email Asynchronously via PhpMailer通过 PhpMailer 异步发送电子邮件
【发布时间】:2015-09-24 00:51:19
【问题描述】:

我正在使用 PHPMailer 发送电子邮件,效果很好。然而问题在于,由于它同步发送电子邮件,后续页面加载需要很长时间。

我正在使用 PhpMailer,如本例所示 https://github.com/PHPMailer/PHPMailer/blob/master/examples/gmail.phps

我想知道是否有办法使电子邮件发送异步。我对此进行了研究,发现 sendmail 可以选择将 DeliveryMode 设置为“后台模式” - 来源 http://php.net/manual/en/function.mail.php

mail($to, $subject, $message, $headers, 'O DeliveryMode=b');

我想知道在 PhpMailer 中是否可以做类似的事情?有人在这方面取得过成功吗?

编辑:-(附加信息) 似乎 PhpMailer 可以配置为使用 sendmail - https://github.com/PHPMailer/PHPMailer/blob/master/class.phpmailer.php 因此,我想知道是否可以通过某种方式利用它来启用后台交付。

/**
 * Which method to use to send mail.
 * Options: "mail", "sendmail", or "smtp".
 * @type string
 */
public $Mailer = 'mail';

/**
 * The path to the sendmail program.
 * @type string
 */
public $Sendmail = '/usr/sbin/sendmail';
/**
 * Whether mail() uses a fully sendmail-compatible MTA.
 * One which supports sendmail's "-oi -f" options.
 * @type boolean
 */
public $UseSendmailOptions = true;

/**
 * Send messages using $Sendmail.
 * @return void
 */
public function isSendmail()
{
    $ini_sendmail_path = ini_get('sendmail_path');
    if (!stristr($ini_sendmail_path, 'sendmail')) {
        $this->Sendmail = '/usr/sbin/sendmail';
    } else {
        $this->Sendmail = $ini_sendmail_path;
    }
    $this->Mailer = 'sendmail';
}

另外 - 显然有办法通过 php.ini 设置 sendmail 选项 http://blog.oneiroi.co.uk/linux/php/php-mail-making-it-not-suck-using-sendmail/

我更愿意将其作为 api 调用与 php.ini 的内联参数来执行,因此这不是全局更改。有人试过吗?

【问题讨论】:

    标签: php email asynchronous phpmailer


    【解决方案1】:

    错误的方法。

    PHPMailer 不是邮件服务器,而这正是您所要求的。 SMTP 是一个冗长、健谈的协议,容易出现延迟和吞吐量缓慢,并且绝对不适合在典型的网页提交期间进行交互发送(这可能是 BlackHatSamurai 链接到的问题正在做的事情)。许多人成功地做到了这一点,但不要被愚弄认为这是一个很好的解决方案,也绝对不要尝试自己实施 MTA。

    您链接到的 gmail 示例是使用 SMTP 连接到远程服务器,这总是比在本地提交要慢。如果您通过 sendmail(或mail() - 它基本上是同一件事)提交到本地服务器并且它需要超过大约 0.1 秒,那么您做错了什么。即使 SMTP 到 localhost 也不会花费太多时间,而且发送到附近的智能主机也不太可能太慢。

    尝试使用线程进行后台处理是一大堆蠕虫,这完全不是解决此问题的方法 - 与适当的邮件服务器相比,无论您以这种方式实现什么都将是可怕的。只是不要这样做。

    正确的做法是安装本地邮件服务器,然后使用 PHPMailer 将邮件提交给它。这种方式非常快(每秒数百条消息),您必须完全什么都不做才能使其正常工作,因为这就是 PHPMailer 默认的工作方式。

    然后,邮件服务器将做它应该做的事情 - 将您的邮件排队、处理连接问题、延迟递送、退回邮件以及您没有考虑过的所有其他事情。

    【讨论】:

    • 很棒的反应。感谢您的详细解释。非常感激!!当谈到这个主题时,我有点菜鸟 - 你对选择/安装哪个邮件服务器有什么建议吗?我正在使用共享托管计划。不确定我的虚拟主机是否允许我安装自定义的。
    • 大多数 linux 发行版都使用 postfix,我更喜欢 exim。不过还有很多其他的。如果您的 ISP 不允许您安装,他们可能已经提供了一些东西,或者附近的智能主机 - 检查他们的文档,打开支持票。如果他们不这样做,我建议安装一个新的服务提供商......
    • 感谢@Synchro。我最终使用了我的托管服务提供商提供的默认邮件服务器,并注意到(带有时间戳)每封电子邮件大约需要 2 秒。所以我打电话给我的虚拟主机,他们说因为我在一个共享主机计划中,所以预计会有延迟(显然他们的邮件服务器发送到一个代理,它在发送前排队)。最后,我在 php.ini(blog.oneiroi.co.uk/linux/php/…) 中设置了“-O DeliveryMode=b”,这产生了巨大的影响。电子邮件现在以后台模式发送,我的脚本在 0.16 秒内返回!
    • 这很酷。您可能可以使用 isSendmail() 从 PHPMailer 内部设置该参数,并将 Sendmail 设置为 /usr/sbin/sendmail -O DeliveryMode=b
    • 是的,我同意,但是当我升级到未来的 PhpMailer 版本时,我必须记住手动执行此操作。更好的选择是正式更改 isSendmail() API 以接受选项作为参数 - isSendmail($options)。下一次 phpMailer 更新需要考虑的事项。
    【解决方案2】:

    根据thisphpMailer 不支持这种类型的调用。您必须编写自己的线程类才能进行异步调用。请参阅 pThreadsThread 类。找到了另一种解决方案here

    【讨论】:

    • 感谢您的回复和链接。我想知道这是否完全准确(最新),因为 phpMailer 似乎允许 sendmail 作为传递机制。我将编辑我的问题并将此信息添加到其中。
    • @rogerb,不管你必须重写 Sendmail 类来使用异步线程。
    • 使用智能主机怎么样?
    猜你喜欢
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2018-09-29
    • 1970-01-01
    • 2017-09-23
    • 2011-04-06
    相关资源
    最近更新 更多