Laravel 5.4 Mail With Amazon SES

laravel mail 的設計對開發者非常便利,預設使用 SwiftMailer 作為發信的 library ,也支援多種 mailer library ,像是 Mailgun、SparkPost、 Amazon SES 等,切換 library 只要改變設定中的 driver ,實際上仍呼叫包裝好的 laravel api function 就可以了,另外一點是他將 email 邏輯跟view 拆開,view 同時支援 html 與 markdown 形式,易用明瞭。

本文將介紹:

  • Amazon SES driver 設定
  • email 相關設定
  • Mailable 開發

一、Amazon SES 設定

  • 安裝 AWS SDK
composer require aws/aws-sdk-php
  • 設定 mailer driver 使用 SES library

config/mail.php是 mailer 的設定檔,可以看到第 19 行設定 driver

‘driver’ => env(‘MAIL_DRIVER’, ‘smtp’)

所以將 .env 檔案中的 MAIL_DRIVER 修改為 ses

MAIL_DRIVER=ses

接下來讀者需要把 SES 的 Key 跟 Secret 加在 .env 中,這些值會對應到 config/services.php 檔案,SES 的 region 要記得加上去,寫進 .env 也可以,region 在 SES Host 網址中可以找到host:mail-smtp.us-west-2.amazonaws.com,這邊以 us-east-1 美東作為範例。

'ses' => [
'key' => env('SES_KEY'),
'secret' => env('SES_SECRET'),
'region' => 'us-east-1',
],

這樣就好了,記得只要有修改 .env 都需要 restart project 使之重新載入變數。

二、設定預設寄/收件人

  • config/mail.php 中已經幫開發者寫好預設寄件人( from ),修改對應的 .env就可以了,如果有 debug 的需求才會統一收件人 (to),bcc 會在寄信時設定。
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
'to' => [
'address' => 'example@example.com',
'name' => 'Example'
],

三、建立 Mailable Class 、View 與寄信

執行 php artisan make:email SignupSuccess 建立一個 mailable,第一次會自行產生相關的資料夾,並在 app\Mail 下出現 SignupSuccess.php 檔案,內有已經寫好的 build function 與所需的 class

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Lang;
class SignupSuccess extends Mailable
{
use Queueable, SerializesModels;
    /**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
// 傳入與初始化所需的 data
}
    /**
* Build the message.
*
* @return $this
*/
public function build()
{
// 指定 view 跟 data
}
}
?>

接著讀者只要在想寄送 email 的程式碼區塊,使用 Mail facade 就可以了

use App\Mail\SignupSuccess;
use Illuminate\Support\Facades\Mail;
...
// 直接發送
Mail::to($user->email)
->send(new SignupSuccess());
// 使用 Queue 發送
Mail::to($user->email)
->queue(new
SignupSuccess());
// 使用 Queue 並延遲 n 秒後發送
Mail::to(
$user->email)
->later($seconds, new
SignupSuccess());

再回過頭來看 Mailable 的撰寫,主要是 constructor 跟 build function,透過 constructor 傳入並初始資料和語系,build function 負責處裡資料與設定 email view、附件、資料等等,語系會在此處裡是因為 App::setLoacle() 會影響整個 project 語系,mail 多語系應該適合個別設定,整個範例如下:

Use App\User;
...
  protected $user, $locale;
  public function __construct(User $user, $locale)
{
$this->user = $user;
$this->locale = $locale;
}
  public function build()
{
$sub = __('mail.signup.success.subject', [], $locale);
    return $this->view('email.signup.success')
// 也可以加上檔案附件
// ->attach('/public/sample/readme.pdf');
->with(['user'=> $this->user, 'locale'=> $this->locale])
->subject($sub);
}

下一步再開建立對應的 blade template : resources\views\email\signup\success.blade.php ,顯示會員名字,對文字設定語系,記得注意使用的 html tag 是否能在信箱正常顯示,可以參考:Email Client CSS Support

@extends('test.email.container')
@section('content')
<div class="banner">
<img src="{{ env('APP_URL') }}/img/mail/signup.png">
</div>
<h3>__('mail.signup.success.greeting', [], $locale)</h3>
<div class="message">
<div class="greeting">Hi {{ $user->name }}</div>
__('mail.signup.success.message', [], $locale)
</div>
<div class="button-section">
<a type="button" href="{{ env('APP_URL') }}">Back</a>
</div>
@include('test.email.signature')
@endsection

這樣一個簡單的 mail 寄送就完成啦~

後記補充

多語系檔案可以用 phpjson 製作,但使用上兩種呼叫方法不同:

  • php

建立形式:resources/lang/en/email.php

<?php
return [
'greeting' => 'Hi, :name',
...
];
?>

呼叫方式: trans('greeting', ['name'=>$user->name], 'en')

  • json

建立形式: resource/lang/en.json

{'mail.success.greeting' => 'Hi, :name'}

呼叫方式: __('mail.success', ['name'=> $user->name], ‘en')

其實筆者覺得 json 用的 function 看起來蠻 magic 的…


想研究更多可以參考官方文件囉!

我們下次見~(好啦我這次拖稿了嗚嗚)