aboutsummaryrefslogtreecommitdiff
path: root/Mailman/Handlers/Sieve.py
blob: 077f5abc7f2943e6f4dce962d31b0892bbe80a01 (plain)
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

Return to:

Send suggestions and report system problems to the System administrator.