郵件
簡介
Laravel 基於熱門的 SwiftMailer 函式庫提供了一個簡潔的 API。Laravel 為 SMTP、Mailgun、Mandrill、Amazon SES、PHP 的 mail
函式及 sendmail
提供驅動,讓你可以快速地以所選擇的本地或雲端服務開始寄送郵件。
驅動前提
基於 API 的驅動,例如 Mailgun 或 Mandrill,通常比 SMTP 伺服器更簡單快速。所有的 API 驅動都需要在應用程式中安裝 Guzzle HTTP 函式庫。你可在 composer.json
檔案中加入下面這一行,以便於在專案中安裝 Guzzle:
"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',
],
SES 驅動
要使用 Amazon SES 驅動,必須安裝 PHP 的 Amazon AWS SDK。你可在 composer.json
檔案的 require
段落加入下面這一行以安裝此函式庫:
"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', // 例如 us-east-1
],
寄送郵件
Laravel 允許你在視圖中存放電子郵件訊息。例如,要組織你的電子郵件,你可以在 resource/views
目錄中建立 emails
目錄:
要寄送訊息,使用 Mail
facade 的 send
方法。send
方法接收三個參數。首先是包含郵件訊息的視圖名稱。其次是一個要傳遞給該視圖的資料陣列。最後是一個閉包
回呼用來接收訊息實例,讓你可以自訂收件者、主旨,以及郵件訊息的其他部分:
<?php
namespace App\Http\Controllers;
use Mail;
use App\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 發封電子郵件提醒給使用者。
*
* @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 程式碼,在郵件視圖中顯示使用者名稱:
<?php echo $user->name; ?>
注意:
$message
變數永遠會被傳遞至電子郵件視圖,且允許內部嵌入附件。因此,你應該避免將message
變數傳至視圖。
建立訊息
如先前討論過的,傳給 send
方法的第三個參數是一個閉包
,讓你可以對電子郵件訊息本體指定不同的選項。使用此閉包,你可以指定訊息的其他屬性,例如副本、密件副本等等:
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 = []);
// 以原始 $data 字串附加一個檔案…
$message->attachData($data, $name, array $options = []);
// 取得底層的 SwiftMailer 訊息實例…
$message->getSwiftMessage();
注意:傳遞至
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);
});
附加檔案至訊息時,你也可以傳遞陣列
給 attach
方法作為第二個參數,以指定顯示名稱和/或 MIME 型別:
$message->attach($pathToFile, ['as' => $display, 'mime' => $mime]);
內部附件
在電子郵件視圖中嵌入圖像
在電子郵件中嵌入內部圖像通常是件很麻煩的事;然而 Laravel 提供一個便利的方法,讓你在電子郵件中附加圖像並取得適當的 CID。要嵌入內部圖像,在電子郵件視圖的 $message
變數中使用 embed
方法。記得,Laravel 會自動讓你所有的電子郵件視圖都能取得 $message
變數:
<body>
這是一張圖片:
<img src="<?php echo $message->embed($pathToFile); ?>">
</body>
在電子郵件視圖中嵌入原始資料
若你已有希望嵌入電子郵件訊息中的原始資料字串,你可以在 $message
變數上使用 embedData
方法:
<body>
這是一張從原始資料來的圖片:
<img src="<?php echo $message->embedData($data, $name); ?>">
</body>
隊列郵件
將郵件訊息加入隊列
由於寄送電子郵件訊息會大幅延長應用程式的回應時間,許多開發者選擇將郵件訊息加入隊列並於背景發送。Laravel 使用其內建的統一的隊列 API,讓你輕鬆地完成此工作。要將郵件訊息加入隊列,使用 Mail
facade 的 queue
方法:
Mail::queue('emails.welcome', $data, function ($message) {
//
});
此方法會自動將工作加入隊列,以便在背景發送郵件訊息。當然,在使用此功能之前,你需要設定你的隊列。
延遲的訊息隊列
若你希望延遲遞送已加入隊列的電子郵件訊息,你可以使用 later
方法。要著手開始,只要將你想要延遲寄送訊息的秒數,作為第一個參數傳送給此方法:
Mail::later(5, 'emails.welcome', $data, function ($message) {
//
});
加入特定隊列
若你想要指定特定的隊列來加入訊息 ,可使用 queueOn
及 laterOn
方法:
Mail::queueOn('queue-name', 'emails.welcome', $data, function ($message) {
//
});
Mail::laterOn('queue-name', 5, 'emails.welcome', $data, function ($message) {
//
});
郵件與本機端開發
當開發需要寄送電子郵件的應用程式時,你有可能不想要實際地送出電子郵件到真正的郵件地址。Laravel 提供了幾種方法以「停止」將電子郵件訊息真正寄出。
日誌驅動
一個解決方案是在本地端開發時使用 log
郵件驅動。此驅動會將所有的電子郵件訊息寫入日誌檔案作為檢驗之用。若需要更多根據環境來設定應用程式的資訊,可參考設定文件。
通用收件者
另一個由 Lavavel 提供的解決方案,是設定一個通用的收件者給框架寄出的所有電子郵件。這樣,應用程式產生的所有電子郵件都會被送到一個特定的地址,而不是寄信時實際指定的收件人地址。這可以透過 config/mail.php
設定檔的 to
選項來完成:
'to' => [
'address' => 'dev@domain.com',
'name' => 'Dev Example'
],
Mailtrap
最後,你可以使用像 Mailtrap 這樣的服務以及 smtp
驅動來將你的郵件訊息寄到一個「假的」郵箱,而你可以在一個真的郵件客戶端檢視它們。這個方法的好處是讓你可以在 Mailtrap 的訊息檢閱器中實際查看最終的電子郵件。
事件
Laravel 會在發送郵件訊息之前觸發 mailer.sending
事件。切記,此事件只會在郵件發送時觸發,在隊列時則不會。你可以在你的 EventServiceProvider
註冊一個事件監聽器:
/**
* 註冊你應用程式中的任何其他事件。
*
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function boot(DispatcherContract $events)
{
parent::boot($events);
$events->listen('mailer.sending', function ($message) {
//
});
}