Gửi mail trong Laravel 5.3
Bài đăng này đã không được cập nhật trong 8 năm
Giới thiệu
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.
Chuẩn bị
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
Khởi tạo Mailable
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
Viết Mailables
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.
Config người gửi
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'],
Config giao diện
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');
}
Gán dữ liệu qua view
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 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');
}
}
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 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,
]);
}
}
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
Để đí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',
]);
}
Nội đính kèm (Inline attachments)
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 mail server
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
Để 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 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));
}
}
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));
Queueing Mail
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 = Carbon\Carbon::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 Illuminate\Bus\Queue
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 Illuminate\Contracts\Queue\ShouldQueue;
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
Kết luận
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.
Tham khảo
All rights reserved