التعامل مع البريد الإلكتروني (Mail) في Laravel
مقدمة
يوفّر Laravel واجهة برمجية (API) سلسة و بسيطة للمكتبة الرائجة SwiftMailer مع برنامج تشغيل لكل من SMTP و Mailgun و SparkPost و Amazon SOS وتابع mail ، و sendmail. ممّا يسمح بالبداية في إرسال الرسائل الإكترونية بسرعة عبر خدمات محلية أو سحابية من اختيارك.
برامج التشغيل اللازمة
تكون برامج التشغيل المعتمدة على الوسائط مثل Mailgun و SparkPost في العادة أسرع وأسهل في الاستعمال من خوادم SMTP. استعمل أحد هذه برامج التشغيل إن أمكنك. تَستعمل كل المشغّلات التي تعتمد على الوسائط (API) المكتبة Guzzle التي يمكنك تثبيتها باستعمال منظم الحزم Composer
.
composer require guzzlehttp/guzzle
برنامج التشغيل Mailgun
لاستخدام برنامج التشغيل Mailgun، أولًا ثبّت Guzzle ثمّ غير الخيار driver
في ملف الضبط config/mail.php
للقيمة mailgun
. بعد ذلك، تثبت من أنّ ملف الضبط config/services.php
يحتوي الخيار التالي:
'mailgun' => [
'domain' => 'your-mailgun-domain',
'secret' => 'your-mailgun-key',
],
برنامج التشغيل SparkPost
لاستخدام برنامج التشغيل SparkPost، أولا ثبّت Guzzle ثمّ غير الخيار driver
في ملف الضبط config/mail.php
للقيمة sparkpost
. بعد ذلك، تثبت من أنّ ملف الضبط config/services.php
يحتوي الخيار التالي:
'sparkpost' => [
'secret' => 'your-sparkpost-key',
],
يمكن أيضًا ضبط نقطة نهاية الوسيط التي يجب استعمالها إن احتجت لذلك: '
sparkpost' => [
'secret' => 'your-sparkpost-key',
'options' => [
'endpoint' => 'https://api.eu.sparkpost.com/api/v1/transmissions',
],
],
برنامج التشغيل SES
لاستخدام برنامج التشغيل Amazon SES يجب أولًا تثبيت Amazon AWS SDK الخاص بلغة PHP. يمكنك تثبيت المكتبة عبر إضافة السطر التالي للقسم require
من الملف composer.json
:
"aws/aws-sdk-php": "~3.0"
بعد ذلك غير الخيار driver
في ملف الضبط config/mail.php
إلى القيمة ses
. ثمّ تثبت من أنّ ملف الضبط config/services.php
يحتوي الخيار التالي:
'ses' => [
'key' => 'your-ses-key',
'secret' => 'your-ses-secret',
'region' => 'ses-region', // e.g. us-east-1
],
إنشاء الأصناف القابلة للإرسال
في Laravel، كل نوع من الرسائل المرسلة من التطبيق تُمَثّل في صنف (class) قابل للإرسال "mailable". تُخزّن هذه الأصناف في المجلد app/Mail
. لا تقلق إذا لم تجد المجلد في تطبيقك إذ سيصنع عندما تُنشِئ أول صنف قابل للإرسال باستعمال الأمر make:mail
:
php artisan make:mail OrderShipped
كتابة الأصناف القابلة لإرسال
يُضبَط الصنف القابل للإرسال في التابع build
. في هذا التابع، يمكنك نداء عدّة عوامل مثل from
و subject
و view
و attach
لضبط طريقة التقديم والإرسال.
ضبط المرسل
استعمال التابع from
لنبدأ أولا بضبط المرسِل، أو المكان الذي سيراه متلقي الرسالة كمصدر الإرسال. توجد طريقتان للقيام بهذا. أولًا، يمكنك استعمال التابع from
داخل التابع build
من الصنف القابل للإرسال:
/**
* بناء الرسالة
*
* @return $this
*/
public function build() {
return $this->from('example@example.com')
->view('emails.orders.shipped');
}
استعمال عنوان عام from
في حالة كان للتطبيق عنوان واحد تُرسَل منه كل الرسائل، قد يصبح من غير المجدي نداء التابع from
في كل صنف قابل للإرسال. عوض ذلك، يمكنك تحديد عنوان عام "from" في ملف الضبط config/mail.php
. سيَستعمل هذا العنوان في حالة عدم ذكر عنوان خاص بالصنف القابل للإرسال
'from' => ['address' => 'example@example.com', 'name' => 'App Name'],
ضبط الواجهة
في التابع build
من الصنف القابل للإرسال، يمكن نداء التابع view
لتحديد أي القوالب يجب استعمالها حين إظهار محتوى الرسائل. حيث تستعمل الرسائل في الغالب قوالب Blade
لإظهار المحتوى، لك كل قوة وسهولة استخدام المحرك blade لبناء الرسالة:
/**
* بناء الرسالة
*
* @return $this
*/
public function build() {
return $this->view('emails.orders.shipped');
}
ملاحظة: قد ترغب بإنشاء المجلد resources/views/emails
ليحتوي على قوالب الرسائل، لكنك حرّ في أن تضع القوالب في أي مكان تريد في المجلد resources/views
.
البريد الإلكتروني ذو النص العادي
يمكنك تعريف نص عادي للرسالة باستعمال التابع text
. مثل view
، يقبل text
اسم القالب الذي سيُستعمل لإظهار محتوى الرسالة. أنت حر في الإختيار بين النسخة العادية ونسخة HTML للرسالة:
/**
* بناء الرسالة
*
* @return $this
*/
public function build() {
return $this->view('emails.orders.shipped')
->text('emails.orders.shipped_plain');
}
إظهار البيانات
عبر الخصائص العمومية
تحتاج في العادة لتمرير بعض البيانات للواجهة لاستعمالها حين إظهار الرسالة. هناك طريقتان لتوفير البيانات للواجهة. أولًا، كل خاصية عامة (public property) معَرّفة في الصنف القابل للإرسال تكون تلقائيًا متاحةً في الواجهة. لذا، يمكنك مثلا تمرير بيانات للتابع الباني في الصنف ثم إعطاء هذه البيانات للخاصيات العامة في الصنف:
<?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;
/**
* خاصية الترتيب
*
* @var Order
*/
public $order;
/**
* صناعة نسخة من الرسالة
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
*بناء الرسالة
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
}
بعد ضبط البيانات، ستكون متاحة للاستعمال في الواجهة ويمكنك الوصول إليها كبقية البيانات في قوالب blade:
<div>
Price: {{ $order->price }}
</div>
عبر التابع with
يمكنك تمرير البيانات يدويًا للواجهة باستعمال التابع with
إذا أردت تخصيص شكل البيانات قبل إرسالها للقالب. في العادة، ستحتاج لتمرير البيانات للتابع الباني للصنف القابل للإرسال، لكن عليك تغيير صفة البيانات إلى protected
أو private
حتى لا تكون متاحة تلقائيًا للقالب. ثمّ عند نداء التابع 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;
/**
* خاصية الترتيب.
*
* @var Order
*/
protected $order;
/**
* صناعة الرسالة.
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
}
بعد ضبط البيانات، ستكون متاحةً للاستعمال في الواجهة ويمكنك ولوجها كبقية البيانات في قوالب blade
<div>
Price: {{ $order->price }}
</div>
المرفقات
لإضافة مرفقات للرسالة، يُستعمل التابع attach
في التابع build
من الصنف. يقبل التابع مسارًا كاملًا للملف كمعامل أول:
/**
* بناء الرسالة
*
* @return $this
*/
public function build()
{ return $this->view('emails.orders.shipped') ->attach('/path/to/file'); }
عند إرفاق ملف مع الرسالة، يمكنك تحديد اسم أو نوع MIME بتمرير مصفوفة كمعامل ثاني للتابع attach
:
/**
* بناء الرسالة.
*
* @return $this
*/
public function build()
{ return $this->view('emails.orders.shipped') ->attach('/path/to/file', [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ]); }
إرفاق معلومات خام
يمكن استعمال التابع attachData
لإرفاق معلومات خام في شكل سلسلة من البيانات الخام. مثلًا، يمكن استعمال هذا التابع لإحداث ملف PDF في الذاكرة و إرفاقها مباشرة بالرسالة دون تسجيلها في القرص الصلب. يقبل التابع attachData
بايت (Bytes) من البيانات الخام كمعامل أول. اسم الملف كمعامل ثاني و مصفوفة خيارات كمعامل ثالث:
/**
* بناء الرسالة.
*
* @return $this
*/
public function build()
{ return $this->view('emails.orders.shipped')
->attachData($this->pdf, 'name.pdf', [ 'mime' => 'application/pdf', ]); }
المرفقات المُضمّنة
يكون تضمين صور في الرسائل في العادة عملية مرهقة وثقيلة، لكن Laravel يوفّر طريقة سهلة لإرفاق الصور بالرسائل واسترجاع رقم CID الملائم. لتضمين صورة، استعمل التابع embed
على المتغيّر message$
في قالب الرسالة. يضيف Laravel تلقائيًا المتغيّر message$
إلى القالب، لذا لا تحتاج لتمريره يدويًا:
<body>
هنا صورة :
<img src="{{ $message->embed($pathToFile) }}">
</body>
تنبيه: المتغير message$
غير موجود في الرسائل المكتوبة بصيغة Markdown.
تضمين مرفقات بيانات خام
إذا كان لديك معلومات بيانات خام تريد تضمينها في قالب الرسالة، يمكنك ذلك باستعمال التابع embedData
على المتغيّر message$
:
<body>
هنا صورة من بيانات خام:
<img src="{{ $message->embedData($data, $name) }}">
</body>
تخصيص رسائل SwiftMailer
يسمح التابع withSwiftMessage
من الصنف الأصلي Mailable
بتسجيل رد نداء يستدعى مع رسالة SwiftMAiler الخام قبل إرسال الرسالة. مما يعطيك إمكانية تخصيص و تكييف الرسالة قبل إرسالها:
/**
*
* @return $this
*/
public function build()
{
$this->view('emails.orders.shipped');
$this->withSwiftMessage(function ($message) {
$message->getHeaders()
->addTextHeader('Custom-Header', 'HeaderValue');
});
}
العناصر القابلة للإرسال Markdown
تسمح لك رسائل Markdown باستغلال قوالب و مكوّنات مصنوعة سابقًا في الرسالة. حيث أنّ الرسائل مكتوبة بلغة Markdown، يتمكن Laravel من إظهار قوالب جميلة و متجاوبة للرسالة و صناعة نسخةِ نص عادي في نفس الوقت.
إنشاء أصناف Markdown
لإنشاء أصناف قابلة للبعث Markdown، يمكن استعمال الخيار markdown--
مع الأمر make:mail
:
php artisan make:mail OrderShipped --markdown=emails.orders.shipped
ثم عند ضبط الصنف في التابع build
، استعمل markdown
بدل view
. يقبل التابع markdown
اسم قالب Markdown
ومصفوفة اختيارية من البيانات لإتاحتها للقالب:
/**
*
* @return $this
*/
public function build() {
return $this->from('example@example.com')
->markdown('emails.orders.shipped');
}
كتابة رسائل Markdown
تستعمل أصناف Markdown
خليطًا من مكوّنات Blade
ونص Markdown
مما يسمح ببناء الرسالة بسهولة باستعمال المكوّنات الجاهزة:
@component('mail::message')
# Order Shipped
Your order has been shipped!
@component('mail::button', ['url' => $url])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
ملاحظة: لا تكثر من استعمال الإزاحات فمحلّل اللغة في Markdown سيظهر النص ذا المساحات المُزاحة الكثيرة كنص شيفرة.
المكوّن button
يُظهر المكوّن button زرَّ ربط في وسط الصفحة. يقبل المكوّن معاملَين: مسار url
ولونًا اختياريًا color
. الألوان المدعومة هي blue
و green
و red
. يمكنك إضافة أي عدد من الأزرار تريد
@component('mail::button', ['url' => $url, 'color' => 'green']) View Order @endcomponent
المكوّن panel
يُظهر المكوّن Panel النص المُمرّر كمجموعة بخلفية مختلفة قليلًا عن بقية الرسالة مما يسمح بجذب الانتباه لهذا النص:
@component('mail::panel') This is the panel content.
@endcomponent
المكوّن table
يسمح المكوّن table بتحويل جدول Markdown لجدول HTML. يقبل المكوّن جدول Markdown كمحتوى ويدعم المحاذاة باستخدام تنسيق Markdown:
@component('mail::table')
| Laravel | Table | Example |
| ---------------|:-----------------:| ------------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned| $20 |
@endcomponent
تخصيص المكوّنات
يمكنك تحميل كل المكونات من Markdown في التطبيق لتخصيصها. لتحويل المكونات، استعمل الأمر vendor:publish
لنشر الأصول laravel-mail:
php artisan vendor:publish --tag=laravel-mail
سيُحمّل هذا الأمر مكونات Markdown
في المجلد resources/views/vendor/mail
. سيحتوي المجلد mail
على المجلد html
ومجلد markdown
، كل منهما يحتوي على النسخة الملائمة من المكوّنات. تُستخدم المكونات في المجلد html
لبناء نسخة html من الرسالة في حين تُستخدم المكونات من المجلد Markdown
لبناء نسخة نص عادي. لك حرية تخصيص هذه المكونات كما تريد.
تخصيص ال CSS
بعد تحميل المكونات، يحتوي المجلد resources/views/vendor/mail/html/themes
على ملف css
المبدئي default.css
. يمكنك تخصيص تخطيط CSS في هذا الملف وسيُضمّن تلقائيًا في عرض HTML لرسائل Markdown.
ملاحظة : إذا أردت بناء نمط جديد لمكون Markdown، اكتب ملف CSS
جديد في المجلد html/themes
وغيّر الخيار theme
في ملف الضبط mail
.
إرسال البريد الإلكتروني
لإرسال رسالة، استعمل التابع to
من الواجهة الثابتة Mail
. يقبل التابع to
عنوانًا إلكترونيًا، أو نسخة من كائن مستخدم، أو مجموعة مستخدمين. إذا مرّرت كائنًا أو مجموعة كائنات، ستُستخدم الخاصيات mail
و name
من الكائن عند ضبط متلقي الرسالة. بعد ضبط المتلقي، يمكنك تمرير مثيل من الصنف للتابع send
:
<?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));
}
}
طبعًا لست محدودًا باستعمال to
لضبط المتلقي، يمكنك أيضا ضبط cc و bcc في نداء واحد:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
عرض الأصناف القابلة للإرسال
قد تحتاج في بعض الأحيان لإظهار محتوى صنف قابل للإرسال دون إرساله، للقيام بهذا يمكن استعمال التابع render
. يعيد هذا التابع النتيجة الحاصلة من الصنف على شكل سلسلة نصية:
$invoice = App\Invoice::find(1);
return (new App\Mail\InvoicePaid($invoice))->render();
معاينة الأصناف في المتصفح
عند تصميم قالب صنف قابل للإرسال، من المفيد أن تتمكن من معاينة نتيجة الصنف الممرّرة في المتصفح كأي قالب Blade. لهذا، يسمح Laravel بإعادة أي صنف قابل للإرسال من وحدات التحكم أو مسارات closure. عندما يعاد الصنف، سيُظهَر في المتصفح لمعاينة التصميم بسرعة دون الحاجة لإرسال الرسالة:
Route::get('/mailable', function () {
$invoice = App\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
});
إضافة الرسائل لطابور الإنتظار
إضافة الرسالة
حيث يطوّل إرسال البريد الاكتروني وقت إجابة التطبيق، يختار العديد من المطوّرين إضافة الرسائل لطابور انتظار لإرسالها في خلفية التطبيق. يُتيح Laravel إمكانية القيام هذا بسهولة باستخدام API Unified queue. لإضافة الرسائل لطابور الانتظار، استعمل التابع queue
من الواجهة الساكنة Mail
بعد تحديد متلقي الرسالة:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
سيتكفّل التابع بدفع مهمّة لطابور الإنتظار تقوم بإرسال الرسالة في خلفية التطبيق. ستحتاج طبعًا لضبط طوابير الإنتظار قبل استعمال هذه الخاصية.
تأخير إضافة الرسالة
إذا أردت تأخير إرسال رسالة ما في طابور الانتظار، استعمل التابع later
. يقبل هذا التابع نسخة الكائن DateTime
يوضّح وقت الإرسال
$when = now()->addMinutes(10);
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later($when, new OrderShipped($order));
الإضافة لطابور انتظار معيّنة
حيث أنّ كل الأصناف القابلة للإرسال تُصنع ياستعمال الأمر mail:make
لخاصيات Illuminate\Bus\Queueable
، يمكن استعمال التابعين onQueue
و onConnection
على أي نسخة لصنف قابل للإرسال. مما يسمح بتحديد الصلة وقائمة الانتظار لكل رسالة:
$message = (new OrderShipped($order))
->onConnection('sqs')
->onQueue('emails');
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue($message);
الإضافة المبدئية
إذا كان لديك أصناف قابلة للإرسال تريد أن تضيفها دائمًا لقائمة الانتظار، يمكنك تنفيذ العقد ShouldQueue في الصنف. في هذه الحال، حتى إن ناديت التابع send للإرسال فإنّ الصنف سيضاف للقائمة باعتباره حاملًا للعقد:
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue {
//
}
الرسائل الإلكترونية والتطوير المحلي
عند تطوير تطبيق، قد لا تريد إرسال بريد لعناوين حقيقية. يوفّر Laravel طرائق عديدة لتعطيل عملية الإرسال في مرحلة التطوير.
المشغل Log
بدل إرسال الرسائل، يكتب المشغل Log
محتوى الرسائل في ملف log
لمعاينتها. لمزيد من المعلومات حول بيئة التطوير، تفقّد توثيق الضبط.
To العام
حل آخر يوفره Laravel هو ضبط متلقي عام تُرسل إليه كل الرسائل من التطبيق. بهذه الطريقة، ستُرسل كل الرسائل من التطبيق إلى العنوان محدّد بدل العنوان المذكور كمتلقي للرسالة. يمكن القيام بهذا باستعمال الخيار to
في ملف الضبط config/mail.php
:
'to' => [
'address' => 'example@example.com',
'name' => 'Example'
],
Mailtrap
في الأخير يمكن استخدام خدمة مثل Mailtrap
و المشغل smtp
لإرسال الرسائل لعنوان وهمي حيث يمكنك رؤيتها من تطبيق رسائل حقيقي. تسمح هذه الطريقة بمعاينة الرسالة النهائية في قارئ رسائل Mailtrap
.
الأحداث
يطلق Laravel حدثين في عملية الإرسال. يُطلق الحدث MessageSending
قبل إرسال الرسالة في حين يُطلق MessageSent
بعد البعث. هذه الأحداث تُطلق حين إرسال الرسائل وليس حين إضافتها لقائمة الإنتظار. يمكنك تسجيل مستمعات لهذه الأحداث في الملف ُEventServiceProvider
:
/**
* المستمعات على الأحداث في التطبيق
*
* @var array
*/
protected $listen = [
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\LogSendingMessage',
],
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];