1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# GNU Mailutils -- a suite of utilities for electronic mail
# 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
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 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, see <http://www.gnu.org/licenses/>.
"""Filter message through GNU Mailutils (sieve)."""
import os
import sys
from email.MIMEMessage import MIMEMessage
from email.MIMEText import MIMEText
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
from mailutils import stream, sieve
from mailutils.error import SieveMachineError,MU_ERR_PARSE
class SieveDiscard(Errors.DiscardMessage):
"""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"""
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):
if msgdata.get('approved'):
return
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
|