post-image

Xử lý thư điện tử với Laravel Mail

Tổng quan

Thư điện tử là một trong những cách trao đổi thông tin, quảng bá nhanh trong bối cảnh Internet đang bùng nổ. Trong các hệ thống website, hệ thống gửi thông tin cho người dùng thông qua email là không thể thiếu. Framework Laravel cũng rất chú trọng đến thư điện tử, với Laravel Mail bạn sẽ dễ dàng tạo ra những ứng dụng có khả năng gửi nhận email.

Hệ thống API của Laravel Mail rất đơn giản, rõ ràng khi sử dụng thư viện của SwiftMailer, nó cho phép làm việc với mail server qua SMTP, với các dịch vụ email như Mailgun, SparkPost, Amazon SES, MailTrap… Mailgun và SparkPost là các dịch vụ email có tốc độ nhanh hơn SMTP thông thường, tuy nhiên khi sử dụng các dịch vụ này cần cài đặt thêm một package Guzzle HTTP, chúng ta có thể cài đặt thông qua composer như sau:

composer require guzzlehttp/guzzle
Code language: JavaScript (javascript)

Thiết lập mail driver

Khi sử dụng các mail driver cho các dịch vụ thư điện tử khác nhau, chúng ta cần khai báo trong config/mail.php.

/* |-------------------------------------------------------------------------- | Mail Driver |-------------------------------------------------------------------------- | | Laravel supports both SMTP and PHP's "mail" function as drivers for the | sending of e-mail. You may specify which one you're using throughout | your application here. By default, Laravel is setup for SMTP mail. | | Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses", | "sparkpost", "log", "array" | */ 'driver' => env('MAIL_DRIVER', 'mailgun'),
Code language: PHP (php)

driver hỗ trợ smtp, mailgun, ses, sparkpost… khi bạn chọn dịch vụ email nào thì cần thiết lập driver cho tương ứng. Sau đó, bạn cần thiết lập các thông số cho dịch vụ email trong config/service.php.

'mailgun' => [ 'domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), ], 'ses' => [ 'key' => env('SES_KEY'), 'secret' => env('SES_SECRET'), 'region' => 'us-east-1', ], 'sparkpost' => [ 'secret' => env('SPARKPOST_SECRET'), ],
Code language: PHP (php)

Tạo mới Mailables Class

Trong Laravel, các dạng email khác nhau được gửi đi đều thông qua Mailables Class, các class này đều được lưu trong thư mục app\Mail. Nếu bạn không thấy thư mục app\Mail cũng đừng lo lắng, các lệnh tạo mới class Mailables sẽ tự động tạo ra thư mục này. Để tạo mới một class Mailables chúng ta sử dụng lệnh artisan như sau:

php artisan make:mail RegisteredUser
Code language: CSS (css)

Trong các class Mailables có phương thức build() sử dụng để thiết lập email cần gửi đi, trong phương thức build() này bạn có thể sử dụng rất nhiều các phương thức khác liên quan đến email như from, attach, subject… ### Thiết lập người gửi email

Trong một email, thông tin người gửi là quan trọng nhất để nhận biết email này đến từ đâu. Thiết lập người gửi email trong Laravel Mail có hai cách: cách thiết lập cho từng email và cách thiết lập cho toàn bộ các email. Để thiết lập người gửi cho từng email chúng ta sử dụng phương thức from().

/** * Build the message. * * @return $this */ public function build() { return $this->from('allaravel.com@gmail.com') ->view('emails.user.registered'); }
Code language: PHP (php)

Chúng ta cũng có thể thiết lập người gửi cho toàn bộ các email bằng cách cấu hình file config/mail.php:

'from' => [ 'address' => env('MAIL_FROM_ADDRESS', 'allaravel.com@gmail.com'), 'name' => env('MAIL_FROM_NAME', 'All Laravel Admin'), ],
Code language: PHP (php)

Hoặc thậm chí trong file thiết lập các biến môi trường .env ở thư mục gốc của dự án:

MAIL_FROM_ADDRESS=allaravel.com@gmail.com MAIL_FROM_NAME=All Laravel Admin

Xây dựng giao diện và nội dung của email gửi bằng Laravel Mail

Trong phương thức build() của class Mailables chúng ta có thể sử dụng view() để chỉ định một Laravel Blade template làm mẫu cho email và có thể truyền các đối tượng vào template này.

/** * Build the message. * * @return $this */ public function build() { $user = User::find($registered_user_id) return $this->view('emails.user.registered')->with('user', $user); }
Code language: PHP (php)

Để truyền dữ liệu vào class Mailables chúng ta sử dụng các thuộc tích public, nó sẽ tự động được gán giá trị khi tạo một instance của class Mailables.

<?php namespace App\Mail; use App\Order; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class UserRegistered extends Mailable { use Queueable, SerializesModels; /** * The order instance. * * @var Order */ public $user; /** * Create a new message instance. * * @return void */ public function __construct(Order $user) { $this->user = $user; } /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.user.registered')->with('user', $this->user); } }
Code language: HTML, XML (xml)

Những chỗ nào cần gửi mail ta chỉ đơn giản thực hiện tạo một instance của class Mailables như sau:

$user = User::find($user_id); $email = new UserRegistered($user); Mail::to($user->email)->send($email);
Code language: PHP (php)

Đính kèm file trong email

Đôi khi, trong một email chúng ta cũng muốn đính kèm các file như một file văn bản hoặc file slide trình bày vấn đề gì đó… việc này khá đơn giản trong Laravel Mail, sử dụng phương thức attach() để đính kèm những gì bạn muốn:

/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.user.registered') ->attach('/path/to/file'); }
Code language: PHP (php)

đầu vào của phương thức attach() có thể là một mảng các thông số cho file đính kèm:

/** * Build the message. * * @return $this */ public function build() { return $this->view('emails.user.registered') ->attach('/path/to/file', [ 'as' => 'Bigsale2017.pdf', 'mime' => 'application/pdf', ]); }
Code language: PHP (php)

Gửi email trong Laravel Mail

Sử dụng phương thức to() của facade Mail để thiết lập người cần gửi email đến, đầu vào của phương thức này có thể là một địa chỉ email, một instance của User hoặc một tập hợp các instance của User. Phương thức to() tự động lấy thuộc tính email và name trong đối tượng truyền vào để gửi email. Cuối cùng, sử dụng phương thức send() với đầu vào là một instance của class Mailables.

<?php namespace App\Http\Controllers\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; class RegisterController extends Controller { ... /** * Handle a registration request for the application. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function register(Request $request) { $this->validator($request->all())->validate(); event(new Registered($user = $this->create($request->all()))); $this->guard()->login($user); // Gui email khi nguoi dung dang ky $email = new WelcomeEmail($this->user); Mail::to($this->user->email) ->cc('admin1@allaravel.com') ->bcc('admin2@allaravel.com') ->send($email); return view('auth.welcome'); }
Code language: HTML, XML (xml)

Chúng ta cũng có thể sử dụng cc() và bcc() cho các tính năng gửi email cho những người khác. ## Ví dụ gửi mail bằng Laravel Mail

Không cần nói nhiều về tác dụng của các ví dụ thực tế, hôm nay tôi sẽ đưa các bạn đến một ví dụ rất thú vị và sử dụng rất nhiều trong các hệ thống website. Trong hệ thống website cần một tính năng gửi email đến các thành viên khi có một tin tức mới, một sản phẩm mới hoặc một chương trình quảng cáo.

Chúng ta sẽ thực hiện tính năng gửi mail này với Gmail, MailGun, MailTrap, Sparkpost, SES… Bắt đầu thực hành nào! Đầu tiên, chúng ta sẽ tạo ra một Controller chứa toàn bộ mã liên quan đến xử lý mail (Xêm thêm Laravel Controller).

php artisan make:controller MailController
Code language: CSS (css)

Câu lệnh này sẽ tạo ra MailController.php trong app\Http\Controllers. Tiếp theo thêm route vào routes/web.php:

Route::get('admin/email', 'MailController@showEmailForm'); Route::post('admin/email', 'MailController@sendEmail');
Code language: PHP (php)

Tạo phương thức showEmailForm() trong MailController:

public function showEmailForm(){ return view('fontend.send-email'); }
Code language: PHP (php)

Phương thức này trả về view send-email, chúng ta thực hiện tạo view này trong resources/views/fontend.

@extends('layouts.default') @section('title', 'Gửi email - Allaravel.com') @section('content') {!! Form::open(array('url' => '/admin/email', 'class' => 'form-horizontal')) !!} <div class="form-group"> {!! Form::label('name', 'Email service', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-3"> {!! Form::select('email_service', array('1' => 'SMTP GMAIL', '2' => 'MailGun', '3' => 'MailTrap', '4' => 'Sparkpost'), '1', array('class' => 'form-control')) !!} </div> </div> <div class="form-group"> {!! Form::label('name', 'Tên người gửi', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-9"> {!! Form::text('from_name', 'All Laravel Admin', array('class' => 'form-control')) !!} </div> </div> <div class="form-group"> {!! Form::label('from_email', 'Email người gửi', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-9"> {!! Form::text('from_email', 'allaravel.com@gmail.com', array('class' => 'form-control')) !!} </div> </div> <div class="form-group"> {!! Form::label('to_email', 'Email người nhận', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-9"> {!! Form::text('to_email', '', array('class' => 'form-control')) !!} </div> </div> <div class="form-group"> {!! Form::label('subject', 'Tiêu đề', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-9"> {!! Form::text('subject', '', array('class' => 'form-control')) !!} </div> </div> <div class="form-group"> {!! Form::label('body', 'Nội dung', array('class' => 'col-sm-3 control-label')) !!} <div class="col-sm-9"> {!! Form::textarea('body', '', array('class' => 'form-control', 'rows' => 5)) !!} </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> {!! Form::submit('Gửi email', array('class' => 'btn btn-success')) !!} </div> </div> {!! Form::close() !!} @endsection
Code language: HTML, XML (xml)

Vào http://laravel.dev/admin/email chúng ta có giao diện như sau:

Ví dụ sử dụng Laravel Mail

Thêm phương thức sendEmail() vào MailController để xử lý việc gửi email: Trường email người nhận sẽ được nhập vào theo kiểu email1@gmail.com, email2@gmail.com,… do đó để kiểm tra được tất cả các email này xem có đúng định dạng email không, chúng ta phải viết một hàm kiểm tra riêng (Xem Laravel Validate để biết thêm cách kiểm tra dữ liệu nhập vào). Để làm được việc này, chúng ta sử dụng phương thức extend() của facade Validator trong service provider mặc định AppServiceProvider (trong app\Providers).

<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Validator; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Validator::extend("emails", function($attribute, $value, $parameters) { $rules = [ 'email' => 'required|email', ]; foreach ($value as $email) { $data = [ 'email' => $email ]; $validator = Validator::make($data, $rules); if ($validator->fails()) { return false; } } return true; }); }
Code language: HTML, XML (xml)

Ok, chúng ta có thể sử dụng mở rộng này để kiểm tra trường nhập các email cần gửi như sau:

'to_email' => 'required|emails'
Code language: PHP (php)

Quay lại với phương thức sendEmail trong MailController.

public function sendEmail(Request $request){ $messages = [ 'required' => 'Trường :attribute bắt buộc nhập.', 'email' => 'Trường :attribute phải có định dạng email' ]; $validator = Validator::make($request->all(), [ 'to_email' => 'required|emails', 'subject' => 'required', 'body' => 'required' ], $messages); if ($validator->fails()) { return redirect('admin/email') ->withErrors($validator) ->withInput(); } else { $email_service = $request->input('email_service'); switch ($email_service) { case 1: // Gmail config(['mail.driver' => 'smtp', 'mail.host' => 'smtp.gmail.com', 'mail.port' => 587, 'mail.username' => 'allaravel.com@gmail.com', 'mail.password' => 'extpoeeoicypxqoie', 'mail.encryption' => 'tls']); break; case 2: // MailGun config(['mail.driver' => 'mailgun']); break; case 3: // MailTrap config(['mail.driver' => 'smtp', 'mail.host' => 'smtp.mailtrap.io', 'mail.port' => 2525, 'mail.username' => '8b5309fif50e74', 'mail.password' => '39ov4ee432ab5c', 'mail.encryption' => 'tls']); break; case 4: // Sparkpost config(['mail.driver' => 'sparkpost', 'mail.host' => 'smtp.sparkpostmail.com', 'mail.port' => 587, 'mail.username' => 'SMTP_Injection', 'mail.password' => 'f57d09lc09a02650d816df6f501409odpkvjcjc6', 'mail.encryption' => 'STARTTLS']); break; } $email_arr = explode(',', $request->input('to_email')); for ($i=0; $i < count($email_arr); $i++) { $mailable = new SendEmail(); Mail::to($email_arr[$i])->send($mailable); } return redirect('admin/email') ->with('message', 'Send email success!'); } }
Code language: PHP (php)

Trong các cấu hình email ở trên chúng ta cần để ý một số vấn đề như sau:

  • Với Gmail, bạn có thể đưa mật khẩu vào MAIL_PASSWORD, tuy nhiên nếu tài khoản đăng bật chế độ 2 bước xác thực thì phải tạo Mật khẩu ứng dụng (app password) rồi đưa vào MAIL_PASSWORD. Khuyến cáo, bạn lên bật chế độ 2 bước xác thực với tài khoản Google để bảo mật. Cách tạo app password cho Google bạn có thể xem tại Sign in using App password hoặc xem trong ví dụ gửi email bằng hàng đợi trong bài Laravel Queue.
  • Với MailTrap, chúng ta tạo tài khoản, sau đó vào inbox sẽ có các thông tin cần thiết như host, port, username, password, encryption.
Thiết lập Laravel Mail với MailTrap
  • Với SparkPost, chúng ta cũng đăng ký, sau đó trong phần quản trị vào Account -> SMTP delay, các thông tin để thiết lập cho mail cũng ở hết trong này.
Thiết lập Laravel Mail với Sparkpost

Tiếp theo chúng ta tạo một class Mailables bằng lệnh artisan:

php artisan make:mail SendEmail
Code language: CSS (css)

Phương thức build() trong ví dụ, chúng ta không truyền dữ liệu vào mà chỉ đơn giản trả về giao diện của email.

<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class SendEmail extends Mailable { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ public function __construct() { // } /** * Build the message. * * @return $this */ public function build() { return $this->view('email.info-email'); } }
Code language: HTML, XML (xml)

Tạo view cho email (resources/views/email/info-email.blade.php) với nội dung đơn giản như sau:

<html> <head> <title>Test Email</title> </head> <body> <h1>Test Email</h1> </body> </html>
Code language: HTML, XML (xml)

Ok, chúng ta đã chuẩn bị xong toàn bộ code để thực hành ví dụ Laravel Mail. Thực hiện thử các dịch vụ mail và kiểm tra email nhận được. Chúc các bạn thực hiện thành công.

Cảm ơn các bạn đã đọc.

Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.


Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.

Nguồn tham khảo: allaravel

Leave a Reply

Your email address will not be published. Required fields are marked *