I built my own send-only email API, it's not that hard.

Disclaimer

This post will relate how I managed to setup my own send-only email server. I’m not an expert, it’s probably the best way to do it. It’s more like a note I wrote if I need to setup a new one later on.

💻 Server setup

System setup

I decided to use a dedicated VPS to host my mail server. The first thing I had to setup is the hostname: mail.mydomain.app

On Ubuntu, we can use the hostnamectl utility to change the hostname if we created the VPS with a wrong one.

1
hostnamectl set-hostname mail.mydomain.app

Besides to setting up the hostname, I also had to edit the /etc/hosts file, so that the email looks like it’s sent from the correct domain name.

1
2
127.0.0.1    localhost.localdomain
127.0.1.1 mail.mydomain.app

Email software

As I want to use nodejs to send emails, I decided to use the sendmail tool as its quite easy to use with the nodemailer library. Again, it might not be the best solution but 👉IT WORKS. Plus, it should be powerful enough for my small apps, I’m not willing to compete against Mailchimp.

Here’s how to install sendmail:

1
apt install sendmail

For the node library, I chose to use nodemailer.

1
2
3
4
# Install node if not already done
apt install -y nodejs npm
# Install the nodemailer library
npm i -s nodemailer

🕸 DNS setup

Before we try to send an email, we need to edit the DNS entries for our domain.

First, create a SPF record with the server ip address.

1
SPF mydomain.app v=spf1 a mx ip4:x.x.x.x ~all

Then add a MX record (some mail systems want it to be set)

1
MX mydomain.app mail.mydomain.app 10

If we really want our email to get delivered, we also need to use the DKIM signature system. This requires a private and public key. I used opendkim-tools to generate the keys. Plus, it automatically generates the TXT record, which we only have to copy/paste into the DNS config.

1
2
3
# Generate DKIM private key and TXT record
apt install opendkim-tools
opendkim-genkey -t -s default -d mydomain.app

📧 Sending emails

Once all the previous steps are done, here’s how simple it is to send an email with nodemailer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const nodemailer = require('nodemailer')
const transporter = nodemailer.createTransport({
sendmail: true
dkim: {
domainName: "mydomain.app",
keySelector: "default",
privateKey: `-----BEGIN RSA PRIVATE KEY-----.......`
}
})

var message = {
from: "MyApp<no-reply@mydomain.app>",
to: "my-email@gmail.com",
subject: "Message title",
text: "Plaintext version of the message",
html: "<p>HTML version of the message</p>"
}

transporter.sendMail(message)

💯 Checking the email score

To check that the DNS and email system setup are OK, we can use a tool called mail-tester.com. After sending an email to their system, they will give you a score between 0-10.

🎁 Bonus: the API

I built a simple API using Fastify, it allows me to send emails from any other program/server without having to use an email library from this server. It’s like using a sendgrid/mailchimp API, but for low volumes.

I won’t release the code as it’s not ready for production yet, but it’s quite simple to build such an API.