用PHP发送电子邮件和使用Google Apps邮件作为SMTP太慢

用PHP发送电子邮件和使用Google Apps邮件作为SMTP太慢,php,zend-framework,email,gmail,google-apps,Php,Zend Framework,Email,Gmail,Google Apps,目前,我一直在使用PHP和Zend框架通过SMTP和GMail的SMTP服务器发送电子邮件。这是因为我有一个谷歌应用程序域设置来处理我的所有电子邮件,所以看起来我的电子邮件来自mailer@mycompany.com. 现在,当用户注册或执行某些操作需要我的web服务器向他们发送电子邮件时,PHP端可能需要5秒钟左右的时间来启动SMTP连接并向他们发送电子邮件。过程如下: 使用者填写登记表格 用户提交表单 PHP脚本将信息保存到数据库并向其发送电子邮件(5-10秒) 用户已重定向到其他页面 现在

目前,我一直在使用PHP和Zend框架通过SMTP和GMail的SMTP服务器发送电子邮件。这是因为我有一个谷歌应用程序域设置来处理我的所有电子邮件,所以看起来我的电子邮件来自mailer@mycompany.com.

现在,当用户注册或执行某些操作需要我的web服务器向他们发送电子邮件时,PHP端可能需要5秒钟左右的时间来启动SMTP连接并向他们发送电子邮件。过程如下:

  • 使用者填写登记表格
  • 用户提交表单
  • PHP脚本将信息保存到数据库并向其发送电子邮件(5-10秒)
  • 用户已重定向到其他页面
  • 现在,当他们刚刚提交表单时,我不能让我的web服务器出现巨大的延迟,因为用户在那里坐了10秒钟,看起来它正在加载。基本上,发送电子邮件的过程是单线程的,因此服务器在完成发送电子邮件之前无法执行任何其他操作。发送电子邮件的时间在5-10秒之间,如果电子邮件地址出现错误,有时为20秒,因此这太长了

    人们通常如何回避这样的问题

    最初我尝试了几件事:

  • 使用另一个库,如SwiftMailer。还是一样的问题。我认为SMTP/TLS握手需要额外的时间

  • 将电子邮件数据存储在数据库中,然后使用fsockopen向另一个页面发起异步请求,该页面将从数据库获取电子邮件数据并发送电子邮件。同时,我的PHP脚本可以同步继续,用户将在表单提交后立即重定向到下一页。问题是无法确认电子邮件是否已发送,或者是否失败。我想我可以在数据库表上设置一个标志,但我想向用户提供即时反馈,告知他们的电子邮件已经发送。这意味着在下一个页面上,在10秒后向另一个页面发出Ajax请求,该页面将检查数据库表上的标志,查看是否发送了该标志,然后在页面上向用户显示响应。如果他们输入了错误的电子邮件,并且无法发送电子邮件,这将不起作用,因为GMail的响应有时会花费20秒来处理一个错误案例,那么数据库标志将不会设置

  • 我提出的另一个选项是将电子邮件数据放入$_会话数组中,因此在提交页面且用户位于重定向页面后,它将向另一个页面发送ajax请求,该页面将获取会话数据并发送电子邮件,然后将响应发送回用户所在的页面,并告诉他们电子邮件已发送。这很有效,但我觉得这可能不是最好的方法


  • 所以我想知道最好的做法是什么?GMail是否因为必须进行TLS握手而太慢了?我是否应该将所有电子邮件排入数据库,每隔几分钟运行一次CRON作业来发送它们,然后在发送后将它们从数据库中删除?问题是没有即时反馈给用户他们的电子邮件发送正确。还是我不需要为此烦恼?他们是否收到电子邮件。

    您是否考虑过使用主机的电子邮件smtp服务器并手动设置发件人地址?这对我来说非常有效。如果这不是一个选项,我的第一反应将是选项3-这类似于Google mail在其web ui中选择延迟发送选项时所做的操作。

    您是否考虑过使用主机的电子邮件smtp服务器并手动设置发件人地址?这对我来说非常有效。如果这不是一个选项,我的第一反应将是选项3-这类似于Google mail在其web ui中选择延迟发送选项时所做的操作。

    编写应用程序脚本并将其用作web应用程序来处理电子邮件怎么样。您可以使用HTTP Get with params让应用程序脚本使用基本邮件服务发送电子邮件。MailApp.sendmail()

    我是一个自学成才的应用程序脚本编写者,所以我只是在这里猜测一下,但从理论上讲,这应该是可行的。我想应该是这样的

    您应该能够通过webApp url传递e.parameter末尾的键

    function doGet(e){
    var userEmail = e.parameter.email;
    
    var body = 'message here';//could even pass params for the body also.
    
    MailApp.sendEmail(userEmail, 'Subject', 'body', {noReply: true});
    }
    
    我们所有的东西都是建立在应用程序脚本上的,我有几十个电子邮件通知要发出,在应用程序脚本中,它是即时的


    希望这能有所帮助。

    写一个应用程序脚本并将其用作Web应用程序来处理电子邮件怎么样。您可以使用HTTP Get with params让应用程序脚本使用基本邮件服务发送电子邮件。MailApp.sendmail()

    我是一个自学成才的应用程序脚本编写者,所以我只是在这里猜测一下,但从理论上讲,这应该是可行的。我想应该是这样的

    您应该能够通过webApp url传递e.parameter末尾的键

    function doGet(e){
    var userEmail = e.parameter.email;
    
    var body = 'message here';//could even pass params for the body also.
    
    MailApp.sendEmail(userEmail, 'Subject', 'body', {noReply: true});
    }
    
    我们所有的东西都是建立在应用程序脚本上的,我有几十个电子邮件通知要发出,在应用程序脚本中,它是即时的


    希望这能有所帮助。

    我遇到了一个确切的问题,我实际上做的是在数据库中对它们进行排队,我有一个cronjob,它每分钟运行一次,以发送在数据库中排队的电子邮件

    顺便说一句,许多中型网站都会这样做,并告诉你应该在5分钟内或很快收到一封电子邮件……等等

    在db中保存的好处是,您可以添加一个额外的列来指示它是否已发送,如果在下一个cronjob中未发送,则可以重试


    锁定Cronjob的更新:

    请注意,这只是一个顺序逻辑,请注意步骤1、2和4是关于Cron#1的


    我有一个确切的问题,我实际上做的是,我只是在数据库中排队,我有一个cronjob,它每分钟运行一次,发送排队在数据库中的电子邮件

    顺便说一句,许多中型网站都这样做,并告诉你应该收到电子邮件
    class My_Job_SendEmail extends My_Job
    {
        /**
         * Message subject:
         * 
         * @var string|null 
         */
        protected $_subject = null;
    
        /**
         * Message body:
         * @var string|null 
         */
        protected $_message = null;
    
        /**
         * Message To:
         * @var string|null 
         */
        protected $_to = null;
    
        public function __construct(Zend_Queue $queue, array $options = null)
        {
            if (is_array($options)) {
                $this->setOptions($options);
            }
    
            parent::__construct($queue);
        }
    
        public function job()
        {
            $mail = new Zend_Mail();
            $mail->addTo($this->_to);
            $mail->setSubject($this->_subject);
            $mail->setBody($this->_message);
            return $mail->send();
        }
    }
    
    $backgroundJob = new My_Job_SendEmail(Zend_Registry::get('queue'), array(
        'to'      => $to,
        'bcc'     => $bcc,
        'subject' => $subject,
        'message' => $message,
    ));
    
    $backgroundJob->execute();