summaryrefslogtreecommitdiff
blob: dc5d84281613afbb4979eaa1b4e9591f31a52f07 (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
"""Reject messages at RCPT_TO time if the envelop sender is not subscribed.

Gentoo's mlmmj is configured to silently drop messages if the poster is not
subscribed (including no bounces) to prevent backscatter. This milter is
intended to work around this problem by rejecting messages at message-send
time. We do this by:

    - Looking at RCPT TO headers to see where the message is headed.
    - If its an mlmmj list, checking the subscriber list.
    - If the envelop sender is not subscribed, reject the message rather
       than accepting it for delivery.

This is accomplished with a sendmail compatible milter that receives
callbacks for every message seen by postfix and computing some extra logic
to enforce these rules.
"""

import os
import Milter
import mlmmj

def SubscribedMilterFactory():
    """Return a SubscribedMilter with a MlmmjSource configured."""
    inst = mlmmj.GetSingletonConfig()
    return SubscribedMilter(mlmmj_config=inst)


class SubscribedMilter(Milter.Base):
    """Rejects messages at accept time if address is not subscribed."""

    def __init__(self, mlmmj_config):
        self.mlmmj_config = mlmmj_config

    def envfrom(self, mailfrom, *args):
        # Store the envelope sender for later computation
        self.mailfrom = mailfrom
        return Milter.CONTINUE

    def envrcpt(self, to, *args):
        if mlmmj_config.IsMailingList(to):
            if mlmmj_config.IsSubscribed(self.mailfrom, to):
                return Milter.ACCEPT
            else:
                self.setreply('550', '5.7.1',
                        '%s is not a subscriber to %d; please subscribe to send messages to this list.' %(self.mailfrom, to))
                return Milter.REJECT

if __name__ == "__main__":
    socketname = "/var/run/mlmmj-milter.sock"
    timeout = 600
    Milter.factory = SubscribedMilterFactory
    Milter.runmilter("MlmmjMilter", socketname, timeout)