\section{milter-\/nomix.\-py}

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