Sending Mail
Learn how to send mail and create templates.
- Message Content
- Defining Templates in the Backend Panel
- Defining Layouts in the Backend Panel
- Defining Views in the Filesystem
- Registering Templates, Layouts & Partials
- Global Variables
- Sending Mail
- Quick Sending
- Building the Message
- Sending Attachments
- Inline Attachments
- Queueing Mail
- Queueing a Mail Message
- Delayed Message Queueing
- Pushing to Specific Queues
This article describes how to build mail content, including using layouts and partials and then the methods used to send them. Basic Twig tags and expressions are supported in mail content. Markdown syntax is also supported, see the section on using HTML in Markdown for more details.
# Message Content
Mail messages can be sent in October CMS using either mail views or mail templates. A mail view is supplied by the application or plugin in the file system in the /views directory. Whereas a mail template is managed using the backend panel via Settings → Mail Templates.
Optionally, mail views can be registered in the plugin registration file with the registerMailTemplates
method. This automatically seeds a mail template allowing them to be customized using the backend panel.
# Defining Templates in the Backend Panel
You can create mail templates stored in the database using backend panel via Settings → Mail Templates. The code given to template is a unique identifier and cannot be changed once created.
For example, if you create a template with code my-template
you can send it using this PHP code:
Mail::send('my-template', $data, function($message) {
// ...
});
If the mail template does not exist in the system, this code will attempt to find a mail view in the filesystem with the same code.
# Defining Layouts in the Backend Panel
Mail layouts can be created by selecting Settings → Mail Templates and clicking the Layouts tab. These behave just like CMS layouts, they contain the scaffold for the mail message. Mail views and templates support the use of mail layouts.
By default, October CMS comes with two default mail layouts.
Layout | Code | Description |
---|---|---|
Default | default | Used for public facing, frontend mail. |
System | system | Used for internal, backend mail. |
# Defining Views in the Filesystem
Mail views reside in the file system and the code used represents the path to the view file. For example sending mail with the code author.plugin::mail.message
would use the content in following file.
├── plugins
| └── author ← "author" Segment
| └── myplugin ← "plugin" Segment
| └── views
| └── mail ← "mail" Segment
| └── message.htm ← "message" Segment
The content inside a mail view file can include up to 3 sections: configuration, plain text, and HTML markup. Sections are separated with the ==
sequence. For example:
subject = "Your product has been added to October CMS project"
Hi {{ name }},
Good news! User {{ user }} just added your product "{{ product }}" to a project.
This message was sent using no formatting (plain text)
<p>Hi {{ name }},</p>
<p>
<strong>Good news!</strong>
User {{ user }} just added your product "{{ product }}" to a project.
</p>
<p>This email was sent using formatting (HTML)</p>
The plain text section is optional and a view can contain only the configuration and HTML markup sections. Markup syntax is also supported as an alternative syntax.
layout = "default"
subject = "Your product has been added to October CMS project"
Hi {{ name }},
**Good news!** User {{ user }} just added your product "{{ product }}" to a project.
# Configuration Section
The configuration section sets the mail view properties. The following configuration properties are supported.
Property | Description |
---|---|
subject | the mail message subject, required. |
layout | the mail layout code or view, optional. Default value is default . |
# Registering Templates, Layouts & Partials
The code value in the backend panel will be the same as the mail view path. For example, author.plugin:mail.message
.
Mail views can be registered as default templates created in the backend panel. Templates are registered by overriding the registerMailTemplates
method of the plugin registration file. Templates can implement partials and layouts, similar to CMS themes, and these are registered with registerMailLayouts
and registerMailPartials
respectively.
public function registerMailTemplates()
{
return [
// ...Templates defined here
];
}
public function registerMailLayouts()
{
return [
// ...Layouts defined here
];
}
public function registerMailPartials()
{
return [
// ...Partials defined here
];
}
In the backend panel, when a generated template is saved for the first time, the customized content will be used when sending mail for the assigned code. In this context, the registered mail views can be considered default or fallback views.
# Registering a Template
The templates
key in the registration array is used for registering views as mail templates. The method should return an array where the key is the template code and the value is the name of a view path. The template code is used to reference the template.
public function registerMailTemplates()
{
return [
'rainlab.user:activate' => 'rainlab.user::mail.activate',
'rainlab.user:restore' => 'rainlab.user::mail.restore',
];
}
Sending a message uses the template code, for example.
Mail::send('rainlab.user:activate', ...);
# Registering a Layout
The registerMailLayouts
method override is used to register layouts and each layout needs a unique code
to identify it, along with the default view file for the contents.
public function registerMailLayouts()
{
return [
'marketing' => 'acme.blog::layouts.marketing',
'notification' => 'acme.blog::layouts.notification',
];
}
The layout can now be referenced in templates using the code
value.
layout = "marketing"
Page contents...
# Registering a Partial
Like layouts, mail partials can be registered with the registerMailPartials
method override and each partial needs a unique code
to identify it, along with the default view file for the contents.
public function registerMailPartials()
{
return [
'tracking' => 'acme.blog::partials.tracking',
'promotion' => 'acme.blog::partials.promotion',
];
}
The partial can now be referenced in templates using the {% partial %}
tag and code
value.
{% partial 'tracking' %}
# File-based Layouts
To reference a file-based layout, you may pass the view code to the layout property. For example, this mail view references a layout of acme.blog::mail.custom-layout
.
layout = "acme.blog::mail.custom-layout"
subject = "Your product has been added to October CMS project"
==
...
Using the code above, it will attempt to load the layout content from the path plugins/acme/blog/views/mail/custom-layout.htm and these contents are an example.
<html>
<body>
<h1>HTML Contents</h1>
<div>
{{ content|raw }}
</div>
</body>
</html>
The contents of file-based layouts cannot be edited in the admin panel.
# Global Variables
You may register variables that are globally available to all mail templates with the View::share
method.
View::share('site_name', 'October CMS');
This code could be called inside the register or boot method of a plugin registration file. Using the above example, the variable {{ site_name }}
will be available inside all mail templates.
# Sending Mail
To send a message, use the send
method on the Mail
facade which accepts three arguments. The first argument is a unique mail code used to locate either the mail view or mail template. The second argument is an array of data you wish to pass to the view. The third argument is a Closure
callback which receives a message instance, allowing you to customize the recipients, subject, and other aspects of the mail message.
// These variables are available inside the message as Twig
$vars = ['name' => 'Joe', 'user' => 'Mary'];
Mail::send('acme.blog:message', $vars, function($message) {
$message->to('admin@domain.tld', 'Admin Person');
$message->subject('This is a reminder');
});
Since we are passing an array containing the name
key in the example above, we could display the value within our e-mail view using the following Twig markup.
{{ name }}
You should avoid passing a message
variable in your message, this variable is always passed and allows the inline embedding of attachments.
# Quick Sending
October CMS also includes an alternative method called sendTo
that can simplify sending mail.
// Send to address using no name
Mail::sendTo('admin@domain.tld', 'acme.blog:message', $params);
// Send using an object's properties
Mail::sendTo($user, 'acme.blog:message', $params);
// Send to multiple addresses
Mail::sendTo(['admin@domain.tld' => 'Admin Person'], 'acme.blog:message', $params);
// Alternatively send a raw message without parameters
Mail::rawTo('admin@domain.tld', 'Hello friend');
The first argument in sendTo
is used for the recipients can take different value types.
Type | Description |
---|---|
String | a single recipient address, with no name defined. |
Array | multiple recipients where the array key is the address and the value is the name. |
Object | a single recipient object, where the email property is used for the address and the name is optionally used for the name. |
Collection | a collection of recipient objects, as above. |
The complete signature of sendTo
is as follows.
Mail::sendTo($recipient, $message, $params, $callback, $options);
$recipient
is defined as above.$message
is the template name or message contents for raw sending.$params
array of variables made available inside the template.$callback
gets called with one parameter, the message builder as described for thesend
method (optional, defaults to null). If not a callable value, works as a substitute for the next options argument.$options
custom sending options passed as an array (optional)
The following custom sending $options
are supported.
Option | Description |
---|---|
queue | specifies whether to queue the message or send it directly, optional. Default: false . |
bcc | specifies whether to add recipients as Bcc or regular To addresses. Default: false . |
# Building the Message
As previously mentioned, the third argument given to the send
method is a Closure
allowing you to specify various options on the e-mail message itself. Using this Closure you may specify other attributes of the message, such as carbon copies, blind carbon copies, etc:
Mail::send('acme.blog:welcome', $vars, function($message) {
$message->from('us@example.tld', 'October');
$message->to('foo@example.tld')->cc('bar@example.tld');
});
Here is a list of the available methods on the $message
message builder instance.
$message->from($address, $name = null);
$message->sender($address, $name = null);
$message->to($address, $name = null);
$message->cc($address, $name = null);
$message->bcc($address, $name = null);
$message->replyTo($address, $name = null);
$message->subject($subject);
$message->priority($level);
$message->attach($pathToFile, array $options = []);
// Attach a file from a raw $data string...
$message->attachData($data, $name, array $options = []);
# Mailing Plain Text
By default, the view given to the send
method is assumed to contain a mail view, where you may specify a plain text view to send in addition to the HTML view.
Mail::send('acme.blog:message', $data, $callback);
Or, if you only need to send a plain text e-mail, you may specify this using the text
key in the array:
Mail::send(['text' => 'acme.blog:text'], $data, $callback);
# Mailing Parsed Raw Strings
You may use the raw
method if you wish to e-mail a raw string directly. This content will be parsed by Markdown.
Mail::raw('Text to e-mail', function ($message) {
//
});
Additionally this string will be parsed by Twig, if you wish to pass variables to this environment, use the send
method instead, passing the content as the raw
key.
Mail::send(['raw' => 'Text to email'], $vars, function ($message) {
//
});
# Mailing Raw Strings
If you pass an array containing either text
or html
keys, this will be an explicit request to send mail. No layout or markdown parsing is used.
Mail::raw([
'text' => 'This is plain text',
'html' => '<strong>This is HTML</strong>'
], function ($message) {
//
});
# Sending Attachments
To add attachments to an e-mail, use the attach
method on the $message
object passed to your Closure. The attach
method accepts the full path to the file as its first argument:
Mail::send('acme.blog:welcome', $data, function ($message) {
//
$message->attach($pathToFile);
});
When attaching files to a message, you may also specify the display name and / or MIME type by passing an array
as the second argument to the attach
method:
$message->attach($pathToFile, ['as' => $display, 'mime' => $mime]);
# Inline Attachments
# Embedding an Image in Mail Content
Embedding inline images into your e-mails is typically cumbersome; however, there is a convenient way to attach images to your e-mails and retrieving the appropriate CID. To embed an inline image, use the embed
method on the message
variable within your e-mail view. Remember, the message
variable is available to all of your mail views:
<body>
Here is an image:
<img src="{{ message.embed(pathToFile) }}">
</body>
If you are planning to use queued emails make sure that the path of the file is absolute. To achieve that you can simply use the app filter:
<body>
Here is an image:
{% set pathToFile = 'storage/app/media/path/to/file.jpg'|app %}
<img src="{{ message.embed(pathToFile) }}">
</body>
# Embedding Raw Data in Mail Content
If you already have a raw data string you wish to embed into an e-mail message, you may use the embedData
method on the message
variable:
<body>
Here is an image from raw data:
<img src="{{ message.embedData(data, name) }}">
</body>
# Queueing Mail
# Queueing a Mail Message
Since sending mail messages can drastically lengthen the response time of your application, many developers choose to queue messages for background sending. This is easy using the built-in unified queue API. To queue a mail message, use the queue
method on the Mail
facade:
Mail::queue('acme.blog:welcome', $data, function ($message) {
//
});
This method will automatically take care of pushing a job onto the queue to send the mail message in the background. Of course, you will need to configure your queues before using this feature.
# Delayed Message Queueing
If you wish to delay the delivery of a queued e-mail message, you may use the later
method. To get started, simply pass the number of seconds by which you wish to delay the sending of the message as the first argument to the method.
Mail::later(5, 'acme.blog:welcome', $data, function ($message) {
//
});
# Pushing to Specific Queues
If you wish to specify a specific queue on which to push the message, you may do so using the queueOn
and laterOn
methods:
Mail::queueOn('queue-name', 'acme.blog:welcome', $data, function ($message) {
//
});
Mail::laterOn('queue-name', 5, 'acme.blog:welcome', $data, function ($message) {
//
});