Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 11 additions & 43 deletions src/Resources/MailResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,18 @@ public static function table(Table $table): Table
->label(__('Resend'))
->icon('heroicon-o-arrow-uturn-right')
->requiresConfirmation()
->modalDescription(__('Are you sure you want to resend the selected mails?'))
->schema(fn ($records) => self::getBulkResendForm($records))
->action(function (Collection $records, array $data) {
->modalDescription(__('Each selected mail is sent again to its own recipients.'))
->action(function (Collection $records) {
// Each mail goes to its own recipients only. A shared
// recipient list would send every selected mail to
// the addresses of all the others.
foreach ($records as $record) {
(new ResendMail)->handle($record, $data['to'], $data['cc'] ?? [], $data['bcc'] ?? []);
(new ResendMail)->handle(
$record,
array_keys($record->to ?: []),
array_keys($record->cc ?: []),
array_keys($record->bcc ?: []),
);
}

Notification::make()
Expand Down Expand Up @@ -595,45 +602,6 @@ private static function getResendForm(): array
];
}

private static function getBulkResendForm($records): array
{
$extractEmails = function ($records, $field) {
return collect($records)
->map(fn ($record) => array_keys($record->{$field} ?? []))
->flatten()
->unique()
->toArray();
};

$toEmails = $extractEmails($records, 'to');
$ccEmails = $extractEmails($records, 'cc');
$bccEmails = $extractEmails($records, 'bcc');

return [
TagsInput::make('to')
->placeholder(__('Recipient(s)'))
->label(__('Recipient(s)'))
->default($toEmails)
->required()
->rules(['array'])
->nestedRecursiveRules(['email:rfc,dns']),

TagsInput::make('cc')
->placeholder(__('CC'))
->label(__('CC'))
->default($ccEmails)
->rules(['nullable', 'array'])
->nestedRecursiveRules(['email:rfc,dns']),

TagsInput::make('bcc')
->placeholder(__('BCC'))
->label(__('BCC'))
->default($bccEmails)
->rules(['nullable', 'array'])
->nestedRecursiveRules(['email:rfc,dns']),
];
}

public static function getPages(): array
{
return [
Expand Down
55 changes: 55 additions & 0 deletions tests/BulkResendTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use Backstage\Mails\Laravel\Jobs\ResendMailJob;
use Backstage\Mails\Laravel\Models\Mail;
use Backstage\Mails\Resources\MailResource;
use Backstage\Mails\Resources\MailResource\Pages\ListMails;
use Backstage\Mails\Tests\Fixtures\User;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;

function sentMail(array $to, array $cc = []): Mail
{
return Mail::create([
'uuid' => (string) Str::uuid(),
'mailer' => 'smtp',
'subject' => 'Your link',
'to' => $to,
'cc' => $cc,
'html' => '<p>Your link</p>',
]);
}

function recipientsOf(ResendMailJob $job): array
{
$read = fn (string $property) => (new ReflectionProperty($job, $property))->getValue($job);

return ['to' => $read('to'), 'cc' => $read('cc')];
}

it('resends each selected mail to its own recipients only', function () {
Queue::fake();
$this->actingAs(User::create(['name' => 'Test User', 'email' => 'test@example.com', 'password' => bcrypt('password')]));

$first = sentMail(['ann@one.test' => 'Ann'], ['boss@one.test' => null]);
$second = sentMail(['bob@two.test' => 'Bob']);

$resend = collect(MailResource::table(Table::make(new ListMails))->getFlatBulkActions())
->first(fn ($action) => $action->getName() === 'resend');

$resend->evaluate($resend->getActionFunction(), ['records' => new Collection([$first, $second])]);

$sent = [];
Queue::assertPushed(ResendMailJob::class, function (ResendMailJob $job) use (&$sent) {
$sent[] = recipientsOf($job);

return true;
});

expect($sent)->toEqualCanonicalizing([
['to' => ['ann@one.test'], 'cc' => ['boss@one.test']],
['to' => ['bob@two.test'], 'cc' => []],
]);
});