forked from slickplaid/node-slack-mailgun
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6dcbe91
commit edd412f
Showing
9 changed files
with
405 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
.* | ||
!/.gitignore | ||
|
||
# Logs | ||
logs | ||
*.log | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directory | ||
# Commenting this out is preferred by some people, see | ||
# https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git | ||
node_modules | ||
|
||
# Users Environment Variables | ||
.lock-wscript |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,65 @@ | ||
# Slack Mailgun Notifications | ||
# Slack Mailgun (SlackGun) | ||
|
||
Slack Mailgun (SlackGun) is a simple webhook system to make it easy to route [Mailgun's](http://mailgun.com) [Webhooks](https://documentation.mailgun.com/user_manual.html#webhooks) to [Slack](https://slack.com/). This was built because there existed no simple way that I saw that could map Mailgun to Slack without [paying](https://zapier.com/app/pricing) an arm and a leg for it. | ||
|
||
Why pay for it when it's easy enough to simply build? | ||
|
||
## Install | ||
|
||
You can integrate SlackGun into your existing web application or use it standalone from the command line. | ||
|
||
### Using it with Express | ||
|
||
`npm install node-slack-mailgun` | ||
|
||
```javascript | ||
var SlackGun = require('node-slack-mailgun'); | ||
var slack_hook_url = 'https://hooks.slack.com/services/aaa/bbb/ccc'; | ||
var mailgun_apikey = '123abc'; | ||
var express = require('express'); | ||
|
||
var app = express(); | ||
|
||
app.use('/api/mailgun', SlackGun({ | ||
slack: { hook: slack_hook_url }, | ||
mailgun: { apikey: mailgun_apikey } | ||
})); | ||
``` | ||
|
||
Now any requests from Mailgun to `/api/mailgun` will be routed to slack as a message. | ||
|
||
### Using it with the build in `http/s` Node.js Module | ||
|
||
#1 | ||
|
||
### Using it from the command line | ||
|
||
#2 Not yet implemented | ||
|
||
## Usage | ||
|
||
`node-slack-mailgun` accepts a few options when initalizing. | ||
|
||
```javascript | ||
var SlackGun = require('node-slack-mailgun'); | ||
|
||
SlackGun({ | ||
slack: { // Options for slack | ||
hook: 'url', // Required. The hook URL for posting messages to slack. | ||
options: 'object' // Optional. Options to pass to https://github.com/xoxco/node-slack#install-slack | ||
}, | ||
mailgun: { // Options for mailgun | ||
apikey: 'string' // Optional. Used for verifying the HMAC token sent with a request. | ||
} | ||
}) | ||
``` | ||
|
||
## Customize Messages Sent To Slack | ||
|
||
#3 Not yet implemented. | ||
|
||
## Honey-Do List | ||
|
||
- Utilize the real time notification API for Slack. Webhooks are soo 2010. | ||
- Send emails from Slack through Mailgun to the user that received the email by responding to a message in Slack. That'd be cool. | ||
- Expand upon security of replay attacks and other possible security issues using Mailgun's webhooks. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
var gulp = require('gulp'); | ||
var runSequence = require('run-sequence'); | ||
var bump = require('gulp-bump'); | ||
var gutil = require('gulp-util'); | ||
var git = require('gulp-git'); | ||
var minimist = require('minimist'); | ||
var opts = minimist(process.argv.slice(2)); | ||
|
||
gulp.task('bump-version', function() { | ||
var type = 'patch'; | ||
|
||
if (opts._.indexOf('minor') > -1) { | ||
type = 'minor'; | ||
} else if (opts._.indexOf('major') > -1) { | ||
type = 'major'; | ||
} | ||
|
||
return gulp.src(['./bower.json', './package.json']) | ||
.pipe(bump({ | ||
type: type | ||
}).on('error', gutil.log)) | ||
.pipe(gulp.dest('./')); | ||
}); | ||
|
||
gulp.task('commit-changes', function() { | ||
return gulp.src('.') | ||
.pipe(git.commit('[Prerelease] Bumped version number', { | ||
args: '-a' | ||
})); | ||
}); | ||
|
||
gulp.task('push-changes', function(cb) { | ||
git.push('origin', 'master', cb); | ||
}); | ||
|
||
gulp.task('create-new-tag', function(cb) { | ||
var version = getPackageJsonVersion(); | ||
git.tag(version, 'Created Tag for version: ' + version, function(error) { | ||
if (error) { | ||
return cb(error); | ||
} | ||
git.push('origin', 'master', { | ||
args: '--tags' | ||
}, cb); | ||
}); | ||
|
||
function getPackageJsonVersion() { | ||
//We parse the json file instead of using require because require caches multiple calls so the version number won't be updated | ||
return JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; | ||
}; | ||
}); | ||
|
||
gulp.task('release', function(callback) { | ||
runSequence( | ||
// 'build', // buildall | ||
|
||
'bump-version', | ||
'commit-changes', | ||
'push-changes', | ||
'create-new-tag', | ||
function(error) { | ||
if (error) { | ||
console.log(error.message); | ||
} else { | ||
console.log('RELEASE FINISHED SUCCESSFULLY'); | ||
} | ||
callback(error); | ||
}); | ||
}); | ||
|
||
gulp.task('minor', function() { | ||
return true; | ||
}); | ||
|
||
gulp.task('major', function() { | ||
return true; | ||
}); | ||
|
||
gulp.task('patch', function() { | ||
return true; | ||
}); | ||
|
||
gulp.task('default', /*['build'],*/ function() { | ||
return true; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/*! | ||
* node-slack-mailgun | ||
* Copyright(c) 2015 Slick Labs, LLC | ||
* MIT Licensed | ||
*/ | ||
|
||
'use strict'; | ||
|
||
/** | ||
* Module dependencies. | ||
* @private | ||
*/ | ||
|
||
var Debug = require('debug'); | ||
var debug = Debug('node-slack-mailgun'); | ||
var Slack = require('node-slack'); | ||
var mustache = require('mustache'); | ||
var verifyMailgun = require('./lib/mailgun-verify'); | ||
var mustacheTemplates = require('./lib/templates'); | ||
var getTemplate = require('./lib/getTemplate'); | ||
|
||
/** | ||
* Module exports. | ||
*/ | ||
|
||
module.exports = SlackGun; | ||
|
||
function SlackGun(options) { | ||
var that = this; | ||
|
||
// Normalize our options and log/throw any problems. | ||
that.options = getOptions(options); | ||
|
||
// Initalize node-slack | ||
that.slack = new Slack(options.slack.hook, options.slack.options); | ||
|
||
|
||
|
||
return function SlackGunMiddleware(req, res, next) { | ||
var err = []; | ||
|
||
// Default to trusting the message if we don't | ||
// have an api key from Mailgun to work with. | ||
var authentic = true; | ||
|
||
if(that.options.mailgun.apikey) { | ||
var apikey = that.options.mailgun.apikey; | ||
var token = req.headers.token; | ||
var timestamp = req.headers.timestamp; | ||
var signature = req.headers.signature; | ||
|
||
var verification = verifyMailgun(apikey, token, timestamp, signature); | ||
|
||
if(!verification.valid) { | ||
authentic = false; | ||
err.push('Invalid token response. Mailgun message could not be authenticated.'); | ||
} | ||
} | ||
|
||
if(!req.body) { | ||
err.push('Unable to get body from Mailgun request.'); | ||
} else { | ||
var parsedMessage = getMessage(req.body); | ||
|
||
if(parsedMessage) { | ||
that.slack.send(parsedMessage); | ||
} | ||
} | ||
|
||
if(err.length) { | ||
// We've hit an error. Let mailgun know | ||
// not to keep hitting us with requests | ||
res.writeHead(406, 'Not Acceptable', { 'Content-Type': 'text/html' }); | ||
res.end(); | ||
|
||
err.forEach(function(e) { | ||
debug(e); | ||
}); | ||
} else { | ||
// Great Success! | ||
// Send response to let mailgun know | ||
res.writeHead(200, 'Success', { 'Content-Type': 'text/html' }); | ||
res.end(); | ||
} | ||
|
||
}; | ||
}; | ||
|
||
function getMessage(body, options) { | ||
debug('Parsing Mailgun message.'); | ||
|
||
if(typeof body === 'undefined') { | ||
debug('Unable to parse message from Mailgun.'); | ||
return false; | ||
} | ||
|
||
var defaultMessage = { | ||
channel: '#general', | ||
username: 'Mailgun', | ||
icon_emoji: 'mailbox_with_mail', | ||
unfurl_links: true, | ||
attachments: [] | ||
}; | ||
|
||
if(!body.event) { | ||
debug('Event type not sent by Mailgun.'); | ||
return false; | ||
} else if(body.event === 'opened') { | ||
|
||
} else if(body.event === 'clicked') { | ||
|
||
} else if(body.event === 'unsubscribed') { | ||
|
||
} else if(body.event === 'complained') { | ||
|
||
} else if(body.event === 'bounced') { | ||
|
||
} else if(body.event === 'dropped') { | ||
|
||
} else if(body.event === 'delivered') { | ||
|
||
} else { | ||
debug('Unknown event type from Mailgun.'); | ||
return false; | ||
} | ||
}; | ||
|
||
function getOptions(options) { | ||
|
||
debug('Setting options'); | ||
|
||
if(typeof options === 'undefined') { | ||
options = {}; | ||
} | ||
|
||
if(typeof options.slack === 'undefined') { | ||
options.slack = {}; | ||
} | ||
|
||
if(typeof options.mailgun === 'undefined') { | ||
options.mailgun = {}; | ||
} | ||
|
||
if(!options.slack.hook) { | ||
throw new Error('You need to set a url for slack communication.'); | ||
} | ||
|
||
if(!options.mailgun.apikey) { | ||
debug('Not using Mailgun HMAC verification due to lack of an API key.'); | ||
} | ||
|
||
if(!options.slack.options) { | ||
debug('No options passed to node-slack.'); | ||
} | ||
|
||
return options; | ||
|
||
}; |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
/*! | ||
* mailgun-verify | ||
* Copyright(c) 2015 Slick Labs, LLC | ||
* MIT Licensed | ||
*/ | ||
|
||
'use strict'; | ||
|
||
/** | ||
* Module dependencies. | ||
* @private | ||
*/ | ||
|
||
var crypto = require('crypto'); | ||
|
||
/** | ||
* Module exports. | ||
*/ | ||
|
||
module.exports = verifyMailgun; | ||
|
||
/** | ||
* Verify mailgun HMAC authentication token | ||
*/ | ||
|
||
function verifyMailgun(apikey, token, timestamp, signature) { | ||
var data = [token, timestamp].join(); | ||
var hmac = crypto.createHmac('sha256', apikey).update(data); | ||
var ourSig = hmac.digest('hex'); | ||
|
||
var output = { | ||
apikey: apikey, | ||
token: token, | ||
timestamp: timestamp, | ||
signature: signature, | ||
generatedSignature: ourSig, | ||
valid: ourSig === signature | ||
}; | ||
|
||
return output; | ||
}; | ||
|
||
/** | ||
* TODO - Reply attack cache check | ||
*/ | ||
|
||
function replayAttackCache() { | ||
this.tokens = []; | ||
}; |
Empty file.
Oops, something went wrong.