Skip to content

Instantly share code, notes, and snippets.

@woolfg
Last active May 31, 2018 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save woolfg/702a97df4b894dea665745789d4f8d56 to your computer and use it in GitHub Desktop.
Save woolfg/702a97df4b894dea665745789d4f8d56 to your computer and use it in GitHub Desktop.
Serverless approach to deliver Emails to Slack using Mailgun & Google Cloud Functions
//Disclaimer: this code is a quick and dirty proof of concept and I am not a JavaScript developer
//see the full story on Medium: https://medium.com/@schafele/serverless-firefighting-deliver-emails-to-slack-using-mailgun-google-cloud-functions-a7e10475d1a2
const channel = "#yourchannel";
const username = "alarm";
const token = "your token";
const { WebClient } = require('@slack/client');
const web = new WebClient(token);
const sendSlackMessage = function(subject,msg) {
return new Promise((resolve, reject) => {
console.log('sending slack message...');
web.chat.postMessage({
channel: channel,
username: username,
"attachments": [
{
text: msg,
fallback: subject,
"author_name": "Operator",
title: subject
}
]
}).then((res) => {
console.log('Message sent: ', res.ts);
resolve();
}).catch(console.error);
});
};
const sendSlackFiles = (uploads) => {
return new Promise((resolve, reject) => {
if (Object.keys(uploads).length > 0) {
for (filename in uploads) {
console.log('sending '+filename);
web.files.upload({filename: 'Details', file: fs.createReadStream(uploads[filename]), channels: channel})
.then((res) => {
console.log('File uploaded: ', res.file.id);
resolve();
})
.catch(console.error);
}
} else {
resolve();
}
});
};
const path = require('path');
const os = require('os');
const fs = require('fs');
const Busboy = require('busboy');
exports.alarmEmail2slack = (req, res) => {
if (req.method === 'POST') {
const busboy = new Busboy({ headers: req.headers });
const tmpdir = os.tmpdir();
const fields = {};
const uploads = {};
busboy.on('field', (fieldname, val) => {
fields[fieldname] = val;
console.log(`Processed field ${fieldname}: ${val}.`);
});
busboy.on('file', (fieldname, file, filename) => {
const filepath = path.join(tmpdir, filename);
uploads[fieldname] = filepath;
file.pipe(fs.createWriteStream(filepath));
});
busboy.on('finish', () => {
console.log('input processed');
if (fields.Subject !== undefined && fields.Subject.includes('secret subject')
&& fields.From !== undefined && fields.From === "secretemail@address.invalid") {
const msg = (fields['body-plain'] !== undefined) ? fields['body-plain'] : 'No Msg';
const subject = fields.Subject;
Promise.all([ sendSlackMessage(subject, msg), sendSlackFiles(uploads)])
.then(values => {
//delete all uploaded files
for (const name in uploads) {
const file = uploads[name];
fs.unlinkSync(file);
}
res.status(200).send('processed');
});
} else {
res.status(200).send('nothing to process');
}
});
busboy.end(req.rawBody); //this version works in production
//req.pipe(busboy); //this version works in the emulator
} else {
res.status(405).end();
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment