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
Now, we need to install nodemailer and dotenv on npm.
$ npm install dotenv
$ npm install nodemailer
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"
}]
}]
}
In your .env
file, enter the following code:
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.
const { createTransport } = require("nodemailer")
require("dotenv").config()
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")
}
}
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}`)
}
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}`)
}
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
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:
- 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! ❤️