如何关闭SwiftMailer中的Smtp连接

时间:2021-07-12 02:32:37

I use SwiftMailer to send emails from a gearman worker process. I'm using the Swift_SmtpTransport class to send emails.

我使用SwiftMailer从一个齿轮工人进程发送电子邮件。我正在使用Swift_SmtpTransport类发送电子邮件。

The problem is that if this worker process stays idle for sometime, the SwiftMailer smtp connection times out. Now when the next job arrives, SwiftMailer fails to send emails as the connection has been timed out.

问题是如果此工作进程暂时保持空闲状态,则SwiftMailer smtp连接会超时。现在,当下一个作业到来时,SwiftMailer无法发送电子邮件,因为连接已超时。

Ideally, I would want to close the smtp connection after every job. I'm unable to locate a api in the class which does this specifically. Neither does unset() object works since this is a static class.

理想情况下,我想在每个工作后关闭smtp连接。我无法在课堂上找到一个具体的api。 unset()对象也不起作用,因为这是一个静态类。

5 个解决方案

#1


10  

There is a rude option: stop the transport explicitly. On subsequent calls of the method sendMail, SwiftMailer will check whether the transport is up (it is not, now) and start it again. IMNSHO, SwiftMailer should intercept the SMTP timeout and reconnect automatically.But, for now, this is the workaround:

有一个粗鲁的选择:明确停止运输。在随后调用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  
    }

}

#2


7  

I send mails in a loop and I was catching the Swift_TransportException and creating a new instance of Swift_Mailer but it wasn't the right fix: the problem is the transport, not the mailer. The solution is to issue an explicit call to Swift_SmtpTransport::stop():

我在一个循环中发送邮件,我正在捕获Swift_TransportException并创建一个新的Swift_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 ;-)
    }
}

This way, Swift detects the mailer is stopped and starts it automatically, so it recovers correctly from communication errors.

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

#3


1  

I got the same exception with symfony2 command line while sending lots of emails using SwiftMailer and AWS SES.

使用SwiftMailer和AWS SES发送大量电子邮件时,我使用symfony2命令行获得了相同的异常。

I could fix my issue by starting and stopping the transport layer each time. Look at my blog post for more details: http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html

我可以通过每次启动和停止传输层来解决我的问题。请查看我的博客文章了解更多详情:http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html

#4


1  

When pipe is broken $mailer->getTransport()->stop() will fail as well. And due to this error transport cannot be stopped. The workaround is

管道坏了时,$ 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);
        }
    }
}

#5


0  

I'm running a worker in an infinite loop using Swiftmailer and AWS SES I was getting the error:

我正在使用Swiftmailer和AWS SES在无限循环中运行一个worker我遇到了错误:

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

Solution for my script:

我的脚本的解决方案:

$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);
}

#1


10  

There is a rude option: stop the transport explicitly. On subsequent calls of the method sendMail, SwiftMailer will check whether the transport is up (it is not, now) and start it again. IMNSHO, SwiftMailer should intercept the SMTP timeout and reconnect automatically.But, for now, this is the workaround:

有一个粗鲁的选择:明确停止运输。在随后调用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  
    }

}

#2


7  

I send mails in a loop and I was catching the Swift_TransportException and creating a new instance of Swift_Mailer but it wasn't the right fix: the problem is the transport, not the mailer. The solution is to issue an explicit call to Swift_SmtpTransport::stop():

我在一个循环中发送邮件,我正在捕获Swift_TransportException并创建一个新的Swift_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 ;-)
    }
}

This way, Swift detects the mailer is stopped and starts it automatically, so it recovers correctly from communication errors.

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

#3


1  

I got the same exception with symfony2 command line while sending lots of emails using SwiftMailer and AWS SES.

使用SwiftMailer和AWS SES发送大量电子邮件时,我使用symfony2命令行获得了相同的异常。

I could fix my issue by starting and stopping the transport layer each time. Look at my blog post for more details: http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html

我可以通过每次启动和停止传输层来解决我的问题。请查看我的博客文章了解更多详情:http://www.prowebdev.us/2013/06/swiftmailersymfony2-expected-response.html

#4


1  

When pipe is broken $mailer->getTransport()->stop() will fail as well. And due to this error transport cannot be stopped. The workaround is

管道坏了时,$ 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);
        }
    }
}

#5


0  

I'm running a worker in an infinite loop using Swiftmailer and AWS SES I was getting the error:

我正在使用Swiftmailer和AWS SES在无限循环中运行一个worker我遇到了错误:

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

Solution for my script:

我的脚本的解决方案:

$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);
}