Mailtrap 提供了簡單的測試郵件的服務,步驟以下:php
登陸網站 Mailtraphtml
註冊用戶laravel
註冊成功以後,會自動建立一個 demo,點進去以後就能夠看到配置信息數據庫
只須要把上面的信息配置到對應的 .env
中便可:markdown
MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=fc0ad24e593f34 MAIL_PASSWORD=aef271516bc810 MAIL_ENCRYPTION=null
這樣,咱們在應用裏面發出去的郵件你都能在網站的 demo 中看到了。閉包
接下來談談要實現的用戶激活功能的基本過程:app
建立數據表,保存用戶激活信息;函數
提供激活選項給登陸其未激活的用戶;測試
用戶點擊激活以後,生成一個惟一的祕鑰,保存到數據庫;同時將祕鑰以參數形式附在超連接的後面顯示在用戶郵箱正文中;網站
用戶在郵箱中點擊超連接,返回網站;
網站根據參數是否匹配以及是否過時(24小時)來判斷用戶是否激活成功;
由於激活的功能並不經常使用,將其單獨放置於一張表中:
$ php artisan make:model UserActivation -m
編輯字段:
/database/migrations/2017_04_21_071142_create_user_activations_table.php public function up() { Schema::create('user_activations', function (Blueprint $table) { $table->integer('user_id')->unsigned()->primary(); $table->string('token')->unique(); $table->boolean('active')->default(0); $table->timestamps(); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); }
執行:
$ php artisan migrate
用戶表與用戶激活表爲一對一關係:
/app/User.php public function activations() { return $this->hasOne(\App\UserActivation::class); }
容許用戶激活表批量賦值:
/app/UserActivation.php protected $fillable= ['user_id','active','token'];
首先,讓登陸且未激活的用戶能夠點擊「激活」按鈕:
/resources/views/layouts/nav.blade.php @if (Auth::check()) <a class="dropdown-item" href="#">{{ Auth::user()->name }}</a> <a class="dropdown-item" href="/logout">登出</a> @if (is_null(Auth::user()->activations) || Auth::user()->activations->active == 0) <a class="dropdown-item" href="/sendActiveMail">發送激活郵件</a> @endif @else
路由指派該請求:
Route::get('/sendActivationMail','RegistrationController@send');
在實現具體的方法以前,咱們先來介紹下如何快速發送郵件。
先來看看 Laravel 提供的選項:
$message->from($address, $name = null); # 郵件的全部者 $message->sender($address, $name = null); # 郵件的實際傳輸人,若全部者與發送者爲同一人,可省略 $message->replyTo($address, $name = null); # 做者建議回覆的地址 $message->to($address, $name = null); # 收件人的地址 $message->cc($address, $name = null); # 收件人外,想讓其餘知道該事的人的地址 $message->bcc($address, $name = null); # 不想讓 cc 的人看到你發送給了誰,那麼就用 bcc $message->subject($subject); #主題 $message->priority($level); $message->attach($pathToFile, array $options = []);
注意,郵件的格式要遵照 RFC2822 規範,不然可能報錯。
from = "From:" mailbox-list CRLF sender = "Sender:" mailbox CRLF reply-to = "Reply-To:" address-list CRLF to = "To:" address-list CRLF cc = "Cc:" address-list CRLF bcc = "Bcc:" (address-list / [CFWS]) CRLF
咱們舉一個簡單的例子:
public function send() { \Mail::raw('test laravel blog email function',function ($message){ $from = ['From: from@qq.com','fromman']; $to = ['To: to@qq.com','toman']; $cc = ['Cc: cc@qq.com','ccman']; $bcc = ['Bcc: bcc@qq.com','bccman']; $replyTo = ['Reply-To: replyto@qq.com','replytoman']; $sender = ['Sender: sender@qq.com','senderman']; $subject = 'Subject Subject'; $message->to($to) ->from($from) ->sender($sender) ->cc($cc) ->bcc($bcc) ->replyTo($replyTo) ->subject($subject); }); return redirect('/'); }
raw
方法發送純文本給對方。同時,咱們在傳入的閉包函數中進行配置。在本例子中,將會給 toman
、ccman
和 bccman
三我的一人發送一封純文本郵件,所以,咱們在 Mailtrap 中會收到三封:
由於 bcc
是密送,因此發送給 ccman
的郵件中看不到 bccman
:
在上述的配置字段中, from
字段以預先定義好,這樣就不須要每次都填寫了。固然,若是使用了 $message->from
方法,就會覆蓋配置。
/config/mail.php 'from' => [ 'address' => env('MAIL_FROM_ADDRESS', '"From: "demo@blog.com'), 'name' => env('MAIL_FROM_NAME', 'Zen'), ],
如今,咱們實現能夠發送激活郵件的功能了:
use App\UserActivation; public function send() { // 生成惟一 token $token = bcrypt(auth()->user()->email.time()); $user = auth()->user(); // 發送郵件 \Mail::send('emails.activation', compact('user', 'token'), function ($message) { $to = ['To: '.auth()->user()->email, auth()->user()->name]; $subject = 'blog demo 請您激活帳戶'; $message->to($to) ->subject($subject); }); // 數據庫保存 token if ($user->activations){ $user->activations()->update(['token'=>$token]); } else { $user->activations()->save(new UserActivation([ 'token' => $token ])); } // 發送並保存成功,跳轉到主頁 return redirect('/'); }
此次,咱們使用的是 Mail::send
方法,該方法能夠傳入視圖做爲郵件內容,同時第二個參數裏傳入給視圖的數據,接下來定義視圖:
/resources/views/emails/activation.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p>您好, {{ $user->name }} ! 請點擊下面連接完成註冊:</p> <a href="http://localhost:8000/activeAccount/?verify={{$token}}">激活連接</a> </body> </html>
用戶將會收到這樣的郵件:
點擊連接以後,會向網站發送請求,路由進行指派:
Route::get('/activeAccount','RegistrationController@active');
最後,判斷該 token
是否過時或者是否匹配,匹配則跳轉到登陸頁面,不然跳轉到主頁。
use Carbon\Carbon; public function active() { $token = request('verify'); $rs = UserActivation::where('token', $token) ->whereBetween('updated_at', [Carbon::now()->subDay(), Carbon::now()]); if ($rs->exists()) { $rs->update(['active'=>true]); return redirect('/login'); } return redirect('/'); }
功能已經實現了。咱們稍微封裝下代碼吧:
/app/Http/Controllers/RegistrationController.php public function send() { $token = bcrypt(auth()->user()->email.time()); $user = auth()->user(); \Mail::send('emails.activation', compact('user', 'token'), function ($message) { $to = ['To: '.auth()->user()->email, auth()->user()->name]; $subject = 'blog demo 請您激活帳戶'; $message->to($to) ->subject($subject); }); $user->addActivationsData($token); return redirect('/'); } public function active() { $token = request('verify'); $rs = UserActivation::where('token', $token) ->notExpired(); if ($rs->exists()) { $rs->update(['active'=>true]); return redirect('/login'); } return redirect('/'); }
addActivationsData
方法用於保存或更新 $token
字段:
/app/User.php public function addActivationsData($token) { if ($this->activations) { $this->activations()->update(['token'=>$token]); } else { $this->activations()->save(new \App\UserActivation([ 'token' => $token ])); } }
notExpired
方法用於判斷 token
是否在 24 小時以內:
/app/UserActivation.php use Carbon\Carbon; public function scopeNotExpired($query) { return $query->whereBetween('updated_at', [Carbon::now()->subDay(), Carbon::now()]); }
在剛纔的例子中,咱們使用的是 Mail
提供的方法來快速建立和發送郵件。實際上,Laravel 提供了管理不一樣類型郵件的方法。咱們來快速瞭解下。
首先,咱們來建立一個用於歡迎新用戶的 mailables
:
$ php artisan make:mail Welcome
首次使用時,會建立 app/Mail
目錄。接下來,咱們就能夠實現給用戶發送歡迎郵件的功能了。
首先,用戶註冊成功以後,發送一封歡迎郵件:
/app/Http/Controllers/RegistrationController.php use App\Mail\Welcome; public function store() { ... auth()->login($user); \Mail::to($user)->send(new Welcome); return redirect()->home(); }
以前咱們經過閉包的方式傳遞 from
、to
等字段,實際上,也能夠直接將 $user
實例直接傳遞給 to
,這樣會自動去識別 name
和 from
字段。而後,send
方法傳入 mailables
類便可。
若是使用
to($user)
可能會報錯,由於不符合咱們以前說的 RFC2822 規範。
接下來,發送郵件的主要功能均可以在定義的 Welcome
類中實現了。
能夠定義郵件的 blade 視圖:
/app/Mail/Welcome.php public function build() { return $this->view('emails.welcome'); }
顯示結果爲:
也能夠定義純文本視圖:
/app/Mail/Welcome.php public function build() { return $this->text('emails.welcome'); }
對應的視圖文件以下:
/resources/views/emails/welcome.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1>{{$name}}, 歡迎成爲 Blog Demo 的會員</h1> </body> </html>
能夠配置郵件的各類信息,跟以前的方式相似:
public function build() { $from = ['From: from@qq.com','fromman']; $to = ['To: to@qq.com','toman']; $subject = 'Subject Subject'; return $this->text('emails.welcome') ->to($to) ->from($from) ->subject($subject); }
能夠傳遞變量給視圖,第一種是直接在 view
裏面傳遞(也可使用 with
):
/app/Mail/Welcome.php public function build() { $from = ['From: from@qq.com','fromman']; $to = ['To: to@qq.com','toman']; $subject = 'Subject Subject'; $user = auth()->user(); return $this->view('emails.welcome',compact('user')) ->to($to) ->from($from) ->subject($subject); } /resources/views/emails/welcome.blade.php <h1> {{$user->name }}, 歡迎成爲 Blog Demo 的會員</h1>
另一種方法是,在 Welcome
類中定義屬性類型爲「公共的」。這樣該屬性就會自動傳遞給視圖:
/app/Http/Controllers/RegistrationController.php \Mail::send(new Welcome); /app/Mail/Welcome.php public $user; public function __construct(User $user) { $this->user = $user; }
最後,咱們還可使用 Markdown 的語法來寫郵件:
$ php artisan make:mail MDWelcome --markdown="emails.md-welcome"
建立使用使用 --markdown
參數來生成對應的視圖便可。具體使用方法能夠查看文檔。
參考資料: