Skip to main content

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();

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:

info

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();
}
);
warning

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 (or qore-mail) in the via method.
  • The notification class should implement the SendableWithQoreMail interface which includes a function called toQoreMail
<?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

  1. The model should use the Notifiable trait
  2. 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;
}
}
tip

You can modify Laravel's internal stub files to change the notification from using default mail channel to the QoreMailChannel.