# Laravel 的 郵件發送功能
- [簡介](#introduction)
- [驅動前提](#driver-prerequisites)
- [生成 Mailable](#generating-mailables)
- [編寫 Mailable](#writing-mailables)
- [配置發送者](#configuring-the-sender)
- [配置視圖](#configuring-the-view)
- [視圖數據](#view-data)
- [附件](#attachments)
- [內部附件](#inline-attachments)
- [自定義 SwiftMailer 消息](#customizing-the-swiftmailer-message)
- [Markdown 格式的郵件](#markdown-mailables)
- [生成 Markdown 格式的郵件](#generating-markdown-mailables)
- [編寫 Markdown 格式的郵件](#writing-markdown-messages)
- [自定義組件](#customizing-the-components)
- [在瀏覽器中預覽郵件](#previewing-mailables-in-the-browser)
- [發送郵件](#sending-mail)
- [隊列郵件](#queueing-mail)
- [郵件與本地開發](#mail-and-local-development)
- [事件](#events)
<a name="introduction"></a>
## 簡介
Laravel 基于 [SwiftMailer](http://swiftmailer.org) 函數庫提供了一套干凈、簡潔的郵件 API ,Laravel 為 SMTP 、Mailgun 、SparkPost 、 Amazon SES 、 PHP 的 `mail` 函數及 `sendmail` 提供驅動,讓你可以快速從本地或云端服務自由地發送郵件。
<a name="driver-prerequisites"></a>
### 驅動前提
基于 API 的驅動,例如 Mailgun 和 SparkPost 通常比 SMTP 服務器更簡單快速。如果可能,你應該盡可能使用這些驅動。所有的 API 驅動都需要 Guzzle HTTP 函數庫,你可以使用 Composer 包管理器安裝它:
composer require guzzlehttp/guzzle
#### Mailgun 驅動
要使用 Mailgun 驅動,首先必須安裝 Guzzle,之后將 `config/mail.php` 配置文件中的 `driver` 選項設置為 `mailgun`。接下來,確認 `config/services.php` 配置文件包含以下選項:
'mailgun' => [
'domain' => 'your-mailgun-domain',
'secret' => 'your-mailgun-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` 文件的 `require` 段落加入下面這一行并運行 `composer update` 命令:
"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
],
<a name="generating-mailables"></a>
## 生成 Mailable
在 Laravel 中,每種類型的郵件都代表一個「Mailable」對象。這些對象存儲在 `app/Mail` 目錄中。如果在你的應用中沒有看見這個目錄,別擔心,在首次使用 `make:mail` 命令創建 Mailable 類時這個目錄會被創建,例如:
php artisan make:mail OrderShipped
<a name="writing-mailables"></a>
## 編寫 Mailable
所有的 「Mailable」類都在其 `build` 方法中完成配置。在這個方法里,你可以調用其他各種方法,如 `from` 、 `subject` 、 `view` 和 `attach` 來配置完成郵件的詳情。
<a name="configuring-the-sender"></a>
### 配置發送者
#### 使用 `from` 方法
首先,演示配置郵件的發送者,也就是郵件的參數 「from」,既誰發送了郵件。有兩種方法配置發送者。第一種是你可以在 `build` 方法中使用 `from` 方法:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('example@example.com')
->view('emails.orders.shipped');
}
#### 使用一個全局 `from` 地址
然而,如果應用使用相同的 `from` 地址,你每次發送郵件這種設置方式顯得笨拙,替代的方法就是在 `config/mail.php` 配置文件中設置一個全局 `from` 地址,這個配置在沒有單獨指定 「from」時是默認的 `from` :
'from' => ['address' => 'example@example.com', 'name' => 'App Name'],
<a name="configuring-the-view"></a>
### 配置視圖
在 `build`方法內,你可以使用 `view` 方法指定郵件的模板,以渲染郵件的內容。因為所有郵件都會使用 [Blade 模板](/docs/{{version}}/blade) 渲染內容,你能很容易的使用 Blade 模板引擎構建郵件的 HTML:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
> {tip} 你可以創建一個 `resources/views/emails` 目錄來存放所有的郵件模板;然而,這不是強制要求,你可以在有的將郵件模板放在 `resources/views` 目錄的任意位置。
#### 純文本郵件
如果你想要定義一個純文本郵件,你可以使用 `text` 方法。如同 `view` 方法,`text` 方法接受一個模板名稱,這個名稱告訴方法使用哪個模板來渲染郵件,可以自由定義郵件 HTML 和純文本消息:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->text('emails.orders.shipped_plain');
}
<a name="view-data"></a>
### 視圖數據
#### 通過公共屬性
通常,你會希望傳遞一些數據來渲染你的郵件的 HTML 。那么有兩種方法可以讓視圖獲得數據,第一種,Mailable 類任何公共屬性都可以在視圖中使用。所以,例如你可以傳遞數據到 Mailable 類的構造函數并且在類中定義數據的公共屬性:
<?php
namespace App\Mail;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* order 實例。
*
* @var Order
*/
public $order;
/**
* 創建一個新消息實例。
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* 構建消息。
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
}
一旦數據被設置為公共屬性,它們將自動在視圖中加載,所以你可以訪問像訪問其他 Blade 模板數據一樣訪問它們:
<div>
Price: {{ $order->price }}
</div>
#### 通過 `with` 方法:
你可以使用 `with` 方法來傳遞數據給模板。一般情況下,你仍然是使用 Mailable 類的構造函數來接受數據傳參。然而你需要為這些數據屬性設置 `protected` 或 `private` 聲明,否則這些數據會被自動加載到模板中。接下來你可以使用 `with` 方法接受鍵值數組傳參來傳遞數據給模板,就如控制器里為視圖傳參一樣:
<?php
namespace App\Mail;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* order 實例。
*
* @var Order
*/
protected $order;
/**
* 創建一個新消息實例。
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* 構建消息。
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
}
一旦數據已經用 `with` 方法傳遞,它們將自動在視圖中加載,所以你可以訪問像訪問其他 Blade 模板數據一樣訪問它們:
<div>
Price: {{ $orderPrice }}
</div>
<a name="attachments"></a>
### 附件
要在郵件中加入附件,在 `build` 方法中使用 `attach` 方法。`attach` 方法接受文件的絕對路徑作為它的第一個參數:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file');
}
附加文件到消息時,你也可以傳遞 `數組` 給 `attache` 方法作為第二個參數,以指定顯示名稱和 / 或是 MIME 類型:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
#### 原始數據附件
`attachData` 可以使用字節數據作為附件。例如,你可以使用這個方法將內存中生成而沒有保存到磁盤中的 PDF 附加到郵件中。`attachData` 方法第一個參數接收原始字節數據,第二個參數為文件名,第三個參數接受一個數組以指定其他參數:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
<a name="inline-attachments"></a>
### 內部附件
在郵件中嵌入內部圖標通常是件麻煩事;然而 Laravel 提供了一個便利的方法,讓你在郵件中附件圖片并獲取適當的 CID 。要嵌入內部圖片,在郵件模板的 `$message` 變量上調用 `embed` 方法,Laravel 會自動讓你所有郵件模板都能夠獲取到 `$message` 變量,所以不必擔心如何手動傳遞它:
<body>
這是一張圖片:
<img src="{{ $message->embed($pathToFile) }}">
</body>
#### 嵌入原始數據附件
如果你已經有想嵌入原始數據,希望嵌入郵件模板,你可以調用 `$message` 變量的 `embedData` 方法:
<body>
這是一張原始數據圖片:
<img src="{{ $message->embedData($data, $name) }}">
</body>
<a name="customizing-the-swiftmailer-message"></a>
### 自定義 SwiftMailer 消息
`Mailable` 基類的 `withSwiftMessage` 方法允許你注冊一個回調,該回調將在郵件發送之前調用,參數是原始 SwiftMailer 消息實例。這讓你有機會在郵件發送之前自定義消息:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$this->view('emails.orders.shipped');
$this->withSwiftMessage(function ($message) {
$message->getHeaders()
->addTextHeader('Custom-Header', 'HeaderValue');
});
}
<a name="markdown-mailables"></a>
## Markdown 格式的 Mailable 類
Markdown 格式的 Mailable 消息允許你從預編譯的模板和你的 Mailable 類中的郵件提醒組件中受益。因為消息是用 Markdown 格式寫的, Laravel 能為消息體渲染出漂亮、響應式的 HTML 模板,也能自動生成一個純文本的副本。
<a name="generating-markdown-mailables"></a>
### 生成 Markdown 格式的 Mailable
要生成一個包含友好的 Markdown 模板的 Mailable 類,你在使用 `make:mail` 這個 Artisan 命令時,要加上 `--markdown` 選項:
php artisan make:mail OrderShipped --markdown=emails.orders.shipped
然后,在使用 `build` 方法配置 Mailable 時,用 `markdown` 方法來換掉 `view` 方法, `markdown` 方法接受一個 Markdown 模板的名稱和一個將在模板中可用的選項數組:
/**
* 構建消息。
*
* @return $this
*/
public function build()
{
return $this->from('example@example.com')
->markdown('emails.orders.shipped');
}
<a name="writing-markdown-messages"></a>
### 編寫 Markdown 格式的消息
Markdown Mailable 使用 Blade 組件和 Markdown 語法的組合,允許你輕松地構建郵件消息,同時利用 Laravel 的預制組件。
@component('mail::message')
# Order Shipped
Your order has been shipped!
@component('mail::button', ['url' => $url])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
#### 按鈕組件
按鈕組件渲染一個居中的連接按鈕,組件接受兩個參數,一個 `url` 和一個可選的 `color` 。支持的顏色有 `blue` 、 `green` 、 和 `red` 。你可以在郵件消息體中加入隨便多個你想要的按鈕。
@component('mail::button', ['url' => $url, 'color' => 'green'])
View Order
@endcomponent
#### 面板組件
面板組件將面板中給定的一塊文字的背景渲染成跟其他的消息體背景稍微不同。這樣可以讓這塊文字引起人們的注意。
@component('mail::panel')
This is the panel content.
@endcomponent
#### 表格組件
表格組件允許你將一個 Markdown 格式的表格轉換成一個 HTML 格式的表格。組件接受 Markdown 格式的表格作為它的內容。表格列對齊方式按照默認的 Markdown 對齊風格而定。
@component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
@endcomponent
<a name="customizing-the-components"></a>
### 自定義組件
你或許會為了自定義而導出你應用中所有的 Markdown 郵件組件。要導出這些組件,使用 `vendor:publish` 這個 Artisan 命令來發布資源文件標簽。
php artisan vendor:publish --tag=laravel-mail
這個命令會發布 Markdown 郵件組件到 `resources/views/vendor/mail` 文件夾。而 `mail` 文件夾會包含一個 `html` 文件夾和一個 `markdown` 文件夾,每個文件夾都包含他們的可用組件的描述。你可以按照你的意愿自定義這些組件。
#### 自定義樣式表 CSS
在導出組件之后,`resources/views/vendor/mail/html/themes` 文件夾將包含一個默認的 `default.css` 文件。你可以在這個文件中自定義 CSS ,你定義的這些樣式將會在 Markdown 格式消息體轉換成 HTML 格式時自動得到應用。
> {tip} 如果你想為 Markdown 組件構建一個全新的主題,只要寫一個新的 CSS 文件,放在 `html/themes` 文件夾,然后在你的 `mail` 配置文件中改變 `theme` 選項就可以了。
<a name="previewing-mailables-in-the-browser"></a>
## 在瀏覽器中預覽郵件
當你設計一個郵件模板時,可以很方便地在瀏覽器中快速預覽渲染出來的郵件,就像典型的 Blade 模板一樣。為此, Laravel 允許你直接從路由閉包或者控制器中返回任何的郵件。當郵件被返回時,他會被渲染并顯示在瀏覽器中,允許你快速預覽其設計,而不必發送到實際的電子郵件地址。
Route::get('/mailable', function () {
$invoice = App\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
});
<a name="sending-mail"></a>
## 發送郵件
要發送郵件,使用 `Mail` [facade](/docs/{{version}}/facades) 的 `to` 方法。 `to` 方法接受一個郵件地址,一個 user 實現或一個 users 集合。如果傳遞一個對象或集合,mailer 將自動使用 `email` 和 `name` 屬性來設置郵件收件人,所以確保你的對象里有這些屬性。一旦指定收件人,你可以傳遞一個實現到 Mailable 類的 `send` 方法:
<?php
namespace App\Http\Controllers;
use App\Order;
use App\Mail\OrderShipped;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Http\Controllers\Controller;
class OrderController extends Controller
{
/**
* Ship the given order.
*
* @param Request $request
* @param int $orderId
* @return Response
*/
public function ship(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);
// Ship order...
Mail::to($request->user())->send(new OrderShipped($order));
}
}
當然,不局限于只使用「to」給收件人發送郵件,你可以通過一個單一的鏈式調用來自由的設置 「to」,「cc」和 「bcc」接收者:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
<a name="queueing-mail"></a>
### 隊列 Mail
#### 將郵件消息加入隊列
由于發送消息會大幅延遲應用響應時間,許多開發者選擇將郵件消息加入隊列在后臺進行發送。Laravel 使用內置的 [統一的隊列 API](/docs/{{version}}/queues) 來輕松完成此工作。將郵件消息加入隊列,使用 `Mail` facade 的 `queue` 方法:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
這個方法會自動將工作加入隊列,以便后臺發送郵件。當然,在使用這個功能前,你需要 [設置你的隊列](/docs/{{version}}/queues) 。
#### 延遲郵件消息隊列
如果你希望延遲發送已加入隊列的郵件消息,你可以使用 `later` 方法。`later` 第一個參數接受一個 `DateTime` 實現以告知這個消息應該何時發送:
$when = Carbon\Carbon::now()->addMinutes(10);
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later($when, new OrderShipped($order));
#### 推送到特定隊列
因為所有 Mailable 類是通過 `make:mail` 命令生成并使用 `Illuminate\Bus\Queueable` trait ,你可以在任何 Mailable 類實現中調用 `onQueue` 來指定隊列名稱,還有 `onConnection` 方法來指定隊列鏈接名稱:
$message = (new OrderShipped($order))
->onConnection('sqs')
->onQueue('emails');
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue($message);
#### 默認隊列
如果你的 Mailable 類想要默認使用隊列,你可以在類中實現 `ShouldQueue` 接口契約。現在,即便你調用 `send` 方法來發送郵件, Mailable 類仍將郵件放入隊列中發送。
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
//
}
<a name="mail-and-local-development"></a>
## 郵件和本地開發
當應用開發發送郵件時,你或許不想真實的發送郵件到真實的郵件地址。Laravel 提供幾種方法以在本地開發時真實發送 「失去能力」。
#### 日志驅動
代替真實發送,`log` 郵件驅動將所有郵件消息寫入日志文件以供檢查,需要更多根據環境來設置應用程序的信息,可參考 [配置文件](/docs/{{version}}/installation#environment-configuration).
#### 通用收件者
另一個由 Laravel 提供的解決方案是設置一個通用郵件接收者,由框架發送郵件。這個方法將所有郵件發送到一個郵件地址,而不是發送給實際收件人。這可以通過 `config/mail.php` 配置文件的 `to` 選項來完成:
'to' => [
'address' => 'example@example.com',
'name' => 'Example'
],
#### Mailtrap
最后,你可以使用像 [Mailtrap](https://mailtrap.io) 和 `smtp` 驅動來將你的郵件消息發送到一個 「虛假的」郵箱中,你卻可以在一個真實的郵件客戶端中查看它們。這個方法的好處是讓你可以在 Mailtrap 的消息閱讀器中查看最終的實際郵件。
<a name="events"></a>
## 事件
Laravel 會在發送郵件消息之前觸發一個事件。切記,這個事件只會在郵件 *發送* 時觸發,在加入隊列時不觸發。你可以在你的 `EventServiceProvider` 注冊一個事件監聽器:
/**
* 應用事件監聽映射。
*
* @var array
*/
protected $listen = [
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\LogSentMessage',
],
];
## 譯者署名
| 用戶名 | 頭像 | 職能 | 簽名 |
|---|---|---|---|
| [@qufo](https://github.com/qufo) | <img class="avatar-66 rm-style" src="https://avatars1.githubusercontent.com/u/2526883?v=3&s=460?imageView2/1/w/100/h/100"> | 翻譯 | 歡迎共同探討。[@Qufo](https://github.com/qufo) |
| [@limxx](https://github.com/limxx) | <img class="avatar-66 rm-style" src="https://avatars0.githubusercontent.com/u/16585030?v=4&s=400"> | 翻譯 | Winter is coming. |
---
> {note} 歡迎任何形式的轉載,但請務必注明出處,尊重他人勞動共創開源社區。
>
> 轉載請注明:本文檔由 Laravel China 社區 [laravel-china.org](https://laravel-china.org) 組織翻譯,詳見 [翻譯召集帖](https://laravel-china.org/topics/5756/laravel-55-document-translation-call-come-and-join-the-translation)。
>
> 文檔永久地址: https://d.laravel-china.org
- 說明
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- HomeStead
- Valet
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- 門面(Facades)
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- 重定向
- Session
- 表單驗證
- 錯誤與日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- API認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Passport OAuth 認證
- Scout 全文搜索
- Socialite 社交化登錄
- 交流說明