Bulk Emails
Mass emails
Domain model
Notifiables
<?php
namespace JohnIt\Bc\Contacts\Domain\Models;
use Illuminate\Notifications\Notifiable;
use JohnIt\Bc\Core\Domain\Contracts\NotifiableContract;
class Contact extends Model implements NotifiableContract
{
use Notifiable;
/**
* Route notifications for the mail channel.
*
* @param \Illuminate\Notifications\Notification $notification
* @return array|string
*/
public function routeNotificationForMail($notification)
{
// Return primary email address of contact
return $this->emails()->primary()->first()?->email;
}
}
Generating emails and sending mass emails
Sending batch e-mails.
Sending batch e-mails is implemented as a 2 step procedure where first step is done by developer and second by end user. It can also be sent without user intervention by developer.
Initiating batch e-mails for user to complete
Initiating batch e-mail sending is very simple. Lets say you want to send email to first 10 people in database:
use JohnIt\Bc\Core\Domain\Models\StoredIterator;
use Domain\Correspondence\Models\BatchDistribution;
use Domain\Person\Models\Person;
$batch = BatchDistribution::forIterator(
StoredIterator::fromQueryBuilder(
Person::with('emails')->has('emails')->limit(10) //do not include ->get(). Query builder itself is needed here, not results.
),
);
return Redirect::to(route('bulk-mails.edit', ['bulk_mail' => $batch->id]));
BatchDistribution
is the key object here. You can pass it an array of related models to be saved and
be viewable later by user. For example if you are sending mass e-mails because of some event include that
event object as a second parameter in array:
use JohnIt\Bc\Core\Domain\Models\StoredIterator;
use Domain\Correspondence\Models\BatchDistribution;
use Domain\Person\Models\Person;
$batch = BatchDistribution::forIterator(
StoredIterator::fromQueryBuilder(
Person::with('emails')->has('emails')->limit(10) //do not include ->get(). Query builder itself is needed here, not results.
),
[$event, $someOtherModelToBeLinkedToThisBatchCampaign]
);
return Redirect::to(route('bulk-mails.edit', ['bulk_mail' => $batch->id]));
\Support\ProvidesPlaceholders
interface and provide your own list of placeholders.
The model object (in this case Person
) must contain an attribute called full_name
and an attribute of type array
called batch_emails
.
JohnIt\Bc\Core\Domain\Models\HasEmails
trait already contains implementation for emails
attribute.
How to initiate batch e-mails from a list in DataTable.
- On server side add this code inside controller (adjust according to your needs):
use JohnIt\Bc\Core\Domain\Models\StoredIterator;
use Domain\Correspondence\Models\BatchDistribution;
use Domain\Person\Models\Person;
use JohnIt\Bc\Ui\Presentation\DataTables\Factory;
public function tabulate(): DataTable
{
$this->authorize('viewAny', Person::class);
return Factory::make(Person::query())
...
->addActionFromObject('sendEmail', $this)
->setRowId('id');
}
public function sendEmail($table): RedirectResponse
{
$this->authorize('create', BatchDistribution::class);
//here pay attention to calling of getFilteredQuery to get current query from DataTable.
$query = $table->getFilteredQuery()->with('emails')->has('emails');
if ($query->count() == 0) {
flash(trans('bc-core-presentation::bulk-mail.flash.list_empty'))->error();
return Redirect::back();
} else {
$batch = BatchDistribution::forIterator(
StoredIterator::fromQueryBuilder($query),
);
return Redirect::to(route('bulk-mails.edit', ['bulk_mail' => $batch->id]));
}
}
On client side add this code:
<x-coreui::datatable
:dataset="[
'buttons' => [
[
'extend' => 'collection',
'text' => '<i class=' . chr(34) . 'cil-clear-all' . chr(34) . '></i> ' . trans('app.batch_actions'),
'autoClose' => true,
'className' => 'btn-info',
'buttons' => [
Auth::user()->can('create', \JohnIt\Bc\Core\Domain\Models\BulkMail::class) ? [
'extend' => 'openAction',
'method' => 'POST',
'name' => 'sendEmail',
'text' => '<i class=' . chr(34) . 'cil-mail' . chr(34) . '></i> '. trans('app.send_email'),
'confirm' => trans('bc-core-presentation::bulk-mail.send_init_confirmation'),
] : []
]
],
],
'ajax' => ['url' => route('person.tabulate')],
'order' => [1, 'asc'],
]"
>
...
</x-coreui::datatable>
Thats all.
Initiating and dispatching batch e-mails completely from code
To send batch e-mails with free text:
use JohnIt\Bc\Core\Domain\Models\StoredIterator;
use Domain\Correspondence\Models\BatchDistribution;
use Domain\Person\Models\Person;
use Domain\Correspondence\Contracts\StartBatchDistributionActionInterface;
$batch = BatchDistribution::forIterator(
StoredIterator::fromQueryBuilder(
Person::with('emails')->has('emails')->limit(10) //do not include ->get(). Query builder itself is needed here, not results.
),
[$someRelatedModel]
);
$action = app(StartBatchDistributionActionInterface::class);
$action(
$batch->id,
'Title for user reference',
'Subject',
'Body',
[], //can provide document ids here
[request('file')]
);
To send batch e-mails with your own Mailable:
use JohnIt\Bc\Core\Domain\Models\StoredIterator;
use Domain\Correspondence\Models\BatchDistribution;
use Domain\Person\Models\Person;
$batch = BatchDistribution::forIterator(
StoredIterator::fromQueryBuilder(
Person::with('emails')->has('emails')->limit(10) //do not include ->get(). Query builder itself is needed here, not results.
)
);
//provided closure will be called for each instance of $model retrieved from database.
$batch->dispatch(function ($batch, $model) {
return new YourOwnMailable($model, [], []);
});
YourOwnMailable
class must NOT implement ShouldQueue
interface as it is already being sent on background thread.