dindarloo

حسین دیندارلو

برنامه نویس و طراح وب
خانه درباره من سرویس ها خدمات نرم افزاری وبلاگ

امنیت ارسال ایمیل در php

اگر از دنبال کننده های آموزه های این سایت هستید و طبق آموزش ها یک فرم php ساختید و از تابع mail برای ارسال آن استفاده کردید لازم است که نکاتی را در مورد امنیت این موضوع بدانید و پیاده کنید.

مشکل فرم ما این است که کاربر می تواند هدر دلخواه خود را جایگذاری کند

مثلا اگر کد زیر را درون یک فیلد ایمیل جایگذاری کند :

user1@example.com%0ACc:user2@example.com%0ABcc:user3@example.com

البته ما در مطلب فیلتر کردن عبارات در فرم ایمیل جلوی این اقدام را گرفته ایم، در این مطلب می خواهم در مورد اضافه کردن هدرها و خودکار کردن آدرس پاسخ بنویسم

در این راه حل سه هدر به ایمیل اضافه می کنیم : from – content-type – reply-to

قبل از اضافه کردن آدرس ایمیل کاربر به هدر ، یکی از تابع های فیلتر php را استفاده می کنیم تا مشخص شود که در مقدار ورودی از فرمت مناسب آدرس ایمیل استفاده شده است.

از آنجایی که دو هدر از سه هدر بالا یعنی from و content-type در هر فرم ثابت است این دو را به contact.php که فرم ماست اضافه می کنیم.

$headers = "From: form name<feedback@example.com>\r\n";
$headers .= 'Content-Type: text/plain; charset=utf-8';

در کد بالا r\n\ را که در انتهای هدر from قرار دارد و به منزله ی کاراکتر بازگشت و خط جدید است به خاطر کاراکتر فرار بودن درون کوتیشن دوتایی قرار دادیم.

چرا هدر content-type کاراکتر بازگشت و خط جدید نمی خواهد ؟ چون هدر آخر است و بعد از آن خطی وجود ندارد ، پس لازم نیست و درون یک کوتیشن منفرد قرار دادیم.

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

اگر فیلد خالی نباشد و ورودی معتبر نباشد لازم است که یک پیغام خطا مبنی بر صحیح نبودن فرمت ایمیل نمایش داده شود.

در فایل پردازشگر فرم که در contact.php اینکلود می کنیم به طریق زیر عمل می کنیم.

// سنجش اعتبار ایمیل
if (!$suspect && !empty($email)) {
    $validemail = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    if ($validemail) {
        $headers .= "\r\nReply-To: $validemail";
    } else {
        $errors['email'] = true;
    }
}

توضیح کد بالا : در ابتدا بررسی می کند که عبارت مشکوکی پیدا شده است یا خیر و فیلد email خالی نمانده است. قبل از هر دو شرط نه منطقی (!) قرار دارد و بنابر این اگر suspect$ و empty($email) هر دو برابر با fase باشد مقدار true برگردانده می شود و شرط برقرار می شود.

نکته : حلقه ی foreach که مقادیر آرایه post_$ را با مقادیر ساده بر اساس کلید آرایه نسبت می دهد و در مطلب پردازش فرم php توضیح دادم POST[’email]_$ را به متغیر email$ نسبت داده است.

خط بعدی از تابع ()filter_input برای تایید اعتبار ایمیل وارد میدان می شود.

INPUT_POST اولین آرگومان این تابع یک ثابت php است کهمشخص می کند مقدار باید درون آرایه post_$ باشد.

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

تابع ()filter_input یا یک مقدار به عنوان مقدار معتبر ارزیابی شده بر می گرداند یا مقدار false . بنابر این اگر فرمت معتبر باشد validemail$ دارای مقدار است و اگر نباشد false است.

نکته : ثابت FILTER_VALIDATE_EMAIL تنها یک آدرس ایمیل قبول می کند. بنابراین اگر کاربر چند آدرس ایمیل وارد کرده باشد قبول نمی شود. همچنیین این ثابت تنها فرمت را بررسی می کند و کاری به نامعتبر بودن آدرس ندارد.

اگر validemail$ برابر با false نباشد آدرس ایمیل در هدر reply-to قرار می گیرد. به این دلیل که در آخرین هدر کاراکتر بازگشت و خط جدید نبود این دو را در ابتدای این هدر قرار می دهیم.

اگر validemail$ برابر با false باشد عنصر email به آرایه ی errors اضافه می شود.

نمایش پیغام مبنی بر نامعتبر بودن ایمیل وارد شده

اکنون در فرم خود <label> را برای فیلد email بدین صورت ویرایش می کنیم تا پیغام مطلوب نمایش داده شود.

<label for="email">Email:
    <?php if ($missing && in_array('email', $missing)) { ?>
        <span class="warning">اخطار خالی بودن فیلد ایمیل</span>
    <?php } elseif (isset($errors['email'])) { ?>
        <span class="warning">اخطار فرمت نامعتبر ایمیل</span>
    <?php } ?>
</label>

توضیح کد بالا

اولین شرط در کد بالا آرایه ی $missing را بررسی می کند. اگر خالی باشد که هیچ و پیغامی نمایش داده نمی شود. اما اگر دارای مقدار بود مقدارش true بوده و سراغ شرط مکمل که بعد از && است می رود که شرط بعدی وقتی true ارزیابی می شود که مقدار email درون آرایه ی $missing باشد ( این را توسط کد $missing[] = $key; در فایل پردازشگر تعیین کردیم). اگر حاوی مقدار نبود یعنی درون آرایه ی $missing بود کد بلاک شرطی اجرا می شود و در کنار لیبل name خطا ظاهر می شود.

قسمت elseif در کد بالا چه می گوید ؟ می گوید اگر مقدار email درون آرایه ی $errors بود که این به منزله ی این است که ایمیل فرمت نامعتبری دارد اخطار نمایش داده شود.

خب مبحث کنترل ورودی در فیلد email به منظور به کارگیری در تابع Mail به پایان رسید.

dindarloo
حسین دیندارلو
بزرگ ترین سرمایه گذاری ، سرمایه گذاری روی خودم بوده و هیچی اندازه ی خودم نتونسته حالم رو واقعا خوب کنه. حتی شادترین لحظه هایی که توسط دیگران به ارمغان آورده شده نمی ارزه به لحظه ای حال خوب که خودم ساخته باشم.