Gửi mail trong Laravel 5.3
Gửi mail là một hoạt động rất hữu ích và cần thiết của hầu hết các ứng dụng. Trước đấy để gửi mail việc lựa chọn thư viện và config khá phức tạp. Nhưng hiện nay, Laravel đã cung cấp một API rõ ràng và đơn giản thông qua thư viện phổ biến SwiftMailer với các driver như SMTP, Mailgun, SparkPost, ...
Gửi mail là một hoạt động rất hữu ích và cần thiết của hầu hết các ứng dụng. Trước đấy để gửi mail việc lựa chọn thư viện và config khá phức tạp. Nhưng hiện nay, Laravel đã cung cấp một API rõ ràng và đơn giản thông qua thư viện phổ biến SwiftMailer với các driver như SMTP, Mailgun, SparkPost, Amazon SES, giúp gửi mail rất đơn giản và dẽ dàng.
Hầu hết các API drivers yêu cầu Guzzle HTTP library, nó có thể được cài đặt thông qua Composer:
composer require guzzlehttp/guzzle
Trong Laravel mỗi loại email được gửi bởi ứng dụng được xem như là một “mailable” class. Và được đặt ở thư mục app/Mail. Thư mục này sẽ đươc tạo ở lần đầu tiên tạo mailable class qua command make:mail:
php artisan make:mail OrderShipped
Tất cả cấu hình của một Mailable class được thực hiện ở phương thức build của class. Trong phương thức này chúng ta có thể gọi các phương thức khác như from, subject, view, attach để config, chỉnh sửa nội dung cũng như giao diện.
Sử dụng phương thức from. Có 2 cách để config người gửi:
Sử dụng phương thức from trong hàm build
/** * Build the message. * * @return $this */ public function build() { return $this->from('example@example.com') ->view('emails.orders.shipped'); }
Sử dụng biến địa chỉ Global from
Mặt khác, chúng ta có thể sử dụng biến global from trong file cấu hình config/mail.php. Địa chỉ này sẽ được sử dụng nếu không chỉ định from address trong mailable class.
'from' => ['address' => 'example@example.com', 'name' => 'App Name'],
Trong phương thức build chúng ta có thể sử dụng phương thức view để chỉ định template được rendering (sử dụng Blade template) khi xây dựng email HTML.
/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped'); }
Chúng ta có thể tạo một thư mục resources/views/emails đẻ lưu trữ các email template.
Plain Text Emails
Nếu muốn định nghĩa một phiên bản plain-text để gửi mail, chúng ta có thể sử dụng phương thức text. Giống như hàm view, hàm text chấp nhận một template chưa nội dung email.
/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->text('emails.orders.shipped_plain'); }
Thông qua thuộc tính public
Thông thường chúng ta cần gán dữ liệu qua view để hiện thị. Có 2 cách để pass dữ liệu qua view. Đầu tiên, bất cứ thược tính public nào được định nghĩa ở mailable class đều tự động pass qua view. Nghĩa là mình sẽ hiển thị được luôn mà không cần phải gán. Ví dụ:
<?php namespace AppMail; use AppOrder; use IlluminateBusQueueable; use IlluminateMailMailable; use IlluminateQueueSerializesModels; 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'); } }
Biến $order là biến public nên nó tự động được truy cập ở view.
<div> Price: {{ $order->price }} </div>
Thông qua phương thức with
Đối với các biến có thuộc tính là protected và private thì có thể pass dữ liệu qua view bằng phương thức with:
<?php namespace AppMail; use AppOrder; use IlluminateBusQueueable; use IlluminateMailMailable; use IlluminateQueueSerializesModels; 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, ]); } }
Mỗi lần dữ liệu được gán qua phương thức with, chúng tự động được truy cập ở view:
<div> Price: {{ $orderPrice }} </div>
Để đính kèm file, sử dụng phương thức attach, nhận đường dẫn của file làm tham số đầu tiên. Tham số thứ 2 là mảng chưa tên file, loại file:
/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attach('/path/to/file', [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ]); }
Còn có phương thức attachData được sử dụng để đính kèm 1 chuỗi ký tự như một file đính kèm. Ví dụ, nếu chúng ta sinh ra một file PDF trong một nhớ và muốn đính kèm email mà ko muốn ghi ra đĩa cứng. Phương thức attachData nhận nội dung string như là tham số đầu tiên, tên của file là tham số thứ 2, và mảng optional là tham số thứ 3.
/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attachData($this->pdf, 'name.pdf', [ 'mime' => 'application/pdf', ]); }
Chúng ta có thể đính kèm file sử dụng phương thức embed của biến $message trong email template. $message là biến global và có thể truy cập ở mọi email template mà không cần phải gán qua view.
<body> Here is an image: <img src="{{ $message->embed($pathToFile) }}"> </body>
Đính kèm chuỗi nội dung (Embedding Raw Data Attachments) Chuỗi nội dung có thể được nhúng trong một email template thông qua phương thức embedData của biến $message:
<body> Here is an image from raw data: <img src="{{ $message->embedData($data, $name) }}"> </body>
Config biến MAIL .env
MAIL_DRIVER=smtp MAIL_HOST=smtp.abc.com MAIL_PORT=587 MAIL_USERNAME=username@abc.com MAIL_PASSWORD=password MAIL_ENCRYPTION=tls
Ngoài ra config thêm địa chỉ người gửi và tên người from trong file config/mail.php. Nếu không chỉ định người gửi bằng phương thức from trong Mailable class thì nó sẽ lấy giá trị này làm giá trị người người mặc định.
'from' => [ 'address' => 'username@abc.com', 'name' => 'Mr David', ],
Để gửi mail, sử dụng phương thức to của Mail facade. Phương thức to chấp nhận một địa chỉa email, một user instance, hoặc một tập hợp các users. Nếu truyền vào tham số là object hoặc tập hợp (collection) các object, mailer sẽ tự động sử dụng thuộc tính email và name để setting địa chỉ người nhận. Sau đó dùng phương thức send để gửi mail.
<?php namespace AppHttpControllers; use AppOrder; use AppMailOrderShipped; use IlluminateHttpRequest; use IlluminateSupportFacadesMail; use AppHttpControllersController; 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)); } }
Laravel còn cung cấp thêm các hàm cc, bcc để thêm người nhận.
Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->send(new OrderShipped($order));
Queue một tin nhắn email
Thường thi gửi mail mất khá nhiều thời gian nên chúng ta thường ném vào queue và chạy background để gửi mail đi. Để queue email message sử dụng phương thức queue của Mail facade.
Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->queue(new OrderShipped($order));
Để xem thêm về Queue chúng ta tham khảo tại trang chủ của Laravel Queues.
Delayed Message Queueing
Nếu chúng ta cần delay việc gửi mail của các email message đã được queue sử dụng method later. Phương thức later nhận một Datetime instance làm đối số.
$when = CarbonCarbon::now()->addMinutes(10); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->later($when, new OrderShipped($order));
Đẩy email message vào queue chỉ định
Tất cả các mailable classes sinh ra bời command make:mail sử dụng IlluminateBusQueue trait, có thể sử dụng 2 phương thức onQueue và onConnnection để chỉ định tên queue và tên connection.
$message = (new OrderShipped($order)) ->onConnection('sqs') ->onQueue('emails'); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->queue($message);
Queue mặc định
Nếu bạn có mailable classes muốn luôn luôn được queue thì bạn phải implement contract ShouldQueue.
use IlluminateContractsQueueShouldQueue; class OrderShipped extends Mailable implements ShouldQueue { // }
Run Queues
Sau khi ném email message vào Queue, chúng ta phải chạy job queue emails để gửi email.
php artisan queue:work redis queue=emails
Việc gửi mail trong Lavavel rất đơn giản và tiện lợi. Tùy từng ứng dụng mà chúng ta có thể sử dụng các config thích hợp.
- Laravel mailer