How to close Smtp connection in SwiftMailer

老子叫甜甜 提交于 2019-11-30 13:44:25

问题


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

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.

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.


回答1:


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:

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:


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():

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.




回答3:


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

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




回答4:


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

// 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:


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

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


来源:https://stackoverflow.com/questions/13257114/how-to-close-smtp-connection-in-swiftmailer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!