How to send emails with Keystone
We often had to send emails in our Keystone projects, so we figured we
might as well make that easier. With the standalone
keystone-email
package, containing Mailgun
and Mandrill integrations, you’ll be sending emails in less than 5
minutes!
Setup
- Install the
keystone-email package
in your project with
npm install keystone-email --save
That’s everything there is to it from the Keystone side!
You will need a Mailgun account to be able to send emails though. (Mailgun gives you 10000 emails/month for free!) Let’s create that:
- Sign up on mailgun.com
- When you’ve created the account you should see a message saying “You’re signed up and we just created your sandbox server xyz.mailgun.org”. Copy the link to your sandbox to a safe place, we’ll use it soon!
- Click on “authorized recipients” on that page and invite yourself with your own email as an authorized recipient
- Activate your account and agree to be an authorized recipient in the two emails Mailgun sent you
- Go to your dashboard, click on your name in the top right corner and show and copy your private API key and store it next to the sandbox URL, we’ll need that too!
Note: You can also use Mandrill with
keystone-email
, but since it has no free tier we’ll skip it for this guide, see thekeystone-email
docs for more information!
Now we’re all setup to start sending emails!
Sending your first email
For exemplary purposes, create a test-email.js
file in the root of
your project and require keystone-email
:
// test-email.js
var Email = require('keystone-email');
keystone-email
uses templates. You can use whatever templating engine
you prefer (set it via the engine
option) but for this guide we’ll be
using pug
! (formerly called jade
)
Create another file in the root folder called test-email.pug
and fill
it with this content:
<!-- test-email.pug -->
doctype html
html(lang="en")
head
body
h1 Your first email sent with Keystone!
p Congratulations on sending your first email with Keystone
Nothing fancy, a simple heading and paragraph for now.
Let’s swap back to our test-email.js
file and tell keystone-email
which template we want to use. We pass that in as the first argument to
new Email()
:
// test-email.js
var Email = require('keystone-email');
new Email('test-email.pug', {});
In the second argument, the email options, we tell it we want to use
Mailgun as the email transport mechanism by setting transport
to
mailgun
(surprisingly!):
// test-email.js
var Email = require('keystone-email');
new Email('test-email.pug', {
transport: 'mailgun',
});
This won’t actually send
the email though! (how should it, we haven’t
told Keystone where to send the email to yet!)
When called, Email
returns a send
function that you can use to
actually send an email with the specified template. It takes three
arguments: the locals
(the data that goes into the template), the
senderOptions
(where to send the email to/from, the subject, the
mailgun options,…) and as the last argument a callback.
Since we don’t have any data in our template yet, we’ll simply set the
locals
to an empty object:
// test-email.js
var Email = require('keystone-email');
new Email('test-email.pug', {
transport: 'mailgun',
}).send({});
The senderOptions
are the meat of this function call. We need to tell
keystone-email
where to send the email to
, where it should pretend
to come from
, what the subject
is and finally the Mailgun API
details and sandbox url:
// test-email.js
var Email = require('keystone-email');
new Email('test-email.pug', {
transport: 'mailgun',
}).send({}, {
apiKey: 'YOURAPIKEYHERE',
domain: 'sandox123asdf234YOURSANDBOX.mailgun.com',
to: 'yourauthorizedrecipient@email.here',
from: {
name: 'Your Site',
email: 'hello@yoursite.com',
},
subject: 'Your first KeystoneJS email',
});
If you tried to run this, it would already work! 🎉 Let’s add a callback though, to make sure we get errors logged if something goes wrong or a message logged if it goes right:
// test-email.js
var Email = require('keystone-email');
new Email('test-email.pug', {
transport: 'mailgun',
}).send({}, {
apiKey: 'YOURAPIKEYHERE',
domain: 'sandox123asdf234YOURSANDBOX.mailgun.com',
to: 'yourauthorizedrecipient@email.here',
from: {
name: 'Your Site',
email: 'hello@yoursite.com',
},
subject: 'Your first KeystoneJS email',
}, function (err, result) {
if (err) {
console.error('🤕 Mailgun test failed with error:\n', err);
} else {
console.log('📬 Successfully sent Mailgun test with result:\n', result);
}
});
Now run this file with node test-email.js
, and you should see this
logged in your console:
📬 Successfully sent Mailgun test with result
{ id: '<somelongid@sandboxsomestuffhere.mailgun.org>',
message: 'Queued. Thank you.'
Go check your inbox! Congratulations, you just sent your first email
with keystone-email
!
Inserting locals
In a real world scenario you will almost always want to pass data into your templates, for example to say hi to your users by name. Let’s do exactly that!
First, adapt your template to accept data. In Pug you use locals
with the #{ recipient.variable }
syntax. Change test-email.pug
to have this
content:
<!-- test-email.pug -->
doctype html
html(lang="en")
head
body
h1 Hi %recipient.firstName% this is your second email sent with Keystone!
p This is your full name: %recipient.firstName% %recipient.name%
As you can see above, we need to pass firstName
and name
to our
template via the locals option. Go back to test-email.js
and take a
look at the Email(...).send()
call we do:
new Email(/* ... */).send({}, {/* ... */}, function (err, result) {/* ... */});
See that empty first argument? Specify your first name and your last name in there like so:
new Email(/* ... */).send({
firstName: 'Max',
name: 'Stoiber',
}, {/* ... */}, function (err, result) {/* ... */});
Now send another email with node test-email.js
! This is the text you
should see once you’ve received it:
Hi Max, this is your second email sent with Keystone!
Let's hope that this is your first and last name: Max Stoiber
(replacing Max
and Stoiber
with your first and last names
respectively)
Amazing, that wasn’t too hard, huh? We’ve successfully sent a personalized email!
Now go ahead and add emails to your app!