diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d9616c --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# BackgroundQueueMailer + +Delegates sending emails to [adt/background-queue](https://github.com/AppsDevTeam/BackgroundQueue). + +## Installation +composer: +``` +composer require adt/background-queue-mailer +``` + +If you're not familiar with [adt/background-queue](https://github.com/AppsDevTeam/BackgroundQueue), +you should head there in the first place. + +## Usage + +To use BackgroundQueueMailer as buffer between your application and SmtpMailer, register +it in your `config.neon`: + +```neon +services: + smtpMailer: + class: \Nette\Mail\SmtpMailer + autowired: no # this is important + + nette.mailer: \ADT\Mail\BackgroundQueueMailer(@smtpMailer, 'backgroundMail') + +backgroundQueue: + callbacks: + backgroundMail: @nette.mailer::process +``` + +where `@smtpMailer` is outgoing mailer, and `backgroundMail` is unique callback name. + +Callback name has to be same in both mailer definition and BackgroundQueue callback list. If they +are not, warning is logged using Tracy. This should get resolved [here](https://github.com/AppsDevTeam/BackgroundQueue/issues/8). + +The `autowired: no` option is important because Nette DI container would not know +which `\Nette\Mail\IMailer` to inject in your application. By setting `autowired: no` on +SMTP mailer only one instance of `IMailer` interface remains. + +You cannot set `autowired: no` on `nette.mailer` because your application +would not be able to inject it. + +It is also important that you autowire `\Nette\Mail\IMailer` throughout your application. \ No newline at end of file diff --git a/composer.json b/composer.json index 2a299ee..b8ab8e2 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,12 @@ }, "minimum-stability": "stable", "require": { - "adt/background-queue": "^3.1" + "adt/background-queue": "^3.1", + "tracy/tracy": "^2.3" + }, + "autoload": { + "psr-4": { + "ADT\\Mail\\BackgroundQueueMailer\\": "src/" + } } } diff --git a/src/Mailer.php b/src/Mailer.php new file mode 100644 index 0000000..28b33d5 --- /dev/null +++ b/src/Mailer.php @@ -0,0 +1,64 @@ +next = $next; + $this->callbackName = $callbackName; + $this->backgroundQueueService = $backgroundQueueService; + } + + public function send(Mail\Message $mail) { + $entity = new BackgroundQueue\Entity\QueueEntity; + $entity->setCallbackName($this->callbackName); + $entity->setParameters([ + // Parameters are stored as LONGTEXT UTF-8, so they cannot contain binary data. + // This should be fine if we encode mail as JSON. + 'mail' => JSON::encode(serialize($mail)), + ]); + + $this->backgroundQueueService + ->publish($entity); + } + + public function process(BackgroundQueue\Entity\QueueEntity $entity) { + if ($entity->getCallbackName() !== $this->callbackName) { + Debugger::log("Callback names do not match, expected: '{$this->callbackName}' but got: '{$entity->getCallbackName()}'; skipping'", Debugger::WARNING); + return FALSE; // repeatable error + } + + $parameters = $entity->getParameters(); + $mail = unserialize(JSON::decode($parameters['mail'])); + + try { + $this->next->send($mail); + return TRUE; // done + } catch (Mail\SendException $e) { + return FALSE; // repeatable error + } + + // everything else is unrepeatable error (logged in BackgroundQueue) + } + +} \ No newline at end of file