Roblog

Sending mail with PHP

People seem to have trouble writing secure mailing scripts, and this is a request that comes up regularly. So, here is how one sends mail securely with PHP:

<?php

// CONFIG
$mail_to = 'r@robm.me.uk';
// END CONFIG

session_start();

function strip_mail_headers_single( $string ) {
    return preg_replace('/(%0A|%0D|\n+|\r+)/i', '', $string);
}

function strip_mail_headers_multi( $string ) {
    return preg_replace('/(%0A|%0D|\n+|\r+)(content-type:|to:|cc:|bcc:)/i', '', $string);
}

function is_valid_email( $string ) {
    return preg_match('^[\_]*([a-z0-9]+(\.|\_*)?)+@([a-z][a-z0-9\-]+(\.|\-*\.))+[a-z]{2,6}$', $string);
}

function send_mail($to, $from, $from_mail, $subject, $message) {
    if ( empty($from) || empty($from_mail) || empty($subject) || empty($message) ) {
        return -1;
    }

    if ( $_SESSION['last_mailed'] + 180 < time() )
        return -2;

    if ( !is_valid_email($from_mail) )
        return -3;

    $from = strip_mail_headers_single($from);
    $from_mail = strip_mail_headers_single($from_mail);
    $subject = strip_mail_headers_single($subject);
    $message = strip_mail_headers_multi($message);

    $_SESSION['last_mailed'] = time();

    return mail($to, $subject, $message, "From: $from <$from_mail>\r\n");
}

if ( !empty($_POST) ) {
    $result = send_mail($mail_to, $_POST['from'], $_POST['from_mail'], $_POST['subject'], $_POST['message']);

    if ( $result == -1 ) {
        echo "<p>Whoops! You need to complete all the fields.</p>";
    } elseif ( $result == -2 ) {
        echo "<p>Whoah, slow down there cowboy! You can only send one mail every three minutes.</p>";
    } elseif ( $result == -3 ) {
        echo "<p>Please enter a valid email address.</p>";
    } else {
        echo "<p>Mail sent successfully!</p>";
    }
}

?>

<form method="post" action="">

    <p><label for="from">Your name:</label></p>
    <p><input type="text" name="from" id="from" /></p>

    <p><label for="from_mail">Your email address:</label></p>
    <p><input type="text" name="from_mail" id="from_mail" /></p>

    <p><label for="subject">Subject:</label></p>
    <p><input type="text" name="subject" id="subject" /></p>

    <p><label for="message">Message:</label></p>
    <p><textarea name="message" id="message"></textarea></p>

    <p><input type="submit" value="Send Message" /></p>

</form>

Either copy and paste, or you can download from here:

Things to note:

  1. It doesn’t trust user input: it strips away newlines in single-line input, and tries to remove headers from multi-line input.
  2. It doesn’t allow people to spam it: it prevents the sending of more than one mail every three minutes.

I’m sure there are some things I’ve missed, but I hope at least it can be a good starting point.