✉️ إعداد Mailgun ¶
📝 مقدمة¶
ليس من الضروري استخدام Mailgun، ولكن ستحتاج إلى أداة بريد إلكتروني لإعداد روابط تسجيل الدخول السحرية ورسائل البريد الإلكتروني لعربات التسوق المهجورة وغيرها.
⚠️ ملاحظة:¶
- قامت Mailgun بإزالة فئة "pay-as-you-go" بشكل غير معلن من صفحة الأسعار، لكنها لا تزال موجودة.
- 💡 نصيحة: ابدأ بفترة تجريبية مجانية لفئة 35 دولارًا، ثم قم بإلغائها.
- 🔄 النتيجة: سيتم تخفيضك تلقائيًا إلى فئة "pay as you go" المجانية.
- 💰 التكلفة: إذا أرسلت أقل من 1000 رسالة بريد إلكتروني شهريًا، ستدفع 1 دولار شهريًا.
⚙️ الإعداد¶
1️⃣ أنشئ حسابًا جديدًا على Mailgun.
2️⃣ في [Sending] انقر على [Domains] ثم [+ Add Domain].
- 🌐 يُفضل إضافة نطاق فرعي مثل mail.yourdomain.com.
3️⃣ إذا اخترت منطقة EU:
- أضف العنوان التالي إلى إعداد عميل Mailgun في libs/mailgun.js:
url: "https://api.eu.mailgun.net/"
4️⃣ أكمل جميع خطوات التحقق من DNS:
- 🌍 إذا كنت تستخدم نطاقًا فرعيًا، تأكد من تحديث سجلات DNS.
5️⃣ أضف DMARC إضافي لتحسين إمكانية الوصول:
TXT | _dmarc.mail.yourdomain.com | v=DMARC1; p=none
6️⃣ إعداد SMTP:
- اذهب إلى [Domain Settings] → [SMTP Credentials] → [Reset Password].
- اختر [Automatic] ثم [Create Password].
- انقر على [Copy] في أسفل يمين النافذة المنبثقة.
- 📂 في .env.local، عيّن:
smtp\://postmaster@[mail.yourdomain.com]:[copied_password]@smtp.mailgun.org:587
7️⃣ إعداد API Key:
- في [Sending API Keys]، انقر على [Create sending key].
- أضفه إلى .env.local كـ MAILGUN_API_KEY.
8️⃣ إعداد config.js:
- أضف الكود التالي داخل كائن config:
mailgun: {
// subdomain to use when sending emails, if you don't have a subdomain, just remove it. Highly recommended to have one (i.e. mg.yourdomain.com or mail.yourdomain.com)
subdomain: "mg",
// REQUIRED — Email 'From' field to be used when sending magic login links
fromNoReply: `SaaSFast <noreply@mg.SaaSfa.st>`,
// REQUIRED — Email 'From' field to be used when sending other emails, like abandoned carts, updates etc..
fromAdmin: `Marc at SaaSFast <marc@mg.SaaSfa.st>`,
// Email shown to customer if need support. Leave empty if not needed => if empty, set up Crisp above, otherwise you won't be able to offer customer support."
supportEmail: "marc@mg.SaaSfa.st",
// When someone replies to supportEmail sent by the app, forward it to the email below (otherwise it's lost). If you set supportEmail to empty, this will be ignored.
forwardRepliesTo: "marc.louvion@gmail.com",
},
9️⃣ إعداد TypeScript (اختياري):
- في types/config.ts، أضف الكود التالي داخل ConfigProps interface:
mailgun: {
subdomain: string;
fromNoReply: string;
fromAdmin: string;
supportEmail?: string;
forwardRepliesTo?: string;
};
🗃️ إعداد مكتبة Mailgun¶
10️⃣ إنشاء ملف جديد:
- أنشئ ملفًا جديدًا libs/mailgun.js وأضف الكود التالي:
import config from "@/config";
const formData = require("form-data");
const Mailgun = require("mailgun.js");
const mailgun = new Mailgun(formData);
const mg = mailgun.client({
username: "api",
key: process.env.MAILGUN_API_KEY || "dummy",
});
if (!process.env.MAILGUN_API_KEY && process.env.NODE_ENV === "development") {
console.group("⚠️ MAILGUN_API_KEY missing from .env");
console.error("It's not mandatory but it's required to send emails.");
console.error("If you don't need it, remove the code from /libs/mailgun.js");
console.groupEnd();
}
/**
* Sends an email using the provided parameters.
*
* @async
* @param {string} to - The recipient's email address.
* @param {string} subject - The subject of the email.
* @param {string} text - The plain text content of the email.
* @param {string} html - The HTML content of the email.
* @param {string} replyTo - The email address to set as the "Reply-To" address.
* @returns {Promise} A Promise that resolves when the email is sent.
*/
export const sendEmail = async ({ to, subject, text, html, replyTo }) => {
const data = {
from: config.mailgun.fromAdmin,
to: [to],
subject,
text,
html,
...(replyTo && { "h:Reply-To": replyTo }),
};
await mg.messages.create(
(config.mailgun.subdomain ? `${config.mailgun.subdomain}.` : "") +
config.domainName,
data
);
};
...
11️⃣ تحديث إعداد EmailProvider:
- في libs/next-auth.js، استبدل إعداد EmailProvider بما يلي:
EmailProvider({
server: process.env.EMAIL_SERVER,
from: config.mailgun.fromNoReply,
}),
12️⃣ استبدال كل حالات config.resend بـ config.mailgun:
- استبدل جميع حالات libs/resend بـ libs/mailgun عبر الكود.
📧 استقبال الرسائل الإلكترونية¶
13️⃣ إعداد Receiving:
- في [Receiving] انقر على [Create Route].
- اختر [Match Recipient] وأضف البريد الإلكتروني الذي تريد الإرسال منه (مثل: name@mail.yourdomain.com).
- أعد التوجيه إلى:
https\://[your-domain].com/api/webhook/mailgun
- انقر على [Create Route].
14️⃣ إعداد Webhooks:
- بعد الانتهاء، اذهب إلى [Sending] → [Webhooks] وانسخ "HTTP webhook signing key".
- أضفه إلى MAILGUN_SIGNING_KEY في .env.local.
15️⃣ إضافة بريد الاستقبال:
- أضف بريدك الإلكتروني للاستقبال (مثل Gmail) في mailgun.forwardRepliesTo في config.js.
🗂️ إنشاء مسار لاستقبال البريد:¶
16️⃣ إنشاء ملف:
- أنشئ ملفًا جديدًا app/api/webhook/mailgun/route.js وأضف الكود التالي:
import { NextResponse } from "next/server";
import { sendEmail } from "@/libs/mailgun";
import config from "@/config";
import crypto from "crypto";
// This route is used to receive emails from Mailgun and forward them to our customer support email.
// See more: https://SaaSfa.st/docs/features/emails
export async function POST(req) {
try {
const formData = await req.formData();
// Get your HTTP webhook signing key from https://app.mailgun.com/mg/sending/mg.<yourdomain>/webhooks and add it to .env.local
const signingKey = process.env.MAILGUN_SIGNING_KEY;
const timestamp = formData.get("timestamp").toString();
const token = formData.get("token").toString();
const signature = formData.get("signature").toString();
const value = timestamp + token;
const hash = crypto
.createHmac("sha256", signingKey)
.update(value)
.digest("hex");
if (hash !== signature) {
return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
}
// extract the sender, subject and email content
const sender = formData.get("From");
const subject = formData.get("Subject");
const html = formData.get("body-html");
// send email to the admin if forwardRepliesTo is et & emailData exists
if (config.mailgun.forwardRepliesTo && html && subject && sender) {
await sendEmail({
to: config.mailgun.forwardRepliesTo,
subject: `${config?.appName} | ${subject}`,
html: `<div><p><b>- Subject:</b> ${subject}</p><p><b>- From:</b> ${sender}</p><p><b>- Content:</b></p><div>${html}</div></div>`,
replyTo: sender,
});
}
return NextResponse.json({});
} catch (e) {
console.error(e?.message);
return NextResponse.json({ error: e?.message }, { status: 500 });
}
}
🔄 التحقق من السجلات:¶
- تحقق من صلاحية السجلات على MxToolbox (أدخل النطاق الفرعي إذا استخدمته).
✉️ إرسال الرسائل الإلكترونية:¶
- SMTP:
-
تُستخدم لإرسال روابط تسجيل الدخول السحرية.
-
Mailgun API:
- لإرسال أي رسائل بريد إلكتروني أخرى، استخدم الدالة:
sendEmail() في libs/mailgun.js
📥 استقبال الرسائل الإلكترونية:¶
- 🚫 ملاحظة: لا يقوم Mailgun بإعادة توجيه الرسائل تلقائيًا أو تخزينها.
- لذلك، أنشأنا مسارًا يتطابق مع الرسائل المرسلة إلى بريد الدعم لدينا (mailgun.supportEmail في config.js) ويعيد توجيهها إلى API الخاص بنا.
- 📧 ميزة: يتم تلقائيًا إضافة عنوان المرسل في reply-to بحيث يمكنك الرد مباشرة من صندوق الوارد الخاص بك.
✅ قائمة التحقق لتجنب مجلد البريد العشوائي:¶
📷 يوجد صورة هنا
````