发送邮件

未匹配的标注

发送邮件

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

:information_source: 注意:每个 mailer 扩展有两大类:MailerMessage。前者总是知道后者的类名和具体内容。不要尝试直接实例化 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::htmlLayoutyii\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\BaseMaileryii\mail\BaseMessage 作为你的解决方案的基类。这些类已经包含了本文档中描述的基本逻辑。但是,它们的使用不是强制性的,只要实现 yii\mail\MailerInterfaceyii\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

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
zhuzixian520
讨论数量: 0
发起讨论 只看当前版本


暂无话题~