دليل الانتقال
الانتقال من SendGrid إلى Mail.Land
غالباً ما يقتصر التغيير على مضيف SMTP واحد أو استدعاء API واحد. يطابق هذا الدليل حقول SendGrid الشائعة مع Mail.Land ويسرد الاختلافات التي تتطلب تعديلاً في الشيفرة.
# Before (SendGrid)
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASS=<your SendGrid API key>
# After (Mail.Land)
SMTP_HOST=smtp.mail.land
SMTP_PORT=587 # STARTTLS
SMTP_USER=apikey # any value; Mail.Land ignores it
SMTP_PASS=<your Mail.Land API key with SMTP enabled>مفاهيم SendGrid في Mail.Land
| SendGrid | Mail.Land |
|---|---|
| مفتاح API | مفتاح API (بيانات اعتماد)، مقصور على API أو SMTP، وعلى نطاقات، وعلى عناوين IP |
| مصادقة المرسل (Sender authentication) | التحقق من النطاق (SPF وDKIM وDMARC ومسار الإرجاع return path) |
| القوالب الديناميكية (Dynamic templates) | قوالب تتضمن عناصر نائبة بصيغة {{name}} |
| قوائم المنع ومجموعات إلغاء الاشتراك (Suppressions وunsubscribe groups) | قوائم منع الإرسال مع نطاق تطبيق: كل البريد، أو التسويقي فقط، أو قائمة بريدية واحدة |
| Event Webhook | Webhook موقّعة باستخدام HMAC-SHA256 |
| Inbound Parse | المسارات الواردة (Inbound routes) |
تحويل SMTP: غيّر ثلاثة إعدادات
إذا كنت ترسل عبر SMTP، فغيّر المضيف والمنفذ وكلمة المرور. ويمكن أن يبقى اسم المستخدم apikey، لأن Mail.Land تتجاهله وتصادق بالمفتاح وحده.
| الإعداد | SendGrid | Mail.Land |
|---|---|---|
| المضيف | smtp.sendgrid.net | smtp.mail.land |
| المنفذ | 25 أو 587 أو 2525 (TLS)، أو 465 (SSL) | 587 مع STARTTLS |
| اسم المستخدم | apikey | أي قيمة، مثل apikey |
| كلمة المرور | مفتاح API الخاص بك في SendGrid | مفتاح API من Mail.Land مع تفعيل SMTP |
لا تقبل Mail.Land تسجيل الدخول إلا بعد STARTTLS، ولا يتوفر المنفذ 465. إذا كان تطبيقك يستخدم المنفذ 465، فحوّله إلى 587 مع STARTTLS.
تحويل استدعاء API
يستخدم استدعاء الإرسال في Mail.Land متن JSON أكثر تسطحاً وترويسة X-API-Key. وإليك الرسالة نفسها في الواجهتين.
curl -X POST https://api.sendgrid.com/v3/mail/send \
-H "Authorization: Bearer $SENDGRID_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"personalizations": [{
"to": [{ "email": "[email protected]", "name": "Jane" }],
"dynamic_template_data": { "orderNumber": "12345" }
}],
"from": { "email": "[email protected]", "name": "Your Shop" },
"reply_to": { "email": "[email protected]" },
"subject": "Order 12345 has shipped",
"content": [
{ "type": "text/plain", "value": "Your order is on its way." },
{ "type": "text/html", "value": "<p>Your order is on its way.</p>" }
],
"categories": ["order-shipped"]
}'curl -X POST https://api.mail.land/v1/transactional/send \
-H "X-API-Key: $MAILLAND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": [{
"email": "[email protected]", "name": "Jane",
"variables": { "orderNumber": "12345" }
}],
"from": { "email": "[email protected]", "name": "Your Shop" },
"replyTo": "[email protected]",
"subject": "Order 12345 has shipped",
"textContent": "Your order is on its way.",
"htmlContent": "<p>Your order is on its way.</p>",
"tags": ["order-shipped"]
}'مطابقة حقول استدعاء الإرسال
من POST /v3/mail/send إلى POST /v1/transactional/send.
| SendGrid | Mail.Land | ملاحظة |
|---|---|---|
Authorization: Bearer <key> | X-API-Key: <key> | ترويسة مختلفة. |
from.email, from.name | from.email, from.name | يجب أن يكون العنوان على نطاق تم التحقق منه. |
personalizations[].to[] | to[] | حتى 5 مستلمين في الطلب الواحد مع مفتاح معاملاتي. وللإرسال بالجملة، استخدم الإرسال على دفعات مع مفتاح تسويقي. |
personalizations[].cc, bcc | لا يوجد | غير مدعوم. أرسل رسالة منفصلة إلى كل مستلم. |
personalizations[].dynamic_template_data | to[].variables | قيم خاصة بكل مستلم. واستخدم variables في المستوى الأعلى للقيم المشتركة بين جميع المستلمين. |
subject | subject | مطلوب ما لم تستخدم قالباً. |
content[] (text/html) | htmlContent | |
content[] (text/plain) | textContent | |
template_id | templateId | أعد إنشاء القالب في Mail.Land أولاً؛ إذ يتغير المعرف. |
reply_to.email | replyTo | سلسلة نصية بسيطة تحتوي العنوان. |
categories, custom_args | tags | تظهر الوسوم في التحليلات وفي أحداث Webhook. |
headers | customHeaders | |
attachments[].content, filename, type | attachments[].content, fileName, contentType | محتوى بترميز Base64. حتى 10 مرفقات و10 MiB إجمالاً. |
attachments[].disposition, content_id | attachments[].inline, contentId | inline: true للصورة المضمّنة. |
send_at (توقيت Unix، حتى 72 ساعة مقدماً) | scheduledAt (تاريخ ووقت UTC، حتى 7 أيام مقدماً) | |
tracking_settings (open, click) | tracking.opens, tracking.clicks | بالنسبة إلى تتبّع الفتح، تكون الأولوية لإعدادات التتبّع الخاصة بالنطاق. |
asm.group_id | لا يوجد في استدعاء الإرسال | تُدار حالات إلغاء الاشتراك التسويقية عبر قوائم Mail.Land وحملاتها. استورد حالات إلغاء الاشتراك الجماعية الحالية، كما هو موضح أدناه. |
لا يوجد مقابل | ترويسة X-Idempotency-Key | خلال فترة الاحتفاظ، تعيد المحاولة بالمفتاح نفسه الاستجابة الأصلية بدلاً من الإرسال مجدداً. |
تجيب الواجهتان كلتاهما بـ 202 Accepted. ويتضمن متن استجابة Mail.Land قيمة jobId، ومعرف رسالة لكل مستلم، وقائمتي المستلمين المقبولين والمرفوضين.
استورد قوائم منع الإرسال أولاً
استوردها قبل أول إرسال عبر Mail.Land، حتى يبقى من ألغوا اشتراكهم أو قدموا شكوى ضمن قائمة منع الإرسال منذ البداية. صدّر كل قائمة من SendGrid بصيغة CSV، ثم استوردها بالنوع والنطاق المطابقين، من لوحة التحكم أو عبر POST /v1/transactional/suppressions/import.
| قائمة SendGrid | النوع في Mail.Land | النطاق |
|---|---|---|
| الارتدادات (Bounces) | HardBounce | Global |
| بلاغات البريد العشوائي (Spam reports) | Complaint | Global |
| العناوين غير الصالحة (Invalid emails) | Invalid | Global |
| حالات إلغاء الاشتراك العامة (Global unsubscribes) | Unsubscribe | Global |
| حالات إلغاء الاشتراك الجماعية (Group unsubscribes) | Unsubscribe | List، للقائمة البريدية المطابقة في Mail.Land؛ أما Marketing فيحظر كل البريد التسويقي |
عمليات الحظر (blocks) في SendGrid غالباً ما تكون رفضاً مؤقتاً. راجعها قبل الاستيراد بدلاً من إدراجها كلها في قائمة منع الإرسال.
وجّه Webhook الخاصة بك إلى Mail.Land
أضف نقطة النهاية الخاصة بك في Mail.Land، واختر الأحداث، وتحقق من ترويسة X-MLND-Signature باستخدام سر الـ Webhook الخاص بك. تختلف أسماء الأحداث عن أسماء SendGrid، لذا حدّث المعالج (handler) لديك:
| حدث SendGrid | حدث Mail.Land |
|---|---|
delivered | message.delivered |
deferred | message.deferred |
bounce | message.bounced |
open, click | غير متاح بعد |
spamreport | message.complained |
unsubscribe | message.unsubscribed |
أزل التكرار بالاعتماد على الحقل event_id: إذ يحمل التسليم المعاد محاولته معرف الحدث نفسه. لا يوجد اليوم في Mail.Land webhook مقابل لحدثَي open وclick في SendGrid: أحداث الفتح والنقر مدرجة في الكتالوج لكنها لا تُرسل.
التحويل خطوة بخطوة
- أضف نطاق الإرسال الخاص بك في Mail.Land وتحقق منه. واحتفظ بسجلات SendGrid: أضف include:spf.mlnd.net إلى سجل SPF الحالي بدلاً من إنشاء سجل ثانٍ، واحتفظ بسجل DMARC واحد فقط.
- استورد قوائم منع الإرسال الخاصة بك.
- أنشئ مفتاح sandbox مضبوطاً على وضع التسجيل فقط (log only)، وشغّل اختبارات التكامل على Mail.Land دون تسليم أي بريد.
- أرسل رسائل حقيقية إلى عناوين تتحكم فيها وراجعها في سجل البريد الإلكتروني.
- انقل تطبيقاً واحداً أو جزءاً صغيراً من حركة الإرسال، ثم راقب التسليم والارتدادات والشكاوى.
- طوال فترة تشغيل المزودين معاً، انسخ حالات إلغاء الاشتراك والشكاوى والارتدادات الجديدة من SendGrid إلى Mail.Land، وأجرِ مزامنة نهائية قبل تحويل آخر جزء من حركة الإرسال.
- انقل الباقي، وأبقِ SendGrid نشطة إلى أن تُرسل آخر رسائلها المجدولة والمعاد محاولة إرسالها.
الأسئلة الشائعة
هل يمكنني مواصلة الإرسال عبر SendGrid أثناء الاختبار؟
نعم. التحقق من نطاق في Mail.Land لا يمنع SendGrid من الإرسال باسمه، لذا يمكنك تشغيل الخدمتين معاً ونقل حركة الإرسال تدريجياً.
هل تدعم Mail.Land الحقلين cc وbcc؟
ليس في استدعاء الإرسال. أرسل بدلاً من ذلك رسالة منفصلة إلى كل مستلم.
هل توجد SDK رسمية لـ Mail.Land؟
ليس بعد. تتضمن الوثائق أمثلة جاهزة للنسخ لـ REST API بثماني لغات، وتعمل أي مكتبة SMTP مع المرحّل.
ماذا يحدث لمجموعات إلغاء الاشتراك الخاصة بي؟
استورد حالات إلغاء الاشتراك لكل مجموعة بنطاق List للقائمة البريدية المطابقة في Mail.Land، وأرسل إلى تلك القائمة حتى يُطبَّق التفضيل. أما نطاق Marketing فهو البديل الأوسع: إذ يحظر كل البريد التسويقي إلى ذلك العنوان.
هل أنت مستعد للانتقال من SendGrid؟
أنشئ حساباً مجانياً وأرسل أول رسالة اختبارية اليوم. وإذا أردت المساعدة، فأخبرنا عن إعداداتك.