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

Good day,
Thank you for the tutorial.
I think there is an error in line 102 ( const attachmentPath = req.file?.path; ).
I think the question mark should be removed.

Thanks once again and more grace to do more.

Copy link

unclebay143 commented Jun 28, 2021

Thanks for the feedback @alaomichael

The JS optional chaining operator (?) is an indication that the req.file can be null or undefined sometimes (because it is optional), that way javascript will not shout at us.

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