Mailing
Qore includes mailing, mail templates and more by default.
You are not required to use this when sending e-mails.
Mail templates use Twig
and may contain pre-defined variables.
Getting started
Scheduling
Qore e-mails can be planned to be sent in the future instead of directly.
Qore comes with the qore:mail
command which will send e-mails that are due for sending. You should schedule this command:
$schedule->command('qore:mail')->everyMinute();
Menu items
Skeleton ships with the following menu items in MakesMenu
:
// Add group: "Mailing"
$this->addTabGroup(1, [
'icon' => 'forward_to_inbox',
'title' => __('Mailing'),
'items' => [
$this->resourceToMenuItem(resource(MailTemplate::class)),
$this->resourceToMenuItem(resource(MailMessage::class)),
$this->resourceToMenuItem(resource(MailFooter::class)),
$this->resourceToMenuItem(resource(TwigTemplate::class)),
[
'route' => '/settings/mailing',
'title' => __('Settings'),
'permissions' => [
'mail management'
]
],
]
]);
Mail templates
Every e-mail message can be sent from a mail template.
Variable lists
You can select a variable list which will determine which resource and which fields (variables) will be availbable in the (Twig) content.
You can define a variable list, for example when sending e-mails to employees:
class EmployeeVariableList extends VariableList
{
// Will be shown in the dropdown (must be unique)
public function name(): string
{
return 'Employee';
}
// The variables that will be shown for the user on the right side
public function variables(): array
{
return [
__('Employee') => $this->resourceToTags(resource('employees'), 'employee'),
'Custom' => [
'somevariable'
]
];
}
// The resource for this variable list
public function resource(): QoreResource
{
return resource('employees');
}
// Here the variables are mapped to actual values
public function map(int|null $modelId, array $args = []): array
{
$resource = resource('employees');
$employee = $resource->retrieve($modelId);
return [
'employee' => $this->resourceToVariables($resource, $employee)
'somevariable' => 'somevalue'
];
}
// Optional: group for the dropdown
public function group(): string
{
return 'Modules';
}
// Optional: to retrieve the e-mail address for the model
public function getEmailAddress(Model $model): string
{
return $model->{$this->emailColumn()};
}
}
You can then register your VariableList
in a Service Provider:
app(VariableListRegistrar::class)->register(new EmployeeVariableList());
Layouts
E-mail messages can be sent with a wrapping layout (optional).
You can define your own layout in recources/views/mailing/layouts
.
Layouts are automatically detected for the dropdown.
Masking sensitive data
Sometimes you need to mask variables that contain sensitive data.
You can do this in the content of your mail templates:
Your new password is: [confidential]{{ password }}[/confidential].
Sending e-mails
You can send e-mails from your mail templates, or manually:
Mails will respect the configured QUEUE_CONNECTION
// Required parameters
QoreMail::send(
codeName: 'Forgot password', // Name of the mail template
to: $this->id, // List of ids or single id
);
// All parameters
QoreMail::send(
// code_name of the mail template or MailTemplate instance
codeName: 'Forgot password',
// array of ids used to fetch models through template->model(), or a Model instance
to: [1, 2],
// Array of arguments passed to the mailTemplate->variableList->map function
args: [
'token' => $token
],
// Moment when the e-mail is due for sending or null
plannedAt: Carbon::now()->addHours(2),
// Additional metadata that should be saved on the message table as json
metadata: [
'some' => 'data'
],
// Instigator (Model that triggered sending the mail, or is related to the mail) For example an invoice
instigator: $this->model,
// Optional closure to modify the mail message just before sending
messageMutator: function (MailMessage $message) {
// Setting custom headers
$message->headers = ['X-Custom-Header' => 'My header information'];
// Setting reply to address
$message->reply_to = [
'address' => 'invoicing#INV.24.00001@qlic.nl',
'name' => 'Finance | Qlic Internet Solutions'
];
// Or edit the content
$message->content = 'Edited mail content';
// Make sure to save..
$message->save();
}
);
Mail templates can be defined per tenant, so when you need to use mail templates outside of the authentication layer, you need to identify with a tenant first.
Fore example, if you want to send the Forgot password
mail for a user, add this to your User
model:
public function sendPasswordResetNotification($token)
{
if (!tenant()) {
if ($this->tenant_id) {
tenancy()->initialize($this->tenant_id);
} else {
tenancy()->initialize(tenants()->first());
}
boot_extensions();
}
QoreMail::send('Forgot password', $this->id, ['token' => $token]);
}
Manually dispatching the job
Sometimes you need more control when sending e-mails. Here is an example:
$mailList = resource('mail_lists')->retrieve($mailListId);
$to = $mailList->getFilteredModels()->pluck('id')->toArray();
$mailTemplate = MailTemplate::find($mailTemplateId);
(new BulkMessageMailer(
$mailTemplate, // Mail template
$to, // Receiver
['form_id' => $this->model->id], // Data for the mail list
null, // Planned at date
[], // Metadata to be stored in the table as json
$this->model // Instigator (optional related model which triggered/related to the mail),
function (MailMessage $message) { // Optional closure to modify the mail message just before sending
$message->content = 'Edited mail content'
$message->save();
}
))->send();
Notifications
You may have a Laravel Notification that you would like to send via email. Instead of using the default Laravel 'mail'
channel you should use QoreMailChannel
.
Preparing the notification
- The notification class should return
QoreMailChannel
(orqore-mail
) in the via method. - The notification class should implement the
SendableWithQoreMail
interface which includes a function calledtoQoreMail
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Qore\System\Mailing\Notifications\QoreMailChannel;
use Qore\System\Mailing\Notifications\QoreMailMessage;
use Qore\System\Mailing\Notifications\SendableWithQoreMail;
class NotificationExample extends Notification implements SendableWithQoreMail
{
use Queueable;
public function via($notifiable): array
{
return [QoreMailChannel::class]; // or return ['qore-mail']
}
...
public function toQoreMail(mixed $notifiable): QoreMailMessage
{
return QoreMailMessage::make('My template password')
->args([
'user' => [
'name' => $this->user->name,
'email' => $this->user->email
]
])
->planAt(Carbon::now()->addHours(2));
}
}
Preparing the model
- The model should use the
Notifiable
trait - Implement the
routeNotificationForQoreMail
method
Qore mailing templates use models to send mail messages to, so routeNotificationForQoreMail
should return an eloquent model.
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class Contact extends Model
{
use Notifiable;
public function routeNotificationForQoreMail(Notification $notification)
{
return $this;
}
}
You can modify Laravel's internal stub files to change the notification from using default mail
channel to the QoreMailChannel
.