Quantcast
Channel: SOS
Viewing all articles
Browse latest Browse all 53

Forwarding an email with attachments using SendGrid and Formidable

0
0

SendGrid.com is a great service for sending emails programmatically, but it also has an InboundParse feature that will call your webhook for any emails sent to your domain. It can be useful to forward these emails elsewhere, e.g. sending support@mydomain.com to your own personal email.

There’s not really a good example of how to do this, while including attachments, that I could find, so here you go.

import fs from "fs";
// You can use "formidable-serverless" if in a serverless environment like
// AWS Lamba or Google Cloud Functions
import formidable from "formidable";
import sendgridMail from "@sendgrid/mail";
import { AttachmentData } from "@sendgrid/helpers/classes/attachment";
sendgridMail.setApiKey(process.env.SENDGRID_API_KEY);
// See https://www.npmjs.com/package/formidable
interface FormidableFile {
// The size of the uploaded file in bytes.
// If the file is still being uploaded (see `'fileBegin'` event),
// this property says how many bytes of the file have been written to disk yet.
size: number;
// The path this file is being written to. You can modify this in the `'fileBegin'` event in
// case you are unhappy with the way formidable generates a temporary path for your files.
path: string;
// The name this file had according to the uploading client.
name: string | null;
// The mime type of this file, according to the uploading client.
type: string | null;
// A Date object (or `null`) containing the time this file was last written to.
// Mostly here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
lastModifiedDate: Date | null;
// If `options.hash` calculation was set, you can read the hex digest out of this var.
hash: string | "sha1" | "md5" | "sha256" | null;
}
// Hook this up to your inbound API however you like, e.g.
// using Express
function handleRequest(req, res) {
const form = new formidable.IncomingForm();
form.uploadDir = "/tmp/";
form.keepExtensions = true;
form.type = "multipart";
form.multiples = false;
form.parse(req, async (_err: any, fields, files) => {
handleFormidableResult(fields, files).then(() => {
// Send whatever you want
res.status(200);
res.json({ success: true });
res.end();
});
});
}
async function handleFormidableResult(fields, files) {
const { to, subject, from, html } = fields;
const fileKeys = Object.keys(files);
let attachments: Array<AttachmentData> = null;
let cleanupPromises = null;
if (fileKeys.length > 0) {
const filesInfo = fileKeys.map((key) => files[key]) as Array<
FormidableFile
>;
const attachmentPromises = filesInfo.map((fileInfo) => {
return new Promise((resolve, reject) => {
fs.readFile(fileInfo.path, (err, data) => {
if (err) {
reject(err);
return;
}
const attachment: AttachmentData = {
// Encode the buffer as a base64 encoded string
content: data.toString("base64"),
filename: fileInfo.name,
type: fileInfo.type,
disposition: "attachment",
contentId: fileInfo.hash,
};
resolve(attachment);
});
});
});
// Feel free to do better error handling, where if one file fails to
// read then you still attach others. Keeping it simple here.
attachments = (await Promise.all(attachmentPromises)) as Array<
AttachmentData
>;
// Delete all temp files.
cleanupPromises = filesInfo.map((fileInfo) => {
return new Promise((resolve, reject) => {
fs.unlink(fileInfo.path, () => {
resolve(null);
});
});
});
}
const emailBody = html || fields.text;
const message = {
from: "no-reply@example.com",
to,
subject,
html: emailBody,
envelope: {
from: "no-reply@example.com",
to,
},
attachments,
};
try {
await sendgridMail.send(message);
} catch (err) {
console.error("Sending email failed with error", err, " message ", message);
} finally {
if (cleanupPromises) {
await Promise.all(cleanupPromises);
}
}
}

Viewing all articles
Browse latest Browse all 53

Latest Images

Trending Articles





Latest Images