From 0018c8d2531e93883441e8bddab87548f190e176 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 18 Apr 2015 08:04:50 +0300 Subject: Rewrite sieve filter script * Mailman/Handlers/Sieve.py: Rewrite using libmu_python * bin/mailsync: Change default location for configuration file. * man/mailsync.1: Update --- Mailman/Handlers/Sieve.py | 96 +++++++++++++++++++++++++++-------------------- bin/mailsync | 5 ++- man/mailsync.1 | 13 +++++-- 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/Mailman/Handlers/Sieve.py b/Mailman/Handlers/Sieve.py index 9b187a4..077f5ab 100644 --- a/Mailman/Handlers/Sieve.py +++ b/Mailman/Handlers/Sieve.py @@ -1,6 +1,5 @@ # GNU Mailutils -- a suite of utilities for electronic mail -# Copyright (C) 1999, 2000, 2001, 2002, 2003, -# 2005, 2006, 2007, 2008, 2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2015 Free Software Foundation, Inc. # # GNU Mailutils is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,62 +12,77 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with GNU Mailutils; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA +# along with GNU Mailutils. If not, see . -"""Filter message through GNU Sieve. +"""Filter message through GNU Mailutils (sieve).""" -Since there is no Mailutils module (yet), the sieve binary is invoked -with `-f -' flag and the message is fed to it. If sieve exits successfully, -the message is accepted. If it exits with code 1, which means the Sieve -script used discard, the message is discarded. Otherwise, the message is -held for approval. -""" - -import string import os +import sys + +from email.MIMEMessage import MIMEMessage +from email.MIMEText import MIMEText -from subprocess import Popen,PIPE from Mailman import mm_cfg from Mailman import Errors +from Mailman import Utils +from Mailman import Message from Mailman.Logging.Syslog import syslog from Mailman.Handlers import Hold -sieve_program = "/usr/local/bin/sieve" -sieve_script_dir="/srv/mailman/sieve" +from mailutils import stream, sieve +from mailutils.error import SieveMachineError,MU_ERR_PARSE class SieveDiscard(Errors.DiscardMessage): - '''The message was discarded by Sieve''' + """The message was discarded by Sieve""" reason = 'Sieve discarded this message' rejection = 'Your message has been discarded by mail filter' class SieveHold(Errors.HoldMessage): - '''The message was held due to Sieve error''' - def __init__(self, retcode, err): - Errors.HoldMessage.__init__(self) - self.reason = 'Your message was held for moderation because of' \ - ' internal software error or misconfiguration.' \ - ' Please, report this to the list owner.' + """The message was held due to Sieve error""" + reason = 'Your message was held for moderation because of' \ + ' internal software error or misconfiguration.' \ + ' Please, report this to the list owner.' - def process(mlist, msg, msgdata): - syslog("post", "begin") if msgdata.get('approved'): return - script = sieve_script_dir + "/" + mlist.internal_name() + '.siv' - syslog("post", "Using script file %s" % (script)) - if os.path.isfile(script): - p = Popen([sieve_program, "--program-name", "mailman-sieve", "-f", "-", script], shell=False, stdin=PIPE, - stdout=PIPE, stderr=PIPE) - (out,err) = p.communicate(str(msg)) - if p.returncode != 0 and p.returncode != 1: - syslog("post", "%s returned %d, error=%s" - % (sieve_program, p.returncode, err)) - if p.returncode == 1: - raise SieveDiscard - elif p.returncode != 0: - Hold.hold_for_approval(mlist, msg, msgdata, - SieveHold(p.returncode, err)) + scriptbasename = mlist.internal_name() + '.siv' + script = mm_cfg.SIEVE_SCRIPT_DIR + "/" + scriptbasename + if not os.path.isfile(script): + return + syslog("post", "Sieve is using script file %s" % script) + + try: + mu_msg = stream.MemoryStream(str(msg)).to_message() + mu_sieve = sieve.Machine() + mu_sieve.compile(script) + mu_sieve.message(mu_msg) + except SieveMachineError, e: + lang = mlist.preferred_language + nmsg = Message.UserNotification(mlist.GetOwnerEmail(), + mlist.GetBouncesEmail(), + 'Sieve error notification', + lang=lang) + nmsg.set_type('multipart/mixed') + if e.status == MU_ERR_PARSE: + text = MIMEText(Utils.wrap('Sieve was unable to compile your script %s. The reason given was as follows:\n\n%s\n\nFor convenience, the failed script is attached herewith.' % (scriptbasename, e.strerror)), + charset=Utils.GetCharSet(lang)) + else: + text = 'Sieve failed to execute script %s:\n\n %s.' % \ + (script, e.strerror) + text = MIMEText(Utils.wrap(text), + charset=Utils.GetCharSet(lang)) + + nmsg.attach(text) + nmsg.attach(MIMEText(open(script, 'r').read())) + + nmsg['X-Mailer'] = "Mailman Sieve Processor" + nmsg.send(mlist) + + Hold.hold_for_approval(mlist, msg, msgdata, SieveHold) + + except Exception, e: + Hold.hold_for_approval(mlist, msg, msgdata, SieveHold) - + if mu_msg.attribute.is_deleted(): + raise SieveDiscard diff --git a/bin/mailsync b/bin/mailsync index a3b7308..04b0f3b 100755 --- a/bin/mailsync +++ b/bin/mailsync @@ -259,7 +259,7 @@ OPTIONS are: exit(code) if __name__ == '__main__': - config = '/etc/mailsync.conf' + config = '' try: opts, args = getopt.getopt(sys.argv[1:], "dhc:nr", ["debug", "help", "config=", "dry-run", @@ -282,6 +282,9 @@ if __name__ == '__main__': if dry_run: dbg += 1 + if config == '': + config = os.path.abspath(os.path.dirname(sys.argv[0]) + '/../etc/mailsync.conf') + read_config(config) if len(args) > 0: diff --git a/man/mailsync.1 b/man/mailsync.1 index cbac3a2..0a68132 100644 --- a/man/mailsync.1 +++ b/man/mailsync.1 @@ -13,7 +13,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with this program. If not, see . -.TH MAILSYNC 1 "April 9, 2015" "MAILSYNC" +.TH MAILSYNC 1 "April 17, 2015" "MAILSYNC" .SH NAME mailsync - synchronize Mailman archives with html .SH SYNOPSIS @@ -33,8 +33,15 @@ for conversion and .BR mknmz (1) for indexing. .PP -All necessary settings are defined in the configuration file -\fB/etc/mailsync.conf\fR. Alternative location can be given using the +All necessary settings are defined in the configuration file. By +default, the program reads file \fBmailsync.conf\fR located in the +directory \fBetc\fR one directory level up relative to the program +itself. E.g. if the full pathname of the program is +.BR /var/mailman/bin/mailsync , +then the configuration file is +.BR /var/mailman/etc/mailsync.conf . +.PP +Alternative location can be given using the \fB\-c\fR (\fB\-\-config\fR) command line option. .PP The file consists of sections and statements. Sections are declared -- cgit v1.2.1