I am in the process of building my contact forms email address validation script. Having debugged it and run basic test's using valid email addresses which all passed I went on to test for invalid addresses. My first test was .ala.dom.com
which is a clear invalid with both starting and ending dots. I expected to get my error message thrown up. However; my host has set the magic_quotes
on and instead the email went through because the escaped the whole local part of the address with " like this ".ala."@dom.com
This is an excert of the actual header that arrived in the email inbox -
Received: by srv28.000webhost.com (Postfix, from userid 7695918)
id 899601EE9C2; Sat, 5 Oct 2013 16:21:37 -0400 (EDT)
To: net@weedy101.netii.net
Subject: Should fold
X-PHP-Script: weedy101.netii.net/new-mail.php for 2.26.7.205
From: ".ala."@dom.com
Reply-To: ".ala."@dom.com
Content-type: text/html
Message-Id: <20131005202137.899601EE9C2@srv28.000webhost.com>
Date: Sat, 5 Oct 2013 16:21:37 -0400 (EDT)
My host's are 000webhosts.com
with a free account so even though they are only using php 5.2.*
I can't access the php.ini
to change the setting so therefore I need to programtically strip the inserted characters, or find another work around. I am totally stumped as to how best to handle this problem. My validation script is -
<?php
if (isset($_POST['name']) && isset($_POST['message']) && isset($_POST['email']) && isset($_POST['subject'])) {
$name = $_POST['name'];
$text = $_POST['message'];
$contact = $_POST['email'];
$subject = $_POST['subject'];
$isValid = true;
$atIndex = strrpos($contact, "@");
$problem = 1;
if (is_bool($atIndex) && !$atIndex) {
$isValid = false;
$problem = 2;
}
else {
$domain = substr($contact, $atIndex+1);
$local = substr($contact, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);
if ($localLen < 1 || $localLen > 64) {
$isValid = false;
$problem = 3;
}
else if ($domainLen < 1 || $domainLen > 255) {
$isValid = false;
$problem = 4;
}
else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
$isValid = false;
$problem = 5;
}
else if (preg_match('/\\.\\./', $domain)) {
$isValid = false;
$problem = 6;
}
else if (!(checkdnsrr($domain,"MX") || checkdnsrr($domain, "A"))) {
$isValid = false;
$problem = 7;
}
else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%£`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) {
if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) {
$isValid = false;
$problem = 8;
}
else if ($local[0] == '.' || $local[$localLen-1] == '.')
$isValid = false;
$problem = 9;
}
else if (preg_match('/\\.\\./', $local)) {
$isValid = false;
$problem = 10;
}
}
}
else {
$problem = 11;
}
if ($isValid == true) {
$message = "Message : <br/>" .$text . "<br/><br/>" . "From: " . $name . "<br/>" . $contact;
$headers = 'From: '. $contact . "\r\n" . 'Reply-To: ' . $contact . "\r\n" . "Content-type: text/html\r\n";
$mailto = 'net@weedy101.netii.net';
mail($mailto, $subject, $message, $headers );
}
header('location: index.php?pass='.$problem);
?>
Fell free to adapt this as I am adapting it from the article "Validate an E-Mail Address with PHP, the Right Way" on http://www.linuxjournal.com/article/9585?page=0,0
<EDIT>
After running through all the help offered here and working through many experiments that is lead to I am still stuck. Although I can get things to work by copying verbatim the original reference articles example at http://www.linuxjournal.com/article/9585?page=0,0 and this is all good, what I can't do is adapt it other than changing the preg match strings which would defeat the object anyway. So if anybody can see a way to make this more adaptable, ie portable as an external function or class so it can be reused at will. I would seriously appreciate the help.
So I'm going to mark this as answered but will keep reading the comments and any new answers in the hope of one day being able to understand what exactly is stopping this subroutine from being separated out and used more flexibly.