Skip to content

Commit

Permalink
feat: add callback on init message (#29)
Browse files Browse the repository at this point in the history
* Add initMessageCallback and move shared methods in a trait class
* Update SesMailerInterface.php
* Add test
* Update `SesMail` facade by adding all available methods in the docblock
  • Loading branch information
leMaur authored Sep 5, 2023
1 parent 4425955 commit 7f3422c
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 101 deletions.
26 changes: 26 additions & 0 deletions src/Facades/SesMail.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,37 @@

namespace Juhasev\LaravelSes\Facades;

use Closure;
use Illuminate\Mail\MailManager;
use Illuminate\Support\Facades\Facade;
use Juhasev\LaravelSes\Contracts\BatchContract;
use Juhasev\LaravelSes\Contracts\SentEmailContract;
use Juhasev\LaravelSes\SesMailFake;
use Symfony\Component\Mime\Email;

/**
* @method SentEmailContract initMessage(Email $email)
* @method string setupTracking(string $setupTracking, SentEmailContract $sentEmail)
* @method array trackingSettings()
* @method int|null getBatchId()
* @method BatchContract|null getBatch()
* @method static setBatch(string $batch)
* @method static useInitMessageCallback(Closure $callback)
* @method static enableAllTracking()
* @method static enableOpenTracking()
* @method static enableLinkTracking()
* @method static enableBounceTracking()
* @method static enableComplaintTracking()
* @method static enableDeliveryTracking()
* @method static enableRejectTracking()
* @method static disableAllTracking()
* @method static disableOpenTracking()
* @method static disableLinkTracking()
* @method static disableBounceTracking()
* @method static disableComplaintTracking()
* @method static disableDeliveryTracking()
* @method static disableRejectTracking()
*
* @see \Illuminate\Mail\Mailer
*/
class SesMail extends Facade
Expand Down
56 changes: 2 additions & 54 deletions src/SesMailFake.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,17 @@

use Exception;
use Illuminate\Mail\Message;
use Illuminate\Support\Carbon;
use Closure;
use Illuminate\Contracts\Mail\Mailable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Testing\Fakes\MailFake;
use Juhasev\LaravelSes\Contracts\SentEmailContract;
use Juhasev\LaravelSes\Exceptions\LaravelSesTooManyRecipientsException;
use Juhasev\LaravelSes\Factories\Events\SesSentEvent;
use Symfony\Component\Mime\Email;

class SesMailFake extends MailFake implements SesMailerInterface
{
use SesMailerTrait;
use TrackingTrait;

/**
* Init message this will be called everytime
*
* @param Email $message
* @return SentEmailContract
* @throws LaravelSesTooManyRecipientsException
* @psalm-suppress NoInterfaceProperties
*/
public function initMessage(Email $message): SentEmailContract
{
$this->checkNumberOfRecipients($message);

return ModelResolver::get('SentEmail')::create([
'message_id' => $message->generateMessageId(),
'email' => $message->getTo()[0]->getAddress(),
'batch_id' => $this->getBatchId(),
'sent_at' => Carbon::now(),
'delivery_tracking' => $this->deliveryTracking,
'complaint_tracking' => $this->complaintTracking,
'bounce_tracking' => $this->bounceTracking
]);
}

/**
* Check message recipient for tracking
* Open tracking etc won't work if emails are sent to more than one recipient at a time
*
* @param Email $message
* @throws LaravelSesTooManyRecipientsException
*/
protected function checkNumberOfRecipients(Email $message)
{
if (sizeOf($message->getTo()) > 1) {
throw new LaravelSesTooManyRecipientsException("Tried to send to too many emails only one email may be set");
}
}

/**
* Send a new message using a view.
*
Expand Down Expand Up @@ -103,21 +63,9 @@ public function send($view, array $data = [], $callback = null): void

/**
* Get the array of failed recipients.
*
* @return array
*/
public function failures()
public function failures(): array
{
return [];
}

/**
* Send event
*
* @param SentEmailContract $sentEmail
*/
protected function sendEvent(SentEmailContract $sentEmail)
{
event(new SesSentEvent($sentEmail));
}
}
45 changes: 1 addition & 44 deletions src/SesMailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Closure;
use Illuminate\Contracts\Mail\Mailable as MailableContract;
use Illuminate\Mail\SentMessage;
use Illuminate\Support\Carbon;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
Expand All @@ -19,7 +18,6 @@
use Juhasev\LaravelSes\Exceptions\LaravelSesSendFailedException;
use Juhasev\LaravelSes\Exceptions\LaravelSesTemporaryServiceFailureException;
use Juhasev\LaravelSes\Exceptions\LaravelSesTooManyRecipientsException;
use Juhasev\LaravelSes\Factories\Events\SesSentEvent;
use PHPHtmlParser\Exceptions\ChildNotFoundException;
use PHPHtmlParser\Exceptions\CircularException;
use PHPHtmlParser\Exceptions\CurlException;
Expand All @@ -31,45 +29,9 @@

class SesMailer extends Mailer implements SesMailerInterface
{
use SesMailerTrait;
use TrackingTrait;

/**
* Init message (this is always called)
* Creates database entry for the sent email
*
* @param Email $message
* @return SentEmailContract
* @throws LaravelSesTooManyRecipientsException
*/
public function initMessage(Email $message): SentEmailContract
{
$this->checkNumberOfRecipients($message);

return ModelResolver::get('SentEmail')::create([
'message_id' => $message->generateMessageId(),
'email' => $message->getTo()[0]->getAddress(),
'batch_id' => $this->getBatchId(),
'sent_at' => Carbon::now(),
'delivery_tracking' => $this->deliveryTracking,
'complaint_tracking' => $this->complaintTracking,
'bounce_tracking' => $this->bounceTracking
]);
}

/**
* Check message recipient for tracking
* Open tracking etc won't work if emails are sent to more than one recipient at a time
*
* @param Email $message
* @throws LaravelSesTooManyRecipientsException
*/
protected function checkNumberOfRecipients(Email $message): void
{
if (sizeOf($message->getTo()) > 1) {
throw new LaravelSesTooManyRecipientsException("Tried to send to too many emails only one email may be set");
}
}

/**
* Throw SampleNinja exceptions
*
Expand Down Expand Up @@ -229,9 +191,4 @@ protected function getConfigurationSetName(): string
{
return App::environment() . '-ses-' . config('services.ses.region');
}

protected function sendEvent(SentEmailContract $sentEmail): void
{
event(new SesSentEvent($sentEmail));
}
}
3 changes: 3 additions & 0 deletions src/SesMailerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Juhasev\LaravelSes;

use Closure;
use Juhasev\LaravelSes\Contracts\BatchContract;
use Juhasev\LaravelSes\Contracts\SentEmailContract;
use Symfony\Component\Mime\Email;
Expand Down Expand Up @@ -49,4 +50,6 @@ public function enableAllTracking(): SesMailerInterface;
public function disableAllTracking(): SesMailerInterface;

public function trackingSettings(): array;

public function useInitMessageCallback(Closure $callback): SesMailerInterface;
}
74 changes: 74 additions & 0 deletions src/SesMailerTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Juhasev\LaravelSes;

use Closure;
use Illuminate\Support\Carbon;
use Juhasev\LaravelSes\Contracts\SentEmailContract;
use Juhasev\LaravelSes\Exceptions\LaravelSesTooManyRecipientsException;
use Juhasev\LaravelSes\Factories\Events\SesSentEvent;
use Symfony\Component\Mime\Email;

/**
* @method getBatchId()
* @mixin TrackingTrait
*/
trait SesMailerTrait
{
private ?Closure $initMessageCallback = null;

/**
* Init message (this is always called)
* Creates database entry for the sent email
*
* @param Email $message
* @return SentEmailContract
* @throws LaravelSesTooManyRecipientsException
*/
public function initMessage(Email $message): SentEmailContract
{
$this->checkNumberOfRecipients($message);

$sentEmailModel = ModelResolver::get('SentEmail')::create([
'message_id' => $message->generateMessageId(),
'email' => $message->getTo()[0]->getAddress(),
'batch_id' => $this->getBatchId(),
'sent_at' => Carbon::now(),
'delivery_tracking' => $this->deliveryTracking,
'complaint_tracking' => $this->complaintTracking,
'bounce_tracking' => $this->bounceTracking
]);

if (($callback = $this->initMessageCallback) !== null) {
$callback($sentEmailModel);
}

return $sentEmailModel;
}

/**
* Check message recipient for tracking
* Open tracking etc won't work if emails are sent to more than one recipient at a time
*
* @param Email $message
* @throws LaravelSesTooManyRecipientsException
*/
protected function checkNumberOfRecipients(Email $message): void
{
if (sizeOf($message->getTo()) > 1) {
throw new LaravelSesTooManyRecipientsException("Tried to send to too many emails only one email may be set");
}
}

public function useInitMessageCallback(Closure $callback): self
{
$this->initMessageCallback = $callback;

return $this;
}

protected function sendEvent(SentEmailContract $sentEmail): void
{
event(new SesSentEvent($sentEmail));
}
}
29 changes: 26 additions & 3 deletions tests/Unit/SesMailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Juhasev\LaravelSes\Tests\Unit;

use Illuminate\Support\Facades\Event;
use Juhasev\LaravelSes\Contracts\SentEmailContract;
use Juhasev\LaravelSes\Exceptions\LaravelSesTooManyRecipientsException;
use Juhasev\LaravelSes\Facades\SesMail;
use Juhasev\LaravelSes\Factories\Events\SesSentEvent;
Expand All @@ -11,7 +12,7 @@

class SesMailerTest extends UnitTestCase
{
public function testSendEmailEventIsSent()
public function testSendEmailEventIsSent(): void
{
SesMail::fake();
Event::fake();
Expand All @@ -25,7 +26,7 @@ public function testSendEmailEventIsSent()
SesMail::assertSent(TestMailable::class);
}

public function testExceptionIsThrownWhenTryingToSendToMoreThanOnePerson()
public function testExceptionIsThrownWhenTryingToSendToMoreThanOnePerson(): void
{
$this->expectException(LaravelSesTooManyRecipientsException::class);

Expand All @@ -37,7 +38,7 @@ public function testExceptionIsThrownWhenTryingToSendToMoreThanOnePerson()
])->send(new TestMailable());
}

public function testTrackingSettingsAreSetCorrectly()
public function testTrackingSettingsAreSetCorrectly(): void
{
SesMail::enableOpenTracking()
->enableLinkTracking()
Expand Down Expand Up @@ -85,4 +86,26 @@ public function testTrackingSettingsAreSetCorrectly()
'complaintTracking' => false,
], SesMail::trackingSettings());
}

public function testSendEmailWithInitMessageCallback(): void
{
SesMail::fake();

$customObject = new CustomObject();

$this->assertNull($customObject->messageId);

SesMail::enableAllTracking()
->useInitMessageCallback(
static fn (SentEmailContract $model) => $customObject->messageId = $model->getMessageId()
)
->to('[email protected]')
->send(new TestMailable());

$this->assertNotNull($customObject->messageId);
}
}

class CustomObject {
public ?string $messageId = null;
}

0 comments on commit 7f3422c

Please sign in to comment.