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 (2)
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!
Thank you so much, the documents are not really that clear about everything and this kind of content is what new developers like me need the most!