Laravel 自帶 SwiftMailer 庫,集成了多種郵件API,可以很方便的實現郵件的發送。
我們使用到的是SMTP(Simple Message Transfer Protocol)簡單郵件傳輸協議,通常理解為郵件發送服務器。
1、開啟POP3和SMTP服務
1.1、在這里我們以QQ郵箱為案例
設置 -> 賬戶 -> POP3 -> 開啟
到這一步會提示驗證,按照提示發送短信通過驗證:
短信發送成功,會出現如下提示、也就代表配置成功。你需要記錄密鑰,這個東西會在配置中用:
1.2、在這里我們以 163郵箱為案例
后期有時間在維護。。。。理解理解。。。
2、對 Laravel 框架中郵件發送的配置文件進行修改:
.env 文件:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=********@qq.com
MAIL_PASSWORD=qq郵箱此處填寫上圖產生的授權碼
MAIL_FROM_NAME=郵箱的名稱
MAIL_ENCRYPTION=ssl
config/mail.php 文件:
return [
'driver' => env('MAIL_DRIVER', 'smtp'),
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
'from' => [
'address' => env("MAIL_USERNAME", ""),
'name' => env("MAIL_FROM_NAME")
],
'encryption' => env('MAIL_ENCRYPTION'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'sendmail' => '/usr/sbin/sendmail -bs',
'pretend' => env('MAIL_PRETEND', false),
];
// driver:用於配置默認的郵件發送驅動。
// Laravel支持多種郵件驅動方式,包括smtp、Mailgun、Maildrill、Amazon SES、mail和sendmail;
// Mailgun和Amazon SES都是收費的Maildrill目前不支持中國區用戶,這三個都是第三方郵件服務。
// mail驅動使用PHP提供的mail函數發送,sendmail驅動通過Sendmail/Postfix(Linux)提供的命令發送郵件;
// smtp驅動通過支持ESMTP的SMTP發送郵件。
// 就目前狀況來看,使用smtp是最明智的選擇;
// mail不安全,sendmail需要安裝配置Sendmail/Postfix,其他要么付費要么不能用。
// host:郵箱所在主機;
// 使用163郵箱,對應值是smtp.163.com;
// 使用QQ郵箱,對應值是smtp.qq.com。
// 使用騰訊企業郵箱,對應值是smtp.exmail.qq.com
// port:用於配置郵箱發送服務端口號,
// 一般默認值是25,但如果設置SMTP使用SSL加密,該值為465。
// from:配置項包含address和name,
// address 表示你自己的郵箱
// name 表示你郵件用戶名(這里郵箱,是用來發郵件的郵箱)。
// encryption:表示加密類型;
// 可以設置為null表示不使用任何加密,也可以設置為tls或ssl。
// username: 表示郵箱賬號,比如123456789@qq.com
// password 表示上述郵箱登錄對應登錄密碼。
// 注意QQ郵箱的話應該開啟POP3|SMTP服務時給的授權碼。
// sendmail: 是在設置driver為sendmail時使用,用於指定sendmail命令路徑。
// pretend: 用於配置是否將郵件發送記錄到日志中;
// 默認為false則發送郵件不記錄日志;
// 如果為true的話只記錄日志不發送郵件,這一配置在本地開發中調試時很有用
3、生產控制器、配置路由
php artisan make:controller MailController
Route::any('mail/send','MailController@sendMail');
4、編輯控制器、加入以下代碼:
// 記得使用內置的郵件類 use Illuminate\Support\Facades\Mail;
public function sendMail() {
$name = '這是郵件發送的標題';
// Mail::send()的返回值為空,所以可以其他方法進行判斷
// Mail::send();需要傳三個參數;
// 第一個為引用的模板
// 第二個為給模板傳遞的變量(郵箱發送的文本內容)
// 第三個為一個閉包,參數綁定Mail類的一個實例。
Mail::send('emails.test',['name'=>$name],function($message){
$to = 'itlaowen@qq.com';
$message ->to($to)->subject('郵件測試');
});
// 返回的一個錯誤數組,利用此可以判斷是否發送成功
dd(Mail::failures());
}
5、由於上面👆指定了郵件發送的視圖層、所以去編輯
在resources/emails下創建一個模板文件。
這是測試郵件!!
{{$name}}
6、測試
訪問:http://localhost/mail/send 如果返回一個空數組則表示郵件發送成功。
7、報錯:stream_socket_client() 、certificate verify failed
具體報錯如下:
stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
原因:
php openssl 沒有加載 ca 證書 , 去下載個 ca 證書然后添加進去即可
解決:
查看phpinfo()、檢查openssl.cafile的文件是否存在
不存在的話進行如下操作
1、找到自己的 php 的安裝目錄
2、進入目錄:cd php/etc/
3、下載 ca 證書:wget http://curl.haxx.se/ca/cacert.pem
4、查看目錄:pwd
5、編輯 php.ini:vim php.ini
6、修改 openssl.cafile 的路徑 openssl.cafile=/usr/local/php/etc/cacert.pem
7.2 報錯 Expected response code 250 but got code "501"
具體報錯如下:
Expected response code 250 but got code "501", with message "501 Mail from address must be same as authorization user. "
解決:
在.env文件中增加兩行
MAIL_FROM_ADDRESS=你的郵箱
MAIL_FROM_NAME=你的郵箱
MAIL_DRIVER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=你的郵箱
MAIL_FROM_ADDRESS=你的郵箱
MAIL_FROM_NAME=你的郵箱
MAIL_PASSWORD=授權碼
MAIL_ENCRYPTION=ssl
8、擴展:發送純文本郵件
public function sendEmail()
{
// 純文本信息郵件測試
Mail::raw('你好,我是PHP程序!', function ($message) {
$to = 'itlaowen@163.com';
$message ->to($to)->subject('純文本信息郵件測試');
});
if (count(Mail::failures()) < 1) {
echo '發送郵件成功,請查收!';
} else {
echo '發送郵件失敗,請重試!';
}
}
9、擴展:郵件內容中增加圖片
視圖文件:
{{$name}}
<br>
hello world。
<br>
<img src="{{ $message->embed($image) }}">
控制器:
public function sendEmail()
{
// 郵件內部附件
$name = '郵件內部附件';
$image = public_path('php/8I0BHkS2QKmxyfQBBfiamBZALR5Ox2zkN62KFFoP.jpeg');
// $image = 'http://t8.baidu.com/it/u=1484500186,1503043093&fm=79&app=86&f=JPEG?w=1280&h=853';//網上圖片
Mail::send('Emails.test', ['image' => $image, 'name' => $name], function ($message) {
$to = 'itlaowen@163.com';
$message->to($to)->subject('圖片測試');
});
if (count(Mail::failures()) < 1) {
echo '發送郵件成功,請查收!';
} else {
echo '發送郵件失敗,請重試!';
}
}
10、擴展:郵件附件
public function sendEmail()
{
// 發送附件郵件
$name = '這是帶附件的郵件';
$image = 'http://t8.baidu.com/it/u=1484500186,1503043093&fm=79&app=86&f=JPEG?w=1280&h=853'; //網上圖片
Mail::send('Emails.test', ['image' => $image, 'name' => $name], function ($message) {
$to = 'itlaowen@163.com';
$message->to($to)->subject('郵件測試');
$attachment = public_path('file/1.xlsx');
// 在郵件中上傳附件
$message->attach($attachment, ['as' => '中文文檔.xlsx']);
});
if (count(Mail::failures()) < 1) {
echo '發送郵件成功,請查收!';
} else {
echo '發送郵件失敗,請重試!';
}
}
如果出現亂碼、可以嘗試以下寫法:
$message->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('中文文檔')."?=.xls"]);