Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP interface class for the Premailer API
<?php
/**
* Premailer API PHP class
* Premailer is a library/service for making HTML more palatable for various inept email clients, in particular GMail
* Primary function is to convert style tags into equivalent inline styles so styling can survive <head> tag removal
* Premailer is owned by Dialect Communications group
* @link http://premailer.dialect.ca/api
* @author Marcus Bointon <marcus@synchromedia.co.uk>
*/
class Premailer {
/**
* The Premailer API URL
*/
const ENDPOINT = 'http://premailer.dialect.ca/api/0.1/documents';
/**
* Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
* @static
* @throws Exception
* @param string $html Raw HTML source
* @param string $url URL of the source file
* @param bool $fetchresult Whether to also fetch the converted output
* @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
* @param string $base_url Base URL for converting relative links
* @param int $line_length Length of lines in the plain text version (default 65)
* @param string $link_query_string Query string appended to links
* @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
* @param bool $remove_ids Remove IDs from the HTML document?
* @param bool $remove_classes Remove classes from the HTML document?
* @param bool $remove_comments Remove comments from the HTML document?
* @return array Either a single strclass object containing the decoded JSON response, or a 3-element array containing result, html and plain parts if $fetchresult is set
*/
protected static function convert($html = '', $url = '', $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
$params = array();
if (!empty($html)) {
$params['html'] = $html;
} elseif (!empty($url)) {
$params['url'] = $url;
} else {
throw new Exception('Must supply an html or url value');
}
if ($adaptor == 'hpricot' or $adaptor == 'nokigiri') {
$params['adaptor'] = $adaptor;
}
if (!empty($base_url)) {
$params['base_url'] = $base_url;
}
$params['line_length'] = (integer)$line_length;
if (!empty($link_query_string)) {
$params['link_query_string'] = $link_query_string;
}
$params['preserve_styles'] = ($preserve_styles?'true':'false');
$params['remove_ids'] = ($remove_ids?'true':'false');
$params['remove_classes'] = ($remove_classes?'true':'false');
$params['remove_comments'] = ($remove_comments?'true':'false');
$options = array(
'timeout' => 15,
'connecttimeout' => 15,
'useragent' => 'PHP Premailer',
'ssl' => array('verifypeer' => false, 'verifyhost' => false)
);
$h = new HttpRequest(self::ENDPOINT, HttpRequest::METH_POST, $options);
$h->addPostFields($params);
try {
$response = $h->send();
$result = json_decode($response->getBody());
$code = $response->getResponseCode();
if ($code != 201) {
switch ($code) {
case 400:
throw new Exception('Content missing', 400);
break;
case 403:
throw new Exception('Access forbidden', 403);
break;
case 500:
default:
throw new Exception('Error', $code);
}
}
$return = array('result' => $result);
if ($fetchresult) {
//Get HTML and plain versions in parallel
http_persistent_handles_clean();
$pool = new HttpRequestPool;
$pool->attach(new HttpRequest($result->documents->html, HttpRequest::METH_GET, $options));
$pool->attach(new HttpRequest($result->documents->txt, HttpRequest::METH_GET, $options));
$pool->send();
foreach($pool as $request) {
if ($request->getUrl() == $result->documents->html) {
$return['html'] = $request->getResponseBody();
} elseif ($request->getUrl() == $result->documents->txt) {
$return['plain'] = $request->getResponseBody();
}
}
return $return;
}
return $result;
} catch (HttpException $e) {
var_dump($h, $e->getMessage());
return false;
}
}
/**
* Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
* @static
* @throws Exception
* @param string $html Raw HTML source
* @param bool $fetchresult Whether to also fetch the converted output
* @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
* @param string $base_url Base URL for converting relative links
* @param int $line_length Length of lines in the plain text version (default 65)
* @param string $link_query_string Query string appended to links
* @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
* @param bool $remove_ids Remove IDs from the HTML document?
* @param bool $remove_classes Remove classes from the HTML document?
* @param bool $remove_comments Remove comments from the HTML document?
* @return array Either a single element array containing the 'result' object, or three elements containing result, html and plain if $fetchresult is set
*/
public static function html($html, $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
return self::convert($html, '', $fetchresult, $adaptor, $base_url, $line_length, $link_query_string, $preserve_styles, $remove_ids, $remove_classes, $remove_comments);
}
/**
* Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
* @static
* @throws Exception
* @param string $url URL of the source file
* @param bool $fetchresult Whether to also fetch the converted output
* @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
* @param string $base_url Base URL for converting relative links
* @param int $line_length Length of lines in the plain text version (default 65)
* @param string $link_query_string Query string appended to links
* @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
* @param bool $remove_ids Remove IDs from the HTML document?
* @param bool $remove_classes Remove classes from the HTML document?
* @param bool $remove_comments Remove comments from the HTML document?
* @return array Either a single element array containing the 'result' object, or three elements containing result, html and plain if $fetchresult is set
*/
public static function url($url, $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
return self::convert('', $url, $fetchresult, $adaptor, $base_url, $line_length, $link_query_string, $preserve_styles, $remove_ids, $remove_classes, $remove_comments);
}
}
/*
Simplest usage:
$pre = Premailer::html($var_with_some_html_in);
$html = $pre['html'];
$plain = $pre['plain'];
//Similarly for URLs:
$pre = Premailer::url($url);
*/
?>
@barockok

This comment has been minimized.

Copy link

barockok commented Jan 6, 2012

i got this
"Fatal error: Class 'HttpRequest' not found in...."

@Synchro

This comment has been minimized.

Copy link
Owner Author

Synchro commented Jan 6, 2012

You need to install/enable the PHP HTTP extension.

@hperrin

This comment has been minimized.

Copy link

hperrin commented Jun 26, 2012

Could you rewrite it using curl?

@hperrin

This comment has been minimized.

Copy link

hperrin commented Jun 26, 2012

Never mind. Looks like there's already one. https://gist.github.com/1591053

@marcovtwout

This comment has been minimized.

Copy link

marcovtwout commented Jul 25, 2012

Bugs in Line 55 + 56: remove $ from array keys

@Synchro

This comment has been minimized.

Copy link
Owner Author

Synchro commented Jul 25, 2012

Thanks, fixed

@withremote

This comment has been minimized.

Copy link

withremote commented Aug 14, 2012

I keep getting 500 error responses from using this api, any idea if that would be on my side or theirs?

@onassar

This comment has been minimized.

Copy link

onassar commented Aug 19, 2013

Hoping it's relevant: I created a PHP proxy/wrapper for the ruby library. It can be viewed here: https://github.com/onassar/PHP-Premailer

@tommytompkins

This comment has been minimized.

Copy link

tommytompkins commented Jan 4, 2020

Is this API still being maintained? Everything was working fine in my app for years and now I'm getting a 404 error when trying to connect to the endpoint http://premailer.dialect.ca/api/0.1/documents. Is there a new endpoint I should be using?

@Synchro

This comment has been minimized.

Copy link
Owner Author

Synchro commented Jan 5, 2020

I don't have anything to do with the hosting of that service; It wouldn't surprise me if it's stopped working as this is many years old. I would recommend switching to a local solution like emogrifier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.