这篇文章描述了如何构建邮件内容,包括使用布局和局部视图,以及发送邮件的方法。邮件内容支持基本的 Twig 标签和表达式。Markdown 语法也受支持,详见在 Markdown 中使用 HTML一节。
邮件消息可以在 October CMS 中使用邮件视图或邮件模板发送。 邮件视图由应用程序或插件在文件系统的 /views 目录中提供。 而邮件模板则通过后端面板,经由 设置 → 邮件模板 进行管理。
可选地,邮件视图可以在 插件注册文件 中使用 registerMailTemplates 方法注册。这会自动预置一个邮件模板,允许它们通过后端面板进行自定义。
您可以通过后端面板创建存储在数据库中的邮件模板,路径为 设置 → 邮件模板。 分配给模板的 代码 是一个唯一标识符,创建后无法更改。
例如,如果您创建一个模板,其代码为 my-template 您可以使用此 PHP 代码发送它:
Mail::send('my-template', $data, function($message) {
// ...
});如果邮件模板在系统中不存在,此代码将尝试在文件系统中查找具有相同代码的邮件视图。
:::
邮件布局可以通过选择 设置 → 邮件模板 并点击 布局 选项卡来创建。它们行为类似于 CMS 布局,包含邮件消息的骨架。邮件视图和模板支持使用邮件布局。
默认情况下,October CMS 带有两个默认邮件布局。
| Layout | Code | Description |
|---|---|---|
| Default | default | Used for public facing, frontend mail. |
| System | system | Used for internal, backend mail. |
邮件视图驻留在文件系统中,并且所使用的代码表示视图文件的路径. 例如,使用代码 author.plugin::mail.message 发送邮件将使用以下文件中的内容.
├── plugins
| └── author ← "author" 片段
| └── myplugin ← "plugin" 片段
| └── views
| └── mail ← "mail" 片段
| └── message.htm ← "message" 片段
邮件视图文件内的内容最多可以包含 3 个部分:配置, 纯文本, 和 HTML 标记。各个部分通过 == 序列分隔。例如:
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>纯文本部分是可选的,一个视图可以只包含配置和HTML 标记部分。标记语法也作为一种替代语法受到支持。
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.配置部分设置邮件视图属性。支持以下配置属性。
| Property | Description |
|---|---|
| subject | the mail message subject, required. |
| layout | the mail layout code or view, optional. Default value is default. |
后端面板中的 code 值将与邮件视图路径相同。例如,
author.plugin:mail.message。
邮件视图可以注册为在后端面板中创建的默认模板。模板通过覆盖 插件注册文件 的 registerMailTemplates 方法进行注册。模板可以实现部分和布局,类似于 CMS 主题,它们分别通过 registerMailLayouts 和 registerMailPartials 进行注册。
public function registerMailTemplates()
{
return [
// ...Templates defined here
];
}
public function registerMailLayouts()
{
return [
// ...Layouts defined here
];
}
public function registerMailPartials()
{
return [
// ...Partials defined here
];
}在后端面板中,当生成模板首次保存时,自定义内容将被用于针对分配代码发送邮件。在此背景下,注册的邮件视图可被视为默认视图或备用视图。
注册数组中的 templates 键用于将视图注册为邮件模板。该方法应返回一个数组,其中键是模板代码,而值是一个 视图路径 的名称。模板代码用于引用该模板。
public function registerMailTemplates()
{
return [
'rainlab.user:activate' => 'rainlab.user::mail.activate',
'rainlab.user:restore' => 'rainlab.user::mail.restore',
];
}发送消息会使用模板代码,例如。
Mail::send('rainlab.user:activate', ...);该 registerMailLayouts 方法重写用于注册布局,并且每个布局都需要一个唯一的 code 来标识它,以及用于其内容的默认视图文件。
public function registerMailLayouts()
{
return [
'marketing' => 'acme.blog::layouts.marketing',
'notification' => 'acme.blog::layouts.notification',
];
}现在可以在模板中使用 code 值引用该布局。
layout = "marketing"Page contents...与布局类似,邮件局部视图可以通过重写 registerMailPartials 方法进行注册,并且每个局部视图都需要一个唯一的 code 来标识它,以及其内容的默认视图文件。
public function registerMailPartials()
{
return [
'tracking' => 'acme.blog::partials.tracking',
'promotion' => 'acme.blog::partials.promotion',
];
}现在可以在模板中使用 {% partial %} 标签和 code 值引用该局部。
{% partial 'tracking' %}要引用基于文件的布局,你可以将视图代码传递给 **layout** 属性。例如,此邮件视图引用了一个 acme.blog::mail.custom-layout 布局。
layout = "acme.blog::mail.custom-layout"
subject = "Your product has been added to October CMS project"
==
...使用上述代码,它将尝试从路径 plugins/acme/blog/views/mail/custom-layout.htm 加载布局内容,并且这些内容是一个示例。
<html>
<body>
<h1>HTML Contents</h1>
<div>
{{ content|raw }}
</div>
</body>
</html>基于文件的布局内容无法在管理面板中编辑。
您可以注册通过 View::share 方法在全局范围内供所有邮件模板使用的变量。
View::share('site_name', 'October CMS');这段代码可以在一个 插件注册文件 的 register 或 boot 方法中调用。使用上述示例,变量 {{ site_name }} 将在所有邮件模板中可用。
要发送消息,请使用 Mail 外观上的 send 方法,该方法接受三个参数。第一个参数是一个唯一的邮件代码,用于定位邮件视图或邮件模板。第二个参数是一个数据数组,您希望将其传递给视图。第三个参数是一个 Closure 回调,它接收一个消息实例,允许您自定义收件人、主题和邮件消息的其他方面。
// 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');
});鉴于我们在上面的例子中传递了一个包含 name 键的数组,我们可以使用以下 Twig 标记在我们的电子邮件视图中显示该值。
{{ name }}您应避免在您的消息中传递
message变量,该变量始终会被传递并允许内联嵌入附件。
October CMS 也包含一种替代方法 称为 sendTo 可以简化发送邮件。
// 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');sendTo 中的第一个参数用于收件人可以接受不同值类型。
| 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. |
sendTo 的完整签名如下所示。
Mail::sendTo($recipient, $message, $params, $callback, $options);$recipient 如上所述定义。$message 是模板名称或用于原始发送的消息内容。$params 模板中可用的变量数组。$callback 会被调用,并带有一个参数,即在 send 方法中描述的消息构建器(可选,默认为 null). 如果它不是一个可调用值,则充当下个选项参数的替代.$options 自定义发送选项,以数组形式传递 (可选)以下自定义发送$options受支持。
| 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. |
如前所述,send 方法的第三个参数是一个 Closure,它允许你指定电子邮件消息本身的各种选项。使用此 Closure,你可以指定消息的其他属性,例如抄送、密送等:
Mail::send('acme.blog:welcome', $vars, function($message) {
$message->from('us@example.tld', 'October');
$message->to('foo@example.tld')->cc('bar@example.tld');
});以下是 $message 消息构建器实例上可用方法的列表。
$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 = []);默认情况下,传递给 send 方法的视图假定包含一个邮件视图,你可以在其中除了 HTML 视图之外,另外指定一个纯文本视图来发送。
Mail::send('acme.blog:message', $data, $callback);或者,如果您只需要发送一封纯文本电子邮件,您可以使用数组中的 text 键来指定:
Mail::send(['text' => 'acme.blog:text'], $data, $callback);你可以使用 raw 方法如果你想直接发送原始字符串。此内容将由 Markdown 解析。
Mail::raw('Text to e-mail', function ($message) {
//
});此外,此字符串将由 Twig 解析,如果您希望将变量传递到此环境中,请改用 send 方法,将内容作为 raw 键传递。
Mail::send(['raw' => 'Text to email'], $vars, function ($message) {
//
});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) {
//
});要向电子邮件添加附件,请使用传递给你的闭包的 $message 对象上的 attach 方法。 attach 方法接受文件的完整路径作为其第一个参数:
Mail::send('acme.blog:welcome', $data, function ($message) {
//
$message->attach($pathToFile);
});当将文件附加到消息时,您还可以通过将 array 作为第二个参数传递给 attach 方法来指定显示名称和/或 MIME 类型:
$message->attach($pathToFile, ['as' => $display, 'mime' => $mime]);在电子邮件中嵌入内联图片通常很麻烦;但是,有一种便捷的方法可以将图片附加到电子邮件并检索相应的CID。要嵌入内联图片,请在电子邮件视图中使用message变量上的embed方法。请记住,message变量在所有邮件视图中都可用:
<body>
Here is an image:
<img src="{{ message.embed(pathToFile) }}">
</body>如果您计划使用队列电子邮件,请确保文件路径是绝对路径。为此,您只需使用 app 过滤器:
<body>
Here is an image:
{% set pathToFile = 'storage/app/media/path/to/file.jpg'|app %}
<img src="{{ message.embed(pathToFile) }}">
</body>如果您已经有一个原始数据字符串,希望将其嵌入到电子邮件中,您可以使用 message 变量上的 embedData 方法:
<body>
Here is an image from raw data:
<img src="{{ message.embedData(data, name) }}">
</body>由于发送邮件消息会大大延长你的应用程序的响应时间,许多开发者选择将消息放入队列进行后台发送。使用内置的 统一队列 API 可以轻松实现这一点。要将邮件消息放入队列,请使用 Mail facade 上的 queue 方法:
Mail::queue('acme.blog:welcome', $data, function ($message) {
//
});这个方法将自动处理把任务推送到队列中,以便在后台发送邮件消息。当然,你需要配置你的队列才能使用此功能。
如果你希望延迟投递队列中的电子邮件消息,你可以使用 later 方法。要开始,只需将你希望延迟消息发送的秒数作为该方法的第一个参数传递。
Mail::later(5, 'acme.blog:welcome', $data, function ($message) {
//
});如果您希望指定一个特定的队列来推送消息,您可以使用 queueOn 和 laterOn 方法来完成:
Mail::queueOn('queue-name', 'acme.blog:welcome', $data, function ($message) {
//
});
Mail::laterOn('queue-name', 5, 'acme.blog:welcome', $data, function ($message) {
//
});