Rails/action mailer basics
أساسيات إجراء المراسلة
يوفّر لك هذا الدليل كل ما تحتاجه للبدء في إرسال واستقبال رسائل البريد الإلكتروني من وإلى تطبيقك، والعديد من عمليّات إجراء المراسلة (Action Mailer) الداخليّة. كما يغطي كيفية اختبار مُرسلي بريدك (mailers).
ستتعلم بعد قراءة هذا الدليل:
- كيفيّة إرسال واستقبال البريد الإلكتروني داخل تطبيق ريلز.
- كيفيّة إنشاء وتعديل صنف إجراء المراسلة والعرض المرتبط به.
- كيفيّة إعداد إجراء المراسلة لبيئتك.
- كيفيّة اختبار أصنافك لإجراء المراسلة.
مقدمة
يسمح لك إجراء المراسلة (Action Mailer) بإرسال رسائل البريد الإلكتروني من تطبيقك باستخدام الأصناف mailer
والعروض المرتبطة بها (views).
تعمل مُرسلات البريد بطريقة مشابهة جدًا لوحدات التحكّم. وهي ترث من ActionMailer::Base
وتتوضع في app/mailers ولديها عروض مرتبطة تظهر في app/views.
إرسال البريد الإلكتروني
سيوفر هذا القسم دليلًا مُفصّلًا لإنشاء مُرسل بريد والعروض المرتبطة به.
خطوات إنشاء مرسل بريد إلكتروني
إنشاء المرسل
$ bin/rails generate mailer UserMailer
create app/mailers/user_mailer.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/user_mailer
create app/views/layouts/mailer.text.erb
create app/views/layouts/mailer.html.erb
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default from: "from@example.com"
layout 'mailer'
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
كما ترى، يمكنك توليد مُرسلات بريد مثلما تستخدم المولّدات الأخرى مع ريلز. تتشابه مُرسلات البريد من الناحية النظرية مع وحدات التحكّم، ولذلك نحصل على مُرسل بريد ومجلّد للعروض واختبار.
إن لم ترغب في استخدام مولّد، يمكنك إنشاء ملفك الخاص داخل app/mailers لكن المهم أن تتأكّد أنّه يرث من ActionMailer::Base
:
class MyMailer < ActionMailer::Base
end
تعديل المرسل
تشبه مُرسلات البريد الإلكتروني إلى حد بعيد وحدات تحكّم ريلز. لديها أيضا توابع تسمّى "إجراءات" (actions) وتستخدم العروض لهيكلة المحتوى. يُنشئ مرسلٌ رسالة للتسليم عبر البريد الإلكتروني عندما تُولّد وحدة التحكّم محتوى مثل HTML لإرساله مرة أخرى إلى العميل.
يحتوي app/mailers/user_mailer.rb على مُرسل بريد فارغ.
class UserMailer < ApplicationMailer
end
فلنضف تابعًا باسم welcome_email
يرسل بريدًا إلكترونيًا إلى عنوان البريد الإلكتروني المسجل للمستخدم:
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email
@user = params[:user]
@url = 'http://example.com/login'
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end
فيما يلي شرح سريع للعناصر المعروضة في التابع. للحصول على قائمة كاملة بجميع الخيارات المتاحة، يرجى إلقاء نظرة أدناه في قسم "قائمة خصائص إجراء المراسلة الكاملة القابلة للتعيين من طرف المستخدم".
default
: (كائنHash
) يمثِّل جدولHash
للقيم الافتراضية لأي بريد إلكتروني ترسله من هذا المُرسل. نُعيّن في هذه الحالة قيمة الترويسةfrom:
لجميع الرسائل في هذا الصنف. يمكن إعادة تعريف (override) هذا الحقل مع كل بريد إلكتروني على حدة.mail
: رسالة البريد الإلكتروني الفعليّة التي نُمرّر الترويستينto:
وsubject:
داخلها.
تصبح أي متغيّرات نسخة نعرّفها في التابع متاحة للاستخدام في العرض مثل حالة وحدات التحكم تمامًا.
إنشاء عرض لإجراء المراسلة
أنشئ ملفًا يسمّى welcome_email.html.erb في app/views/user_mailer/. سيُستخدم هذا القالب (template) للبريد الإلكتروني بتنسيق HTML:
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Welcome to example.com, <%= @user.name %></h1>
<p>
You have successfully signed up to example.com,
your username is: <%= @user.login %>.<br>
</p>
<p>
To login to the site, just follow this link: <%= @url %>.
</p>
<p>Thanks for joining and have a great day!</p>
</body>
</html>
لننشئ أيضًا جزءًا نصيًا لهذا البريد الإلكتروني. لا يفضّل كل العملاء رسائل إلكترونيّة بتنسيق HTML، وبالتالي إرسال كليهما هو أفضل الممارسات. أنشئ إذًا ملفًّا يسمّى welcome_email.text.erb في app/views/user_mailer/ :
Welcome to example.com, <%= @user.name %>
===============================================
You have successfully signed up to example.com,
your username is: <%= @user.login %>.
To login to the site, just follow this link: <%= @url %>.
Thanks for joining and have a great day!
عند استدعاء التابع mail
الآن، سيكتشف إجراء المراسلة قالبين (النص و HTML) ويُنشئ بريدًا إلكترونيًّا multipart/alternative تلقائيًا.
استدعاء المرسل
مُرسلات البريد هي في الواقع مجرد طريقة أخرى لتصيير (rendering) العرض. بدلًا من تصيير عرض وإرساله عبر بروتوكول HTTP، يُرسلونه ببساطة عبر بروتوكولات البريد الإلكتروني. ونتيجة لهذا، من المنطقي أن تطلب وحدة تحكّمك من مرسل رسائل البريد بإرسال بريد إلكتروني عند إنشاء مستخدم بنجاح.
ضبط هذه العملية بسيط للغاية.
فلننشئ أولًا، سقالة بسيطة (أي scaffold) باسم User
:
$ bin/rails generate scaffold user name email login
$ bin/rails db:migrate
لدينا الآن نموذج مُستخدم للتلاعب به. سنُعدّل فقط على الملف app/controllers/users_controller.rb بجعله يرشد UserMailer
لإرسال بريد إلكتروني للمستخدم حديث الإنشاء عبر تعديل إجراء الإنشاء (create action) وإدخال نداء إلى UserMailer.with(user: @user).welcome_email
مباشرةً بعد حفظ المستخدم بنجاح.
يتكامل إجراء المراسلة بشكل جيد مع الوظيفة الفعالة (Active Job)، لذا تتمكن من إرسال رسائل إلكترونيّة خارج دورة الطلب-الاستجابة، بحيث لا يضطر المستخدم إلى الانتظار:
class UsersController < ApplicationController
# POST /users
# POST /users.json
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
# Tell the UserMailer to send a welcome email after save
UserMailer.with(user: @user).welcome_email.deliver_later
format.html { redirect_to(@user, notice: 'User was successfully created.') }
format.json { render json: @user, status: :created, location: @user }
else
format.html { render action: 'new' }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
end
ملاحظة: السلوك الافتراضي للوظيفة الفعالة (Active Job) هو تنفيذ المهام عبر المحوّل async:
. لذا يمكنك استخدام deliver_later
الآن لإرسال رسائل البريد الإلكتروني بشكل غير متزامن. يُشغّل محوّل الوظيفة الفعالة الافتراضي المهام مع مجمع خيوط قيد المعالجة. وهو مناسب تمامًا لبيئات التطوير/الاختبار، نظرًا لأنَّه لا يتطلب أي بنية تحتيّة خارجيّة ولكنه غير ملائم للإنتاج بما أنّه يزيل الوظائف المعلّقة عند إعادة التشغيل. إن كنت في حاجة إلى خلفيّة دائمة (persistent backend)، فستحتاج لاستخدام محوّل وظيفة فعالة (Active Job adapter) يحوي خلفيّة دائمة (Sidekiq ،Resque، إلخ).
إن رغبت في إرسال بريد إلكتروني على الفور (من cronjob على سبيل المثال) فقط استدعي deliver_now
:
class SendWeeklySummary
def run
User.find_each do |user|
UserMailer.with(user: user).weekly_summary.deliver_now
end
end
end
أي زوج قيم مفتاح مُمرّر إلى with
يصبح params
لإجراء المراسلة (mailer action). لذلك، يجعل
with(user: @user, account: @user.account)
المعاملين params[:user]
و params[:account]
متوفّرين في إجراء المراسلة.
ويعيد التابع welcome_email
كائنًا من النوع ActionMailer::MessageDelivery
والذي يمكن إخباره لاحقًا بالإرسال الأن عبر deliver_now
أو الإرسال لاحقًا عبر deliver_later
لإرسال نفسه. الكائن ActionMailer::MessageDelivery
هو مجرد غلاف (wrapper) حول Mail::Message
. إن رغبت في فحص أو تغيير أو فعل بأي شيء آخر مع الكائن Mail::Message
، تستطيع الوصول إليه عبر التابع message
في الكائن ActionMailer::MessageDelivery
.
التشفير التلقائي لقيم الترويسة
يعالج إجراء المراسلة الترميز التلقائي لأحرف متعددة البايت داخل الترويسات وجسم الرسالة.
لأمثلة أكثر تعقيدًا مثل تعريف مجموعات أحرف بديلة أو ترميز النص ذاتيًّا أولًا، الرجاء الرجوع إلى المكتبة Mail.
قائمة توابع إجراء المراسلة الكاملة
تحتاج ثلاثة توابع فقط لأي رسالة بريد إلكتروني:
headers
- يحدّد أي ترويسة بريد تريدها. تستطيع تمرير جدول Hash بأسماء حقول وأزواج القيم أو يمكنك استدعاءه بالشكلheaders[:field_name] = 'value'
.
attachments
- يسمح لك بإضافة مرفقات إلى بريدك الإلكتروني مثلattachments['file-name.jpg'] = File.read('file-name.jpg')
.
mail
- يرسل البريد الإلكتروني الفعلي ذاته. تستطيع تمرير ترويسة كجدول Hash إلى التابعmail
كمعاملة، ثم يُنشئ التابع بريدًا إلكترونيَّا، إما كنص عادي أو نص متعدّد الأجزاء، اعتمادًا على قوالب البريد الإلكتروني التي عرّفتها.
إضافة المرفقات
يُسهّل إجراء المراسلة إضافة المرفقات.
- مرّر اسم الملف والمحتوى وسيخمّن إجراء المراسلة وجوهرة البريد (Mail gem) تلقائيًا النوع MIME، ويضبط التشفير وينشئ المُرفق.
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
عندما ينفَّذ التابع mail
، سيُرسل بريد إلكتروني متعدد الأجزاء مع مُرفق، مُضمّن بشكل مناسب مع كون المستوى الأعلى multipart/mixed
والجزء الأول عبارة عن multipart/alternative
يحتوي على النص العادي ورسائل بريد إلكتروني بتنسيق HTML.
ملاحظة: سيُشفّر البريد المُرفق تلقائيا بتشفير Base64. إن أردت شيئًا مختلفًا شفّر مُحتواك ومرّره المحتوى المشفّر وترميزه داخل جدول Hash إلى التابع attachments
.
- مرّر اسم الملف وحدد الترويسة والمحتوى وسيستخدم إجراء المراسلة و
mail
الإعدادات التي تمررها.
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
}
ملاحظة: يفترض البريد أنَّ محتواك مُشفّر مسبقًا ولا يحاول تشفيره عبر Base64.
إنشاء مرفقات مضمّنة (Making Inline Attachments)
يجعل إجراء المراسلة 3.0 المُرفقات المضمّنة - والتي تطلّبت الكثير من التلاعب في الإصدارات قبل 3.0 - بالبساطة والسهولة كما يجدر بها أن تكون.
- أولًا لتأمر mail يتحويل مُرفق إلى مُرفق مضمّن (Inline Attachment) عليك فقط استدعاء
inline.
مع تابع المرفقات داخل مُرسلك (Mailer):
def welcome
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
end
- ثم تستطيع في عرضك أن تشير (reference) إلى
attachments
كجدول Hash وتحدد المُرفق الذي تريد إظهاره، وتستدعيurl
عليه ثم تمرر النتيجة إلى التابعimage_tag
:
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url %>
- نظرًا لأن هذا استدعاء اعتيادي إلى
image_tag
، تستطيع تمرير جدول Hash من الخيارات بعد عنوان URL المُرفق كما هو الحال مع أي صورة أخرى:
<p>Hello there, this is our image</p>
<%= image_tag attachments['image.jpg'].url, alt: 'My Photo', class: 'photos' %>
إرسال بريد إلكتروني إلى عدة مستلمين
من الممكن إرسال بريد إلى مستلم واحد أو أكثر في بريد إلكتروني واحد (مثلًا إعلام كافة المسؤولين بتسجيل جديد) عن طريق تعيين قائمة بعناوين البريد إلى المفتاح to:
. يمكن أن تكون قائمة عناوين البريد مصفوفة من عناوين البريد أو سلسلة واحدة مع عناوين مفصولة بفواصل.
class AdminMailer < ApplicationMailer
default to: -> { Admin.pluck(:email) },
from: 'notification@example.com'
def new_registration(user)
@user = user
mail(subject: "New User Signup: #{@user.email}")
end
end
يمكن استخدام نفس التنسيق لوضع نسخة كربونية (:Cc) ونسخة كربونية مخفية (:Bcc) باستخدام المفتاحين cc:
و bcc:
على التوالي.
إرسال البريد الإلكتروني بالاسم
قد ترغب في بعض الأحيان في إظهار اسم الشخص بدلًا عن مجرّد عنوان بريده الإلكتروني عندما يستلم البريد الإلكتروني الذي أرسلته إليه. وطريقة عمل ذلك هي بتنسيق عنوان البريد الإلكتروني بالشكل "Full Name" <email>
.
def welcome_email
@user = params[:user]
email_with_name = %("#{@user.name}" <#{@user.email}>)
mail(to: email_with_name, subject: 'Welcome to My Awesome Site')
end
عروض المرسل (Mailer Views)
تُوجد عروض المُرسل (Mailer) في المُجلّد app/views/name_of_mailer_class. يعرف الصنف عرض مرسل البريد المحدّد تلقائيًّا لأنَّ اسمه مماثل لتابع المُرسل. في المثال الوارد أعلاه، سيكون عرض مُرسل بريدنا للتابع welcome_email
هو app/views/user_mailer/welcome_email.html.erb بالنسبة للنسخة HTML و welcome_email.text.erb لنسخة النص العادي.
لتغيير عرض المُرسل الافتراضي لإجرائك (action)،نفّذ ما يلي:
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email
@user = params[:user]
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site',
template_path: 'notifications',
template_name: 'another')
end
end
سيبحث في هذه الحالة عن قوالب في app/views/notifications بالاسم another
. تستطيع أيضًا تحديد مصفوفة مسارات لـ template_path
وسيُبحث بها حسب الترتيب.
إن أردت مزيدًا من المرونة، تستطيع أيضًا تمرير كتلة (block) وتصيير (render) قوالب محددّة أو حتى تصيير على نفس السطر أو تصيير نص دون استخدام ملف قالب:
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email
@user = params[:user]
@url = 'http://example.com/login'
mail(to: @user.email,
subject: 'Welcome to My Awesome Site') do |format|
format.html { render 'another_template' }
format.text { render plain: 'Render text' }
end
end
end
سيُصيّر هذا القالب "another_template.html.erb" لجزء HTML ويستخدم النص المُصيّر للجزء النصّي.
أمر التصيير (render) هو نفسه المُستخدم داخل وحدة التحكم (Action Controller) كي تستطيع استخدام جميع الخيارات نفسها مثل text:
و inline:
...إلخ.
التخزين المؤقت لعرض المرسل
تستطيع تخزين الأجزاء مؤقّتًّا (fragment caching) في عروض المُرسل مثلما نفعل مع عروض التطبيق باستخدام التابع cache
.
<% cache do %>
<%= @company.name %>
<% end %>
ولاستخدام هذه الخاصيّة، تحتاج لإعداد تطبيقك بالشكل التالي:
config.action_mailer.perform_caching = true
يُدعم التخزين المؤقت للأجزاء أيضًا في رسائل البريد متعدّدة الأجزاء. اقرأ المزيد حول التخزين المؤقت في دليل التخزين المؤقت في ريلز.
تخطيطات إجراء المراسلة
يملك مُرسل البريد تخطيطات تمامًا مثل عروض وحدات التحكّم. يجب أن يكون اسم التخطيط نفس اسم مُرسلك مثل user_mailer.html.erb و user_mailer.text.erb كي يُتعرّف عليه تلقائيًا كتخطيط من طرف مُرسلك.
استدعي التابع layout
كي تستخدم ملفًّا مختلفًا في مُرسلك:
class UserMailer < ApplicationMailer
layout 'awesome' # use awesome.(html|text).erb as the layout
end
استخدم yield
لتصيير العرض داخل التخطيط مثل طرق العرض لوحدات التحكّم تمامًا.
تستطيع أيضًا تمرير الخيار 'layout: 'layout_name
لاستدعاء التصيير داخل بُنية التنسيق لتحديد مخططات مختلفة للتنسيقات المختلفة:
class UserMailer < ApplicationMailer
def welcome_email
mail(to: params[:user].email) do |format|
format.html { render layout: 'my_layout' }
format.text
end
end
end
سيُعرض جزء HTML باستخدام الملف my_layout.html.erb وجزء النص مع ملف user_mailer.text.erb المعتاد في حالة وجوده.
معاينة رسائل البريد الإلكتروني (Previewing Emails)
توفر معاينات إجراء المراسلة طريقة لمعرفة كيفيّة ظهور الرسائل الإلكترونية من خلال زيارة عنوان URL خاص يعرضها. يجب تسمية صنف معاينة UserMailer
في المثال أعلاه UserMailerPreview
ووضعه في test/mailers/previews/user_mailer_preview.rb. لمشاهدة معاينة welcome_email
، عرّف استخدام تابع له نفس الاسم واستدعي UserMailer.welcome_email
:
class UserMailerPreview < ActionMailer::Preview
def welcome_email
UserMailer.with(user: User.first).welcome_email
end
end
ثم ستُصبح المعاينة متاحة في http://localhost:3000/rails/mailers/user_mailer/welcome_email.
سيُعاد التحميل تلقائيًا إن غيّرت شيئًا ما في app/views/user_mailer/welcome_email.html.erb أو المُرسل نفسه حتى تتمكن من رؤية التنسيق الجديد على الفور. تتوفّر أيضًا قائمة بالمعاينات في http://localhost:3000/rails/mailers.
توجد أصناف المعاينة هذه في test/mailers/previews. يمكن إعدادها باستخدام الخيار preview_path
. إن أردت مثلًا تغييرها إلى lib/mailer_previews تستطيع إعداد في config/application.rb:
config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
توليد العناوين URL في عروض إجراء المراسلة
لا تحتوي نسخة البريد على أي سياق حول الطلب الوارد عكس وحدات التحكّم، لذا عليك تقديم المعامل host:
بنفسك.
نظرًا لأنه عادةً ما يكون host:
متسقًا عبر التطبيق، تستطيع إعداده على العموم (globally) في config/application.rb:
config.action_mailer.default_url_options = { host: 'example.com' }
لا تستطيع استخدام أي من المساعدين path_*
داخل البريد الإلكتروني بسبب هذا السلوك. سوف تحتاج بدلًا من ذلك إلى استخدام المساعد url_*
. مثلًا بدل استخدام:
<%= link_to 'welcome', welcome_path %>
ستحتاج لاستخدام:
<%= link_to 'welcome', welcome_url %>
ستعمل الروابط الآن في رسائلك الإلكترونية باستخدام العنوان URL الكامل.
إنشاء عناوين URL مع url_for
ينشئ url_for
عنوان URL كامل افتراضيًا في القوالب.
إن لم تضبط الخيار host:
على المستوى العام، تأكّد من تمريره إلى url_for
.
<%= url_for(host: 'example.com',
controller: 'welcome',
action: 'greeting') %>
إنشاء عناوين URL باستخدام المسارات المسماة
لا يمتلك عملاء البريد الإلكتروني أي سياق ويب وبالتالي لا تحتوي المسارات على عنوان URL أساسي لتكوين عناوين ويب كاملة. لذلك يجب دائمًا استخدام المتغيّر "url_" لمساعدي المسارات الموجهة المُسمّاة.
إن لم تضبط الخيار host:
على المستوى العام، فتأكّد من تمريره إلى المساعد url
.
<%= user_url(@user, host: 'example.com') %>
ملاحظة: تتطلب الروابط غير GET استخدام rails-ujs أو jQuery UJS ولن تعمل في قوالب المُرسل (mailer templates). سيؤدي ذلك إلى طلبات GET العادية.
إضافة الصور في عروض إجراء المراسلة
لا تحتوي نسخة البريد على أي سياق حول الطلب الوارد عكس وحدات التحكّم، لذا عليك تقديم المعامل asset_host:
بنفسك.
نظرًا لكون asset_host:
عادةً متسقًا عبر التطبيق، تستطيع إعداده بشكل عام (globally) في config/application.rb:
config.action_mailer.asset_host = 'http://example.com'
تستطيع الآن عرض صورة داخل رسالتك الإلكترونيّة.
<%= image_tag 'image.jpg' %>
إرسال رسائل متعددة الأجزاء
سيُرسل إجراء المراسلة رسائل إلكترونيّة متعددة الأجزاء تلقائيًا إن كان لديك قوالب مختلفة لنفس الإجراء (action). لذلك، سيُسرسل إجراء المراسلة تلقائيًا رسالة إلكترونيّة متعدّدة الأجزاء مع نسختين نصيّة و HTML مُعدّتين كجزئين مختلفين بالنسبة لمثالنا UserMailer
إن كان الملف welcome_email.text.erb والملف welcome_email.html.erb موجودين في app/views/user_mailer.
يُحدّد parts_order:
ترتيب الأجزاء التي تُدخَل داخل التابع ActionMailer::Base.default
.
إرسال البريد الإلكتروني مع خيارات التسليم الديناميكي (Dynamic Delivery Options)
إن رغبت في إعادة تعريف (override) خيارات التسليم الافتراضيّة (مثل بيانات اعتماد SMTP) أثناء تسليم البريد الإلكتروني، تستطيع القيام بذلك باستخدام delivery_method_options
في الإجراء mailer
.
class UserMailer < ApplicationMailer
def welcome_email
@user = params[:user]
@url = user_url(@user)
delivery_options = { user_name: params[:company].smtp_user,
password: params[:company].smtp_password,
address: params[:company].smtp_host }
mail(to: @user.email,
subject: "Please see the Terms and Conditions attached",
delivery_method_options: delivery_options)
end
end
إرسال رسائل البريد الإلكتروني دون تصيير القالب
قد توجد حالات تريد فيها تخطّي خطوة تصيير القالب وتزويد نص البريد الإلكتروني كسلسلة نصيّة. يمكنك تحقيق ذلك باستخدام الخيار body:
. لا تنسَ في مثل هذه الحالات إضافة الخيار content_type:
. وإلّا سوف يفترض ريلز انّ نوعه text/plain افتراضيّا.
class UserMailer < ApplicationMailer
def welcome_email
mail(to: params[:user].email,
body: params[:email_body],
content_type: "text/html",
subject: "Already rendered!")
end
end
استلام رسائل البريد الإلكتروني
يمكن أن يكون تلقي رسائل البريد الإلكتروني وتحليلها باستخدام إجراء المراسلة معقّدًا نوعًا ما. عليك إعداد نظامك لتوجيه رسائل البريد إلى تطبيقك بطريقة ما، قبل وصول بريد إلكتروني إلى تطبيقك ريلز، والذي يحتاج للاستماع كي يتحقّق. لذلك لتلقي رسائل البريد الإلكتروني في تطبيق ريلز ستحتاج إلى:
- تعريف استخدام التابع
receive
في مُرسل بريدك. - إعداد خادم بريدك الإلكتروني لإعادة توجيه الرسائل من العنوان (أو العناوين) الذي تريد استلام رسائل البريد الإلكتروني إلى
/path/to/app/bin/rails runner 'UserMailer.receive(STDIN.read)'
.
يُحلّل (parse) إجراء المراسلة البريد الإلكتروني الوارد الخام بمجرّد تعريف التابع المُسمّى receive
جاعلًا منه كائن بريد إلكتروني، ثم يفك ترميزه، وينشئ نسخة مُرسل بريد جديدة، ويُمرّر كائن البريد الإلكتروني إلى تابع نُسخة المُرسل receive
. إليك مثال على ذلك:
class UserMailer < ApplicationMailer
def receive(email)
page = Page.find_by(address: email.to.first)
page.emails.create(
subject: email.subject,
body: email.body
)
if email.has_attachments?
email.attachments.each do |attachment|
page.attachments.create({
file: attachment,
description: email.subject
})
end
end
end
end
ردود نداء إجراء المراسلة
يتيح لك إجراء المراسلة تحديد before_action
و after_action
و around_action
.
- يمكن تحديد الفلاتر ببُنية أو رمز لتابع في صنف مرسل البريد بشكل شبيه بوحدات التحكّم.
- تستطيع استخدام
before_action
لتعبئة كائن البريد افتراضيًا أوdelivery_method_options
أو إدراج ترويسات ومرفقات افتراضية.
class InvitationsMailer < ApplicationMailer
before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
before_action { @account = params[:inviter].account }
default to: -> { @invitee.email_address },
from: -> { common_address(@inviter) },
reply_to: -> { @inviter.email_address_with_name }
def account_invitation
mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
end
def project_invitation
@project = params[:project]
@summarizer = ProjectInvitationSummarizer.new(@project.bucket)
mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
end
end
- تستطيع استخدام
after_action
لتنفيذ إعداد مشابه كإجراء سابقbefore_action
ولكن باستخدام متغيّرات نسخة (instance variables) مضبوطة بإجراء مُرسل بريدك (mailer action).
class UserMailer < ApplicationMailer
before_action { @business, @user = params[:business], params[:user] }
after_action :set_delivery_options,
:prevent_delivery_to_guests,
:set_business_headers
def feedback_message
end
def campaign_message
end
private
def set_delivery_options
# mail لديك الوصول إلى النسخة,
# @business و @user ومتغيرات النسخة
if @business && @business.has_smtp_settings?
mail.delivery_method.settings.merge!(@business.smtp_settings)
end
end
def prevent_delivery_to_guests
if @user && @user.guest?
mail.perform_deliveries = false
end
end
def set_business_headers
if @business
headers["X-SMTPAPI-CATEGORY"] = @business.code
end
end
end
- تقوم مرشحات إجراء المراسلة بإحباط المعالجة الإضافيّة إن ضبط جسم الرسالة إلى قيمة غير معدومة (non-nil).
استخدام مساعدي مُرسل الأفعال إجراء المراسلة
يرث إجراء المراسلة الآن من AbstractController، لذلك لديك حق الوصول إلى نفس المُساعدات العاديّة كما تفعل في Action Controller.
إعداد مُرسل البريد
من الأفضل وضع خيارات التكوين التالية في أحد ملفات البيئة (environment.rb ،production.rb، إلخ ...)
الإعداد | الوصف |
logger | يولّد معلومات حول الدورة البريديّة (mailing run) إن توفّرت. يمكن ضبطه على nil كي لا يُسجّل أي شيء. يتوافق مع كل من مُسجّل روبي Logger والمسجّلات Log4r. |
smtp_settings | يسمح بالإعداد المُفصّل لتابع التسليم smtp:
|
sendmail_settings | يسمح لك بإعادة تعريف خيارات تابع التسليم sendmail:
|
raise_delivery_errors | ما إن وجب رفع الأخطاء أم لا إن لم يُسلّم البريد الإلكتروني. يعمل هذا الإعداد فقط إن أُعدّ خادم البريد الإلكتروني الخارجي للتسليم الفوري. |
delivery_method | يُعرّف تابع تسليم. القيم المحتملة هي:
راجع توثيقات API لمزيد من المعلومات. |
perform_deliveries | يحدّد إن نُفّذت عمليات التسليم فعلًا عند مُناداة التابع deliver على رسالة البريد. ذلك هو الوضع إفتراضيًّا ولكن يمكن إيقاف تشغيله للمساعدة في الاختبار الوظيفي. |
deliveries | يحافظ على مصفوفة من جميع الرسائل المرسلة عبر إجراء المراسلة مع delivery_method :test. مفيدة خاصّة بلاختبار الوحدوي والوظيفي. |
default_options | تسمح لك بتعيين القيم الافتراضية لخيارات التابع mail (مثل from: و reply_to: وما إلى ذلك). |
للحصول على معلومات كاملة عن الإعدادات المحتملة راجع توثيق إعداد إجراء المراسلة في دليلنا إعداد تطبيقات ريلز.
مثال لإعداد إجراء المراسلة
مثال على ذلك هو إضافة ما يلي بملفك config/environments/$RAILS_ENV.rb المناسب:
config.action_mailer.delivery_method = :sendmail
# Defaults to: # config.action_mailer.sendmail_settings = { # location: '/usr/sbin/sendmail', # arguments: '-i' # } config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.default_options = {from: 'no-reply@example.com'} |
إعداد إجراء المراسلة لـ Gmail
بما أن إجراء المراسلة يستخدم الآن جوهرة البريد تصبح العمليّة ببساطة الإضافة إلى ملفكconfig/environments/$RAILS_ENV.rb:
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: 'smtp.gmail.com', port: 587, domain: 'example.com', user_name: '<username>', password: '<password>', authentication: 'plain', enable_starttls_auto: true } |
ملاحظة: اعتبارًا من 15 تموز 2014 عمدت Google إلى زيادة إجراءاتها الأمنيّة وتحظر الآن محاولات التطبيقات التي تراها أقل أمانًا. تستطيع تغيير إعدادات حسابك Gmail هنا للسماح بالمحاولات. إن كانت المصادقة الثنائيةمُفعّلة بحسابك Gmail ستحتاج لتعيين كلمة مرور تطبيق واستخدامها بدلاً من كلمة مرورك العاديّة. أو تستطيع بدلاً من ذلك استخدام ESP آخر لإرسال البريد الإلكتروني عن طريق استبدال "smtp.gmail.com" أعلاه بعنوان موفّرك.
اختبار مُرسل البريد (Mailer Testing)
تستطيع إيجاد تعليمات مفصّلة حول كيفيّة اختبار مُرسلي بريدك في دليل الاختبار.
اعتراض رسائل البريد الإلكتروني
هناك حالات تحتاج فيها لتعديل بريد إلكتروني قبل تسليمه. لحسن الحظ يوفّر إجراء المراسلة خطافًا لاعتراض كل بريد إلكتروني. تستطيع تسجيل مُعترض لإجراء تعديلات على رسائل البريد قبل تسليمها لوكلاء التوصيل مباشرة.
class SandboxEmailInterceptor
def self.delivering_email(message) message.to = ['sandbox@example.com'] end end |
يجب تسجيل المُعترض في إطار عمل إجراء المراسلة قبل أن يتمكن من القيام بواجبه. يمكنك ذلك في ملف تهيئة (initializer) من config/initializers/sandbox_email_interceptor.rb
if ريلز.env.staging?
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) end |
يستخدم المثال أعلاه بيئة مخصصّة تسمى "التدريج" لاختبار خادم شبيه بخادم الإنتاج ولكن لأغراض الاختبار. تستطيع قراءة إنشاء بيئات ريلز لمزيد من المعلومات حول بيئات ريلز المخصصّة.
مصدر
- صفحة إجراء المراسلة بتوثيق ريلز