Skip to content

Commit

Permalink
Force reconnection to fix mailing on daemon queues.
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Apr 29, 2015
1 parent bc924d5 commit af8eb1f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
14 changes: 14 additions & 0 deletions src/Illuminate/Mail/Mailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ public function plain($view, array $data, $callback)
*/
public function send($view, array $data, $callback)
{
$this->forceReconnection();

// First we need to parse the view, which could either be a string or an array
// containing both an HTML and plain text versions of the view which should
// be used when sending an e-mail. We will extract both of them out here.
Expand Down Expand Up @@ -271,6 +273,18 @@ protected function getQueuedCallable(array $data)
return $data['callback'];
}

/**
* Force the transport to re-connect.
*
* This will prevent errors in daemon queue situations.
*
* @return void
*/
protected function forceReconnection()
{
$this->getSwiftMailer()->getTransport()->stop();
}

/**
* Add the content to a given message.
*
Expand Down
40 changes: 29 additions & 11 deletions tests/Mail/MailMailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ public function testMailerSendSendsMessageWithProperViewContent()
{
unset($_SERVER['__mailer.test']);
$mailer = $this->getMock('Illuminate\Mail\Mailer', array('createMessage'), $this->getMocks());
$message = m::mock('StdClass');
$message = m::mock('Swift_Mime_Message');
$mailer->expects($this->once())->method('createMessage')->will($this->returnValue($message));
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->with('foo', array('data', 'message' => $message))->andReturn($view);
$view->shouldReceive('render')->once()->andReturn('rendered.view');
$message->shouldReceive('setBody')->once()->with('rendered.view', 'text/html');
$message->shouldReceive('setFrom')->never();
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$message->shouldReceive('getSwiftMessage')->once()->andReturn($message);
$mailer->getSwiftMailer()->shouldReceive('send')->once()->with($message, array());
$mailer->send('foo', array('data'), function($m) { $_SERVER['__mailer.test'] = $m; });
Expand All @@ -34,7 +34,7 @@ public function testMailerSendSendsMessageWithProperPlainViewContent()
{
unset($_SERVER['__mailer.test']);
$mailer = $this->getMock('Illuminate\Mail\Mailer', array('createMessage'), $this->getMocks());
$message = m::mock('StdClass');
$message = m::mock('Swift_Mime_Message');
$mailer->expects($this->once())->method('createMessage')->will($this->returnValue($message));
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->with('foo', array('data', 'message' => $message))->andReturn($view);
Expand All @@ -43,7 +43,7 @@ public function testMailerSendSendsMessageWithProperPlainViewContent()
$message->shouldReceive('setBody')->once()->with('rendered.view', 'text/html');
$message->shouldReceive('addPart')->once()->with('rendered.view', 'text/plain');
$message->shouldReceive('setFrom')->never();
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$message->shouldReceive('getSwiftMessage')->once()->andReturn($message);
$mailer->getSwiftMailer()->shouldReceive('send')->once()->with($message, array());
$mailer->send(array('foo', 'bar'), array('data'), function($m) { $_SERVER['__mailer.test'] = $m; });
Expand All @@ -55,7 +55,7 @@ public function testMailerSendSendsMessageWithProperPlainViewContentWhenExplicit
{
unset($_SERVER['__mailer.test']);
$mailer = $this->getMock('Illuminate\Mail\Mailer', array('createMessage'), $this->getMocks());
$message = m::mock('StdClass');
$message = m::mock('Swift_Mime_Message');
$mailer->expects($this->once())->method('createMessage')->will($this->returnValue($message));
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->with('foo', array('data', 'message' => $message))->andReturn($view);
Expand All @@ -64,7 +64,7 @@ public function testMailerSendSendsMessageWithProperPlainViewContentWhenExplicit
$message->shouldReceive('setBody')->once()->with('rendered.view', 'text/html');
$message->shouldReceive('addPart')->once()->with('rendered.view', 'text/plain');
$message->shouldReceive('setFrom')->never();
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$message->shouldReceive('getSwiftMessage')->once()->andReturn($message);
$mailer->getSwiftMailer()->shouldReceive('send')->once()->with($message, array());
$mailer->send(array('html' => 'foo', 'text' => 'bar'), array('data'), function($m) { $_SERVER['__mailer.test'] = $m; });
Expand Down Expand Up @@ -131,14 +131,14 @@ public function testMailerCanQueueMessagesToItselfLaterOnAnotherQueue()
public function testMessagesCanBeLoggedInsteadOfSent()
{
$mailer = $this->getMock('Illuminate\Mail\Mailer', array('createMessage'), $this->getMocks());
$message = m::mock('StdClass');
$message = m::mock('Swift_Mime_Message');
$mailer->expects($this->once())->method('createMessage')->will($this->returnValue($message));
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->with('foo', array('data', 'message' => $message))->andReturn($view);
$view->shouldReceive('render')->once()->andReturn('rendered.view');
$message->shouldReceive('setBody')->once()->with('rendered.view', 'text/html');
$message->shouldReceive('setFrom')->never();
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$message->shouldReceive('getTo')->once()->andReturn(array('[email protected]' => 'Taylor'));
$message->shouldReceive('getSwiftMessage')->once()->andReturn($message);
$mailer->getSwiftMailer()->shouldReceive('send')->never();
Expand All @@ -154,7 +154,7 @@ public function testMessagesCanBeLoggedInsteadOfSent()
public function testMailerCanResolveMailerClasses()
{
$mailer = $this->getMock('Illuminate\Mail\Mailer', array('createMessage'), $this->getMocks());
$message = m::mock('StdClass');
$message = m::mock('Swift_Mime_Message');
$mailer->expects($this->once())->method('createMessage')->will($this->returnValue($message));
$view = m::mock('StdClass');
$container = new Illuminate\Container\Container;
Expand All @@ -169,7 +169,7 @@ public function testMailerCanResolveMailerClasses()
$view->shouldReceive('render')->once()->andReturn('rendered.view');
$message->shouldReceive('setBody')->once()->with('rendered.view', 'text/html');
$message->shouldReceive('setFrom')->never();
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$message->shouldReceive('getSwiftMessage')->once()->andReturn($message);
$mailer->getSwiftMailer()->shouldReceive('send')->once()->with($message, array());
$mailer->send('foo', array('data'), 'FooMailer');
Expand All @@ -183,7 +183,7 @@ public function testGlobalFromIsRespectedOnAllMessages()
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->andReturn($view);
$view->shouldReceive('render')->once()->andReturn('rendered.view');
$mailer->setSwiftMailer(m::mock('StdClass'));
$this->setSwiftMailer($mailer);
$mailer->alwaysFrom('[email protected]', 'Taylor Otwell');
$me = $this;
$mailer->getSwiftMailer()->shouldReceive('send')->once()->with(m::type('Swift_Message'), array())->andReturnUsing(function($message) use ($me)
Expand All @@ -198,6 +198,8 @@ public function testFailedRecipientsAreAppendedAndCanBeRetrieved()
{
unset($_SERVER['__mailer.test']);
$mailer = $this->getMailer();
$mailer->getSwiftMailer()->shouldReceive('getTransport')->andReturn($transport = m::mock('Swift_Transport'));
$transport->shouldReceive('stop');
$view = m::mock('StdClass');
$mailer->getViewFactory()->shouldReceive('make')->once()->andReturn($view);
$view->shouldReceive('render')->once()->andReturn('rendered.view');
Expand All @@ -216,6 +218,16 @@ protected function getMailer()
}


public function setSwiftMailer($mailer)
{
$swift = m::mock('Swift_Mailer');
$swift->shouldReceive('getTransport')->andReturn($transport = m::mock('Swift_Transport'));
$transport->shouldReceive('stop');
$mailer->setSwiftMailer($swift);
return $mailer;
}


protected function getMocks()
{
return array(m::mock('Illuminate\Contracts\View\Factory'), m::mock('Swift_Mailer'));
Expand All @@ -229,4 +241,10 @@ public function send($message, &$failed)
{
$failed[] = '[email protected]';
}
public function getTransport()
{
$transport = m::mock('Swift_Transport');
$transport->shouldReceive('stop');
return $transport;
}
}

11 comments on commit af8eb1f

@nik-418
Copy link

@nik-418 nik-418 commented on af8eb1f May 1, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@taylorotwell Under what conditions would there be mailer errors without the reconnect? Just noticed this commit and I'm curious about the reasons behind it.

@matthewdaniel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when the queue:worker in daemon mode attempts to send queued emails.

@nik-418
Copy link

@nik-418 nik-418 commented on af8eb1f May 1, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewdaniel and it would always fail before this commit?

@nik-418
Copy link

@nik-418 nik-418 commented on af8eb1f May 7, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@taylorotwell any chance of this seeing a tagged 5.0 release?

@GrahamCampbell
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any chance of this seeing a tagged 5.0 release?

A 5.0.x tag will be coming shortly, I'm sure. In the meanwhile, you can append @dev to your version constraint for laravel if you really need this fix.

@taylorotwell
Copy link
Member Author

@taylorotwell taylorotwell commented on af8eb1f May 7, 2015 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GrahamCampbell
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 :)

@nik-418
Copy link

@nik-418 nik-418 commented on af8eb1f May 7, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TY! 👍

@garf
Copy link

@garf garf commented on af8eb1f Apr 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.

@idoadiv
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea why I have this is my Code but I still get errors?

@lukepolo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same : fwrite(): send of 30 bytes failed with errno=32 Broken pipe in /var/www/html/prod/forcebook/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:232

Latest version of 5.2

Please sign in to comment.