WireMailPostmarkApp by NB Communication

Extends WireMail to use the Postmark API for sending emails.

WireMail Postmark API

Extends WireMail to use the Postmark API for sending emails.

Installation

  1. Download the zip file at Github or clone the repo into your site/modules directory.
  2. If you downloaded the zip file, extract it in your sites/modules directory.
  3. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module.

API

Prior to using this module, you must set up a server in your Postmark account and create an API Token. You should also set up a Sender Signature. Add the API Token and Sender Signature to the module configuration.

Usage


Usage is similar to the basic WireMail implementation, although a few extra options are available. Please refer to the WireMail documentation for full instructions on using WireMail, and to the examples below.

Extra Methods


The following are extra methods implemented by this module:

Chainable

The following methods can be used in a chained statement:

setSenderSignature(string $senderSignature) - Set a different sender signature than the default.

  • Must use a registered and confirmed Sender Signature.
  • To include a name, use the format "Full Name <sender@domain.com>" for the address.

cc(string|array|null $email) - Set a "cc" email address.

  • Only used when $sendBatch is set to false.
  • Please refer to WireMail::to() for more information on how to use this method.

bcc(string|array|null $email) - Set a "bcc" email address.

  • Only used when $sendBatch is set to false.
  • Please refer to WireMail::to() for more information on how to use this method.

attachInlineImage(string $file, string $filename) - Add an inline image for referencing in HTML.

  • Reference using "cid:" e.g. <img src="https://raw.githubusercontent.com/nbcommunication/WireMailPostmarkApp/main/cid:filename.ext'>

setTag(string $tag) - Set the email tag.

setTrackOpens(bool $trackOpens) - Override "Track opens" module setting on a per-email basis.

  • Disabled automatically for 'Forgot Password' emails from ProcessWire

setTrackLinks(bool $trackLinks) - Override "Track links" module setting on a per-email basis.

  • Disabled automatically for 'Forgot Password' emails from ProcessWire

setMetaData(string|array $key, string $value = '') - Add custom metadata to the email.

setMessageStream(string $messageStream) - Set the message stream.

setSendBatch(bool $sendBatch) - Set the batch mode.

  • This is off by default, meaning that a single email is sent with each recipient seeing the other recipients
  • If this is on, any email addresses set by cc() and bcc() will be ignored
  • Postmark has a limit on 50 email addresses per message and 500 messages per batch request. This module will split the recipients into batches if necessary and will also split up batches of messages too.

setRecipientVariables(array $variables, string $email = '') - Set the recipient variables

  • $variables should be an array of data keyed by the recipient email address, or specific for a recipient specified by $email.
  • Variables are only used when either $sendBatch or a template is being used.

setTemplate(string $template, array $variables = [], bool $inlineCss = true) - Set the template alias or id

  • You can set template variables by passing an array to $variables.
  • You can toggle the $inlineCss setting. More information

setTemplateVariables(array $variables) - Set the template variables.

  • These are variables shared by each recipient's message

Other

getClient() - Return the Postmark client.

  • For more details please see the documentation for postmark-php.

getResponse(int $index = null) - Return the last send() response

  • Returns a Postmark\Models\DynamicResponseModel object.
  • Pass an $index if you want to get a specific response from a batch send.

getResponses() - Return the last batch send() responses

  • Returns an array of Postmark\Models\DynamicResponseModel objects.

send() - Send the email.

  • Returns a positive number (indicating number of emails sent) or 0 on failure.

Examples


Basic Example

Send an email:

$postmark = $mail->new();
$sent = $postmark->to('user@domain.com')
	->from('you@company.com')
	->subject('Message Subject')
	->body('Message Body')
	->send();

Advanced Example

Send an email using all supported WireMail methods and extra methods implemented by WireMailPostmarkApp:

$postmark = $mail->new();

// WireMail methods
$postmark->to([
		'user@domain.com' => 'A User',
		'user2@domain.com' => 'Another User',
	])
	->from('you@company.com', 'Company Name')
	->replyTo('reply@company.com', 'Company Name')
	->subject('Message Subject')
	->bodyHTML(
		'<p>Message Body with variables: {{name}} = {{toName}} <{{toEmail}}> ({{key3}})</p>' .
		'<img src="https://raw.githubusercontent.com/nbcommunication/WireMailPostmarkApp/main/cid:filename-inline.jpg">'
	) // A text version will be automatically created
	->header('key1', 'value1')
	->headers(['key2' => 'value2'])
	->attachment('/path/to/file.ext', 'filename.ext');

// WireMailPostmarkApp methods
$postmark->setSenderSignature('Alternate <another@company.com>') // Use a different Sender Signature
	->cc('cc@domain.com')
	->bcc(['bcc@domain.com', 'bcc2@domain.com'])
	->attachInlineImage('/path/to/file-inline.jpg', 'filename-inline.jpg') // Add inline image
	->setTag('tag1') // Set the tag
	->setTrackOpens(false) // Disable tracking opens
	->setTrackLinks(false)  // Disable tracking clicks
	->setMetaData('key1', 'value1') // Custom metadata
	->setMetaData(['key2' => 'value2']) // Custom metadata as array
	->setMessageStream('outbound') // The stream to use
	->setSendBatch(false) // A single email will be sent, both 'to' recipients shown
	->setRecipientVariables([
		'user@domain.com' => [
			'name' => 'user',
		],
		'user2@domain.com' => [
			'name' => 'user2',
		]
	]) // variables for each of the 'to' addresses
	->setTemplate('template1') // The template to use
	->setTemplateVariables(['key3' => 'value3']); // Set template variables


// Batch mode is set to false, so 1 returned if successful
$numSent = $postmark->send();

echo 'The email was ' . ($numSent ? '' : 'not ') . 'sent.';

Sending in Batch Mode

// If using batch mode, the recipient variable 'toName' is inferred from the `to` addresses, e.g.
$postmark = $mail->new();
$postmark->to([
		'user@domain.com' => 'A User',
		'user2@domain.com' => 'Another User',
	])
	->setSendBatch(true)
	->subject('Message Subject')
	->bodyHTML('<p>Dear {{toName}},</p>')
	->send();

// to =
// A User <user@domain.com>
// Another User <user2@domain.com>
//
// recipientVariables =
// {
//		"user@domain.com": {
//			"toName": "A User",
//			"toEmail": "user@domain.com"
//		},
//		"user2@domain.com": {
//			"toName": "Another User",
//			"toEmail": "user2@domain.com"
//		}
// }
//
// bodyHTML[user@domain.com] =
// <p>Dear A User,</p>
// bodyHTML[user2@domain.com] =
// <p>Dear Another User,</p>

// You can also use `setRecipientVariables()` to extend/override the inferred `recipientVariables` e.g.
$postmark = $mail->new();
$postmark->to([
		'user@domain.com' => 'A User',
		'user2@domain.com' => 'Another User',
	])
	->setRecipientVariables([
		'user@domain.com' => [
			'title' => 'A User (title)',
		],
		'user2@domain.com' => [
			'toName' => 'Another User (changed name)',
			'title' => 'Another User (title)',
		],
	])
	->setSendBatch(true)
	->subject('Message Subject')
	->bodyHTML('<p>Dear {{toName}},</p><p>Title: {{title}}!</p>')
	->send();

// to =
// A User <user@domain.com>
// Another User <user2@domain.com>
//
// recipientVariables =
// {
//		"user@domain.com": {
//			"toName": "A User",
//			"toEmail": "user@domain.com",
//			"title": "A User (title)"
//		},
//		"user@domain.com": {
//			"toName": "Another User (changed name)",
//			"toEmail": "user2@domain.com",
//			"title": "Another User (title)"
//		}
// }
//
// bodyHTML[user@domain.com] =
// <p>Dear A User,</p><p>Title: A User (title)!</p>
// bodyHTML[user2@domain.com] =
// <p>Dear Another User (changed name),</p><p>Title: Another User (title)!</p>

Sending with a template

How you set up your templates and layouts in Postmark is up to you, and this will determine which variables you pass to Postmark. This module provides some defaults however. Alongside toName and toEmail, if a body or bodyHTML is set, these variables are also passed when using a template. The module will also attempt to replace any tags in these values with template/recipient variables. Hopefully the example below will demonstrate this:

$postmark = $mail->new();
$postmark->to('user@example.com, user2@example.com')
	->setTemplate('template1')
	->setTemplateVariables([
		'siteUrl' => $pages->get(1)->httpUrl, // https://www.example.com/
		'test' => 123,
	])
	->setRecipientVariables([
		'user@example.com' => [
			'name' => 'User',
			'toName' => 'User',
		],
		'user2@example.com' => [
			'name' => 'User 2',
			'test' => 456,
		],
	])
	->bodyHTML(
		'<p>Dear {{name}}</p>' .
		'<p>This email was sent to {{toName}} <{{toEmail}}> from {{siteUrl}}.</p>' .
		'<p>{{test}}</p>'
	)
	->send();

The template subject:

Message from {{name}} on {{siteUrl}}

The HTML template (template1):

<table>
	<tr>
		<td>{{{bodyHTML}}}</td>
	</tr>
</table>

Note the three curly braces being used - this prevents the value from being entity encoded (e.g. allows you to use HTML).

The Text template (template1)

{{body}}

The two HTML emails sent:

<!-- To: user@example.com -->
<!-- Subject: Message from User on https://www.example.com/ -->
<table>
	<tr>
		<td>
			<p>Dear User</p>
			<p>This email was sent to User <user@example.com> from https://www.example.com/.</p>
			<p>123</p>
		</td>
	</tr>
</table>

<!-- To: user2@example.com -->
<!-- Subject: Message from User 2 on https://www.example.com/ -->
<table>
	<tr>
		<td>
			<p>Dear User 2</p>
			<p>This email was sent to  <user2@example.com> from https://www.example.com/.</p>
			<p>456</p>
		</td>
	</tr>
</table>

Using postmark-php for extended integration

$postmarkClient = $modules->get('WireMailPostmarkApp')->getClient();
$postmarkClient->getOpenStatistics();

Setting WireMailPostmarkApp as default


If WireMailPostmarkApp is the only WireMail module you have installed, then you can skip this step. However, if you have multiple WireMail modules installed, and you want WireMailPostmarkApp to be the default one used by ProcessWire, then you should add the following to your /site/config.php file:

$config->wireMail('module', 'WireMailPostmarkApp');

Install and use modules at your own risk. Always have a site and database backup before installing new modules.

Latest news

  • ProcessWire Weekly #524
    In the 524th issue of ProcessWire Weekly we'll check out what's new in the core this week, introduce a new module called SEO Text Width, and more. Read on!
    Weekly.pw / 25 May 2024
  • ProFields Table Field with Actions support
    This week we have some updates for the ProFields table field (FieldtypeTable). These updates are primarily focused on adding new tools for the editor to facilitate input and management of content in a table field.
    Blog / 12 April 2024
  • Subscribe to weekly ProcessWire news

“I am currently managing a ProcessWire site with 2 million+ pages. It’s admirably fast, and much, much faster than any other CMS we tested.” —Nickie, Web developer