Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ console.log("AWS Lambda SES Forwarder // @arithmetric // Version 5.0.0");
// `[email protected]` would be treated as if it was sent to
// `[email protected]`.
//
// - rejectSpam: Rejects any emails that fail the SES spam checks.
//
// - forwardMapping: Object where the key is the lowercase email address from
// which to forward and the value is an array of email addresses to which to
// send the message.
Expand All @@ -41,6 +43,7 @@ var defaultConfig = {
emailBucket: "s3-bucket-name",
emailKeyPrefix: "emailsPrefix/",
allowPlusSign: true,
rejectSpam: false,
forwardMapping: {
"[email protected]": [
"[email protected]",
Expand Down Expand Up @@ -85,6 +88,36 @@ exports.parseEvent = function(data) {
return Promise.resolve(data);
};

/**
* Filters out SPAM emails
*
* @param {object} data - Data bundle with context, email, etc.
*
* @return {object} - Promise resolved with data.
*/
exports.filterSpam = function(data) {
const receipt = data.event.Records[0].ses.receipt;
if (data.config.rejectSpam && receipt) {
const verdicts = [
'spamVerdict',
'virusVerdict',
'spfVerdict',
'dkimVerdict',
'dmarcVerdict'
];
for (let key of verdicts) {
const verdict = receipt[key];
if (verdict && verdict.status === 'FAIL') {
return Promise.reject(
new Error('Error: Email failed spam filter: ' + key)
);
}
}
}

return Promise.resolve(data);
};

/**
* Transforms the original recipients to the desired forwarded destinations.
*
Expand Down Expand Up @@ -340,6 +373,7 @@ exports.handler = function(event, context, callback, overrides) {
var steps = overrides && overrides.steps ? overrides.steps :
[
exports.parseEvent,
exports.filterSpam,
exports.transformRecipients,
exports.fetchMessage,
exports.processMessage,
Expand Down
120 changes: 120 additions & 0 deletions test/filterSpam.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@

/* global describe, it */

var assert = require("assert");
var fs = require("fs");

var index = require("../index");

describe('index.js', function() {
describe('#filterSpam()', function() {
it('skip if not configured',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {}
};
index.filterSpam(data)
.then(function() {
assert.ok(true, "filterSpam returned successfully");
done();
});
});

it('skip if filtering disabled',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: false}
};
index.filterSpam(data)
.then(function() {
assert.ok(true, "filterSpam returned successfully");
done();
});
});

it('allow good message through',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: true}
};
index.filterSpam(data)
.then(function() {
assert.ok(true, "filterSpam returned successfully");
done();
});
});

it('should reject spam messages',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: true}
};
data.event.Records[0].ses.receipt.spamVerdict.status = "FAIL";
index.filterSpam(data)
.catch(function(err) {
assert.ok(err, "Error: Email failed spam filter: spamVerdict");
done();
});
});

it('should reject messages that might have a virus',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: true}
};
data.event.Records[0].ses.receipt.virusVerdict.status = "FAIL";
index.filterSpam(data)
.catch(function(err) {
assert.ok(err, "Error: Email failed spam filter: virusVerdict");
done();
});
});

it('should reject messages that fail a DKIM check',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: true}
};
data.event.Records[0].ses.receipt.dkimVerdict.status = "FAIL";
index.filterSpam(data)
.catch(function(err) {
assert.ok(err, "Error: Email failed spam filter: dkimVerdict");
done();
});
});

it('should reject messages that fail a SPF check',
function(done) {
var data = {
event: JSON.parse(fs.readFileSync("test/assets/event.json")),
log: console.log,
context: {},
config: {rejectSpam: true}
};
data.event.Records[0].ses.receipt.spfVerdict.status = "FAIL";
index.filterSpam(data)
.catch(function(err) {
assert.ok(err, "Error: Email failed spam filter: spfVerdict");
done();
});
});
});
});