Introduction
Sending emails from NodeJS with Nodemailer is easy. In this guide, we'll explore how to set up and use Nodemailer with Gmail APIs to send emails effortlessly.
Essentials
- A
MERN
stack or aNextJS
app. - A verified Google account that can use Google Developer features.
- This guide demonstrates using typescript, but the same thing can be built in JavaScript just by removing type declarations.
Google Application Setup
- Go to Google Cloud Console.
- Click on create a new project.
- Select the organization and click on Create Project.
- Select the recently made project from the above corner.
- Go to
APIs and Services
and selectEnabled APIs and Services
from the left panel. - Search for Gmail API and enable it.
- Go to the Credentials Screen from the left bar, and click on the
Configure Consent
button.
- Select the Internal user type
- Fill in the required details.
- Make sure that you have a
png
of your120x120
logo. - Add the scope for sending emails on your behalf:
auth/gmail.send
- In the next screen, click Create and click on Go to Dashboard
- In credentials screening, click on Create credentials.
- Select a web application.
- Enter the details.
- Make sure to add the deployment link and localhost link in URIs.
- For redirect URIs, make sure to add Google OAuthPlayground
- Click on Create
- Make sure to download the JSON for the credentials.
- Now go to the Google OAuthPlayground
- In the top right, press the gear icon and check the
Use your own OAuth credentials
button. - Paste the client ID and secret in it.
- Now search for https://mail.google.com in the left search and after selecting that, click on Authorize APIs.
- Allow the application to access.
- After redirecting back to the playground, select the
Exchange authorization code for tokens
button. - Copy the refresh token for later.
Writing the code
Install nodemailer
and googleapis
packages.
Note: While working with typescript, don't forget to install @types/nodemailer
package too.
Export the credentials stored in .env
file.
GOOGLE_CLIENT_ID="your client id"
GOOGLE_CLIENT_SECRET="your client secret"
GOOGLE_REFRESH_TOKEN="your refresh token"
GOOGLE_REDIRECT_URI="https://developers.google.com/oauthplayground"
GOOGLE_EMAIL="your email"
type GOOGLE_MAIL_SERVICE_KEYS =
| "clientId"
| "clientSecret"
| "refreshToken"
| "redirectUri"
| "email";
export const googleEmailConfig: Record<GOOGLE_MAIL_SERVICE_KEYS, string> = {
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
refreshToken: process.env.GOOGLE_REFRESH_TOKEN || "",
redirectUri: process.env.GOOGLE_REDIRECT_URI || "",
email: process.env.GOOGLE_EMAIL || "",
};
Configuring OAuth client
Create a file services/gauth.ts
and export the OAuthClient
from it.
import { google } from "googleapis";
const OAuth2 = google.auth.OAuth2;
const id = googleEmailConfig.clientId;
const secret = googleEmailConfig.clientSecret;
const myOAuth2Client = new OAuth2(id, secret);
export default myOAuth2Client;
Creating email service
Create a service (services/email.ts
) for sending email by configuring SMTP transport with Nodemailer, OAuth client, and your application's configurations.
- Get the access token from your OAuth client after providing the refresh token.
- Use the
createTransport
service fromnodemailer
to create your SMTP transport with your Google config. - Create an object with
from
,to
, thesubject
of the mail, and the body of the mail as HTML. - Use the
smtpTransport
to send the mail.
import { createTransport } from "nodemailer";
export const sendEmailService = async (
to: string,
subject: string,
html: string
) => {
try {
myOAuth2Client.setCredentials({
refresh_token: googleEmailConfig.refreshToken,
});
const accessToken = await myOAuth2Client.getAccessToken();
const transportOptions: any = {
service: "gmail",
auth: {
type: "OAuth2",
user: googleEmailConfig.email,
clientId: googleEmailConfig.clientId,
refreshToken: googleEmailConfig.refreshToken,
accessToken: accessToken.token,
},
};
const smtpTransport = createTransport(transportOptions);
const mailOptions = {
from: {
name: "Your application name",
address: googleEmailConfig.email,
},
to,
subject,
html,
};
await smtpTransport.sendMail(mailOptions);
} catch (error: any) {
console.error(error);
}
};
Create a utility (utils/email.ts
) for sending emails with this sendEmailService
.
export const getEmailHTML = (title: string, subtitle: string): string => `<html>
<head>
<title>${title}</title>
</head>
<body>
<h1>${title}</h1>
<p>${subtitle}</p>
</body>
</html>`;
export const sendEmail = async (to: string, subject: string) => {
const html = getEmailHTML(subject, "This is a test email");
await sendEmailService(to, subject, html);
};
That's it, your email service is configured successfully.
Testing out
Create a temporary API route and call a controller with another email to check this route.
- Add the recipient email, in this case, your email (different from the email with which you configured the mailing service).
- Use the
sendMail
utility with this email and a test subject to send the email.
export const sendMailApi = async (req: NextApiRequest, res: NextApiResponse) => {
try {
const to = "test@example.com";
const subject = "Test email";
await sendEmail(to, subject);
return res.status(200).json({ message: "Email sent successfully" });
} catch (error) {
console.error();
return res.status(500).json({ error: RESPONSE_MESSAGES.SERVER_ERROR });
}
};
Call this into your API route and test it by hitting the route.
If you are using ExpressJS
:
router.get("/api/v1/email", sendMailApi);
For NextJS API routes:
import { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
const handler: NextApiHandler = async (
req: NextApiRequest,
res: NextApiResponse
) => {
if (req.method === "GET") {
return sendMailApi(req, res);
}
return res
.status(405)
.json({ message: Method </span><span class="p">${</span><span class="nx">method</span><span class="p">}</span><span class="s2"> Not Allowed
});
};
export default handler;
Conclusion
This article demonstrates the use of Google Mailing service and Nodemailer.
Questions and feedback are most welcome. 😊
Top comments (1)
This is a really great way to add emailing to a website: I was doing this using the OAuth playground for some time. However, recently I learned that Google has the ability to create app passwords for an email account. If you have 2-Step Verification enabled on the email account you're sending from, you can use an app password without having to setup anything in Google Cloud!