From Postmark

What an import brings over from Postmark, how it maps onto coss.com, and how to switch your code.

Start an import from the dashboard's Import page (see the overview) with a Postmark token:

  • An account token (Postmark's API Tokens page) imports domains as well, and lets you choose which server to import. coss.com reads that server's own token from Postmark on each run and never stores it.
  • A server token imports only its server, without domains.

Each import brings one server into one environment. To bring over several servers (say, production and staging), import each into its own environment.

Postmark keeps no contacts, lists or custom fields, so there are none to import.

What's imported

Not imported: layouts as templates of their own (each template gets its layout merged in), inbound rules, message streams' settings, server and account tokens, and webhooks' basic auth credentials and custom headers (coss.com signs its requests instead).

Suppressions

Suppressions of transactional and broadcast streams are imported; inbound streams are skipped:

Postmark's broadcast streams match coss.com's marketing stream.

Templates

Postmark templates use Mustachio. The import merges each template into its layout (at {{{ @content }}}) and converts it to coss.com's template language. Postmark's suggested template model, the data a template expects, tells loops from objects and text from numbers:

{{{unsubscribe_url}}} is filled on marketing sends.

A template that converts exactly is published. These are left in the draft as they were, for you to rewrite before you publish it: partials, changed delimiters, sections over an object (their fields become separate variables, shown even when the object is missing), loops inside loops, lists of plain values ({{.}}: each item becomes an object with a value field) and {{#name}} over a number (coss.com treats 0 as true).

A template keeps its Postmark alias when it is a valid coss.com alias (lower-case letters, digits, - and _; aliases are lower-cased). One without an alias gets one made from its name.

Webhooks

Each webhook becomes an endpoint subscribed to the coss.com events its enabled triggers map to:

Postmark's webhooks belong to a message stream; coss.com's endpoints get the whole environment's events. The server's inbound webhook becomes an endpoint for email.received, which carries the message's details, not the whole message (fetch it through the API); mail reaches it once you set up receiving.

The payloads differ from Postmark's, and requests are signed with the endpoint's new secret, so update your handler before you enable an endpoint (see verifying requests).

Domains and DNS

coss.com's records (DKIM CNAMEs and the send subdomain for bounces) don't collide with Postmark's (…pm._domainkey and the pm-bounces Return-Path). Add them and keep sending through Postmark while they verify.

Switch your code

A template send with the postmark library:

await client.sendEmailWithTemplate({
  From: "hello@acme.com",
  To: "ada@example.com",
  TemplateAlias: "welcome",
  TemplateModel: { name: "Ada", company: { name: "Acme" } },
  MessageStream: "outbound",
});

On coss.com, the template keeps its alias and nested data uses the renamed variables. coss.com returns errors instead of throwing them:

const { ,  } = await ..({
  : "hello@acme.com",
  : "ada@example.com",
  : "welcome",
  : { : "Ada", : "Acme" },
});

For a broadcast stream, send with stream: "marketing": marketing email goes to one recipient per send and needs your postal address.