Sending Emails with Postmark and PHP

Sending emails from your app can suck. Half the time, messages that get sent from your own server just get dumped into the recipient's junk folder. The truth is, successfully delivering emails from your app to your users can be a painstaking task. That's why we decided to use Postmark for one of our latest projects.

Postmark is an app that makes sending emails from your own app easy. Once you get things setup, your emails are almost guaranteed to hit your users' inbox. They take care of all the difficult stuff:

We handle things like whitelisting, ISP throttling, reverse DNS, feedback loops, content scanning, and delivery monitoring to ensure your emails get to the inbox.

Once you create an account and get things setup on Postmark's website, sending an email is a simple call to their API. (Bonus feature: Postmark also handles inbound emails if you need that capability.)

The only problem is that they don't have a PHP SDK, so they rely on third party libraries to get the job done. Here is our take on writing a minimalistic function to send emails using the Postmark API.

The Code

Before we start, we'll need to define our Postmark API key. Let's do that with a constant:

define('POSTMARK_API_KEY', 'YOUR-API-KEY-HERE');

Now for the function. For the sake of simplicity, we're going to call it send_email. The function accepts an array to determine what to send. A quick glance at the function will show you all the options you can specify, which are mapped to the values found in the documentation. Optionally, you can specify $response and $http_code to get the resulting JSON response and HTTP code that Postmark sends back:

function send_email($email, &$response = null, &$http_code = null) {

    $json = json_encode(array(
        'From' => $email['from'],
        'To' => $email['to'],
        'Cc' => $email['cc'],
        'Bcc' => $email['bcc'],
        'Subject' => $email['subject'],
        'Tag' => $email['tag'],
        'HtmlBody' => $email['html_body'],
        'TextBody' => $email['text_body'],
        'ReplyTo' => $email['reply_to'],
        'Headers' => $email['headers'],
        'Attachments' => $email['attachments']
    ));

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'http://api.postmarkapp.com/email');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Content-Type: application/json',
        'X-Postmark-Server-Token: ' . POSTMARK_API_KEY
    ));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    $response = json_decode(curl_exec($ch), true);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $http_code === 200;

}

And here's how we send an email:

$sent = send_email(array(
    'to' => 'you@yourdomain.com',
    'from' => 'Me <me@mydomain.com>',
    'subject' => 'That was easy',
    'text_body' => 'This will be shown to plain-text mail clients',
    'html_body' => '<html><body>But <em>this</em> will be shown to HTML mail clients</body></html>'
), $response, $http_code);

// Did it send successfully?
if( $sent ) {
    echo 'The email was sent!';
} else {
    echo 'The email could not be sent!';
}

// Show the response and HTTP code
echo '<pre>';
echo 'The JSON response from Postmark:<br />';
print_r($response);
echo 'The HTTP code was: ' . $http_code;
echo '</pre>';

Room For Improvement

This function could easily be transformed into a PHP class, and probably should for more serious applications. As-is, you still need to manually handle base64 encoding for file attachments, there's no programmatic way to use SSL (just change the http to https in the URL), and there's no timeout for the cURL operation. However, this will get you started using Postmark quickly, so feel free to use it as a starting point in your own app!

Author avatar

About the author

New Hampshirite building web apps in Florida. Creator of Surreal CMS, Postleaf, and DirtyMarkup.

Need to get in touch? Catch me on Twitter.