Skip to content

Instantly share code, notes, and snippets.

Created June 15, 2021 13:28
Show Gist options
  • Save unclebay143/d21748097ab04cbad551508f79d538d4 to your computer and use it in GitHub Desktop.
Save unclebay143/d21748097ab04cbad551508f79d538d4 to your computer and use it in GitHub Desktop.
// Import express into our project
const express = require("express");
// Import multer
const multer = require("multer");
// Creating an instance of express function
const app = express();
// Import dotenv
// The port we want our project to run on
const PORT = 3000;
// Express should add our path -middleware
// Body parser
app.use(express.urlencoded({ extended: false }));
// Nodemailer
const nodemailer = require("nodemailer");
// FS
const fs = require("fs");
// Googleapis
const { google } = require("googleapis");
// Pull out OAuth from googleapis
const OAuth2 = google.auth.OAuth2;
// Multer file storage
const Storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, "./attachments");
filename: function (req, file, callback) {
callback(null, `${file.fieldname}_${}_${file.originalname}`);
// Middleware to get attachments
const attachmentUpload = multer({
storage: Storage,
const createTransporter = async () => {
//Connect to the oauth playground
const oauth2Client = new OAuth2(
// Add the refresh token to the Oauth2 connection
refresh_token: process.env.OAUTH_REFRESH_TOKEN,
const accessToken = await new Promise((resolve, reject) => {
oauth2Client.getAccessToken((err, token) => {
if (err) {
reject("Failed to create access token : error message(" + err);
// Authenticating and creating a method to send a mail
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: process.env.SENDER_EMAIL,
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
refreshToken: process.env.OAUTH_REFRESH_TOKEN,
return transporter;
// Root directory -homepage
app.get("/", (req, res) => {
// Route to handle sending mails"/send_email", (req, res) => {
attachmentUpload(req, res, async function (error) {
if (error) {
return res.send("Error uploading file");
} else {
// Pulling out the form data from the request body
const recipient =;
const mailSubject = req.body.subject;
const mailBody = req.body.message;
const attachmentPath = req.file?.path;
// Mail options
let mailOptions = {
from: process.env.SENDER_EMAIL,
to: recipient,
subject: mailSubject,
text: mailBody,
attachments: [
path: attachmentPath,
try {
// Get response from the createTransport
let emailTransporter = await createTransporter();
// Send email
emailTransporter.sendMail(mailOptions, function (error, info) {
if (error) {
// failed block
} else {
// Success block
console.log("Email sent: " + info.response);
// Delete file from the folder after sent
fs.unlink(attachmentPath, function (err) {
if (err) {
return res.end(err);
} else {
console.log(attachmentPath + " has been deleted");
return res.redirect("/success.html");
} catch (error) {
return console.log(error);
// Express allows us to listen to the port and trigger a console.log() when you visit the port
app.listen(PORT, () => {
console.log(`Server is currently 🏃‍♂️ on port ${PORT}`);
Copy link

I have copied an dpasted the code above and yet I get this error in the terminal
Failed to create access token : error message(Error: No refresh token or refresh handler callback is set.

Copy link

unclebay143 commented Feb 20, 2022

Hi @harrydarwin , did you forget to set up your environment variables?

Copy link

U got it @unclebay143 - I missed my own test email in the .env file - not sure if you included that.

thanks for your article, this was extremely useful/helpful.

Copy link

Nice tutorial. Quite detailed.

Copy link

Hi, @harrydarwin, glad to hear you found a fix, can you kindly tell me more about the test email in the .env file that you missed to know if I missed it in the tutorial article. Thanks

Copy link

@Taofeekfolami Thanks a lot for the feedback! Glad to hear this really.

Copy link

Hi @unclebay143, I am not able to find the hosted link. Can you provide that here?


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment