Laravel: Mail (Phần 1)

Giới thiệu về gửi Mail trong Laravel

Laravel cung cấp API rất đơn giản thông qua thư viện với drivers SMTP, Mailgun, SparkPost, Amazon SES, hàm mail của PHP, và sendmail, cho phép bạn nhanh chóng bắt đầu gửi mail qua dịch vụ mail local hay cloud tuỳ theo lựa chọn của bạn.

Tìm hiểu các loại Driver Prerequisites

Các API dựa trên driver như Mailgun và SparkPost thường đơn giản và nhanh hơn SMTP server. Nếu có thể, bạn nên sử dụng trong những dirver này. Tất cả các API driver yêu cầu sử dụng thư viện Guzzle HTTP có thể cài đặt thông qua Composer:

composer require guzzlehttp/guzzle

Mailgun Driver

Để sử dụng Mailgun driver, đầu tiên cần cài Guzzle, sau đó cấu hình driver trong file config/mail.php vào mailgun. Tiếp theo, xác định rằng file config/services.php của bạn cấu hình theo options:

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

SparkPost Driver

Để sử dụng SparkPost driver, đầu tiên cần phải cài đặt Guzzle, sau đó tùy chỉnh driver trong file cấu hình config/mail.php vào sparkpost. Tiếp theo, bạn phải cấu hình file config/services.php theo options sau:

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

SES Driver

Để sử dụng Amazon SES driver bạn cần phải cài đặt Amazon AWS SDK cho PHP. Bạn có thể cài đặt thư viện này bằng cách thêm 1 dòng vào phần require trong file composer.json và chạy lệnh composer update:

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

Tiếp theo, đặt tùy chỉnh driver trong file config/mail.php vào ses và xác định file cấu hình config/services.php được cấu hình theo options:

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

Tìm hiểu Generating Mailables

Trong Laravel, mỗi loại email được gửi đi bởi ứng dụng của bạn được đại diện như một class "mailable". Các class đó được lưu trong thư mục app/Mail. Đừng lo lắng nếu bạn không nhìn thấy đường dẫn đó trong ứng dụng của bạn, vì nó sẽ được tạo ra khi bạn tạo class mailable lần đầu tiên bằng cách dùng lệnh make:mail:

php artisan make:mail OrderShipped

Writing Mailables

Tất cả của một class mailable đều được cấu hình trong phương thức build. Bên trong hàm này, bạn có thể gọi nhiều phương thức như from, subject, view, và attach để cấu hình mail nhận.

Configuring The Sender

Using The from Method

Đầu tiên, hãy tìm hiểu cấu hình email của người gửi. Hoặc, theo một nghĩa khác, người gửi mail là "from". Có hai cách để cấu hình người gửi. Đầu tiên, bạn có thể sử dụng phương thức from cùng với phương thức build của class mailable của bạn:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->from('')
                ->view('emails.orders.shipped');
}

 

Using A Global from Address Tuy nhiên, nếu ứng dụng của bạn sử dụng địa chỉ "from" cho tất cả các mail, nó có thể trở lên dài dòng để gọi hàm from trong mỗi class mailable bạn tạo ra. Thay vì, bạn có thể chỉ định địa chỉ "from" trong file cấu hình config/mail.php. Địa chỉ này sẽ được sử dụng nếu không có địa chỉ "from" được chỉ định của class mailable:

'from' => ['address' => '', 'name' => 'App Name'],

 

Configuring The View Hàm build trong class mailable, bạn có thể sử dụng hàm view để chỉ định template được sử dụng khi render nội dung email. Vì mỗi email sử dụng để render nội dung, bạn có toàn quyền và thoải mái xây dựng Blade templating HTML:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped');
}

Plain Text Emails

Nếu bạn muốn định nghĩa một phiên bản plain-text cho email của bạn, bạn có thể sử dụng hàm text. Giống như hàm view, hàm text nhận một tên template sẽ được sử dụng để render nội dung của email. Nếu bạn định thoải mái nghĩa một HTML và một phiên bản plain-text cho message của bạn:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->text('emails.orders.shipped_plain');
}

View Data

Via Public Properties

Thông thường, bạn sẽ muốn truyền một số data vào trong view của bạn muốn sử dụng khi render ra HTML. Có hai cách bạn có thể hiển thị dữ liệu trong view. Thứ nhất, bất cứ thuộc tính public được định nghĩa trong class mailable sẽ được tự động tồn tại trong view. Vì vậy, ví dụ, bạn có thể truyền dữ liệu có thuộc tính public vào trong hàm khởi tạo của class mailable và đặt dữ liệu bạn muốn truyền vào trong đó:

<?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;

    /**
     * The order instance.
     *
     * @var Order
     */
    public $order;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped');
    }
}

Mỗi dữ liệu được set một thuộc tính public, nó sẽ tự động trở thành có sẵn trong view của bạn, vì vậy bạn có thể truy cập nó giống như bạn truy cập bất cứ dữ liệu nào khác trong Blade templates:

<div>
    Price: {{ $order->price }}
</div>

Via The with Method:

Nếu bạn muốn tùy biến định dạng data trước khi gửi nó vào template, bạn có thể tùy biến data của bạn vào view qua phương thức with. Thông thường, bạn sẽ vẫn truyền data qua hàm khởi tạo của class mailable; tuy nhiên, bạn nên đặt data thành thuộc tính protected hoặc privatevì data sẽ không tự động được tạo sẵn trong view template. Sau đó, khi gọi phương thức with, truyền một mảng data bạn muốn vào trong template:

<?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;

    /**
     * The order instance.
     *
     * @var Order
     */
    protected $order;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->with([
                        'orderName' => $this->order->name,
                        'orderPrice' => $this->order->price,
                    ]);
    }
}

Khi data đã được truyền vào phương thức with, nó sẽ tự động tồn tại ở trong view, bạn có thể truy cập bình thường như khi sử dụng dữ liệu với Blade templates:

<div>
    Price: {{ $orderPrice }}
</div>

 

Attachments

Để đính kèm vào email, sử dụng phương thức attach cùng với phương thức build của class mailable. Phương thức attach chấp nhận đường dẫn đầy đủ của file là tham số thứ nhất:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attach('/path/to/file');
    }

Khi đính kèm các file vào một message, bạn cũng có thể ghi rõ display name và / hoặc MIME type bằng cách truyền vào array như là tham số thứ hai của phương thức attach:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attach('/path/to/file', [
                        'as' => 'name.pdf',
                        'mime' => 'application/pdf',
                    ]);
    }

 

Raw Data Attachments

Phương thức attachData có thể sử dụng để đính kèm một raw string của bytes như một đính kèm. Ví dụ, bạn có thể sử dụng phương thức này nếu bạn muốn sinh một PDF trong memory và muốn đính kèm nó vào email mà không cần viết nó vào ổ cứng. Phương thức attachData chấp nhận dữ liệu dạng raw data bytes là tham số thứ nhất, tên của file là tham số thứ hai, và một mảng tùy biến là tham số thứ ba:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->attachData($this->pdf, 'name.pdf', [
                        'mime' => 'application/pdf',
                    ]);
    }

 

Inline Attachments

Nhúng inline images vào emails thường không đơn giản; tuy nhiên, Laravel cung cấp một cách khá thuận tiện để bạn đính kèm ảnh vào emails và nhận CID thích hợp. Để nhúng một ảnh inline images, sử dụng phương thức embed trên biến $message cùng với email template. Laravel tự động tạo biến $message tồn tại cho tất cả email templates, vì vậy bạn không cần phải truyền nó một cách thủ công:

<body>
    Here is an image:

    <img src="{{ $message->embed($pathToFile) }}">
</body>

 

Embedding Raw Data Attachments

Nếu bạn có một raw data string bạn muốn nhúng vào email template, bạn có thể sử dụng phương thức embedData trên biến $message:

<body>
    Here is an image from raw data:

    <img src="{{ $message->embedData($data, $name) }}">
</body>

 

Customizing The SwiftMailer Message

Phương thức withSwiftMessage của class Mailable cho phép bạn đăng ký 1 callback sẽ được gọi với raw SwiftMailer message instance trước khi gửi message. Điều này sẽ cho bạn một cơ hội để tùy chỉnh message trước khi nó được gửi:

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $this->view('emails.orders.shipped');

        $this->withSwiftMessage(function ($message) {
            $message->getHeaders()
                    ->addTextHeader('Custom-Header', 'HeaderValue');
        });
    }

Tags