Header Image Sending and receiving email in Node.js and TypeScript in 2021 with CloudMailin

Sending and Receiving Email in Node.js and TypeScript in 2021

In this article, we'll cover a couple of ways to send email in Node.js and TypeScript. Following this we'll outline a quick and easy way to receive email with CloudMailin.

To get some SMTP credentials to send and receive emails, you can signup for a free CloudMailin account.

Sending email with Nodemailer via SMTP

Nodemailer provides a great library to get started sending email with Node.js. We'll start by installing Nodemailer using NPM.

npm install --save nodemailer

Nodemailer doesn't have TypeScript types by default. If you're using TypeScript we'll need to install the types from the DefinitelyTyped repo:

npm install --save @types/nodemailer

Installing the package will provide the expected types for Nodemailer. We're going to write all of the examples in TypeScript. However, it should be relatively clear how to use Javascript instead if required.

Creating a transport

Once we've added Nodemailer to our Node.js app we can use the following to setup the SMTP transport:

import nodemailer from "nodemailer";
import Mail from "nodemailer/lib/mailer";
// const nodemailer = require("nodemailer");

async function main() {
  const = "hostname from account page";
  const = "username from account page";
  const = "password from account page";

  const transporter = nodemailer.createTransport({
    host: hostname,
    port: 587,
    secure: false,
    requireTLS: true,
    auth: {
      user: username,
      pass: password,
    },
    logger: true
  });

Here we imported Nodemailer but also the Mail type so that we can make use of types later.

Currently, most email servers use the STARTTLS command rather than a specific port for secure connections. In order to make sure that nodemailer calls STARTTLS we need to set secure: false and requireTLS: true. This means that we open the connection in Plain text and immediately upgrade to a more secure TLS connection. We've also set the hostname and port and enabled the logger to help to debug any issues.

Sending the email

Once we've created our SMTP transport, we can actually send an email from our Node application using the following:

  // send mail with defined transport object
  const info = await transporter.sendMail({
    from: '"Sender Name" <from@example.net>',
    to: "to@example.com",
    subject: "Hello from node",
    text: "Hello world?",
    html: "<strong>Hello world?</strong>",
    headers: { 'x-myheader': 'test header' }
  });

  console.log("Message sent: %s", info.response);
}

The above code constructs an email with both a Plain and HTML part and sets the subject. Additional headers can be specified using the headers parameter, which we use here to set x-cloudmta-class to standard.

This code prints the SMTP response (the output from the call) to the console once finished. That's it! We've just sent our first Hello World email over SMTP.

Sending email via the CloudMailin API

SMTP has a number of benefits. However, it's a pretty verbose protocol. It's not unheard of, even when two systems are on the same network, for communication to take a second or two.

In order to send an email, the typical communication will take at least 6 commands, which then sit waiting for a response from the server before continuing. CloudMailin allows us to be much more performant than this. With CloudMailin we can send an email directly via an HTTP API.

Installing the CloudMailin Package

To get started with the HTTP API to send email we can use the CloudMailin NPM package.

npm install --save cloudmailin

With the package installed we need to create a client with the username and apiToken (password) in a similar manner to setting the Nodemailer transport.

import { MessageClient } from "cloudmailin"

const client = new MessageClient({ username: USERNAME, apiKey: API_KEY});
const response = await client.sendMessage({
  from: '"Sender Name" <from@example.net>',
  to: "to@example.com",
  subject: "Hello from node",
  plain: "Hello world?",
  html: "<strong>Hello world?</strong>",
  headers: { 'x-myheader': 'test header' }
  attachments: [
    {
      "file_name": "pixel.png",
      "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP0rdr1HwAFHwKCk87e6gAAAABJRU5ErkJggg==",
      "content_type": "image/png"
    }
  ]
});

Note: We've changed text for plain here compared to the SMTP example above. Although the CloudMailin and Nodemailer packages have a similar form, the CloudMailin parameters are named after our long-established inbound email. We also added an attachment this time. The content field is simply a Base64 encoded string with the content of a single-pixel png image (in CloudMailin blue).

That's it! Sending via the API is faster and we can see all of the details of the sent message in the returned JSON. The sendMessage function returns a promise with all the details. You can also see the details of the message within the CloudMailin dashboard.

Outbound Summary Dashboard

Receiving Email

CloudMailin also makes it super easy to receive email in TypeScript with our new NPM package too.

npm install --save cloudmailin

With the package installed we get all of the types needed. Since CloudMailin sends emails to Web applications via HTTP POST we're going to give this example using express:

import express from "express";
import bodyParser from "body-parser";
import { IncomingMail } from "cloudmailin";
import fs from "fs";

const app = express();

app.use(bodyParser.json());

app.post("/incoming_mails/", (req, res) => {
  const mail = <InboundPOST>req.body;

  const body = mail.html || mail.plain;
  console.log(body)

  const attachment = mail.attachments[0];

  if (attachment.content) {
    const data: Buffer = Buffer.from(attachment.content, 'base64');
    fs.writeFileSync(attachment.file_name, data);

    return res.status(201).json({ status: `wrote ${attachment.file_name}` });
  }

  res.status(422).json({ status: "Content passed" });
});

app.listen(80, "0.0.0.0", () => {
  console.log(`server started http://0.0.0.0:80`);
});

This example receives the message body and writes the first attachment to disk. This gives a taster of the options. More details are available in the CloudMailin Node Documentation. Again, you can access all of the details on the dashboard too.

2021-03-12
CloudMailin Team