Skip to content

Instantly share code, notes, and snippets.

@bunnyhawk
Created October 30, 2020 18:12
Show Gist options
  • Save bunnyhawk/9faf7e203ba2dd726e4e7bc543a34070 to your computer and use it in GitHub Desktop.
Save bunnyhawk/9faf7e203ba2dd726e4e7bc543a34070 to your computer and use it in GitHub Desktop.
aws nodemailer handler
"use strict";
// Express is our server here. It will host any routes we need to leverage (in this case, just the one)
const express = require("express");
const sls = require("serverless-http"); // Serverless wrapper
const bodyParser = require("body-parser"); // Middleware that parses our incoming requests
const Busboy = require("busboy"); // Busboy is used to parse HTML data from our form
const nodemailer = require("nodemailer");
const { Logger } = require("lambda-logger-node"); // Optional: Provides cleaner error logging in AWS
const app = express(); // Kick off the server
const logger = Logger(); // Start a logger to better understand errors
// Setting up our server and making sure it's ready to handle outside (non-CORS) incoming requests
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser.raw());
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", true);
res.header(
"Access-Control-Allow-Headers",
"x-www-form-urlencoded, Origin, X-Requested-With, Content-Type, Accept, Authorization, *"
);
next();
});
// This is our POST route that the form will leverage
app.post("/send-mail", async (req, res, next) => {
const result = {
files: [],
};
// Initial headers for our request
var busboy = new Busboy({
headers: {
...req.headers,
"content-type":
req.headers["Content-Type"] || req.headers["content-type"],
},
});
// Busboy is watching for attached files and setting up our object(s) to pass along
busboy.on("file", function (fieldname, file, filename, encoding, mimetype) {
let currentFile = {
filename,
encoding,
contentType: mimetype,
data: [],
};
// Building a data array from the incoming stream
file.on("data", function (data) {
currentFile.data.push(data);
});
// Once finished, concat the data in to a single Buffer object
file.on("end", function () {
currentFile.data = Buffer.concat(currentFile.data);
result.files.push(currentFile);
});
});
// Busboy is watching for the remaining fields and building a result map
busboy.on("field", function (fieldname, value) {
try {
result[fieldname] = JSON.parse(value);
} catch (err) {
result[fieldname] = value;
}
});
// Once data is handled, kick off the transport message
busboy.on("finish", function () {
main();
});
req.pipe(busboy);
function main() {
let transporter = nodemailer.createTransport({
host: "smtp.gmail.com", // Notes on this below
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "example@gmail.com",
pass: process.env.MAIL_ACCESS, // Passed in via the YAML
},
});
// Build the message
const message = {
from: '"Mike" <example@gmail.com>', // sender address
to: "receiver@gmail.com", // list of receivers
subject: "Honor A Loved One: Submission",
text: "A submission for consideration on the COVID Memorial", // plain text body
html: `<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>Honor A Loved One: Submission</h1>
<p>THE DECEASED</p>
<ul>
<li>First Name: ${result.firstName}</li>
<li>Last Name: ${result.lastName}</li>
<li>Age: ${result.age}</li>
<li>Location: ${result.location}</li>
<li>What were they like?: ${result.about}</li>
</ul>
<p>SUBMITTER</p>
<ul>
<li>Name: ${result.submitName}</li>
<li>Relation: ${result.submitRelation}</li>
<li>Email: ${result.email}</li>
</ul>
</body>
</html>`,
attachments: result.files.map((file, index) => ({
filename: file.filename,
content: new Buffer.from(file.data, "binary"),
contentType: file.contentType,
})),
};
// Send it out!
transporter.sendMail(message, function (err, info) {
if (err) {
logger.error(err);
} else {
res.status(200).send("Submit is a success");
}
});
}
});
// Matches up with in our YAML as functions: -> covidApi: -> handler:
module.exports.covidApi = sls(app);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment