pymilter  0.9.8
milter-nomix.py
1 ## A very simple milter to prevent mixing of internal and external mail.
2 # Internal is defined as using one of a list of internal top level domains.
3 # This code is open-source on the same terms as Python.
4 
5 import Milter
6 import time
7 import sys
8 from Milter.utils import parse_addr
9 
10 internal_tlds = ["corp", "personal"]
11 
12 ## Determine if a hostname is internal or not.
13 # True if internal, False otherwise
14 def is_internal(hostname):
15  components = hostname.split(".")
16  return components.pop() in internal_tlds:
17 
18 # Determine if internal and external hosts are mixed based on a list
19 # of hostnames
20 def are_mixed(hostnames):
21  hostnames_mapped = map(is_internal, hostnames)
22 
23  # Num internals
24  num_internal_hosts = hostnames_mapped.count(True)
25 
26  # Num externals
27  num_external_hosts = hostnames_mapped.count(False)
28 
29  return num_external_hosts >= 1 and num_internal_hosts >= 1
30 
31 class NoMixMilter(Milter.Base):
32 
33  def __init__(self): # A new instance with each new connection.
34  self.id = Milter.uniqueID() # Integer incremented with each call.
35 
36 
37  ## def envfrom(self,f,*str):
38  @Milter.noreply
39  def envfrom(self, mailfrom, *str):
40  self.mailfrom = mailfrom
41  self.domains = []
42  t = parse_addr(mailfrom)
43  if len(t) > 1:
44  self.domains.append(t[1])
45  else:
46  self.domains.append('local')
47  self.internal = False
48  return Milter.CONTINUE
49 
50  ## def envrcpt(self, to, *str):
51  def envrcpt(self, to, *str):
52  self.R.append(to)
53  t = parse_addr(to)
54  if len(t) > 1:
55  self.domains.append(t[1])
56  else:
57  self.domains.append('local')
58 
59  if are_mixed(self.domains):
60  # FIXME: log recipients collected in self.mailfrom and self.R
61  self.setreply('550','5.7.1','Mixing internal and external TLDs')
62  return Milter.REJECT
63 
64  return Milter.CONTINUE
65 
66 def main():
67  socketname = "/var/run/nomixsock"
68  timeout = 600
69  # Register to have the Milter factory create instances of your class:
70  Milter.factory = NoMixMilter
71  print "%s milter startup" % time.strftime('%Y%b%d %H:%M:%S')
72  sys.stdout.flush()
73  Milter.runmilter("nomixfilter",socketname,timeout)
74  logq.put(None)
75  bt.join()
76  print "%s nomix milter shutdown" % time.strftime('%Y%b%d %H:%M:%S')
77 
78 if __name__ == "__main__":
79  main()