Skip to content

Commit

Permalink
Merge pull request #22 from mailcarrierapp/fix/retry-email-attachments
Browse files Browse the repository at this point in the history
[2.x] Fix attachments on retry email feature
  • Loading branch information
danilopolani authored Feb 20, 2024
2 parents d2745c7 + 4b8e18d commit 23f99dd
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 43 deletions.
7 changes: 1 addition & 6 deletions src/Actions/SendMail.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

namespace MailCarrier\Actions;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str;
use Laravel\SerializableClosure\SerializableClosure;
use MailCarrier\Dto\AttachmentDto;
use MailCarrier\Dto\GenericMailDto;
use MailCarrier\Dto\RecipientDto;
use MailCarrier\Dto\SendMailDto;
Expand Down Expand Up @@ -125,10 +123,7 @@ protected function send(RecipientDto $recipient): void
cc: $recipient->cc,
bcc: $recipient->bcc,
subject: $this->params->subject,
attachments: array_map(
fn (UploadedFile $file) => new AttachmentDto($file),
$recipient->attachments
),
attachments: $recipient->attachments,
remoteAttachments: $recipient->remoteAttachments,
template: $this->template,
variables: $recipient->variables,
Expand Down
30 changes: 18 additions & 12 deletions src/Dto/AttachmentDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@
namespace MailCarrier\Dto;

use Illuminate\Http\UploadedFile;
use Spatie\DataTransferObject\DataTransferObject;

class AttachmentDto extends DataTransferObject
class AttachmentDto
{
public readonly string $name;

public readonly string $content;

public readonly int $size;

public function __construct(UploadedFile $file)
public static function fromUploadedFile(UploadedFile $file): self
{
$this->name = $file->getClientOriginalName();
$this->content = base64_encode($file->getContent());
$this->size = $file->getSize();
return new self(
name: $file->getClientOriginalName(),
content: base64_encode($file->getContent()),
size: $file->getSize(),
);
}

/**
* @param string $content Base64 encoded file content
*/
public function __construct(
public readonly string $name,
public readonly string $content,
public readonly int $size
) {
//
}
}
2 changes: 1 addition & 1 deletion src/Dto/RecipientDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class RecipientDto extends DataTransferObject
#[CastWith(ContactArrayCaster::class)]
public ?array $bcc;

/** @var \Illuminate\Http\UploadedFile[] */
/** @var \MailCarrier\Dto\AttachmentDto[] */
public array $attachments = [];

/** @var \MailCarrier\Dto\RemoteAttachmentDto[] */
Expand Down
2 changes: 1 addition & 1 deletion src/Dto/SendMailDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class SendMailDto extends DataTransferObject

public ?string $trigger;

/** @var \Illuminate\Http\UploadedFile[] */
/** @var \MailCarrier\Dto\AttachmentDto[] */
public array $attachments = [];

/** @var \MailCarrier\Dto\RemoteAttachmentDto[] */
Expand Down
20 changes: 19 additions & 1 deletion src/Http/Controllers/MailCarrierController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use MailCarrier\Actions\Attachments\Download;
use MailCarrier\Actions\SendMail;
use MailCarrier\Dto\AttachmentDto;
use MailCarrier\Dto\SendMailDto;
use MailCarrier\Enums\ApiErrorKey;
use MailCarrier\Exceptions\AttachmentNotDownloadableException;
Expand Down Expand Up @@ -39,7 +42,22 @@ public function send(SendMailRequest $request, SendMail $sendMail): JsonResponse
{
try {
$sendMail->run(
new SendMailDto($request->validated())
new SendMailDto([
...$request->safe()->except(['recipients', 'attachments']),
'recipients' => !$request->has('recipients')
? null
: $request->collect('recipients')
->map(fn (array $recipient, int $i) => [
...$recipient,
'attachments' => Collection::make($request->file("recipients.{$i}.attachments"))
->map(fn (UploadedFile $file) => AttachmentDto::fromUploadedFile($file))
->all(),
])
->all(),
'attachments' => Collection::make($request->file('attachments'))
->map(fn (UploadedFile $file) => AttachmentDto::fromUploadedFile($file))
->all(),
])
);
} catch (MissingVariableException $e) {
report($e);
Expand Down
15 changes: 15 additions & 0 deletions src/Models/Log.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,19 @@ public function prunable(): EloquentBuilder
fn (EloquentBuilder $query, string $period) => $query->where('created_at', '<=', Carbon::now()->sub(...explode(' ', $period)))
);
}

public function isFailed(): bool
{
return $this->status === LogStatus::Failed;
}

public function isPending(): bool
{
return $this->status === LogStatus::Pending;
}

public function isSent(): bool
{
return $this->status === LogStatus::Sent;
}
}
56 changes: 47 additions & 9 deletions src/Resources/LogResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@
use Filament\Tables;
use Filament\Tables\Actions\Action as TablesAction;
use Filament\Tables\Enums\FiltersLayout;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\View;
use Illuminate\Support\HtmlString;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use MailCarrier\Actions\Logs\GetTriggers;
use MailCarrier\Actions\SendMail;
use MailCarrier\Dto\AttachmentDto;
use MailCarrier\Dto\LogTemplateDto;
use MailCarrier\Dto\SendMailDto;
use MailCarrier\Enums\LogStatus;
use MailCarrier\Facades\MailCarrier;
use MailCarrier\Models\Attachment;
use MailCarrier\Models\Log;
use MailCarrier\Models\Template;
use MailCarrier\Resources\LogResource\Pages;
Expand All @@ -28,7 +32,7 @@ class LogResource extends Resource
{
protected static ?string $model = Log::class;

protected static ?string $navigationIcon = 'heroicon-o-paper-airplane';
protected static ?string $navigationIcon = 'heroicon-o-envelope';

/**
* List all the records.
Expand Down Expand Up @@ -151,22 +155,29 @@ protected static function getTableActions(): array
->modalCancelActionLabel('Close')
->modalFooterActionsAlignment(Alignment::Right),

Tables\Actions\Action::make('manual_retry')
Tables\Actions\Action::make('resend_email')
->label(fn (Log $record) => $record->isFailed() ? 'Retry now' : 'Send again')
->icon('heroicon-o-arrow-path')
->color(Color::Orange)
->color(fn (Log $record) => $record->isFailed() ? Color::Orange : 'primary')
->form([
FileUpload::make('attachments')
->label('Additional attachments')
->helperText('Any extra attachment will be sent along the original ones')
->multiple()
->preserveFilenames()
->storeFiles(false),
])
->modalWidth('2xl')
->modalIcon('heroicon-o-arrow-path')
->modalDescription('Are you sure you want to manually retry to send this email?')
->modalSubmitActionLabel('Retry')
->modalDescription(
fn (Log $record) => $record->isFailed()
? 'Are you sure you want to manually retry to send this email?'
: 'Are you sure you want to to send again this email?'
)
->modalSubmitActionLabel(fn (Log $record) => $record->isFailed() ? 'Retry' : 'Resend')
->modalFooterActionsAlignment(Alignment::Right)
->action(fn (?Log $record, array $data) => $record ? static::retryEmail($record, $data) : null)
->visible(fn (?Log $record) => $record?->status === LogStatus::Failed),
->action(fn (?Log $record, array $data) => $record ? static::resendEmail($record, $data) : null)
->visible(fn (?Log $record) => $record?->status !== LogStatus::Pending),
];
}

Expand Down Expand Up @@ -197,8 +208,15 @@ protected static function getTemplateValue(LogTemplateDto $templateDto, ?Templat
);
}

protected static function retryEmail(Log $log, array $data): void
protected static function resendEmail(Log $log, array $data): void
{
// Update the status to Failed just to send email again
if ($log->isSent()) {
$log->update([
'status' => LogStatus::Failed,
]);
}

try {
SendMail::resolve()->run(
new SendMailDto([
Expand All @@ -212,7 +230,27 @@ protected static function retryEmail(Log $log, array $data): void
'trigger' => $log->trigger,
'tags' => $log->tags ?: [],
'metadata' => $log->metadata ?: [],
'attachments' => $data['attachments'] ?? [],
'attachments' => $log->attachments
->map(
fn (Attachment $attachment) => !$attachment->canBeDownloaded()
? null
: new AttachmentDto(
name: $attachment->name,
content: $attachment->content,
size: $attachment->size
)
)
->filter()
->merge(
Collection::make($data['attachments'])->map(
fn (TemporaryUploadedFile $file) => new AttachmentDto(
name: $file->getClientOriginalName(),
content: base64_encode(file_get_contents($file->getRealPath())),
size: $file->getSize()
)
)
)
->all(),
]),
$log
);
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/TemplateResource/Pages/EditTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ protected function sendTestMail(array $data): void
Notification::make()
->title('Test email sent correctly')
->icon('heroicon-o-mail')
->iconColor('success')
->success()
->send();
}
}
6 changes: 3 additions & 3 deletions tests/Feature/Logs/CreateFromGenericMailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
template: Template::factory()->create(),
variables: ['name' => 'foo'],
attachments: [
new AttachmentDto(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
AttachmentDto::fromUploadedFile(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
],
remoteAttachments: [
new RemoteAttachmentDto(
Expand Down Expand Up @@ -290,7 +290,7 @@
template: Template::factory()->create(),
variables: ['name' => 'foo'],
attachments: [
new AttachmentDto(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
AttachmentDto::fromUploadedFile(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
],
remoteAttachments: [
new RemoteAttachmentDto(
Expand Down Expand Up @@ -402,7 +402,7 @@
template: Template::factory()->create(),
variables: ['name' => 'foo'],
attachments: [
new AttachmentDto(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
AttachmentDto::fromUploadedFile(UploadedFile::fake()->create('image.jpg', 100, 'image/jpeg')),
],
remoteAttachments: [
new RemoteAttachmentDto(
Expand Down
19 changes: 10 additions & 9 deletions tests/Feature/SendMailTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Mail;
use MailCarrier\Actions\SendMail;
use MailCarrier\Dto\AttachmentDto;
use MailCarrier\Dto\GenericMailDto;
use MailCarrier\Dto\RemoteAttachmentDto;
use MailCarrier\Dto\SendMailDto;
Expand Down Expand Up @@ -722,8 +723,8 @@
'subject' => 'Welcome!',
'recipient' => '[email protected]',
'attachments' => [
$attachment1 = UploadedFile::fake()->image('foo.jpg'),
$attachment2 = UploadedFile::fake()->image('bar.jpg'),
AttachmentDto::fromUploadedFile($attachment1 = UploadedFile::fake()->image('foo.jpg')),
AttachmentDto::fromUploadedFile($attachment2 = UploadedFile::fake()->image('bar.jpg')),
],
]));

Expand Down Expand Up @@ -820,7 +821,7 @@
'subject' => 'Welcome!',
'recipient' => '[email protected]',
'attachments' => [
$attachment = UploadedFile::fake()->image('foo.jpg'),
AttachmentDto::fromUploadedFile($attachment = UploadedFile::fake()->image('foo.jpg')),
],
'remoteAttachments' => [
new RemoteAttachmentDto([
Expand Down Expand Up @@ -868,13 +869,13 @@
[
'email' => '[email protected]',
'attachments' => [
$attachment1 = UploadedFile::fake()->image('foo.jpg'),
AttachmentDto::fromUploadedFile($attachment1 = UploadedFile::fake()->image('foo.jpg')),
],
],
[
'email' => '[email protected]',
'attachments' => [
$attachment2 = UploadedFile::fake()->image('bar.jpg'),
AttachmentDto::fromUploadedFile($attachment2 = UploadedFile::fake()->image('bar.jpg')),
],
],
],
Expand Down Expand Up @@ -1012,7 +1013,7 @@
[
'email' => '[email protected]',
'attachments' => [
$attachment1 = UploadedFile::fake()->image('foo1.jpg'),
AttachmentDto::fromUploadedFile($attachment1 = UploadedFile::fake()->image('foo1.jpg')),
],
'remoteAttachments' => [
new RemoteAttachmentDto([
Expand All @@ -1024,7 +1025,7 @@
[
'email' => '[email protected]',
'attachments' => [
$attachment2 = UploadedFile::fake()->image('bar1.jpg'),
AttachmentDto::fromUploadedFile($attachment2 = UploadedFile::fake()->image('bar1.jpg')),
],
'remoteAttachments' => [
new RemoteAttachmentDto([
Expand Down Expand Up @@ -1100,7 +1101,7 @@
'template' => 'welcome',
'subject' => 'Welcome!',
'attachments' => [
$globalAttachment = UploadedFile::fake()->image('globalRaw.jpg'),
AttachmentDto::fromUploadedFile($globalAttachment = UploadedFile::fake()->image('globalRaw.jpg')),
],
'remoteAttachments' => [
new RemoteAttachmentDto([
Expand All @@ -1121,7 +1122,7 @@
[
'email' => '[email protected]',
'attachments' => [
$recipientAttachment = UploadedFile::fake()->image('bar.jpg'),
AttachmentDto::fromUploadedFile($recipientAttachment = UploadedFile::fake()->image('bar.jpg')),
],
],
],
Expand Down

0 comments on commit 23f99dd

Please sign in to comment.