Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

haraka-plugin-rspamd

Package Overview
Dependencies
Maintainers
4
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

haraka-plugin-rspamd - npm Package Compare versions

Comparing version 1.1.6 to 1.1.7

.eslintrc.yaml

2

.github/PULL_REQUEST_TEMPLATE.md

@@ -11,3 +11,1 @@ Fixes #

- [ ] Changes.md updated
- [ ] package.json.version bumped
- [ ] published to NPM (will be done by @core)

@@ -0,1 +1,10 @@

### Unreleased
## 1.1.7 - 2022-06-05
- ci: replace travis & appveyor with GitHub actions
- test: replace nodeunit with mocha
- test: update header checks against lower cased header names
## 1.1.6 - 2020-02-29

@@ -5,2 +14,3 @@

## 1.1.5 - 2019-04-01

@@ -10,2 +20,3 @@

## 1.1.4 - 2019-01-28

@@ -15,2 +26,3 @@

## 1.1.3 - 2018-12-19

@@ -20,2 +32,3 @@

## 1.1.2 - 2018-11-03

@@ -25,2 +38,3 @@

## 1.1.1 - 2018-05-10

@@ -27,0 +41,0 @@

@@ -10,450 +10,449 @@ 'use strict';

exports.register = function () {
this.load_rspamd_ini();
this.load_rspamd_ini();
}
exports.load_rspamd_ini = function () {
const plugin = this;
const plugin = this;
plugin.cfg = plugin.config.get('rspamd.ini', {
booleans: [
'-check.authenticated',
'+dkim.enabled',
'-check.private_ip',
'-check.local_ip',
'-check.relay',
'+reject.spam',
'-reject.authenticated',
'+rewrite_subject.enabled',
'+rmilter_headers.enabled',
'+soft_reject.enabled',
'+smtp_message.enabled',
],
}, () => {
plugin.load_rspamd_ini();
});
plugin.cfg = plugin.config.get('rspamd.ini', {
booleans: [
'-check.authenticated',
'+dkim.enabled',
'-check.private_ip',
'-check.local_ip',
'-check.relay',
'+reject.spam',
'-reject.authenticated',
'+rewrite_subject.enabled',
'+rmilter_headers.enabled',
'+soft_reject.enabled',
'+smtp_message.enabled',
],
}, () => {
plugin.load_rspamd_ini();
});
if (!plugin.cfg.reject.message) {
plugin.cfg.reject.message = 'Detected as spam';
}
if (!plugin.cfg.reject.message) {
plugin.cfg.reject.message = 'Detected as spam';
}
if (!plugin.cfg.soft_reject.message) {
plugin.cfg.soft_reject.message = 'Deferred by policy';
}
if (!plugin.cfg.soft_reject.message) {
plugin.cfg.soft_reject.message = 'Deferred by policy';
}
if (!plugin.cfg.spambar) {
plugin.cfg.spambar = { positive: '+', negative: '-', neutral: '/' };
}
if (!plugin.cfg.spambar) {
plugin.cfg.spambar = { positive: '+', negative: '-', neutral: '/' };
}
if (!plugin.cfg.main.port) plugin.cfg.main.port = 11333;
if (!plugin.cfg.main.host) plugin.cfg.main.host = 'localhost';
if (!plugin.cfg.main.port) plugin.cfg.main.port = 11333;
if (!plugin.cfg.main.host) plugin.cfg.main.host = 'localhost';
if (!plugin.cfg.main.add_headers) {
if (plugin.cfg.main.always_add_headers === true) {
plugin.cfg.main.add_headers = 'always';
}
else {
plugin.cfg.main.add_headers = 'sometimes';
}
if (!plugin.cfg.main.add_headers) {
if (plugin.cfg.main.always_add_headers === true) {
plugin.cfg.main.add_headers = 'always';
}
else {
plugin.cfg.main.add_headers = 'sometimes';
}
}
if (!plugin.cfg.subject) {
plugin.cfg.subject = "[SPAM] %s";
}
if (!plugin.cfg.subject) {
plugin.cfg.subject = "[SPAM] %s";
}
}
exports.get_options = function (connection) {
const plugin = this;
const plugin = this;
// https://rspamd.com/doc/architecture/protocol.html
// https://github.com/vstakhov/rspamd/blob/master/rules/http_headers.lua
const options = {
headers: {},
path: '/checkv2',
method: 'POST',
};
// https://rspamd.com/doc/architecture/protocol.html
// https://github.com/vstakhov/rspamd/blob/master/rules/http_headers.lua
const options = {
headers: {},
path: '/checkv2',
method: 'POST',
};
if (plugin.cfg.main.unix_socket) {
options.socketPath = plugin.cfg.main.unix_socket;
}
else {
options.port = plugin.cfg.main.port;
options.host = plugin.cfg.main.host;
}
if (plugin.cfg.main.unix_socket) {
options.socketPath = plugin.cfg.main.unix_socket;
}
else {
options.port = plugin.cfg.main.port;
options.host = plugin.cfg.main.host;
}
if (connection.notes.auth_user) {
options.headers.User = connection.notes.auth_user;
}
if (connection.notes.auth_user) {
options.headers.User = connection.notes.auth_user;
}
if (connection.remote.ip) options.headers.IP = connection.remote.ip;
if (connection.remote.ip) options.headers.IP = connection.remote.ip;
const fcrdns = connection.results.get('fcrdns');
if (fcrdns && fcrdns.fcrdns && fcrdns.fcrdns[0]) {
options.headers.Hostname = fcrdns.fcrdns[0];
const fcrdns = connection.results.get('fcrdns');
if (fcrdns && fcrdns.fcrdns && fcrdns.fcrdns[0]) {
options.headers.Hostname = fcrdns.fcrdns[0];
}
else {
if (connection.remote.host) {
options.headers.Hostname = connection.remote.host;
}
else {
if (connection.remote.host) {
options.headers.Hostname = connection.remote.host;
}
}
}
if (connection.hello.host) options.headers.Helo = connection.hello.host;
if (connection.hello.host) options.headers.Helo = connection.hello.host;
let spf = connection.transaction.results.get('spf');
let spf = connection.transaction.results.get('spf');
if (spf && spf.result) {
options.headers.SPF = { result: spf.result.toLowerCase() };
}
else {
spf = connection.results.get('spf');
if (spf && spf.result) {
options.headers.SPF = { result: spf.result.toLowerCase() };
options.headers.SPF = { result: spf.result.toLowerCase() };
}
else {
spf = connection.results.get('spf');
if (spf && spf.result) {
options.headers.SPF = { result: spf.result.toLowerCase() };
}
}
if (connection.transaction.mail_from) {
const mfaddr = connection.transaction.mail_from.address().toString();
if (mfaddr) {
options.headers.From = mfaddr;
}
}
if (connection.transaction.mail_from) {
const mfaddr = connection.transaction.mail_from.address().toString();
if (mfaddr) {
options.headers.From = mfaddr;
}
const rcpts = connection.transaction.rcpt_to;
if (rcpts) {
options.headers.Rcpt = [];
for (let i=0; i < rcpts.length; i++) {
options.headers.Rcpt.push(rcpts[i].address());
}
const rcpts = connection.transaction.rcpt_to;
if (rcpts) {
options.headers.Rcpt = [];
for (let i=0; i < rcpts.length; i++) {
options.headers.Rcpt.push(rcpts[i].address());
}
// for per-user options
if (rcpts.length === 1) {
options.headers['Deliver-To'] = options.headers.Rcpt[0];
}
// for per-user options
if (rcpts.length === 1) {
options.headers['Deliver-To'] = options.headers.Rcpt[0];
}
}
if (connection.transaction.uuid)
options.headers['Queue-Id'] = connection.transaction.uuid;
if (connection.transaction.uuid)
options.headers['Queue-Id'] = connection.transaction.uuid;
if (connection.tls.enabled) {
options.headers['TLS-Cipher'] = connection.tls.cipher.name;
options.headers['TLS-Version'] = connection.tls.cipher.version;
}
if (connection.tls.enabled) {
options.headers['TLS-Cipher'] = connection.tls.cipher.name;
options.headers['TLS-Version'] = connection.tls.cipher.version;
}
return options;
return options;
}
exports.get_smtp_message = function (r) {
const plugin = this;
const plugin = this;
if (!plugin.cfg.smtp_message.enabled || !r.data.messages) return;
if (typeof(r.data.messages) !== 'object') return;
if (!r.data.messages.smtp_message) return;
if (!plugin.cfg.smtp_message.enabled || !r.data.messages) return;
if (typeof(r.data.messages) !== 'object') return;
if (!r.data.messages.smtp_message) return;
return r.data.messages.smtp_message;
return r.data.messages.smtp_message;
}
exports.do_rewrite = function (connection, data) {
const plugin = this;
const plugin = this;
if (!plugin.cfg.rewrite_subject.enabled) return false;
if (data.action !== 'rewrite subject') return false;
if (!plugin.cfg.rewrite_subject.enabled) return false;
if (data.action !== 'rewrite subject') return false;
const rspamd_subject = data.subject || plugin.cfg.subject;
const old_subject = connection.transaction.header.get('Subject') || '';
const new_subject = rspamd_subject.replace('%s', old_subject);
const rspamd_subject = data.subject || plugin.cfg.subject;
const old_subject = connection.transaction.header.get('Subject') || '';
const new_subject = rspamd_subject.replace('%s', old_subject);
connection.transaction.remove_header('Subject');
connection.transaction.add_header('Subject', new_subject);
connection.transaction.remove_header('Subject');
connection.transaction.add_header('Subject', new_subject);
}
exports.add_dkim_header = function (connection, data) {
const plugin = this;
const plugin = this;
if (!plugin.cfg.dkim.enabled) return;
if (!data['dkim-signature']) return;
if (!plugin.cfg.dkim.enabled) return;
if (!data['dkim-signature']) return;
connection.transaction.add_header('DKIM-Signature', data['dkim-signature']);
connection.transaction.add_header('DKIM-Signature', data['dkim-signature']);
}
exports.do_milter_headers = function (connection, data) {
const plugin = this;
const plugin = this;
if (!plugin.cfg.rmilter_headers.enabled) return;
if (!data.milter) return;
if (!plugin.cfg.rmilter_headers.enabled) return;
if (!data.milter) return;
if (data.milter.remove_headers) {
Object.keys(data.milter.remove_headers).forEach((key) => {
connection.transaction.remove_header(key);
})
}
if (data.milter.remove_headers) {
Object.keys(data.milter.remove_headers).forEach((key) => {
connection.transaction.remove_header(key);
})
}
if (data.milter.add_headers) {
Object.keys(data.milter.add_headers).forEach((key) => {
const header_value = data.milter.add_headers[key];
if (!header_value) return;
if (data.milter.add_headers) {
Object.keys(data.milter.add_headers).forEach((key) => {
const header_value = data.milter.add_headers[key];
if (!header_value) return;
if (typeof header_value === 'object') {
connection.transaction.add_header(key, header_value.value);
}
else {
connection.transaction.add_header(key, header_value);
}
})
}
if (typeof header_value === 'object') {
connection.transaction.add_header(key, header_value.value);
}
else {
connection.transaction.add_header(key, header_value);
}
})
}
}
exports.hook_data_post = function (next, connection) {
const plugin = this;
const plugin = this;
if (!connection.transaction) return next();
if (!plugin.should_check(connection)) return next();
if (!connection.transaction) return next();
if (!plugin.should_check(connection)) return next();
let timer;
const timeout = plugin.cfg.main.timeout || plugin.timeout - 1;
let timer;
const timeout = plugin.cfg.main.timeout || plugin.timeout - 1;
let calledNext=false;
function nextOnce (code, msg) {
clearTimeout(timer);
if (calledNext) return;
calledNext=true;
next(code, msg);
}
let calledNext=false;
function nextOnce (code, msg) {
clearTimeout(timer);
if (calledNext) return;
calledNext=true;
next(code, msg);
}
timer = setTimeout(() => {
if (!connection) return;
if (!connection.transaction) return;
connection.transaction.results.add(plugin, {err: 'timeout'});
nextOnce();
}, timeout * 1000);
timer = setTimeout(() => {
if (!connection) return;
if (!connection.transaction) return;
connection.transaction.results.add(plugin, {err: 'timeout'});
nextOnce();
}, timeout * 1000);
const start = Date.now();
const start = Date.now();
const req = http.request(plugin.get_options(connection), (res) => {
let rawData = '';
const req = http.request(plugin.get_options(connection), (res) => {
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
const r = plugin.parse_response(rawData, connection);
if (!r || !r.data || !r.log) return nextOnce();
res.on('end', () => {
const r = plugin.parse_response(rawData, connection);
if (!r || !r.data || !r.log) return nextOnce();
r.log.emit = true; // spit out a log entry
r.log.time = (Date.now() - start)/1000;
r.log.emit = true; // spit out a log entry
r.log.time = (Date.now() - start)/1000;
if (!connection.transaction) return nextOnce();
if (!connection.transaction) return nextOnce();
connection.transaction.results.add(plugin, r.log);
if (r.data.symbols) connection.transaction.results.add(plugin, { symbols: r.data.symbols });
connection.transaction.results.add(plugin, r.log);
if (r.data.symbols) connection.transaction.results.add(plugin, { symbols: r.data.symbols });
const smtp_message = plugin.get_smtp_message(r);
const smtp_message = plugin.get_smtp_message(r);
plugin.do_rewrite(connection, r.data);
plugin.do_rewrite(connection, r.data);
if (plugin.cfg.soft_reject.enabled && r.data.action === 'soft reject') {
nextOnce(DENYSOFT, DSN.sec_unauthorized(smtp_message || plugin.cfg.soft_reject.message, 451));
}
else if (plugin.wants_reject(connection, r.data)) {
nextOnce(DENY, smtp_message || plugin.cfg.reject.message);
}
else {
plugin.add_dkim_header(connection, r.data);
plugin.do_milter_headers(connection, r.data);
plugin.add_headers(connection, r.data);
if (plugin.cfg.soft_reject.enabled && r.data.action === 'soft reject') {
nextOnce(DENYSOFT, DSN.sec_unauthorized(smtp_message || plugin.cfg.soft_reject.message, 451));
}
else if (plugin.wants_reject(connection, r.data)) {
nextOnce(DENY, smtp_message || plugin.cfg.reject.message);
}
else {
plugin.add_dkim_header(connection, r.data);
plugin.do_milter_headers(connection, r.data);
plugin.add_headers(connection, r.data);
nextOnce();
}
});
})
req.on('error', (err) => {
if (!connection || !connection.transaction) return;
connection.transaction.results.add(plugin, { err: err.message});
nextOnce();
}
});
})
connection.transaction.message_stream.pipe(req);
// pipe calls req.end() asynchronously
req.on('error', (err) => {
if (!connection || !connection.transaction) return;
connection.transaction.results.add(plugin, { err: err.message});
nextOnce();
});
connection.transaction.message_stream.pipe(req);
// pipe calls req.end() asynchronously
}
exports.should_check = function (connection) {
const plugin = this;
const plugin = this;
let result = true; // default
let result = true; // default
if (plugin.cfg.check.authenticated == false && connection.notes.auth_user) {
connection.transaction.results.add(plugin, { skip: 'authed'});
result = false;
}
if (plugin.cfg.check.authenticated == false && connection.notes.auth_user) {
connection.transaction.results.add(plugin, { skip: 'authed'});
result = false;
}
if (plugin.cfg.check.relay == false && connection.relaying) {
connection.transaction.results.add(plugin, { skip: 'relay'});
result = false;
}
if (plugin.cfg.check.relay == false && connection.relaying) {
connection.transaction.results.add(plugin, { skip: 'relay'});
result = false;
}
if (plugin.cfg.check.local_ip == false && connection.remote.is_local) {
connection.transaction.results.add(plugin, { skip: 'local_ip'});
result = false;
}
if (plugin.cfg.check.local_ip == false && connection.remote.is_local) {
connection.transaction.results.add(plugin, { skip: 'local_ip'});
result = false;
}
if (plugin.cfg.check.private_ip == false && connection.remote.is_private) {
if (plugin.cfg.check.local_ip == true && connection.remote.is_local) {
// local IPs are included in private IPs
}
else {
connection.transaction.results.add(plugin, { skip: 'private_ip'});
result = false;
}
if (plugin.cfg.check.private_ip == false && connection.remote.is_private) {
if (plugin.cfg.check.local_ip == true && connection.remote.is_local) {
// local IPs are included in private IPs
}
else {
connection.transaction.results.add(plugin, { skip: 'private_ip'});
result = false;
}
}
return result;
return result;
}
exports.wants_reject = function (connection, data) {
const plugin = this;
const plugin = this;
if (data.action !== 'reject') return false;
if (data.action !== 'reject') return false;
if (connection.notes.auth_user) {
if (plugin.cfg.reject.authenticated == false) return false;
}
else {
if (plugin.cfg.reject.spam == false) return false;
}
if (connection.notes.auth_user) {
if (plugin.cfg.reject.authenticated == false) return false;
}
else {
if (plugin.cfg.reject.spam == false) return false;
}
return true;
return true;
}
exports.wants_headers_added = function (rspamd_data) {
const plugin = this;
const plugin = this;
if (plugin.cfg.main.add_headers === 'never') return false;
if (plugin.cfg.main.add_headers === 'always') return true;
if (plugin.cfg.main.add_headers === 'never') return false;
if (plugin.cfg.main.add_headers === 'always') return true;
// implicit add_headers=sometimes, based on rspamd response
if (rspamd_data.action === 'add header') return true;
return false;
// implicit add_headers=sometimes, based on rspamd response
if (rspamd_data.action === 'add header') return true;
return false;
}
exports.get_clean = function (data, connection) {
const plugin = this;
const clean = { symbols: {} };
const plugin = this;
const clean = { symbols: {} };
if (data.symbols) {
Object.keys(data.symbols).forEach(key => {
const a = data.symbols[key];
// transform { name: KEY, score: VAL } -> { KEY: VAL }
if (a.name && a.score !== undefined) {
clean.symbols[ a.name ] = a.score;
return;
}
// unhandled type
connection.logerror(plugin, a);
})
if (data.symbols) {
Object.keys(data.symbols).forEach(key => {
const a = data.symbols[key];
// transform { name: KEY, score: VAL } -> { KEY: VAL }
if (a.name && a.score !== undefined) {
clean.symbols[ a.name ] = a.score;
return;
}
// unhandled type
connection.logerror(plugin, a);
})
}
// objects that may exist
['action', 'is_skipped', 'required_score', 'score'].forEach((key) => {
switch (typeof data[key]) {
case 'boolean':
case 'number':
case 'string':
clean[key] = data[key];
break;
default:
connection.loginfo(plugin, `skipping unhandled: ${ typeof data[key]}`);
}
});
// objects that may exist
['action', 'is_skipped', 'required_score', 'score'].forEach((key) => {
switch (typeof data[key]) {
case 'boolean':
case 'number':
case 'string':
clean[key] = data[key];
break;
default:
connection.loginfo(plugin, "skipping unhandled: " + typeof data[key]);
}
});
// arrays which might be present
['urls', 'emails', 'messages'].forEach(b => {
// collapse to comma separated string, so values get logged
if (!data[b]) return;
// arrays which might be present
['urls', 'emails', 'messages'].forEach(b => {
// collapse to comma separated string, so values get logged
if (!data[b]) return;
if (data[b].length) {
clean[b] = data[b].join(',');
return;
}
if (data[b].length) {
clean[b] = data[b].join(',');
return;
}
if (typeof(data[b]) == 'object') {
// 'messages' is probably a dictionary
Object.keys(data[b]).map((k) => {
return `${k} : ${data[b][k]}`;
}).join(',');
}
});
if (typeof(data[b]) == 'object') {
// 'messages' is probably a dictionary
Object.keys(data[b]).map((k) => {
return `${k} : ${data[b][k]}`;
}).join(',');
}
});
return clean;
return clean;
}
exports.parse_response = function (rawData, connection) {
const plugin = this;
const plugin = this;
if (!rawData) return;
if (!rawData) return;
let data;
try {
data = JSON.parse(rawData);
}
catch (err) {
connection.transaction.results.add(plugin, {
err: 'parse failure: ' + err.message
});
return;
}
let data;
try {
data = JSON.parse(rawData);
}
catch (err) {
connection.transaction.results.add(plugin, {
err: `parse failure: ${ err.message}`
});
return;
}
if (Object.keys(data).length === 0) return;
if (Object.keys(data).length === 0) return;
if (Object.keys(data).length === 1 && data.error) {
connection.transaction.results.add(plugin, {
err: data.error
});
return;
}
if (Object.keys(data).length === 1 && data.error) {
connection.transaction.results.add(plugin, {
err: data.error
});
return;
}
return {
'data' : data,
'log' : plugin.get_clean(data, connection),
};
return {
data,
'log' : plugin.get_clean(data, connection),
};
}
exports.add_headers = function (connection, data) {
const plugin = this;
const cfg = plugin.cfg;
const plugin = this;
const cfg = plugin.cfg;
if (!plugin.wants_headers_added(data)) return;
if (!plugin.wants_headers_added(data)) return;
if (cfg.header && cfg.header.bar) {
let spamBar = '';
let spamBarScore = 1;
let spamBarChar = cfg.spambar.neutral || '/';
if (data.score >= 1) {
spamBarScore = Math.floor(data.score);
spamBarChar = cfg.spambar.positive || '+';
}
else if (data.score <= -1) {
spamBarScore = Math.floor(data.score * -1);
spamBarChar = cfg.spambar.negative || '-';
}
for (let i = 0; i < spamBarScore; i++) {
spamBar += spamBarChar;
}
connection.transaction.remove_header(cfg.header.bar);
connection.transaction.add_header(cfg.header.bar, spamBar);
if (cfg.header && cfg.header.bar) {
let spamBar = '';
let spamBarScore = 1;
let spamBarChar = cfg.spambar.neutral || '/';
if (data.score >= 1) {
spamBarScore = Math.floor(data.score);
spamBarChar = cfg.spambar.positive || '+';
}
else if (data.score <= -1) {
spamBarScore = Math.floor(data.score * -1);
spamBarChar = cfg.spambar.negative || '-';
}
for (let i = 0; i < spamBarScore; i++) {
spamBar += spamBarChar;
}
connection.transaction.remove_header(cfg.header.bar);
connection.transaction.add_header(cfg.header.bar, spamBar);
}
if (cfg.header && cfg.header.report) {
const prettySymbols = [];
for (const k in data.symbols) {
if (data.symbols[k].score) {
prettySymbols.push(data.symbols[k].name +
'(' + data.symbols[k].score + ')');
}
}
connection.transaction.remove_header(cfg.header.report);
connection.transaction.add_header(cfg.header.report,
prettySymbols.join(' '));
if (cfg.header && cfg.header.report) {
const prettySymbols = [];
for (const k in data.symbols) {
if (data.symbols[k].score) {
prettySymbols.push(`${data.symbols[k].name }(${ data.symbols[k].score })`);
}
}
connection.transaction.remove_header(cfg.header.report);
connection.transaction.add_header(cfg.header.report,
prettySymbols.join(' '));
}
if (cfg.header && cfg.header.score) {
connection.transaction.remove_header(cfg.header.score);
connection.transaction.add_header(cfg.header.score, '' + data.score);
}
if (cfg.header && cfg.header.score) {
connection.transaction.remove_header(cfg.header.score);
connection.transaction.add_header(cfg.header.score, `${ data.score}`);
}
}
{
"name": "haraka-plugin-rspamd",
"version": "1.1.6",
"version": "1.1.7",
"description": "Haraka plugin for rspamd",
"main": "index.js",
"scripts": {
"lint": "./node_modules/.bin/eslint *.js test/**/*.js",
"lintfix": "./node_modules/.bin/eslint --fix *.js test/**/*.js",
"cover": "./node_modules/.bin/istanbul cover ./node_modules/.bin/nodeunit",
"test": "./node_modules/.bin/nodeunit"
"lint": "npx eslint *.js test",
"lintfix": "npx eslint --fix *.js test",
"test": "npx _mocha"
},

@@ -28,6 +27,6 @@ "repository": {

"devDependencies": {
"eslint": ">=3",
"eslint": ">=8",
"eslint-plugin-haraka": "*",
"haraka-test-fixtures": "*",
"nodeunit": "*"
"haraka-test-fixtures": "^1.0.35",
"mocha": ">=9"
},

@@ -34,0 +33,0 @@ "dependencies": {

'use strict';
// var Address = require('address-rfc2821');
const assert = require('assert')
const fixtures = require('haraka-test-fixtures');
const connection = fixtures.connection;
const _set_up = function (done) {
function _set_up (done) {
this.plugin = new fixtures.plugin('rspamd');
this.plugin.register();
this.connection = connection.createConnection();
this.connection.transaction = fixtures.transaction.createTransaction()
// this.connection.init_transaction();
this.plugin = new fixtures.plugin('rspamd');
done();
}
describe('register', function () {
beforeEach(_set_up)
it('loads the rspamd plugin', function (done) {
assert.equal('rspamd', this.plugin.name);
done();
})
it('register loads rspamd.ini', function (done) {
this.plugin.register();
this.connection = connection.createConnection();
this.connection.init_transaction();
assert.ok(this.plugin.cfg);
assert.equal(true, this.plugin.cfg.reject.spam);
assert.ok(this.plugin.cfg.header.bar);
done();
})
})
describe('add_headers', function () {
beforeEach(_set_up)
it('add_headers exists as function', function (done) {
// console.log(this.plugin.cfg);
assert.equal('function', typeof this.plugin.add_headers);
done();
}
})
exports.register = {
setUp : _set_up,
'loads the rspamd plugin': function (test) {
test.expect(1);
test.equal('rspamd', this.plugin.name);
test.done();
},
'register loads rspamd.ini': function (test) {
test.expect(2);
this.plugin.register();
test.ok(this.plugin.cfg);
test.equal(true, this.plugin.cfg.reject.spam);
test.done();
},
}
it('adds a header to a message with positive score', function (done) {
const test_data = {
score: 1.1,
symbols: {
FOO: {
name: 'FOO',
score: 0.100000,
description: 'foo',
options: ['foo', 'bar'],
},
BAR: {
name: 'BAR',
score: 1.0,
description: 'bar',
}
}
};
this.plugin.cfg.main.add_headers = 'always';
this.plugin.add_headers(this.connection, test_data);
assert.deepEqual(this.connection.transaction.header.headers['x-rspamd-score'], [ '1.1' ]);
assert.deepEqual(this.connection.transaction.header.headers['x-rspamd-bar'], ['+']);
assert.deepEqual(this.connection.transaction.header.headers['x-rspamd-report'], ['FOO(0.1) BAR(1)']);
done();
})
exports.load_rspamd_ini = {
setUp : _set_up,
'loads rspamd.ini': function (test) {
test.expect(1);
this.plugin.load_rspamd_ini();
test.ok(this.plugin.cfg.header.bar);
test.done();
},
}
it('adds a header to a message with negative score', function (done) {
const test_data = {
score: -1
};
this.plugin.cfg.main.add_headers = 'always';
this.plugin.add_headers(this.connection, test_data);
// console.log(this.connection.transaction.header);
assert.deepEqual(this.connection.transaction.header.headers['x-rspamd-score'], ['-1']);
assert.deepEqual(this.connection.transaction.header.headers['x-rspamd-bar'], ['-']);
done();
})
})
exports.add_headers = {
setUp : _set_up,
'add_headers exists as function': function (test) {
test.expect(1);
// console.log(this.plugin.cfg);
test.equal('function', typeof this.plugin.add_headers);
// test.ok(!this.plugin.score_too_high(this.connection, {score: 5}));
test.done();
},
'adds a header to a message with positive score': function (test) {
test.expect(3);
const test_data = {
score: 1.1,
symbols: {
FOO: {
name: 'FOO',
score: 0.100000,
description: 'foo',
options: ['foo', 'bar'],
},
BAR: {
name: 'BAR',
score: 1.0,
description: 'bar',
}
}
};
this.plugin.cfg.main.add_headers = 'always';
this.plugin.add_headers(this.connection, test_data);
test.equal(this.connection.transaction.header.headers['X-Rspamd-Score'], '1.1');
test.equal(this.connection.transaction.header.headers['X-Rspamd-Bar'], '+');
test.equal(this.connection.transaction.header.headers['X-Rspamd-Report'], 'FOO(0.1) BAR(1)');
test.done();
},
'adds a header to a message with negative score': function (test) {
test.expect(2);
const test_data = {
score: -1
};
this.plugin.cfg.main.add_headers = 'always';
this.plugin.add_headers(this.connection, test_data);
// console.log(this.connection.transaction.header);
test.equal(this.connection.transaction.header.headers['X-Rspamd-Score'], '-1');
test.equal(this.connection.transaction.header.headers['X-Rspamd-Bar'], '-');
test.done();
}
}
exports.wants_headers_added = {
setUp : _set_up,
'wants no headers when add_headers=never': function (test) {
test.expect(1);
this.plugin.cfg.main.add_headers='never';
test.equal(
this.plugin.wants_headers_added({ action: 'add header' }),
false
);
test.done();
},
'always wants no headers when add_headers=always': function (test) {
test.expect(1);
this.plugin.cfg.main.add_headers='always';
test.equal(
this.plugin.wants_headers_added({ action: 'beat it' }),
true
);
test.done();
},
'wants headers when rspamd response indicates, add_headers=sometimes': function (test) {
test.expect(2);
this.plugin.cfg.main.add_headers='sometimes';
test.equal(
this.plugin.wants_headers_added({ action: 'add header' }),
true
);
test.equal(
this.plugin.wants_headers_added({ action: 'brownlist' }),
false
);
test.done();
}
}
describe('wants_headers_added', function () {
exports.parse_response = {
setUp : _set_up,
'returns undef on empty string': function (test) {
test.expect(1);
// console.log(this.connection.transaction);
test.equal(
this.plugin.parse_response('', this.connection),
undefined
);
test.done();
},
'returns undef on empty object': function (test) {
test.expect(1);
test.equal(
this.plugin.parse_response('{}', this.connection),
undefined
);
test.done();
},
}
beforeEach(_set_up)
function _check_setup (done) {
it('wants no headers when add_headers=never', function (done) {
this.plugin.cfg.main.add_headers='never';
assert.equal(
this.plugin.wants_headers_added({ action: 'add header' }),
false
);
done();
})
it('always wants no headers when add_headers=always', function (done) {
this.plugin.cfg.main.add_headers='always';
assert.equal(
this.plugin.wants_headers_added({ action: 'beat it' }),
true
);
done();
})
it('wants headers when rspamd response indicates, add_headers=sometimes', function (done) {
this.plugin.cfg.main.add_headers='sometimes';
assert.equal(
this.plugin.wants_headers_added({ action: 'add header' }),
true
);
assert.equal(
this.plugin.wants_headers_added({ action: 'brownlist' }),
false
);
done();
})
})
describe('parse_response', function () {
beforeEach(_set_up)
it('returns undef on empty string', function (done) {
// console.log(this.connection.transaction);
assert.equal(
this.plugin.parse_response('', this.connection),
undefined
);
done();
})
it('returns undef on empty object', function (done) {
assert.equal(
this.plugin.parse_response('{}', this.connection),
undefined
);
done();
})
})
describe('should_check', function () {
beforeEach(function (done) {
this.plugin = new fixtures.plugin('rspamd');

@@ -165,105 +161,91 @@ this.plugin.register();

done()
}
})
exports.should_check = {
setUp : _check_setup,
'checks authenticated': function (test) {
this.connection.notes.auth_user = "username";
this.plugin.cfg.check.authenticated = true;
it('checks authenticated', function (done) {
this.connection.notes.auth_user = "username";
this.plugin.cfg.check.authenticated = true;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'skips authenticated': function (test) {
this.connection.notes.auth_user = "username";
this.plugin.cfg.check.authenticated = false;
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('skips authenticated', function (done) {
this.connection.notes.auth_user = "username";
this.plugin.cfg.check.authenticated = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), false);
test.done();
},
'skips relaying': function (test) {
this.connection.relaying = true;
this.plugin.cfg.check.relay = false;
assert.equal(this.plugin.should_check(this.connection), false);
done();
})
it('skips relaying', function (done) {
this.connection.relaying = true;
this.plugin.cfg.check.relay = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), false);
test.done();
},
'checks not relaying': function (test) {
this.connection.relaying = false;
this.plugin.cfg.check.relay = false;
assert.equal(this.plugin.should_check(this.connection), false);
done();
})
it('checks not relaying', function (done) {
this.connection.relaying = false;
this.plugin.cfg.check.relay = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'checks relaying when enabled': function (test) {
this.connection.relaying = true;
this.plugin.cfg.check.relay = true;
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('checks relaying when enabled', function (done) {
this.connection.relaying = true;
this.plugin.cfg.check.relay = true;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'checks local IP': function (test) {
this.connection.remote.is_local = true;
this.plugin.cfg.check.local_ip = true;
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('checks local IP', function (done) {
this.connection.remote.is_local = true;
this.plugin.cfg.check.local_ip = true;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'skips local IP': function (test) {
this.connection.remote.is_local = true;
this.plugin.cfg.check.local_ip = false;
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('skips local IP', function (done) {
this.connection.remote.is_local = true;
this.plugin.cfg.check.local_ip = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), false);
test.done();
},
'checks private IP': function (test) {
this.connection.remote.is_private = true;
this.plugin.cfg.check.private_ip = true;
assert.equal(this.plugin.should_check(this.connection), false);
done();
})
it('checks private IP', function (done) {
this.connection.remote.is_private = true;
this.plugin.cfg.check.private_ip = true;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'skips private IP': function (test) {
this.connection.remote.is_private = true;
this.plugin.cfg.check.private_ip = false;
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('skips private IP', function (done) {
this.connection.remote.is_private = true;
this.plugin.cfg.check.private_ip = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), false);
test.done();
},
'checks public ip': function (test) {
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
'skip localhost if check.local_ip = false and check.private_ip = true': function (test) {
this.connection.remote.is_local = true;
this.connection.remote.is_private = true;
assert.equal(this.plugin.should_check(this.connection), false);
done();
})
it('checks public ip', function (done) {
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
it('skip localhost if check.local_ip = false and check.private_ip = true', function (done) {
this.connection.remote.is_local = true;
this.connection.remote.is_private = true;
this.plugin.cfg.check.local_ip = false;
this.plugin.cfg.check.private_ip = true;
this.plugin.cfg.check.local_ip = false;
this.plugin.cfg.check.private_ip = true;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), false);
test.done();
},
'checks localhost if check.local_ip = true and check.private_ip = false': function (test) {
this.connection.remote.is_local = true;
this.connection.remote.is_private = true;
assert.equal(this.plugin.should_check(this.connection), false);
done();
})
it('checks localhost if check.local_ip = true and check.private_ip = false', function (done) {
this.connection.remote.is_local = true;
this.connection.remote.is_private = true;
this.plugin.cfg.check.local_ip = true;
this.plugin.cfg.check.private_ip = false;
this.plugin.cfg.check.local_ip = true;
this.plugin.cfg.check.private_ip = false;
test.expect(1);
test.equal(this.plugin.should_check(this.connection), true);
test.done();
},
}
assert.equal(this.plugin.should_check(this.connection), true);
done();
})
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc