16

我使用 SwiftMailer 从 gearman 工作进程发送电子邮件。我正在使用该Swift_SmtpTransport课程发送电子邮件。

问题是如果这个工作进程保持空闲一段时间,SwiftMailer smtp 连接就会超时。现在,当下一个作业到达时,由于连接超时,SwiftMailer 无法发送电子邮件。

理想情况下,我想在每次工作后关闭 smtp 连接。我无法在专门执行此操作的类中找到 api。对象也不起作用,unset()因为这是一个静态类。

4

4 回答 4

11

有一个粗鲁的选择:明确停止运输。在随后调用 sendMail 方法时,SwiftMailer 将检查传输是否已启动(现在未启动)并再次启动它。IMNSHO,SwiftMailer 应该拦截 SMTP 超时并自动重新连接。但是,现在,这是解决方法:

function sendMail($your_args) {
    try{ 
      $mailer = Swift_Mailer::newInstance($transport);
      $message = Swift_Message::newInstance('Wonderful Subject')
        ->setFrom(array('john@doe.com' => 'John Doe'))
        ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
        ->setBody('Here is the message itself');

      $result = $mailer->send($message);
      $mailer->getTransport()->stop();

    } catch (Swift_TransportException $e) {
      //this should be caught to understand if the issue is on transport
    } catch (Exception $e) {
      //something else happened  
    }

}
于 2013-06-14T14:12:16.407 回答
11

我在一个循环中发送邮件,我正在捕获Swift_TransportException并创建一个新实例,Swift_Mailer但这不是正确的解决方法:问题是transport,而不是mailer。解决方案是发出显式调用Swift_SmtpTransport::stop()

foreach($recipients as $to => $body){
    try{
        $message->setTo($to);
        $message->setBody(body);
        $mailer->send($message);
    }catch(Swift_TransportException $e){
        $mailer->getTransport()->stop();
        sleep(10); // Just in case ;-)
    }
}

这样,Swift 会检测到邮件程序已停止并自动启动,因此它可以从通信错误中正确恢复。

于 2014-03-25T08:40:57.680 回答
1

当管道损坏时, $mailer->getTransport()->stop() 也会失败。由于此错误,传输无法停止。解决方法是

// Let's try to send an email.
$tries = 3;
while ($tries--) {
    try {
        $sent = $this->mailer->send($message);
        break;
    } catch (\Exception $e) {
        // Connection problems
        // @see https://github.com/swiftmailer/swiftmailer/issues/490
        try {
            // Try to stop
            $this->mailer->getTransport()->stop();
        } catch (\Exception $e) {
            // Got Exception while stopping transport.
            // We have to set _started to 'false' manually, because due to an exception it is 'true' now.
            $t = $this->mailer->getTransport();
            $reflection = new \ReflectionClass($t);
            $prop = $reflection->getProperty('_started');
            $prop->setAccessible(true);
            $prop->setValue($t, false);
            $prop->setAccessible(false);
        }
    }
}
于 2017-01-27T16:09:53.313 回答
0

我正在使用 Swiftmailer 和 AWS SES 在无限循环中运行工作人员,但出现错误:

Expected response code 250 but got code "421", with message "421 Timeout waiting for data from client.

我的脚本的解决方案:

$love = true;
while($love) {
    $message = Message::to($record->to)
        ->from(array('no-reply@clouddueling.com' => $user->name()))
        ->reply(array($user->email => $user->name()))
        ->subject($record->subject)
        ->body($body->value)
        ->html(true)
        ->send();

    if (! $message->was_sent())
        throw new Swift_TransportException($errstr . ': ' . $errno);
}
于 2013-02-04T17:45:37.870 回答