SHET33

ارسال ایمیل با PHP و تابع mail() و ساخت فرم تماس با ما

ارسال ایمیل با PHP و تابع mail() و ساخت فرم تماس با ما

هر سایتی بالاخره به ارسال ایمیل نیاز پیدا می‌کنه؛ از تأیید ثبت‌نام و بازیابی رمز گرفته تا همون فرم ساده‌ی «تماس با ما». مشکل اینجاست که فرستادن ایمیل با PHP ظاهراً کار ساده‌ایه — یه تابع صدا می‌زنید و تمام — ولی در عمل اکثر آدم‌ها یا ایمیلشون اصلاً ارسال نمی‌شه، یا ارسال می‌شه و مستقیم می‌ره تو پوشه‌ی اسپم.

تو این راهنما اول با تابع داخلی mail() شروع می‌کنیم تا منطق پایه دستتون بیاد، بعد می‌ریم سراغ روش استاندارد امروز یعنی PHPMailer روی SMTP، و در نهایت یه فرم تماس با ما می‌سازیم که واقعاً امن باشه — نه اینکه فقط اسمش امن باشه.

خلاصه: اگه پروژه‌ی واقعی دارید، سراغ mail() نرید. از PHPMailer با SMTP احراز هویت‌شده استفاده کنید و رکوردهای SPF و DKIM و DMARC دامنه‌تون رو تنظیم کنید. اگه وردپرس دارید و کد نمی‌خواید بنویسید، یه افزونه‌ی فرم به‌علاوه‌ی یه افزونه‌ی SMTP کل کار رو براتون انجام می‌ده.

کدام روش برای شما مناسب است؟

قبل از اینکه وارد کد بشیم، این جدول کمک می‌کنه وقتتون رو روی مسیر درست بذارید:

روشمناسب برایسختیاحتمال رفتن به اسپم
mail()فقط یادگیری و تست سریع روی لوکالخیلی کمخیلی زیاد
PHPMailer + SMTP هاست خودتاناکثر سایت‌ها؛ فرم تماس، اعلان‌ها، بازیابی رمزمتوسطکم (با SPF و DKIM درست)
PHPMailer + سرویس تراکنشیحجم بالا، خبرنامه، سایت‌های پرترافیکمتوسطخیلی کم
افزونه‌ی وردپرسسایت وردپرسی، بدون کدنویسیخیلی کمکم (با افزونه‌ی SMTP)

اگه وردپرس دارید و اصلاً حوصله‌ی کد ندارید، می‌تونید مستقیم برید سراغ بخش وردپرس. بقیه با ما بیاید.

روش ۱: تابع mail() — فقط برای درک منطق پایه

این بخش رو می‌نویسیم تا بفهمید پشت صحنه چه خبره، سعی کنید روی سایت واقعی از این روش استفاده نکنید. اگه عجله دارید، مستقیم برید به بخش PHPMailer.

پیش‌نیاز سمت سرور

تابع mail() خودش ایمیل نمی‌فرسته؛ فقط کار رو به یه سرویس ارسال ایمیل روی سرور (MTA) مثل Sendmail یا Postfix می‌سپاره. روی هاست‌های اشتراکی این سرویس معمولاً از قبل فعاله. اگه روی سرور مجازی خودتون کار می‌کنید، اول وضعیت رو چک کنید:

systemctl status postfix
# یا
systemctl status sendmail

اگه فعال نبود، روی اوبونتو یا دبیان نصبش کنید:

sudo apt install postfix
sudo systemctl enable --now postfix

فایل تست

یه فایل به اسم testmail.php تو public_html بسازید و این کد رو توش بذارید:

<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

$from    = "noreply@yourdomain.com";   // حتماً از دامنه‌ی خودتان
$to      = "your-email@example.com";
$subject = "تست ارسال ایمیل";
$message = "این یک ایمیل تستی است که با تابع mail() ارسال شده.";

// موضوع فارسی باید کدگذاری MIME بشه، وگرنه به‌هم‌ریخته نمایش داده می‌شه
$encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';

$headers = [
    'From'         => $from,
    'Reply-To'     => $from,
    'Content-Type' => 'text/plain; charset=UTF-8',
    'MIME-Version' => '1.0',
];

if (mail($to, $encodedSubject, $message, $headers)) {
    echo "ایمیل تحویل سرویس ارسال شد.";
} else {
    echo "ارسال ناموفق بود. لاگ‌های سرور را بررسی کنید.";
}

حالا فایل رو از مرورگر باز کنید. اگه پیام موفقیت دیدید یعنی سرور درخواست رو قبول کرده — که هنوز به معنی رسیدن ایمیل نیست. این تفاوت مهمیه که خیلی‌ها گیرش می‌افتن.

🔴 بعد از تست حتماً این فایل رو پاک کنید. یه اسکریپت ارسال ایمیل که با آدرس عمومی قابل اجراست، دقیقاً همون چیزیه که ربات‌های اسپمر دنبالش می‌گردن. اگه پیداش کنن، از سرور شما اسپم می‌فرستن و در نهایت آی‌پی هاستتون بلاک می‌شه.

چرا موضوع فارسی به‌هم می‌ریزد؟

این یکی از رایج‌ترین مشکلاتیه که تو آموزش‌های فارسی معمولاً بهش اشاره نمی‌شه. هدرهای ایمیل طبق استاندارد باید ASCII باشن. وقتی موضوع فارسی رو مستقیم می‌فرستید، خیلی از کلاینت‌ها نمی‌دونن باید چطور بخوننش و کاراکترهای درهم نشون می‌دن.

راه‌حلش همون خطیه که تو کد بالا دیدید:

$encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';

این یعنی «موضوع با UTF-8 نوشته شده و به Base64 کدگذاری شده». نکته اینکه charset=UTF-8 که تو هدر Content-Type می‌ذارید فقط مربوط به بدنهی ایمیله و هیچ کاری با موضوع نداره. تو PHPMailer اصلاً درگیر این نمی‌شید، چون خودش این کار رو انجام می‌ده.

چرا در پروژه‌ی واقعی سراغش نریم؟

  • احراز هویت نداره. ایمیل بدون هویت مشخص از سرور بیرون می‌ره و سرویس گیرنده دلیلی نداره بهش اعتماد کنه.
  • بازخورد درستی نمی‌ده. خروجی true فقط یعنی «تحویل صف شد»، نه «تحویل داده شد». پس عملاً کور کار می‌کنید.
  • وابسته به تنظیمات سرورـه و روی هاست‌های مختلف رفتار متفاوتی داره.
  • پیوست و HTML رو باید دستی و با ساختار MIME بسازید که هم پرخطاست هم وقت‌گیر.

خلاصه: منطقش رو یاد بگیرید، ولی برای سایت واقعی بریم سراغ روش بعدی.

روش ۲: PHPMailer با SMTP (روش استاندارد)

PHPMailer یه کتابخانه‌ی متن‌باز و جاافتاده‌ست که از SMTP با احراز هویت، رمزنگاری TLS، ایمیل HTML، پیوست و کدگذاری صحیح هدرها پشتیبانی می‌کنه. تفاوت اصلیش با mail() اینه که مستقیم به یه سرور ایمیل معتبر وصل می‌شه و با نام کاربری و رمز، خودش رو معرفی می‌کنه. همین یه تغییر، بیشترین اثر رو روی نرفتن ایمیل به اسپم داره.

نصب با کامپوزر

composer require phpmailer/phpmailer

اگه روی هاستتون کامپوزر ندارید، می‌تونید کتابخانه رو از مخزن رسمی گیت‌هاب دانلود کنید و دستی داخل پروژه بذارید — ولی اگه امکانش هست کامپوزر رو ترجیح بدید، چون به‌روزرسانی‌های امنیتی رو خیلی راحت‌تر مدیریت می‌کنه.

اطلاعات ورود را کجا نگه داریم؟

این بخش رو جدی بگیرید، چون تو اکثر آموزش‌ها نادیده گرفته می‌شه: رمز ایمیل رو داخل فایلی که تو public_html است ننویسید.

یه فایل تنظیمات بیرون از ریشه‌ی وب بسازید، مثلاً /home/username/config/mail.php:

<?php
return [
    'host'     => 'mail.yourdomain.com',
    'username' => 'noreply@yourdomain.com',
    'password' => 'رمز واقعی اینجا',
    'port'     => 587,
];

و بعد تو کدتون این‌جوری صداش بزنید:

$config = require '/home/username/config/mail.php';

دلیلش ساده‌ست: اگه یه روز PHP روی سرور از کار بیفته یا یه فایل بکاپ با پسوند دیگه جا بمونه، محتوای فایل‌های داخل public_html به‌صورت متن ساده قابل مشاهده می‌شه. رمز ایمیل شما نباید جزو اون‌ها باشه.

کد ارسال ساده

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';
$config = require '/home/username/config/mail.php';

$mail = new PHPMailer(true);

try {
    $mail->isSMTP();
    $mail->Host       = $config['host'];
    $mail->SMTPAuth   = true;
    $mail->Username   = $config['username'];
    $mail->Password   = $config['password'];
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    $mail->Port       = $config['port'];
    $mail->CharSet    = 'UTF-8';   // برای متن فارسی لازم است

    $mail->setFrom($config['username'], 'نام سایت شما');
    $mail->addAddress('receiver@example.com', 'نام گیرنده');

    $mail->isHTML(true);
    $mail->Subject = 'تست ارسال با PHPMailer';
    $mail->Body    = 'این ایمیل <strong>با موفقیت</strong> ارسال شد.';
    $mail->AltBody = 'این متن برای ایمیل‌خوان‌های بدون HTML است.';

    $mail->send();
    echo 'ایمیل ارسال شد.';
} catch (Exception $e) {
    // جزئیات خطا فقط در لاگ، نه روی صفحه
    error_log('Mail error: ' . $mail->ErrorInfo);
    echo 'ارسال ایمیل ناموفق بود. لطفاً بعداً تلاش کنید.';
}

دو تا نکته‌ی ریز ولی مهم تو این کد:

  • $mail->CharSet = 'UTF-8' رو فراموش نکنید، وگرنه متن فارسی به‌هم می‌ریزه.
  • خطای واقعی رو لاگ کنید، به کاربر نشون ندید. مقدار ErrorInfo می‌تونه آدرس سرور، نام کاربری و جزئیات پیکربندی رو لو بده. این دقیقاً همون اطلاعاتیه که یه مهاجم دنبالشه.

SMTP هاست خودتان، جیمیل یا سرویس تراکنشی؟

SMTP هاست خودتان — برای اکثر سایت‌ها بهترین گزینه‌ست. یه ایمیل مثل noreply@yourdomain.com تو کنترل‌پنل بسازید و از همون استفاده کنید. مزیت بزرگش اینه که فرستنده و دامنه‌ی سایت یکی هستن که برای اعتماد سرویس‌های گیرنده حیاتیه.

جیمیل — برای تست و پروژه‌های خیلی کوچیک خوبه. باید احراز هویت دو مرحله‌ای رو فعال کنید و به‌جای رمز عادی، «رمز عبور برنامه» (App Password) بسازید. ولی حواستون باشه که جیمیل محدودیت ارسال روزانه داره و برای فرم پرترافیک یا ارسال گروهی اصلاً مناسب نیست. ضمناً ایمیلی که از آدرس جیمیل فرستاده بشه ولی خودش رو نماینده‌ی دامنه‌ی شما جا بزنه، شانس بیشتری برای اسپم شدن داره.

سرویس‌های تراکنشی — برای حجم بالا ساخته شدن و بهترین نرخ تحویل رو دارن. فقط یه نکته‌ی عملی برای کاربران ایرانی: ثبت‌نام و استفاده از سرویس‌های بین‌المللی این حوزه معمولاً به‌دلیل محدودیت‌ها عملی نیست. اگه به این سطح نیاز دارید، سراغ سرویس‌های تراکنشی داخلی برید که هم دسترسی پایدارتری دارن هم پشتیبانی فارسی.

افزودن فایل پیوست و ایمیل HTML

پیوست کردن فایل با PHPMailer یه خط بیشتر نیست. کافیه قبل از send() اضافه‌ش کنید:

$mail->addAttachment('/home/username/files/invoice.pdf', 'فاکتور.pdf');

پارامتر دوم اسمیه که گیرنده می‌بینه. برای ایمیل HTML هم isHTML(true) رو فعال کنید و حتماً AltBody رو پر کنید؛ نسخه‌ی متنی هم برای کلاینت‌های قدیمی لازمه و هم روی امتیاز ضداسپم شما اثر مثبت داره.

برای فایل‌های بزرگ سراغ پیوست نرید. اکثر سرویس‌های ایمیل محدودیت حجم دارن و ایمیل‌های سنگین بیشتر در معرض فیلتر شدنن. به‌جاش فایل رو روی سرور بذارید و لینک دانلودش رو بفرستید.

ساخت فرم تماس با ما؛ نسخه‌ای که واقعاً امن است

حالا می‌رسیم به کاربردی‌ترین بخش. ولی قبل از کد، چهار تا اشتباهی رو ببینیم که تو اکثر نمونه‌کدهای فرم تماس تکرار می‌شن — چون اگه این‌ها رو ندونید، کدی می‌نویسید که ظاهرش کار می‌کنه ولی امن نیست.

چهار اشتباه رایج

  • ۱. تمیز کردن ورودی در ورود به‌جای خروج. خیلی‌ها همون اول htmlspecialchars رو روی داده اجرا می‌کنن و همون مقدار رو همه‌جا استفاده می‌کنن. نتیجه‌ش اینه که کاربر تو ایمیل متنی &quot; می‌بینه و اگه دوباره موقع نمایش هم escape بشه، دو بار کدگذاری اتفاق می‌افته. قاعده‌ی درست: داده رو خام نگه دارید، فقط لحظه‌ی نمایش و متناسب با محیط مقصد escape کنید.
  • ۲. تصور اینکه htmlspecialchars جلوی header injection رو می‌گیره. نمی‌گیره. این تابع مربوط به HTML ئه و هیچ ربطی به هدرهای ایمیل نداره. محافظت واقعی از خود PHPMailer میاد که مقادیر هدر رو اعتبارسنجی می‌کنه و کاراکترهای خط جدید رو نمی‌پذیره. برای همینه که نباید هدرها رو دستی سرهم کنید.
  • ۳. نداشتن توکن CSRF. بدون این، یه سایت دیگه می‌تونه از طرف بازدیدکننده‌ی شما فرم رو ارسال کنه.
  • ۴. نداشتن محافظت در برابر ربات. یه فرم تماس عمومی بدون هیچ فیلتری، ظرف چند روز تبدیل می‌شه به شیر اسپم — و چون ایمیل‌ها از سرور شما ارسال می‌شن، در نهایت شهرت دامنه‌ی خودتون خراب می‌شه.

کد کامل فرم تماس

این کد رو تو فایلی به اسم contact.php بذارید. هر چهار مورد بالا توش رعایت شده:

<?php
session_start();

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';
$config = require '/home/username/config/mail.php';

// ساخت توکن CSRF و ثبت زمان نمایش فرم
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
if (empty($_SESSION['form_time'])) {
    $_SESSION['form_time'] = time();
}

$msg = '';
$msgClass = '';
$name = $email = $message = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // داده‌ها رو خام نگه می‌داریم؛ فقط فاصله‌های اضافه رو حذف می‌کنیم
    $name    = trim($_POST['name'] ?? '');
    $email   = trim($_POST['email'] ?? '');
    $message = trim($_POST['message'] ?? '');

    $errors = [];

    // ۱) بررسی توکن CSRF
    if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
        $errors[] = 'نشست شما منقضی شده است. لطفاً صفحه را دوباره بارگذاری کنید.';
    }

    // ۲) تشخیص ربات: فیلد هانی‌پات پر شده یا فرم خیلی سریع ارسال شده
    $isBot = !empty($_POST['website'])
          || (time() - $_SESSION['form_time']) < 3;

    // ۳) اعتبارسنجی
    if ($name === '' || $email === '' || $message === '') {
        $errors[] = 'لطفاً همه‌ی فیلدها را پر کنید.';
    }
    if (mb_strlen($name) > 100 || mb_strlen($message) > 5000) {
        $errors[] = 'طول ورودی بیش از حد مجاز است.';
    }
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'آدرس ایمیل معتبر نیست.';
    }

    if ($errors) {
        $msg = implode(' ', $errors);
        $msgClass = 'error';
    } elseif ($isBot) {
        // به ربات پیام موفقیت نشان می‌دهیم ولی چیزی ارسال نمی‌کنیم
        $msg = 'پیام شما ارسال شد.';
        $msgClass = 'success';
        $name = $email = $message = '';
    } else {
        $mail = new PHPMailer(true);
        try {
            $mail->isSMTP();
            $mail->Host       = $config['host'];
            $mail->SMTPAuth   = true;
            $mail->Username   = $config['username'];
            $mail->Password   = $config['password'];
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            $mail->Port       = $config['port'];
            $mail->CharSet    = 'UTF-8';

            // فرستنده همیشه ایمیل خود دامنه؛ ایمیل کاربر فقط برای پاسخ
            $mail->setFrom($config['username'], 'فرم تماس سایت');
            $mail->addAddress('admin@yourdomain.com', 'مدیر سایت');
            $mail->addReplyTo($email, $name);

            $mail->isHTML(true);
            $mail->Subject = 'پیام جدید از فرم تماس';

            // اینجا و فقط اینجا برای محیط HTML امن‌سازی می‌کنیم
            $safeName    = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
            $safeEmail   = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
            $safeMessage = nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8'));

            $mail->Body = "<p><strong>نام:</strong> {$safeName}</p>
                           <p><strong>ایمیل:</strong> {$safeEmail}</p>
                           <p><strong>پیام:</strong><br>{$safeMessage}</p>";

            // نسخه‌ی متنی باید خام باشد، نه escape شده
            $mail->AltBody = "نام: {$name}\nایمیل: {$email}\nپیام:\n{$message}";

            $mail->send();

            $msg = 'پیام شما با موفقیت ارسال شد. به‌زودی پاسخ می‌دهیم.';
            $msgClass = 'success';
            $name = $email = $message = '';

            // توکن جدید برای جلوگیری از ارسال تکراری
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
            $_SESSION['form_time']  = time();

        } catch (Exception $e) {
            error_log('Contact form error: ' . $mail->ErrorInfo);
            $msg = 'ارسال پیام با مشکل مواجه شد. لطفاً بعداً تلاش کنید.';
            $msgClass = 'error';
        }
    }
}
?>

و بخش HTML فرم:

<form method="POST" action="">
    <input type="hidden" name="csrf_token"
           value="<?php echo $_SESSION['csrf_token']; ?>">

    <!-- فیلد هانی‌پات: کاربر نمی‌بیندش، ربات پرش می‌کند -->
    <div style="position:absolute; left:-9999px;" aria-hidden="true">
        <label>وب‌سایت</label>
        <input type="text" name="website" tabindex="-1" autocomplete="off">
    </div>

    <label for="name">نام و نام خانوادگی</label>
    <input type="text" name="name" id="name" required
           value="<?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?>">

    <label for="email">آدرس ایمیل</label>
    <input type="email" name="email" id="email" required
           value="<?php echo htmlspecialchars($email, ENT_QUOTES, 'UTF-8'); ?>">

    <label for="message">پیام شما</label>
    <textarea name="message" id="message" rows="6" required><?php
        echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'); ?></textarea>

    <button type="submit">ارسال پیام</button>
</form>

چند نکته‌ی مهم درباره‌ی این کد

  • فرستنده همیشه ایمیل دامنه‌ی خودتونه، نه ایمیل کاربر. اگه setFrom رو با ایمیل کاربر پر کنید، عملاً دارید از طرف یه دامنه‌ی دیگه ایمیل می‌فرستید و SPF شکست می‌خوره و ایمیل مستقیم می‌ره اسپم. ایمیل کاربر باید تو addReplyTo بشینه تا دکمه‌ی Reply درست کار کنه.
  • موضوع ثابت گذاشتیم. اگه اسم کاربر رو داخل موضوع بذارید، اسپمرها ازش برای تزریق متن تبلیغاتی استفاده می‌کنن.
  • هانی‌پات با display:none نساختیم. ربات‌های امروزی این حالت رو تشخیص می‌دن؛ بردن فیلد بیرون از کادر دید مؤثرتره.
  • برای فرم‌های پرترافیک این حد کافی نیست. محدودیت تعداد ارسال بر اساس IP یا یک کپچا رو هم اضافه کنید.

وردپرس: بدون یک خط کد

اگه سایتتون وردپرسیه، احتمالاً اصلاً لازم نیست کد بنویسید. ولی یه نکته‌ی فنی هست که باید بدونید:

وردپرس برای ارسال ایمیل از تابع wp_mail() استفاده می‌کنه که در حالت پیش‌فرض پشت صحنه همون mail() رو صدا می‌زنه. یعنی همه‌ی مشکلاتی که اول مقاله گفتیم، به‌صورت پیش‌فرض تو وردپرس هم وجود داره. برای همینه که خیلی‌ها می‌گن «ایمیل‌های وردپرس من نمیاد».

راه‌حل دو تا افزونه‌ست:

  1. یک افزونه‌ی SMTP که wp_mail() رو مجبور می‌کنه به‌جای mail() از SMTP احراز هویت‌شده استفاده کنه. این مهم‌ترین قطعه‌ی پازله و بدون این، بقیه‌ش فایده نداره.
  2. یک افزونه‌ی فرم‌ساز برای ساخت خود فرم تماس.

ترتیب کار هم مهمه: اول SMTP رو تنظیم و تست کنید، بعد فرم رو بسازید. اگه برعکس عمل کنید و ایمیل نیاد، نمی‌دونید مشکل از فرمه یا از ارسال.

کاری کنیم ایمیل‌ها به اسپم نروند

این بخش مهم‌تر از کدیه که نوشتیم. می‌تونید بی‌نقص‌ترین کد دنیا رو بنویسید و باز هم ایمیل‌هاتون تو اسپم بیفتن، چون تصمیم‌گیرنده سرویس گیرنده‌ست، نه شما. از سال ۲۰۲۴ به بعد هم گوگل و یاهو شرایط سخت‌گیرانه‌تری برای فرستنده‌ها گذاشتن، پس این سه تا رکورد دیگه اختیاری نیستن:

SPF

مشخص می‌کنه چه سرورهایی مجازن از طرف دامنه‌ی شما ایمیل بفرستن. یه رکورد TXT روی دامنه‌ی اصلی:

v=spf1 include:mail.yourhost.com ~all

مهم: برای هر دامنه فقط و فقط یک رکورد SPF مجازه. اگه از چند سرویس استفاده می‌کنید، باید همه رو تو همون یک رکورد با include کنار هم بیارید. دو رکورد SPF جدا یعنی هر دو بی‌اعتبار می‌شن.

DKIM

یه امضای رمزنگاری‌شده به هر ایمیل اضافه می‌کنه تا گیرنده مطمئن بشه محتوا دستکاری نشده. تو کنترل‌پنل‌های امروزی معمولاً با یه کلیک فعال می‌شه و رکوردش خودکار ساخته می‌شه. اگه فعال نبود، از پشتیبانی هاست بخواید فعالش کنن.

DMARC

به سرویس گیرنده می‌گه اگه SPF یا DKIM شکست خورد، چه کار کنه. برای شروع با حالت گزارش‌گیری بذارید تا ببینید چه اتفاقی می‌افته:

_dmarc.yourdomain.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"

بعد از چند هفته که گزارش‌ها رو دیدید و مطمئن شدید همه‌ی ایمیل‌های قانونی‌تون درست احراز می‌شن، می‌تونید سیاست رو سخت‌گیرانه‌تر کنید. از همون اول سراغ حالت سخت‌گیرانه نرید، چون ممکنه ایمیل‌های واقعی خودتون هم رد بشن.

چند نکته‌ی تکمیلی

  • از موضوع‌های تحریک‌کننده مثل «برنده شدید» یا «پیشنهاد ویژه» و حتی «تست» پرهیز کنید.
  • نسبت متن به تصویر رو رعایت کنید؛ ایمیلی که فقط یه تصویر بزرگه، پرچم قرمزه.
  • تو ایمیل‌های گروهی حتماً لینک لغو اشتراک بذارید.
  • قبل از ارسال انبوه، ایمیلتون رو با ابزارهای سنجش اسپم (مثل Mail-tester) امتیازدهی کنید.

رفع خطاهای رایج

خطایعنی چیراه‌حل
Sender address rejectedسرور گیرنده آدرس فرستنده رو قبول نمی‌کنهفرستنده رو به ایمیل دامنه‌ی خودتون تغییر بدید و SPF رو تنظیم کنید
SMTP connect() failedاتصال به سرور SMTP برقرار نشدهاست، پورت و باز بودن پورت خروجی رو چک کنید؛ روی هاست اشتراکی معمولاً باید از پشتیبانی بخواید بازش کنه
SMTP Error: Could not authenticateنام کاربری یا رمز اشتباههبرای جیمیل حتماً App Password بسازید، نه رمز عادی حساب
ایمیل ارسال می‌شود ولی به اسپم می‌رودسرویس گیرنده به فرستنده اعتماد ندارهSPF و DKIM و DMARC رو کامل کنید و فرستنده رو هم‌دامنه با سایت کنید
متن فارسی به‌هم ریخته استکدگذاری تنظیم نشدهدر PHPMailer مقدار CharSet = 'UTF-8' رو ست کنید
Gmail couldn’t verify that … sent this messageاحراز هویت دامنه ناقصهDKIM رو فعال و DMARC رو تنظیم کنید

سؤالات متداول

چرا ایمیل‌های سایت من به اسپم می‌روند؟

شایع‌ترین دلیل، نبود احراز هویت دامنه‌ست. اگه رکوردهای SPF و DKIM تنظیم نشده باشن یا ایمیل فرستنده هم‌دامنه با سایت نباشه، سرویس گیرنده دلیلی برای اعتماد نداره. اول این‌ها رو درست کنید، بعد سراغ بقیه‌ی جزئیات برید.

تابع mail() بهتر است یا PHPMailer؟

برای هر پروژه‌ی واقعی، PHPMailer با SMTP. تابع mail() احراز هویت نداره، بازخورد درستی از نتیجه‌ی ارسال نمی‌ده و به تنظیمات سرور وابسته‌ست. فقط برای یادگیری منطق پایه ازش استفاده کنید.

آیا می‌شود با جیمیل ایمیل‌های سایت را فرستاد؟

برای تست و پروژه‌های کوچیک بله، به‌شرطی که احراز هویت دو مرحله‌ای رو فعال و یه App Password بسازید. ولی جیمیل محدودیت ارسال روزانه داره و برای سایت پرترافیک یا ارسال گروهی مناسب نیست.

فرم تماس با ما را چطور از اسپم ربات‌ها محافظت کنیم؟

ترکیب هانی‌پات (فیلد پنهانی که فقط ربات پرش می‌کنه) و بررسی زمان ارسال، جلوی بخش بزرگی از ربات‌های ساده رو می‌گیره. برای سایت‌های پرترافیک، محدودیت تعداد ارسال بر اساس IP یا یک کپچا رو هم اضافه کنید.

چرا ایمیل‌های وردپرس ارسال نمی‌شوند؟

چون وردپرس در حالت پیش‌فرض از تابع mail() استفاده می‌کنه که روی خیلی از سرورها یا کار نمی‌کنه یا ایمیل‌ها رو به اسپم می‌فرسته. راه‌حل، نصب یه افزونه‌ی SMTP و تنظیم ارسال از طریق یه حساب ایمیل معتبره.

جمع‌بندی

خلاصه‌ی کل مسیر: تابع mail() رو برای فهمیدن منطق پایه یاد بگیرید ولی روی سایت واقعی ازش استفاده نکنید. PHPMailer با SMTP احراز هویت‌شده رو بردارید، اطلاعات ورود رو بیرون از ریشه‌ی وب نگه دارید، و برای فرم تماس حتماً CSRF و محافظت در برابر ربات رو اضافه کنید.

ولی مهم‌ترین نکته‌ای که باید با خودتون ببرید اینه: کیفیت کد شما تعیین‌کننده‌ی رسیدن ایمیل نیست. تنظیم درست SPF و DKIM و DMARC روی دامنه، بیشتر از هر خط کدی روی رسیدن یا نرسیدن ایمیل‌هاتون اثر می‌ذاره. اگه فقط وقت یک کار رو دارید، همون رو انجام بدید.

اگه جایی به خطا خوردید، تو بخش نظرات بنویسید؛ خوشحال می‌شیم کمک کنیم. موفق و پیروز باشید. 🙂

نظر شما در این مورد چیه؟

  1. U321426۲۷ بهمن ۱۴۰۱

    سلام من خواستم یک ایمیل سرور راه اندازی کنم روی ویندوز سرور با دامنه خودم میشه لطفا کمکم کنید من کار با رکورد mx هم بلد نیستم هر آموزشی هم نگاه کردم نشد

    • رضا راد۱۰ اسفند ۱۴۰۱

      سلام یکم طولانی هست جواب سوالتون و به نظرم با سرچ توی گوگل بهتر پیداش میکنید اما به طور کلی باید یک a با نام mx بسازید با آی پی ایمیل سرور و سپس رکورد mx با اون رکورد a بسازید.

  2. U311836۲ اسفند ۱۴۰۰

    سلام، با تشکر از سایت و مطلب خوبتون
    راستش من توی php اطلاعاتی ندارم. فایل تست اول رو من ایجاد کردم و آدرسهای ایمیل خودم رو هم جایگزین کردم ولی ایمیلی ارسال نمیشه! آیا نیاز به فایلهای دیگه و یا احیانا تغییراتی توی هاست داره؟ من در سی پنل و روی هاست واقعی تست میکنم
    با سپاس

    • رضا راد۴ اسفند ۱۴۰۰

      سلام تغییرات هاست با مدیریت هست و اگر تنظیمات سرور صحیح باشه باید ارسال کنه

  3. U38410۵ تیر ۱۴۰۰

    سلام
    در ادامه سوال قبلی درباره فرم ثبت نام زمانی که استانی انتخاب می شود شهرهای مربوط به همان استان نشان داده می شود. آیا افزونه ای که همه این کارها را انجام دهد وجود دارد

    • رضا راد۵ تیر ۱۴۰۰

      درود بر شما بله از افزونه‌هایی مثل گرویتی فرمز میتونید استفاده کنید فقط باید شهر ها را دستی وارد کنید

  4. U38410۵ تیر ۱۴۰۰

    سلام وقت شما بخیر
    ببخشید آیا بدون کدنویسی می توان همچین فرمی در ورد پرس ساخت. اول اینکه از چند بخش تشکیل شده است و ثانیا امکان اضافه کردن و پر کردن برخی از فیلدها مثلا مدارج دانشگاهی یا زبان که در این فرم در بخش دوم و آخر این امکان به کاربر هنگام ثبت نام داده شده است. و ثالثا حاشیه فیلدها کمی گرد است که زیباتر شده است.
    ممنون

    • رضا راد۵ تیر ۱۴۰۰

      سلام وقت بخیر. بله افزونه‌های فرم ساز زیادی هست با چنین قابلیت‌هایی

      • U38410۶ تیر ۱۴۰۰

        خیلی ممنون. میشه اسم اون افزونه ها را بفرمایید. البته رایگان باشند بهتره. من یادمه خیلی وقت پیش یکی از مخزن وردپرس نصب کردم و قابلیتهای زیادی داست ولی متاسفانه الان اسمش یادم نمیاد. الان اون هایی هم که قابلیتهای خوبی دارند اون قسمتهای خوبشون را پولی قرار دادند 🙁

        • رضا راد۶ تیر ۱۴۰۰

          درود بر شما wp forms مناسب هست.

پشتیبانپشتیبانپشتیبانپشتیبانپشتیبان
تیم میهن وردپرس
پشتیبانپشتیبانپشتیبانپشتیبانپشتیبان
تیم میهن وردپرسآنلاین و پاسخگوی شما هستیم.آنلاین

در حال بارگذاری...

هر سوالی دارید بپرسید.پاسخگوی شما هستیم.