aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorcebka@lenovo-laptop <cebka@lenovo-laptop>2010-02-01 20:01:20 +0300
committercebka@lenovo-laptop <cebka@lenovo-laptop>2010-02-01 20:01:20 +0300
commitbb5a1a9fb091ae443dd37c497fcf9202649ba95d (patch)
tree89630df9ae350df9cb29932387042e3626ae723a /src
parent18b4a627676f71b37c98f566218fad6a249025cb (diff)
downloadrspamd-bb5a1a9fb091ae443dd37c497fcf9202649ba95d.tar.gz
rspamd-bb5a1a9fb091ae443dd37c497fcf9202649ba95d.zip
* Add maillist plugin for detecting mailmain/ezml and subscribe.ru lists
Diffstat (limited to 'src')
-rw-r--r--src/main.c1
-rw-r--r--src/plugins/lua/maillist.lua179
2 files changed, 180 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
index ee0a1ae56..49ac3da86 100644
--- a/src/main.c
+++ b/src/main.c
@@ -610,6 +610,7 @@ main (int argc, char **argv, char **env)
/* First set logger to console logger */
rspamd_set_logger (RSPAMD_LOG_CONSOLE, rspamd->cfg);
+ (void)open_log ();
g_log_set_default_handler (rspamd_glib_log_function, cfg);
#ifndef HAVE_SETPROCTITLE
diff --git a/src/plugins/lua/maillist.lua b/src/plugins/lua/maillist.lua
new file mode 100644
index 000000000..18514aa86
--- /dev/null
+++ b/src/plugins/lua/maillist.lua
@@ -0,0 +1,179 @@
+-- Module for checking mail list headers
+
+
+local metric = 'default'
+local symbol = 'MAILLIST'
+
+-- EZMLM
+-- Mailing-List: .*run by ezmlm
+-- Precedence: bulk
+-- List-Post: <mailto:
+-- List-Help: <mailto:
+-- List-Unsubscribe: <mailto:[a-zA-Z\.-]+-unsubscribe@
+-- List-Subscribe: <mailto:[a-zA-Z\.-]+-subscribe@
+function check_ml_ezmlm(task)
+ local message = task:get_message()
+ -- Mailing-List
+ local header = message:get_header('mailing-list')
+ if not header or not string.find(header[1], 'ezmlm$') then
+ return false
+ end
+ -- Precedence
+ header = message:get_header('precedence')
+ if not header or not string.match(header[1], '^bulk$') then
+ return false
+ end
+ -- Other headers
+ header = message:get_header('list-post')
+ if not header or not string.find(header[1], '^<mailto:') then
+ return false
+ end
+ header = message:get_header('list-help')
+ if not header or not string.find(header[1], '^<mailto:') then
+ return false
+ end
+ -- Subscribe and unsubscribe
+ header = message:get_header('list-subscribe')
+ if not header or not string.find(header[1], '<mailto:[a-zA-Z.-]+-subscribe@') then
+ return false
+ end
+ header = message:get_header('list-unsubscribe')
+ if not header or not string.find(header[1], '<mailto:[a-zA-Z.-]+-unsubscribe@') then
+ return false
+ end
+
+ return true
+end
+
+-- MailMan (the gnu mailing list manager)
+-- Precedence: bulk [or list for v2]
+-- List-Help: <mailto:
+-- List-Post: <mailto:
+-- List-Subscribe: .*<mailto:.*=subscribe>
+-- List-Id:
+-- List-Unsubscribe: .*<mailto:.*=unsubscribe>
+-- List-Archive:
+-- X-Mailman-Version: \d
+function check_ml_mailman(task)
+ local message = task:get_message()
+ -- Mailing-List
+ local header = message:get_header('x-mailman-version')
+ if not header or not string.find(header[1], '^%d') then
+ return false
+ end
+ -- Precedence
+ header = message:get_header('precedence')
+ if not header or (not string.match(header[1], '^bulk$') and not string.match(header[1], '^list$')) then
+ return false
+ end
+ -- For reminders we have other headers than for normal messages
+ header = message:get_header('x-list-administrivia')
+ local subject = message:get_header('subject')
+ if (header and string.find(header[1], 'yes')) or (subject and string.find(subject[1], 'mailing list memberships reminder$')) then
+ if not message:get_header('errors-to') or not message:get_header('x-beenthere') then
+ return false
+ end
+ header = message:get_header('x-no-archive')
+ if not header or not string.find(header[1], 'yes') then
+ return false
+ end
+ return true
+ end
+
+ -- Other headers
+ header = message:get_header('list-id')
+ if not header then
+ return false
+ end
+ header = message:get_header('list-post')
+ if not header or not string.find(header[1], '^<mailto:') then
+ return false
+ end
+ header = message:get_header('list-help')
+ if not header or not string.find(header[1], '^<mailto:') then
+ return false
+ end
+ -- Subscribe and unsubscribe
+ header = message:get_header('list-subscribe')
+ if not header or not string.find(header[1], '<mailto:.*=subscribe>') then
+ return false
+ end
+ header = message:get_header('list-unsubscribe')
+ if not header or not string.find(header[1], '<mailto:.*=unsubscribe>') then
+ return false
+ end
+
+ return true
+
+end
+
+-- Subscribe.ru
+-- Precedence: normal
+-- List-Id: <.*.subscribe.ru>
+-- List-Help: <http://subscribe.ru/catalog/.*>
+-- List-Subscribe: <mailto:.*-sub@subscribe.ru>
+-- List-Unsubscribe: <mailto:.*-unsub@subscribe.ru>
+-- List-Archive: <http://subscribe.ru/archive/.*>
+-- List-Owner: <mailto:.*-owner@subscribe.ru>
+-- List-Post: NO
+function check_ml_subscriberu(task)
+ local message = task:get_message()
+ -- List-Id
+ local header = message:get_header('list-id')
+ if not header or not string.find(header[1], '^<.*%.subscribe%.ru>$') then
+ return false
+ end
+ -- Precedence
+ header = message:get_header('precedence')
+ if not header or not string.match(header[1], '^normal$') then
+ return false
+ end
+ -- Other headers
+ header = message:get_header('list-archive')
+ if not header or not string.find(header[1], '^<http://subscribe.ru/archive/.*>$') then
+ return false
+ end
+ header = message:get_header('list-owner')
+ if not header or not string.find(header[1], '^<mailto:.*-owner@subscribe.ru>$') then
+ return false
+ end
+ header = message:get_header('list-help')
+ if not header or not string.find(header[1], '^<http://subscribe.ru/catalog/.*>$') then
+ return false
+ end
+ -- Subscribe and unsubscribe
+ header = message:get_header('list-subscribe')
+ if not header or not string.find(header[1], '^<mailto:.*-sub@subscribe.ru>$') then
+ return false
+ end
+ header = message:get_header('list-unsubscribe')
+ if not header or not string.find(header[1], '^<mailto:.*-unsub@subscribe.ru>$') then
+ return false
+ end
+
+ return true
+
+end
+
+function check_maillist(task)
+ if check_ml_ezmlm(task) then
+ task:insert_result(metric, symbol, 1, 'ezmlm')
+ elseif check_ml_mailman(task) then
+ task:insert_result(metric, symbol, 1, 'mailman')
+ elseif check_ml_subscriberu(task) then
+ task:insert_result(metric, symbol, 1, 'subscribe.ru')
+ end
+end
+
+-- Configuration
+local opts = rspamd_config:get_all_opt('maillist')
+if opts then
+ if opts['symbol'] then
+ if opts['metric'] then
+ metric = opts['metric']
+ end
+ symbol = opts['symbol']
+ local m = rspamd_config:get_metric(metric)
+ m:register_symbol(symbol, 1.0, 'check_maillist')
+ end
+end