انتقل إلى المحتوى

✉️ ‫إعداد 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 (أدخل النطاق الفرعي إذا استخدمته).

✉️ إرسال الرسائل الإلكترونية:

  1. SMTP:
  2. تُستخدم لإرسال روابط تسجيل الدخول السحرية.

  3. Mailgun API:

  4. لإرسال أي رسائل بريد إلكتروني أخرى، استخدم الدالة:

sendEmail() في libs/mailgun.js


📥 استقبال الرسائل الإلكترونية:

  • 🚫 ملاحظة: لا يقوم Mailgun بإعادة توجيه الرسائل تلقائيًا أو تخزينها.
  • لذلك، أنشأنا مسارًا يتطابق مع الرسائل المرسلة إلى بريد الدعم لدينا (mailgun.supportEmail في config.js) ويعيد توجيهها إلى API الخاص بنا.
  • 📧 ميزة: يتم تلقائيًا إضافة عنوان المرسل في reply-to بحيث يمكنك الرد مباشرة من صندوق الوارد الخاص بك.

قائمة التحقق لتجنب مجلد البريد العشوائي:

📷 يوجد صورة هنا
````