Contact form sending blank emails occasionally

Hi, my form works correctly most of the time, but occasionally an email shows up with nothing in the body, not even the “You’ve received a lead” message. The user’s name, email, and subject are sent through, just not in the body. I’ve tried sending emails with every special character in them, but I haven’t been able to duplicate the problem. Anyone know what might be causing this?

I’m linking the user to the contact page with a link like this: http://www.site.com/contact/contact.php?subject=subject&sendto=email@email.com

Here is the form:

<form name="contactform" method="post" action="sendcontact.php">
  <td height="486" align="center"><br><table border="0" cellpadding="3" cellspacing="3">
    <tr><td class="main" align="right">Name:</td>
        <td align="left"><input name="realname" type="text" size="52"></td>
        <td align="left" class="main"><font color="#FF0000">Required</font></td>
      </tr>
      <tr>
        <td align="right" class="main">E-mail:</td>
        <td align="left"><input name="email" type="text" size="52"></td><td align="left" class="main"><font color="#FF0000">Required</font></td>
      </tr>
      <tr>
        <td align="right" class="main">Phone Number:</td>
        <td align="left"><input name="phone" type="text" size="52"></td><td align="left" class="main"></td>
      </tr>
      <tr>
        <td align="right" class="main">Subject:</td>
        <td align="left"><input name="subject2" type="text" size="52" value="<?= $_GET['subject'] ?>"></td><td align="left" class="main"><font color="#FF0000">Required</font></td>
      </tr>
      <tr>
        <td align="right" class="main">City/State</td>
        <td align="left"><input name="city" type="text" size="52"></td>
        <td align="left" class="main"><font color="#FF0000">Required</font></td>
      </tr>
      <tr>
        <td valign="top" align="right" class="main">Questions/Comments:</td>
        <td align="left">
<textarea name="comments" cols="40" rows="13"></textarea>
<input name="sendto" type="hidden" size="52" value="<?= $_GET['sendto'] ?>"><input name="subject" type="hidden" size="52" value="<?= $_GET['subject'] ?>"></td><td align="left" class="main" valign="top"><font color="#FF0000">Required</font></td>
      </tr>
      <tr>
        <td valign="top">&nbsp;</td>
        <td align="center">
          <input name="Submit" type="submit" value="Send"></td>
      </tr>
    </table></td></form>

and here is sendcontact.php:


<?php

  if(isset($_POST['email'])) {

    // EDIT THE 2 LINES BELOW AS REQUIRED

    function died($error) {

      // your error code can go here

      echo "Sorry, but there were error(s) found with the form you submitted. ";

      echo "<br /><br />";

      echo $error."<br /><br />";

      echo "Please go back and fix these errors.<br /><br />";

      die();

    }

    // validation expected data exists

    // validation expected data exists
    if(!isset($_POST['realname']) ||
       !isset($_POST['email']) ||
       !isset($_POST['phone']) ||
       !isset($_POST['subject']) ||
       !isset($_POST['subject2']) ||
       !isset($_POST['sendto']) ||
       !isset($_POST['city']) ||
       !isset($_POST['comments'])) {
      died('We are sorry, but there appears to be a problem with the form you submitted.'); 
    }
    $realname = $_POST['realname']; // required
    $email_from = $_POST['email']; // required
    $email_from2 = "sales@site.com";
    $phone = $_POST['phone']; // not required
    $email_subject = $_POST['subject']; // required
    $email_to = $_POST['sendto']; // not required
    $city = $_POST['city']; // not required
    $subject2 = $_POST['subject2']; // required
    $comments = $_POST['comments']; // required
    $error_message = "";
    $email_exp = '/^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$/';
    if(!preg_match($email_exp,$email_from)) {
      $error_message .= 'The email address you entered does not appear to be valid.<br />';
    }
    if(strlen($email_subject) < 2) {
      $error_message .= 'The subject you entered does not appear to be valid.<br />';
    }
    if(strlen($realname) < 2) {
      $error_message .= 'The name you entered does not appear to be valid.<br />';
    }
    if(strlen($subject2) < 2) {
      $error_message .= 'The subject you entered does not appear to be valid.<br />';
    }

    if(strlen($comments) < 2) {
      $error_message .= 'The comments you entered do not appear to be valid.<br />';
    }
    if(strlen($error_message) > 0) {
      died($error_message);
    }
    $email_message = "You've received a sales lead\
\
";
    function clean_string($string) {
      $bad = array("content-type","bcc:","to:","cc:","href");
      return str_replace($bad,"",$string);
    }
    $email_message .= "Name: ".clean_string($realname)."\
";
    $email_message .= "Email: ".clean_string($email_from)."\
";
    $email_message .= "Phone Number: ".clean_string($phone)."\
";
    $email_message .= "Subject: ".clean_string($email_subject)."\
";
    $email_message .= "Subject By User: ".clean_string($subject2)."\
";
    $email_message .= "City/State: ".clean_string($city)."\
";
    $email_message .= "Questions/Comments: ".clean_string($comments)."\
";
    // create email headers
    $headers = 'From: '.$email_from2."\\r\
".
            'Reply-To: '.$email_from."\\r\
" .
            'X-Mailer: PHP/' . phpversion();
    @mail($email_to, $email_subject, $email_message, $headers); 

    header ('Location: http://www.site.com/contact/thankyou.htm');

    exit();
  }

?>

Thanks,
Matt

You’ve got multiple security vulnerabilities in your code.

First, you aren’t sanitizing inputs for the form itself. At least do a htmlspecialchars() for each $_GET variable. Otherwise, you’ve opened up that site to a XSS attack.

Second, your form allows any ‘from’ and ‘to’, effectively creating a web form relay that uses your email server. Spammers love relay forms.

Third, the subject line isn’t sanitized. I would wager that is your injection point. Took me a while to find it. The fact you are receiving blank emails and this issue exists, tells me someone is probably using your form for sending spam. Oops.

I’m not sure what the point of clean_string() is. The things you are removing are mostly header-related. The user doesn’t have an opportunity to inject into the headers within the body. Also, the message is plain-text, so removing ‘href’ does nothing. Basically, the function doesn’t do anything.

As far as your blank e-mail issue goes, I was originally looking for a way to modify the headers via the from address to bury the original message in an alternate MIME type that would never be shown because that’s what I would do. The regular expression on the email address stops that from happening. Took me a while to find the subject line issue, but I’d wager that not sanitizing the subject line is the problem.

I never call the PHP mail() function directly because there are too many problems with doing that. I use a library such as PHP Mailer or Barebones Ultimate E-mail Toolkit or similar to send email. Good libraries do way more than just send email, they sanitize inputs for you prior to delivery to the email server and provide useful tools to get the job done because getting email right is much harder than most people think since the PHP mail() function was never intended to be called directly and email address validation is also hard to get right (your regex has numerous issues - the only thing going for it is that it does stop header injection).

On a couple of stylistic notes, you are using tables and it looks like you are embedding ‘form’ tags in invalid locations (outside ‘td’ tags is invalid HTML). Also, it is better to fall through to the original form on an error and let the user correct the problem. Pressing ‘Back’ may result in a blank form, forcing the user to type in everything again, so most users won’t bother. In your case, that translates to lost sales leads.

Thank you for the reply SarinWasari, I appreciate it. Can someone please tell me exactly how to add the sanitizing code into mine? I don’t know anything about PHP.

Also, at least one of the blank emails came from a customer that was definitely not a spammer.

Thanks,
Matt