PHP Secure Mailer Script
In order to circumvent the harvesting of email addresses from a page, many web designers are putting form mailers into their pages. Sadly, most aren't taking security into account, and it is just adding to already monumental Spam problems.
The biggest problem is with Header Injection. There are a ton of good articles on the web about how to keep malicious users from injecting headers with a mailer script. Just run "php mail header injection" through a Google search, and you will find some.
If you are just beginning in PHP, however, some of these articles can be difficult to understand. I've seen a lot of fresh PHP coders put insecure mailer scipts online due to a lack of knowledge, and the inabilty to easily find a secure script to use. Way too many pre-written scripts are just:
$to_address = "your email here";
$from_address = $_POST['user_input_email_address'];
$message = $_POST['user_input_message'];
$subject = $_POST['user_input_subject'];
$headers = 'From:' . $from_address . "\n" . 'Reply-To: ' . $from_address;
mail($to_address, $subject, $message, $headers);
?>
There are a lot of problems with that script. First and foremost, none of the user $_POST input is being filtered. It would be easy for a malicious user to put something in the input box that would break the mailer, and allow them to send mail to whoever they wanted.
(Run that Google search I posted up there, to find out more about how they do this)
Why should you care if someone uses your script to send email to someone else?
Well, there are a couple of reasons. Understand that the bulk of the people that would want to use your page to send emails are spammers. An unselfish reason to keep spammers from using your page to send emails would be to help combat spam.
However, I'm cynical, and I know that a lot of people don't care about it, as long as it doesn't directly affect them. Here's the selfish reason to make sure that people aren't using your scripts to send mail:
When your server is marked for sending spam, ISPs will blacklist you. Having your server IP on a spam blacklist isn't very good for business, and can be very difficult to sort out. This means that your clients, or anyone else on the server, will have problems sending email to any ISP that runs a blacklist. It doesn't take too many bounced emails before a client decides to go somewhere else, and from my experience, they won't let their server admin know that there is a problem until they have already decided to move to a host that isn't blacklisted.
The following script is one that I have written. It has been throughly tested, and I have yet to have anyone use it to send spam.
I have another version of this script, which isn't free. The other version has the following extra features:
- Keeps a list of IP addresses that have tried to use the form to send spam
- Allows the user to add IP address ranges to an array, for blacklisting
- Uses the blacklists that it creates to keep those on the lists from accessing the page that contains the mailer
- Sends alerts to an administrator whenever malicious activity is detected.
- Contains better filter statements.
- Contains a filter that will kill the page if the referring form isn't one specified, in order to cut down on cross-site scripting.
If you are interested in the modified version of the script, contact me.
Now, for the free version of the script. Use this at your own risk. Just because I haven't had anyone break it doesn't mean that someone won't.
//on the page that calls this, use the following form values:
/*
<form action="INSERT NAME AND LOCATION OF THIS FILE" method="post">
<p>Your Email Address: <input type="text" name="returnaddress" size="30" /></p>
<p>Subject:
<!--NOTE: You can use as many options as you wish. You don't have to use a dropdown for this, you can let the user type in whatever they wish. -->
<select name="subject">
<option value="">------ Select a Subject -------</option>
<option value="SUBJECT CHOICE">OPTION NAME</option>
</select></p>
<p><textarea name="message" >Type your Question/Comments here.</textarea></p>
<p><input type="Submit" value="Send Message" /></p>
</form>
*/
//BEGIN Taylored Solutions' fancy-schmancy
//Webform Validator and Automatic Ice Cream Maker.
//set your email address.
$to = '<a href="mailto:\'myaddress@mydomain\'">myaddress@mydomain</a>';
//check for forbidden content in every element sent.
//Right now, this is any sign of content-type injection or bcc:
// or cc:: stuff, as these are the most commonly tried exploits.
foreach($_POST as $value) {
$value = strtolower($value);
if((strpos($value,'content-type:') !== FALSE) || (strpos($value,'bcc:') !== FALSE) || (strpos($value,'cc:') !== FALSE)) {
//kill the script
die('Please don\'t do that.');
}
}
//make the variables work
$comments = $_POST['message'];
$subject = $_POST['subject'];
$email = $_POST['returnaddress'];
//check for the existence of the input information
if ($comments == '' || $subject == '') {
//you could also make the next line return them to the previous page,
//with an error message.
die ('Please fill in all the information.');
}
//validate the email address with regex. Some may argue that this
//regex isn't very robust, but the information has already been
//through a rudimentary filter, and this isn't going
//anywhere except in the message body.
if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email)) {
//if this fails, kill the script, and send a message
die('Invalid Email Address.');
}
//set the header information
//I don't use the email address that was input here because it's
//just better to leave any input information out of the headers.
//Also, some hosts have an issue sending with php mail() with
//a from or reply-to address that isn't from a domain on their server.
//This will also make it easier to add a filter to your email client,
//and put these in a special folder when they come in.
$headers = 'From: '. $to . "\r\n" .
'Reply-To: ' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
//set the subject line of the email
$subject = "Comment from my web mailer form.";
//set the message. This will contain the email address that the user
//input, the subject that the user chose, and the user's comments.
$msg .= 'Email Address: ' . $email . "\n";
$msg .= 'Subject: ' . $subject . "\n";
$msg .= 'Comments: ' . $comments . "\n";
//and off it goes!
$mail_success = mail($to, $subject, $msg, $headers);
//make ice cream.
//To be inserted at a later date.
if ($mail_success == true) {
//send a message to the user
?>
<br />
Thank you for your message!<br />
We will contact you shortly!
<?php
} else {
?>
<br />
There was an error sending the message.<br />
Please try again later.
<?php
}
//END Taylored Solutions' fancy-schmancy
//Webform Validator and Automatic Ice Cream Maker.
?>
Tags: header, injection, mail form, php, php mail, phpmailer, script
August 26th, 2009 at 4:37 pm
Is there any chance you could convert the ‘’ to regular single quotes to make it easier for others to copy the script?
Also, I think this line needs quotes around the value:
$to = ‘myaddress@mydomain’;
Should be:
$to = ‘myaddress@mydomain‘;
I think
September 9th, 2009 at 8:55 am
Good idea about the single quotes. That, and the misplaced quotes around the $to line have both been addressed. Thanks for pointing them out!
May 3rd, 2010 at 10:14 pm
@anonymous: Thanks. It should all be under control, now.