Skip to content

Instantly share code, notes, and snippets.

@hailwood
Created September 25, 2019 01:56
Show Gist options
  • Save hailwood/2fa45c53e2b00f4ec8a8c69c2c1d3f50 to your computer and use it in GitHub Desktop.
Save hailwood/2fa45c53e2b00f4ec8a8c69c2c1d3f50 to your computer and use it in GitHub Desktop.
Laravel Alternative Mailer
<?php
namespace App\Services\AlternateMailer;
use Illuminate\Mail\Mailer;
use Swift_Mailer;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Swift_DependencyContainer;
use Illuminate\Support\ServiceProvider;
class AlternateMailerServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerSwiftMailer();
$this->registerIlluminateMailer();
}
/**
* Register the Illuminate mailer instance.
*
* @return void
*/
protected function registerIlluminateMailer()
{
$this->app->singleton('alternate-mailer.mailer', function () {
$config = $this->app->make('config')->get('alternate-mailer');
// Once we have create the mailer instance, we will set a container instance
// on the mailer. This allows us to resolve mailer classes via containers
// for maximum testability on said classes instead of passing Closures.
$mailer = new Mailer(
$this->app['view'],
$this->app['alternate-mailer.swift.mailer'],
$this->app['events']
);
if ($this->app->bound('queue')) {
$mailer->setQueue($this->app['queue']);
}
// Next we will set all of the global addresses on this mailer, which allows
// for easy unification of all "from" addresses as well as easy debugging
// of sent messages since they get be sent into a single email address.
foreach (['from', 'reply_to', 'to'] as $type) {
$this->setGlobalAddress($mailer, $config, $type);
}
return $mailer;
});
}
/**
* Set a global address on the mailer by type.
*
* @param \Illuminate\Mail\Mailer $mailer
* @param array $config
* @param string $type
* @return void
*/
protected function setGlobalAddress($mailer, array $config, $type)
{
$address = Arr::get($config, $type);
if (is_array($address) && isset($address['address'])) {
$mailer->{'always'.Str::studly($type)}($address['address'], $address['name']);
}
}
/**
* Register the Swift Mailer instance.
*
* @return void
*/
public function registerSwiftMailer()
{
$this->registerSwiftTransport();
// Once we have the transporter registered, we will register the actual Swift
// mailer instance, passing in the transport instances, which allows us to
// override this transporter instances during app start-up if necessary.
$this->app->singleton('alternate-mailer.swift.mailer', function () {
if ($domain = $this->app->make('config')->get('alternate-mailer.domain')) {
Swift_DependencyContainer::getInstance()
->register('mime.idgenerator.idright')
->asValue($domain);
}
return new Swift_Mailer($this->app['alternate-mailer.swift.transport']->driver());
});
}
/**
* Register the Swift Transport instance.
*
* @return void
*/
protected function registerSwiftTransport()
{
$this->app->singleton('alternate-mailer.swift.transport', function () {
return new TransportManager($this->app);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return [
'alternate-mailer.mailer', 'alternate-mailer.swift.mailer', 'alternate-mailer.swift.transport'
];
}
}
<?php
function getMailer($type)
{
if ($type === 'secondary') {
return app('alternate-mailer.mailer');
} else {
return app('mailer');
}
}
getMailer($type)
->to($recipient)
->send(new \App\Mail\AnEmailMessage($something));
<?php
namespace App\Services\AlternateMailer;
use Aws\Ses\SesClient;
use Psr\Log\LoggerInterface;
use Illuminate\Log\LogManager;
use Swift_SmtpTransport as SmtpTransport;
use Illuminate\Mail\Transport\LogTransport;
use Swift_SendmailTransport as SendmailTransport;
class TransportManager extends \Illuminate\Mail\TransportManager
{
/**
* Create an instance of the SMTP Swift Transport driver.
*
* @return \Swift_SmtpTransport
*/
protected function createSmtpDriver()
{
$config = $this->app->make('config')->get('alternate-mailer');
// The Swift SMTP transport instance will allow us to use any SMTP backend
// for delivering mail such as Sendgrid, Amazon SES, or a custom server
// a developer has available. We will just pass this configured host.
$transport = new SmtpTransport($config['host'], $config['port']);
if (isset($config['encryption'])) {
$transport->setEncryption($config['encryption']);
}
// Once we have the transport we will check for the presence of a username
// and password. If we have it we will set the credentials on the Swift
// transporter instance so that we'll properly authenticate delivery.
if (isset($config['username'])) {
$transport->setUsername($config['username']);
$transport->setPassword($config['password']);
}
// Next we will set any stream context options specified for the transport
// and then return it. The option is not required any may not be inside
// the configuration array at all so we'll verify that before adding.
if (isset($config['stream'])) {
$transport->setStreamOptions($config['stream']);
}
return $transport;
}
/**
* Create an instance of the Sendmail Swift Transport driver.
*
* @return \Swift_SendmailTransport
*/
protected function createSendmailDriver()
{
return new SendmailTransport($this->app['config']['alternate-mailer']['sendmail']);
}
/**
* Create an instance of the Log Swift Transport driver.
*
* @return \Illuminate\Mail\Transport\LogTransport
*/
protected function createLogDriver()
{
$logger = $this->app->make(LoggerInterface::class);
if ($logger instanceof LogManager) {
$logger = $logger->channel($this->app['config']['alternate-mailer.log_channel']);
}
return new LogTransport($logger);
}
/**
* Get the default mail driver name.
*
* @return string
*/
public function getDefaultDriver()
{
return $this->app['config']['alternate-mailer.driver'];
}
/**
* Set the default mail driver name.
*
* @param string $name
* @return void
*/
public function setDefaultDriver($name)
{
$this->app['config']['alternate-mailer.driver'] = $name;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment