Sending Email in PHP

Sending Email in PHP can be accomplished in many different ways:

The mail() function is universal, easy-to-use, and requires no additional configuration. The mail() function, if not used correctly, is vulnerable to attacks and can turn a web site into a spam hub. Pear::Mail is aging, and not adequately up to PHP 5 coding standards. SwiftMailer is fully featured, resistant against Email injection attacks, and more flexible. However, it is not universally deployed on all servers. Another option available is SendGrid. SendGrid is a fully featured API that handles the sending of mail so that an SMTP server does not have to be maintained or installed. While it is easy to configure SMTP with a VPS it becomes much harder to configure with a containerized hosting approach. For PWP we will be using the SendGrid approach.

Installing SwiftMailer Using Composer

Create a composer.json File


To use either PHPMailer or SwiftMailer, Composer must be installed. Composer is a package manager for PHP that automatically manages packages, their dependencies, and their versions. At its core, Composer uses a file called composer.json. This file enumerates all the composer packages imported into the project and configures the composer command to download all the requested packages. To install SwiftMailer, create a composer.json file in the root of the git project:

{
"require": {
"sendgrid/sendgrid":"@stable"
}
}

Ignore Composer Generated Files


Composer generates files that will pollute a git repository and present a security risk if committed to git. All these files are in the vendor directory. Add the following line to the .gitignore file:

/vendor

Commit and push the .gitignore file.

Execute Composer to Install SwiftMailer


This will tell composer to install the latest stable SendGrid. Add the composer.json file to git and commit and push it.

Once the composer.json file is committed, SSH to the project and execute the following commands:

cd public_html/project-name
composer install

This will tell composer to read the composer.json file and download all the specified packages. After this process is complete, composer will generate two items:

  • vendor: directory containing all the code downloaded
  • composer.lock: automatically generated file containing package data

Download the composer.lock file and add, commit, and push it to git. The composer.json and composer.lock files should be the only composer related files on git.

Example Form

<form class="form-horizontal well" action="email.php">
	<div class="form-group">
		<label for="name">Name</label>
		<div class="input-group">
			<div class="input-group-addon">
				<i class="fa fa-user" aria-hidden="true"></i>
			</div>
			<input type="text" class="form-control" id="name" name="name" placeholder="Name">
		</div>
	</div>
	<div class="form-group">
		<label for="email">Email address</label>
		<div class="input-group">
			<div class="input-group-addon">
				<i class="fa fa-envelope" aria-hidden="true"></i>
			</div>
			<input type="email" class="form-control" id="email" name="email" placeholder="Email">
		</div>
	</div>
	<div class="form-group">
		<label for="subject">Subject</label>
		<div class="input-group">
			<div class="input-group-addon">
				<i class="fa fa-pencil" aria-hidden="true"></i>
			</div>
			<input type="text" class="form-control" id="subject" name="subject" placeholder="Subject">
		</div>
	</div>
	<div class="form-group">
		<label for="message">Message</label>
		<div class="input-group">
			<div class="input-group-addon">
				<i class="fa fa-comment" aria-hidden="true"></i>
			</div>
			<textarea class="form-control" rows="5" id="message" name="message" placeholder="Message"></textarea>
		</div>
	</div>
	<button class="btn btn-success" type="submit"><i class="fa fa-paper-plane"></i> Send</button>
	<button class="btn btn-warning" type="reset"><i class="fa fa-ban"></i> Reset</button>
</form>

Example Code

<?php
/**
 * mailer.php
 *
 * This file handles secure mail transport using the Swiftmailer
 * library with Google reCAPTCHA integration.
 *
 * @author Rochelle Lewis <rlewis37@cnm.edu>
 **/
// require all composer dependencies
require_once(dirname(__DIR__, 1) . "/vendor/autoload.php");
// require mail-config.php
require_once("mail-config.php");

use \SendGrid\Mail;
$sendgrid = new \SendGrid($sendGridSecret);
// verify user's reCAPTCHA input
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($_POST["g-recaptcha-response"], $_SERVER["REMOTE_ADDR"]);
try {
	// if there's a reCAPTCHA error, throw an exception
//	if (!$resp->isSuccess()) {
//		throw(new Exception("reCAPTCHA error!"));
//	}
	/**
	 * Sanitize the inputs from the form: name, email, subject, and message.
	 * This assumes jQuery (NOT Angular!) will be AJAX submitting the form,
	 * so we're using the $_POST superglobal.
	 **/
	$name = filter_input(INPUT_POST, "name", FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
	$email = filter_input(INPUT_POST, "email", FILTER_SANITIZE_EMAIL);
	$subject = filter_input(INPUT_POST, "subject", FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
	$message = filter_input(INPUT_POST, "message", FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
	// create SendGrid object
	$emailObject = new Mail();
	/**
	 * Attach the sender to the message.
	 * This takes the form of an associative array where $email is the key for the real name.
	 **/
	$emailObject->setFrom($email, $name);
	/**
	 * Attach the recipients to the message.
	 * $MAIL_RECIPIENTS is set in mail-config.php
	 **/
	$recipients = $MAIL_RECIPIENTS;
	$emailObject->addTo("test@email.com","Full Name");
	// attach the subject line to the message
	$emailObject->setSubject($subject);
	/**
	 * Attach the actual content for the email.
	 **/
	$emailObject->addContent("text/plain", $message);
	/**
	 * using the sendgrid object from above call the send method and use the emailObject as an argument.
	 */
	$response = $sendgrid->send($emailObject);
	// report a successful send!
	echo "<div class=\"alert alert-success\" role=\"alert\">Email successfully sent.</div>";
} catch(\Exception $exception) {
	echo "<div class=\"alert alert-danger\" role=\"alert\"><strong>Oh snap!</strong> Unable to send email: " . $exception->getMessage() . "</div>";
}