发送邮件
发送邮件
Yii 支持电子邮件信息的合成和发送。然而,框架核心只提供内容组合功能和基本接口。实际的邮件发送机制应该由扩展提供,因为不同的项目可能需要不同的实现,它通常依赖于外部服务和库。
对于最常见的情况,你可以使用 yii2-swiftmailer
官方扩展,一般在 Yii2 框架应用模板安装后就自动安装了这个扩展。
当然你可以使用 yii2-symfonymailer
官方扩展。这个扩展为 Yii 框架 2.0 提供了一个 Symfony Mailer 邮件解决方案,在本文后面的内容中,都将介绍。
配置
邮件组件配置取决于您所选择的扩展。一般来说,你的应用程序配置应该是这样的:
return [
//....
'components' => [
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// 包含用于撰写邮件消息的视图文件的目录,默认值是 '@app/mail'
'viewPath' => '@common/mail',
// 'useFileTransport' => true,
// 'useFileTransport' 的默认值为 true,即将所有邮件发送到一个文件。你必须将它设置为 false,并为邮件发送者配置一个传输来发送真实的邮件。
'useFileTransport' => false,
// 当 'useFileTransport' 为 false 时,才配置。
'transport' => [
'class' => 'Swift_SmtpTransport',
'encryption' => 'tls',
'host' => 'your_mail_server_host',
'port' => 'your_smtp_port',
'username' => 'your_username',
'password' => 'your_password',
],
],
],
];
你也可以跳过 transport
属性的配置。在这种情况下,默认的 \Swift_SendmailTransport
传输将被用于发送电子邮件。
你在配置中使用 ‘constructArgs’ 键,来指定传输构造函数参数。您还可以指定插件列表,这些插件应该使用 ‘plugins’ 键,来注册到传输。例如:
'transport' => [
'class' => 'Swift_SmtpTransport',
'constructArgs' => ['localhost', 25],
'plugins' => [
[
'class' => 'Swift_Plugins_ThrottlerPlugin',
'constructArgs' => [20],
],
],
],
基本用法
一旦 mailer
组件被配置,你就可以使用下面的代码来发送电子邮件消息:
Yii::$app->mailer->compose()
->setFrom('from@domain.com')
->setTo('to@domain.com')
->setSubject('Message subject')
->setTextBody('Plain text content')
->setHtmlBody('<b>HTML content</b>')
->send();
在上面的例子中,compose()
方法创建了一个邮件消息的实例,然后填充并发送该邮件消息。如果需要,你可以在这个过程中加入更复杂的逻辑,例如:
$message = Yii::$app->mailer->compose();
// 游客
if (Yii::$app->user->isGuest) {
$message->setFrom('from@domain.com');
} else {
$message->setFrom(Yii::$app->user->identity->email);
}
$message->setTo(Yii::$app->params['adminEmail'])
->setSubject('Message subject')
->setTextBody('Plain text content')
->send();
注意:每个
mailer
扩展有两大类:Mailer
和Message
。前者总是知道后者的类名和具体内容。不要尝试直接实例化Message
对象,而是一如既往地使用compose()
方法接口。
批量发送邮件
你也可以一次同时发送多条邮件消息:
$messages = [];
foreach ($users as $user) {
$messages[] = Yii::$app->mailer->compose()
// ...
->setTo($user->email);
}
Yii::$app->mailer->sendMultiple($messages);
一些特定的邮件扩展可以从这种方法中受益,比如,使用单一的网络消息等。
撰写邮件内容
Yii 允许你通过一些特殊的视图文件,来组合实际的邮件消息内容。默认情况下,这些文件应该位于 @app/mail
路径下,高级模板一般位于 @common/mail
下。邮件视图文件内容的示例如下:
<?php
use yii\helpers\Html;
use yii\helpers\Url;
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\BaseMessage instance of newly created mail message */
?>
<h2>This message allows you to visit our site home page by one click</h2>
<?= Html::a('Go to home page', Url::home('http')) ?>
In order to compose message content via view file simply pass view name to the compose()
method:
Yii::$app->mailer->compose('home-link') // a view rendering result becomes the message body here
->setFrom('from@domain.com')
->setTo('to@domain.com')
->setSubject('Message subject')
->send();
You may pass additional view parameters to compose()
method, which will be available inside the view files:
Yii::$app->mailer->compose('greetings', [
'user' => Yii::$app->user->identity,
'advertisement' => $adContent,
]);
You can specify different view files for HTML and plain text message contents:
Yii::$app->mailer->compose([
'html' => 'contact-html',
'text' => 'contact-text',
]);
如果你将视图名指定为一个标量字符串,它的呈现结果将被用作 HTML 主体,而纯文本主体将通过从 HTML 中删除所有的 HTML 实体来组成。
视图渲染结果可以包装到布局(layout)中,可以使用 yii\mail\BaseMailer::htmlLayout
和 yii\mail\BaseMailer::textLayout
来设置。它的工作方式与常规 web 应用中的布局相同。布局可以用来设置邮件 CSS 样式或其他共享内容,示例如下:
<?php
use yii\helpers\Html;
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
<style type="text/css">
.heading {...}
.list {...}
.footer {...}
</style>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<?= $content ?>
<div class="footer">With kind regards, <?= Yii::$app->name ?> team</div>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>
文件附件
您可以使用方法 attach()
和 attachContent()
向邮件消息中添加附件,示例如下:
$message = Yii::$app->mailer->compose();
// 从本地文件系统附加文件
$message->attach('/path/to/source/file.pdf');
// 动态创建附件
$message->attachContent('Attachment content', ['fileName' => 'attach.txt', 'contentType' => 'text/plain']);
插入图片
你可以使用 embed()
方法将图像嵌入到邮件消息内容中。此方法返回附件 ID,然后在 img
标签中使用该 ID。当通过视图文件编写消息内容时,这个方法很容易使用,示例如下:
Yii::$app->mailer->compose('embed-email', ['imageFileName' => '/path/to/image.jpg'])
// ...
->send();
然后在邮件视图文件中,你可以使用以下代码:
<img src="<?= $message->embed($imageFileName); ?>" alt="">
测试与调试
开发人员经常需要检查应用程序发送了哪些邮件,邮件内容是什么等等。这种能力由 Yii 通过 yii\mail\BaseMailer::useFileTransport
属性授予。如果这个属性为 true,此选项强制将邮件消息数据保存到本地文件中,而不是常规发送。这些文件将保存在 yii\mail\BaseMailer::fileTransportPath
属性值表示的路径下,默认为 @runtime/mail
。
注意:您可以将消息保存到文件中,也可以将它们发送到实际的收件人,但不能同时做这两件事。
邮件消息文件可以由常规文本文件编辑器打开,这样您就可以浏览实际的消息头、内容等。在调试应用程序或运行单元测试时,可以证明这种机制本身。
注意:邮件消息文件内容是通过
\yii\mail\MessageInterface::toString()
组成的,所以它取决于你在应用程序中使用的实际邮件扩展名。
Symfony Mailer 扩展
这个扩展为 Yii 框架 2.0 提供了一个 Symfony Mailer 邮件解决方案。
安装
安装此扩展的首选方式是通过 composer,命令如下:
composer require yiisoft/yii2-symfonymailer
或者在您的 composer.json
文件中的 require 部分增加以下内容:
"yiisoft/yii2-symfonymailer": "~2.0.0"
然后执行 composer install
命令即可。
用法
要使用这个扩展,只需在您的应用程序配置中添加以下代码:
return [
//....
'components' => [
'mailer' => [
'class' => \yii\symfonymailer\Mailer::class,
'transport' => [
'scheme' => 'smtps',
'host' => '',
'username' => '',
'password' => '',
'port' => 465,
'dsn' => 'native://default',
],
'viewPath' => '@common/mail',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure transport
// for the mailer to send real emails.
'useFileTransport' => false,
],
],
];
或者:
return [
//....
'components' => [
'mailer' => [
'class' => \yii\symfonymailer\Mailer::class,
'transport' => [
'dsn' => 'smtp://user:pass@smtp.example.com:25',
],
],
],
];
然后你可以发送电子邮件,示例如下:
Yii::$app->mailer->compose('contact/html')
->setFrom('from@domain.com')
->setTo($form->email)
->setSubject($form->subject)
->send();
自定义邮件解决方案
为了创建您自己的自定义邮件解决方案,您需要创建两个类:一个用于 Mailer
,另一个用于 Message
。您可以使用 yii\mail\BaseMailer
和 yii\mail\BaseMessage
作为你的解决方案的基类。这些类已经包含了本文档中描述的基本逻辑。但是,它们的使用不是强制性的,只要实现 yii\mail\MailerInterface
和 yii\mail\MessageInterface
接口就足够了。然后,您需要实现所有抽象方法来构建您的解决方案。示例如下:
namespace common\components;
use yii\mail\BaseMailer;
class CustomMailer extends BaseMailer
{
//...
}
namespace common\components;
use yii\mail\BaseMessage;
class CustomMessage extends BaseMessage
{
//...
}
或者:
namespace common\components;
use yii\base\Component;
use yii\mail\MailerInterface;
use yii\base\ViewContextInterface;
class CustomMailer extends Component implements MailerInterface, ViewContextInterface
{
//...
}
namespace common\components;
use yii\base\BaseObject;
use yii\mail\MessageInterface;
class CustomMessage extends BaseObject implements MessageInterface
{
//...
}
💖喜欢本文档的,欢迎点赞、收藏、留言或转发,谢谢支持!
作者邮箱:zhuzixian520@126.com,github地址:github.com/zhuzixian520