Preventing Email Injection in PHP

Security measures should be taken that will assist in preventing email injection in PHP. Notably of spam-related content into the email.

Emails in PHP often use the standard mail() function. This means that your code might look something like this:

mail("support@somewebsite.com", "Contact Form Reply", $message, "From: $email" );

The code above sends the message to ‘support@somewebsite.com’ in response to a contact form submission from an email address stored in the $email variable, which is typically obtained from the web form.

If the script takes no effort to validate the $email variable before calling mail(), it is possible for a spammer to inject additional lines into the $email variable, such as:

$email = "customer@email.com\n\nBCC:spam@somethingspammy.com"

The PHP mail() function will insert those lines and essentially you’ve made yourself a spam host. This is a simple example of email injection.

To filter valid emails for use in the recipient email field, the filter_var() function can be used.

<?php
$email = filter_var($_POST['recipient_email'], FILTER_VALIDATE_EMAIL);

if ($email === FALSE) {
    echo 'Invalid email';
    exit(1);
}

The filter_var() function filters a variable with a specified filter. The two parameters used in this function include the variable to check against, and the in-built filter to be used.

Some of the filters that can be used include:

  • FILTER_VALIDATE_EMAIL
  • FILTER_VALIDATE_FLOAT
  • FILTER_VALIDATE_INT
  • FILTER_VALIDATE_IP

This will make sure your users only supply singular, valid emails, which you can then pass to the mail() function.

When the mail() function talks directly to an SMTP server, starting lines with full stops will need to be prevented in the message body. Therefore a simple str_replace() function should be used.

$body = str_replace("\n.", "\n..", $body);

It is also possible to inject via the email subject. Unfortunately we do not have a ‘FILTER_VALIDATE_EMAIL_SUBJECT’ filter available when using filter_var(), the filtering will need to be performed using PHP functions, such as str_ireplace

$subject = str_ireplace(array("\r", "\n", '%0A', '%0D'), '', $_POST['subject']);

Other techniques of preventing email injection include:

  • Do not provide open relays
  • Open the SMTP port only if essential
  • Use a ‘tarpits’ technique to slow requests as a means of dissuading attacks. This delays incoming connections with delayed response

Note: This article is based on PHP version 5.5.