📨 Building your Email API with Fastmail for free!
Tags: node, opensource, tutorial, api
Published: 2024-03-01 09:57:26

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](https://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
```

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

### Step 2: Creating the email

Now, go ahead to [https://fastmail.com](fastmail) 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:
```json
{
  "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"
    }]
  }]
}
```

In your `.env` file, enter the following code:
```env
EMAIL=example@fastmail.com
PASSWORD=password
```

*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.
```javascript
const { createTransport } = require("nodemailer")
require("dotenv").config()
```

Now, we need to handle the client request and validate it.
```javascript
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")
  }
}
```

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

```javascript
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}`)
}
```

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

```javascript
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}`)
}
```

### 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:
```http
X-Mail-Subject: Lorem Ipsum Dolor Sit Amet, Consectetur
X-Mail-Reciever: johndoe@example.com
```

*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! ❤️