laravel 基础教程 —— 邮件

邮件

简介

laravel 基于流行的 SwiftMailer 类库构建了一种干净简洁的邮件 API。laravel 提供了驱动以支持 SMTP,Mandrill,SparkPost,Amazon SES,PHP 的 mail 方法和 sendmail 方法,这允许你快速的开始构建通过本地或云服务发送邮件的功能。

驱动先决条件

基于 API 的驱动程序如 Mailgun 和 Mandrill 通常要比 SMTP 服务简单快速。所有的 API 驱动都必须引入 Guzzle HTTP 类库,你可以通过在 composer.json 文件中添加下面的内容来进行安装:

"guzzlehttp/guzzle": "~5.3|~6.0"

Mailgun 驱动

如果使用 Mailgun 驱动,你首先需要安装 Guzzle,然后设置 config/mail.php 配置文件的 driver 选项为 mailgun。然后,你需要确认你的 config/services.php 配置文件中包含以下选项:

'mailgun' => [
  'domain' => 'your-mailgun-domain',
  'secret' => 'your-mailgun-key',
],

Mandrill 驱动

如果使用 Mandrill 驱动,你首先需要安装 Guzzle,然后设置 config/mail.php 配置文件的 driver 选项为 mandrill。接着,你需要确认你的 config/services.php 配置文件中包含以下选项:

'mandrill' => [
  'secret' => 'your-mandrill-key',
],

SparkPost 驱动

如果使用 SparkPost 驱动,你首先需要安装 Guzzle,然后设置你的 config/mail.php 配置文件中的 driver 选项为 sparkpost。接着,你需要确认你的 config/services.php 配置文件中包含以下选项:

'sparkpost' => [
  'secret' => 'your-sparkpost-key',
],

SES 驱动

如果使用 Amazon SES 驱动,你需要在 PHP 中引入 Amazon AWS SDK。你可以通过在 composer.json 文件中进行引入安装:

"aws/aws-sdk-php": "~3.0"

然后设置你的 config/mail.php 配置文件的 driver 选项为 ses。接着,你需要确认你的 config/services.php 配置文件中包含以下选项:

'ses' => [
  'key' => 'your-ses-key',
  'secret' => 'your-ses-secret',
  'region' => 'ses-region', //e.g. us-east-1
],

发送邮件

laravel 允许你使用视图来存储你的邮件信息。比如,你可以在 resources/views 目录下创建一个 emails 目录来管理你的邮件视图:

你需要使用 Mail 假面的 send 方法来发送一个邮件。send 方法接收三个参数,第一个参数应该是视图的名称。第二个参数应该是传递到视图中的数据所组成的数组。最后,是一个 Closure 回调函数,这个回调函数会接收一个 message 实例,这允许你自由的配置收件人,主题,和其他方面的邮件信息:

<?php

namespace App\Http\Controller;

use Mail;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Send an e-mail reminder to the user.
   *
   * @param Request $request
   * @param int $id
   * @return Response
   */
   public function sendEmailReminder(Request $request, $id)
   {
     $user = User::findOrFail($id);

     Mail::send('emails.reminder', ['user' => $user], function ($m) use ($user) {
       $m->from('hello@app.com', 'Your Application');

       $m->to($user->email, $user->name)->subject('Your Reminder!');
     });
   }
}

因为上面的示例中我们传递了 user 键到数组中,所以我们可以在我们的邮件视图中使用用户的名称:

<?php echo $user->name; ?>

注意: 一个 $message 变量会自动的传递到邮件视图,并且允许内联附件。所以,你应该避免手动的传递到视图 message 变量。

构建一个 Message

就如我们上面谈到的,传递到 send 方法的第三个参数是一个 Closure,这个闭包允许你设置邮件信息的各种选项。使用闭包,你可以指定信息的其它属性,比如复写,密抄等:

Mail::send('emails.welcome', $data, function ($message) {
  $message->from('us@example.com', 'Laravel');

  $message->to('foo@example.com')->cc('bar@example.com');
});

这里列出了 $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 = []);

// Get the underlying SwiftMailer message instance...
$message->getSwiftMessage();

注意:message 实例继承自 SwiftMailer 信息类并会被传递到 Mail::send 闭包中。这允许你在访问所有 SwiftMailer 信息类的方法。

纯文本邮件

默认的,send 方法会假设传递到其中的视图包含了 HTML。但是,你可以传递一个数组到 send 方法的第一个参数,你指定一个纯文本视图来合并 HTML 视图:

Mail::send(['html.view', 'text.view'], $data, $callback);

或者你可以只传递一个纯文本的邮件,你需要指定数组的键为 text:

Mail::send(['text' => 'view'], $data, $callback);

原始字符串邮件

你可以使用 raw 方法来直接发送原始字符串邮件:

Mail::raw('Text to e-mail', function ($message){
  //
});

附件

你可以使用传递到闭包中的 $message 对象的 attach 方法来在邮件中添加附件。attach 方法接收一个完整的文件路径作为第一个参数:

Mail::send('emails.welcome', $data, function ($message) {
  //

  $message->attach($pathToFile); 
});

当你添加一个邮件附件时,你可能也需要指定附件显示的名称或者 MIME type。你可以向 attach 方法传递一个数组作为第二个参数:

$message->attach($pathToFile, ['as' => $display, 'mime' => $mime]);

attachData 方法可以用来添加一个原始字节字符串作为一个附件。比如,你可能需要使用这个方法来将内存中生成的 PDF 直接添加到附件中,而不需要先存储到磁盘:

$message->attachData($pdf, 'invoice.pdf');

$message->attachData($pdf, 'invoice.pdf', ['mime' => $mime]);

内联附件

在邮件视图中嵌入一个图片

在邮件中内联一个图片通常是比较笨重的。但是,laravel 提供了一种便捷的方式在你的邮件中附加一个图片并且取回适当的 CID。你需要在邮件视图中使用 $message 变量的 embed 方法。你应该记得,Laravel 会自动的创建一个 $message 变量并将其传递到你的邮件视图中:

<body>
  Here is an image:

  <img src="<?php echo $message->embed($pathToFile); ?>"
</body>

嵌入原始数据到视图

如果你希望嵌入一个原始数据到邮件信息中,你可以使用 $message 变量的 embedData 方法:

<body>
  Here is an image from raw data:

  <img src="<?php echo $message->embedData($data, $name); ?>"
</body>

邮件队列

队列化邮件信息

由于发送邮件是非常消耗资源的一件事,这样会影响到应用的响应时间。所以很多开发者都选择使用队列来完成异步的邮件发送。Laravel 使用统一的队列接口来使这些非常简单。你需要使用 Mail 假面的 queue 方法来使邮件队列化:

Mail::queue('emails.welcome', $data, function ($message) {
  // 
});

该方法会自动的在队列添加发送邮件的任务,该任务会在后台自动的执行。当然,你需要先配置好队列。

延迟消息队列

如果你希望延迟执行邮件的发送队列。你需要使用 later 方法。你需要在方法的第一个参数传送一个你希望延迟执行的秒数:

Mail::later(5, 'emails.welcome', $data, function ($message) {
  //
});

添加到指定的队列

如果你希望添加邮件任务到指定的队列,你需要使用 queueOnlaterOn 方法:

Mail::queueOn('queue-name', 'emails.welcome', $data, function ($message) {
  // 
});

Mail::laterOn('queue-name', 5, 'emails.welcome', $data, function ($message) {
  // 
});

邮件 & 本地开发

当开发一个发送邮件的服务时,你可能并不希望真实的去发送一个邮件。只需要模拟测试成功就可以了。laravel 提供了多种方式来禁用真实的邮件发送。

log 驱动

其中一个解决方案就是在本地开发时使用 log 邮件驱动。这个驱动会将所有的邮件信息写入到日志文件中。

通用的邮件

另外一个解决方案就是设置一个通用的邮件来接收所有的应用发出的邮件。这种方式,会使应用生成的所有邮件都发送到这个地址。你可以通过配置 config/mail.php 文件的 to 选项来进行设置:

'to' => [
  'address' => 'dev@domain.com',
  'name' => 'Dev Example'
],

mailtrap

最后,你也可以使用一些像 Mailtrapsmtp 驱动的服务来发送你的邮件到一个虚拟邮箱,而且你也可以通过真实的邮件客户端进行查看。这可以使你看到真实的邮件在 Mailtrap 中的显示效果。

事件

laravel 会在发送邮件之前触发事件。你应该注意的是,它是在邮件发送之前触发事件,而不是添加到队列时。你可以在 EventServiceProvider 中注册一个事件监听者:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
 protected $listen = [
  'Illuminate\Mail\Events\MessageSending' => [
    'App\Listeners\LogSentMessage',
  ],
 ];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容