SkillAgentSearch skills...

Campaign

:love_letter: Compose responsive email templates easily, fill them with models, and send them out.

Install / Use

/learn @bevacqua/Campaign
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

![campaign.png][9]

Compose responsive email templates easily, fill them with models, and send them out.

This is the stuff responsible for sending beautiful emails in [Pony Foo][3]. I've isolated that code, and turned it into a reusable package, called campaign. It comes with a dead simple API, and a beautiful responsive layout, [originally written by MailChimp][7], adapted by me. It's also easily configurable, and comes with nice conventions over configuration, so you don't need to do a lot to get going.

Being highly configurable is important to campaign, and for that reason it ships with several plugins to popular view engines: campaign-mustache, campaign-jade, and campaign-jadum. You can use any of these to manage your email templates. Typically, you'll want to use the same templating engine you use in your front-end views, for consistency across your codebase.

Campaign can send emails through a variety of services using different plugins as well. You could also create your own email service provider plugin.

  • [campaign-mailgun][16] sends emails through mailgun
  • [campaign-terminal][19] renders emails as Terminal-friendly Markdown in your terminal for convenient debugging
  • [campaign-nodemailer][20] sends emails through nodemailer
  • [campaign-mandrill][21] sends emails through mandrill-api
  • [campaign-sparkpost][27] sends emails through sparkpost

Reference

Quick links for reference.

Features

  • Extensible. Pick a template engine and an email-sending service or SMTP and roll with it
  • Takes care of boring stuff: CSS inlining, @media queries, JSON-LD, plain-text versions of your HTML
  • Takes care of important stuff: batching requests, providing a sane API, view layouts, etc.
  • Provides debugging facilities for sending test emails and capturing output in a terminal session

Getting Started

Install using npm.

npm i --save campaign

Set it up.

Construct a client.

var client = require('campaign')({
  templateEngine: require('campaign-jade'),
  provider: require('campaign-mailgun')({
    apiKey: 'key-12rvasxx'
  })
});

Send emails!

client.send(template, options, done);
client.sendString('<p>{{something}}</p>', options, done);

<sub>(detailed information below)</sub>

Screenshot

Here is a screenshot of an email sent using this library, as seen on [Pony Foo][3] subscriptions, in production. This email is using the default layout provided by campaign.

![sample.png][8]

Client Options

There's a few configurable options, here's an overview of the default values.

{
  "from": null,
  "provider": null,
  "templateEngine": null,
  "layout": null,
  "formatting": null,
  "headerImage": null,
  "trap": false
}

from

The from address for our emails. The provider is responsible for trying to make it look like that's the send address. Not necessarily used for authentication.

provider

You can pick any supported email providers, creating your own or choosing one that comes with campaign. To implement a provider yourself, you'll need to create a custom provider object. The provider object should have a send function, which takes a model, and a done callback. You can read more about custom providers below.

Available providers listed below.

  • [campaign-mailgun][16]
  • [campaign-terminal][19]
  • [campaign-nodemailer][20]
  • [campaign-mandrill][21]
  • [campaign-sparkpost][27]

templateEngine

You can use other template engines, creating your own. You'll need to create a custom engine object with both render and renderString methods. Note that template engines govern the default layouts. If you implement your own engine, you'll have to provide a default layout, as well.

Available engines listed below.

  • [campaign-jadum][18]
  • [campaign-jade][14]
  • [campaign-mustache][17]

layout

The layout used in your emails. Templates for email sending are meant to have the bare minimum needed to fill out an email. Since you want a consistent UX, the same layout should be used for every email your product sends.

A default layout template is provided by supporting template engines. You can provide a different one, just set layout to the absolute path of a template file that's supported by your template engine. For information about the model passed to the layout, see the Templates section.

formatting

When you want to customize HTML before submission, but after your template engine and layout have been rendered into a single piece of HTML, you can use the formatting option. Useful for tweaking CSS or markup in a global manner for all emails without having to touch the models every time.

function formatting (html) {
  return change(html);
}

headerImage

You may provide the full path to an image. This image will be encoded in base64 and embedded into the email as a heading. Embedding helps people view your emails offline.

This image should have a 3:1ish ratio. For instance, I use 600x180 in [my blog][3]'s emails.

trap

If true, then emails won't be sent to any recipients at all. You could also set trap to nico@bevacqua.io, and all emails would be sent to me instead of the intended recipients. Great for spamming me, and also great for testing.

When you trap recipients, the email will get a nifty JSON at the end detailing the actual recipients that would've gotten it.

Email Sending Options

Once you've created a client, you can start sending emails. Here are the default options, and what you need to fill out. The from and trap fields are inherited from the configuration object passed to campaign, and they can be overridden on an email-by-email basis.

{
  "subject": "<not provided>",
  "teaser": "<options.subject>",
  "from": "<campaign.from>",
  "trap": "<campaign.trap>",
  "to": "<not provided>",
  "when": "YYYY/MM/DD HH:mm, UTC Z",
  "images": "<empty>",
  "attachments": "<empty>",
  "social": {
    "twitter": "<not provided>",
    "landing": "<not provided>",
    "name": "<not provided>"
  },
  "provider": {
    "tags": "<not provided>",
    "merge": "<not provided>"
  },
  "styles": "<defaults>"
}

.send vs .sendString

The only difference between .send and .sendString is that .send takes the path to a file, rather than the template itself. .send compiles the template and keeps it in a cache, while .sendString compiles the template every time.

You can also use .render or .renderString as the equivalents to both of these methods that will only render the emails as HTML. This is useful for debugging and to render emails identically to what your customers see, but handle the rendering logic yourself.

subject

The email subject.

teaser

This is the line that most email clients show as a teaser for the email message. It defaults to the subject line. Changing it is extremely encouraged.

to

These are the recipients of the email you're sending. Simply provide a single recipient's email address, or an array of email addresses.

when

Here you can pass a moment [format string][15]. Eg. '[um] HH:mm [am] DD.MM.YYYY'. The default format passed to moment is 'YYYY/MM/DD HH:mm, UTC Z'.

attachments

A list of files you'd like to attach to your emails.

[
  { name: 'invoice', file: path.join(__dirname, 'invoice.png') }
]

images

If you want to provide the template with embedded images (other than the optional email header when creating the campaign client) you can set images to a list of file paths and names (to later reference them in your templates), as shown below.

[
  { name: 'housing', file: path.join(__dirname, 'housing.png') }
]

Instead of a file you can provide a data value with the base64 encoded data, and avoid the overhead of creating a temporary file. If you choose this approach you must set the mime property as well.

[
  { name: 'housing', mime: 'image/png', data: buff.toString('base64') }
]

social

Social metadata used when sending an email can help build your brand. You can provide a twitter handle, a name for your brand, and a landing page.

The name is used as the name of the send address, as well as in the "Visit <name>" link.

provider

Configuration specifically used by the email-sending provider.

Many email providers allow you to add dynamic content to your templates. For instance, the feature is supported by both the [campaign-mailgun][16] and the [campaign-mandrill][21] providers, out the box. Read more about [merge variables][4] in Mandrill.

provider.merge

Providers have wildly different merge API in terms of how they want you to give them these recipient-specific variables and how you can reference them in your templates. Campaign helps by providing a reasonable API and then deals with obscure provider data formats under the hood, so you don't have to.

The following example shows merge variables for a couple emails and defaults that are used when a particular recipient doesn't have a value for a given variable.

{
  "someone@accounting.is": {
    "something": "is a merge variable for the guy with that email"
  },
  "someone.else@accounting.is": {
    "here": "is a merge variable for another peep"
  },
  "*": {
    "whatever": "is a merge variable for everyone, useful for defaults"
  }
}

In your email templates, you can reference these variables simply using {{something}}

View on GitHub
GitHub Stars646
CategoryDevelopment
Updated4d ago
Forks38

Languages

JavaScript

Security Score

95/100

Audited on Mar 23, 2026

No findings