DEV Community

creuser
creuser

Posted on

๐Ÿ“จ Building your Email API with Fastmail for free!

Have you ever wondered how to host an email system without paying even a single penny? Well, this blog will guide you through the process of building your own email system on Node.js with the integration of fastmail.com.

GIST: https://gist.github.com/creuserr/97a78069be7e33069f14b179d7bc3a9f

Step 1: Creating the project

You need to create a new private repository for this API service, and soon we'll be deploying it on Vercel.

The file structures must be like this:

/
โ”œโ”€โ”€ api
โ”‚   โ””โ”€โ”€ index.js
โ”‚   โ””โ”€โ”€ .env
โ””โ”€โ”€ vercel.json
Enter fullscreen mode Exit fullscreen mode

Now, we need to install nodemailer and dotenv on npm.

$ npm install dotenv
$ npm install nodemailer
Enter fullscreen mode Exit fullscreen mode

Step 2: Creating the email

Now, go ahead to https://fastmail.com and create your new email.

After that, go to Settings > Privacy & Security > Integrations > New App Password. Then, set the access to SMTP, and save the app password.

Step 3: Building the basics

In your vercel.json file, enter the following code:

{
  "version": 2,
  "builds": [{
    "src": "api/index.js",
    "use": "@vercel/node"
  }],
  "rewrites": [{
    "source": "/api/(.*)",
    "destination": "/api/index.js"
  }],
  "headers": [{
    "source": "/api/index.js",
    "headers": [{
      "key": "Access-Control-Allow-Origin",
      "value": "*"
    }, {
      "key": "Access-Control-Allow-Methods",
      "value": "POST"
    }]
  }]
}
Enter fullscreen mode Exit fullscreen mode

In your .env file, enter the following code:

EMAIL=example@fastmail.com
PASSWORD=password
Enter fullscreen mode Exit fullscreen mode

Where EMAIL is your fastmail address, and PASSWORD is the app password you generated earlier.

Step 4: Building the API

We need to import nodemailer library and initialize the environment variables.

const { createTransport } = require("nodemailer")
require("dotenv").config()
Enter fullscreen mode Exit fullscreen mode

Now, we need to handle the client request and validate it.

module.exports = (req, res) => {
  // if the client is within the server,
  // you can remove this header to
  // prevent outside access.
  res.setHeader("Access-Control-Allow-Origin", "*")
  res.setHeader("Content-Type", "text/plain")
  if(req.method != "POST") {
    return res.status(400).end("400 Bad Request: Invalid method")
  }
  if(req.body.length < 5) {
    return res.status(400).end("400 Bad Request: Body is too short (min 5)")
  }
  var reciever = req.headers["x-mail-reciever"]
  var subject = req.headers["x-mail-subject"]
  if(reciever == null || subject == null) {
    return res.status(400).end("400 Bad Request: Incomplete headers")
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, after the validation, we need to create a transport. Basically, we need to log onto the email.

const sender = process.env.EMAIL
const password = process.env.PASSWORD
try {
  var transporter = createTransport({
    host: "smtp.fastmail.com",
    port: 465,
    auth: {
      user: sender,
      pass: password
    }
  })
  const options = {
    from: sender,
    to: reciever,
    subject,
    html: req.body
  }
} catch(e) {
  res.status(500).end(`500 Internal Error: Failed to initialize transporter: ${e}`)
}
Enter fullscreen mode Exit fullscreen mode

And lastly, after logging in, we will now send the mail to reciever.

try {
  transporter.sendMail(options, function(e, i) {
    if(e) {
      res.status(400).end(`400 Bad Request: Failed to send mail: ${e}`)
    } else {
      res.status(200).end("200 Success")
    }
  })
} catch(e) {
  res.status(400).end(`400 Bad Request: Failed to send mail: ${e}`)
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Deploying the API

Now, go ahead to Vercel and deploy the API.

And congrats, you have just created your own email system!

But wait! How to use it though?

Usage

To send an email, you need to create a POST request to your API, with the following headers:

X-Mail-Subject: Lorem Ipsum Dolor Sit Amet, Consectetur
X-Mail-Reciever: johndoe@example.com
Enter fullscreen mode Exit fullscreen mode

Where X-Mail-Subject is the subject of the mal and X-Mail-Reciever is the email address you want this mail to recieve.

Moreover, the body is the content of the mail, which supports HTML.

If the API responded with 200 Success, then your mail was sent to the reciever and your API works perfectly fine.

Wait.. Where is the mail? I can't find it?
.

Disadvantages

One of the biggest disadvantage of this method is:

  1. It is considered as spam. I believe it's because we used SMTP directly without any additional credentials to tell incoming servers that our mail is not a spam.

Thank you for reading this blog! I hope you like it! Please leave me a single react or comment; I will appreciate it so much! โค๏ธ

Top comments (2)

Collapse
 
shawn2208 profile image
Shawn2208

I made similar article dev.to/shawn2208/nodejs-tutorial-h... but i just used hotmail as the host

Collapse
 
emmabase profile image
Emmanuel Eneche

Thanks for sharing ๐Ÿ‘