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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import asynchat, asyncore, socket
import pwd, os, sys, logging, logging.handlers
import mailbox, email
class SMTPChannel(asynchat.async_chat):
def __init__(self, server, sock, addr):
asynchat.async_chat.__init__(self, sock)
self.server = server
self.set_terminator("\n")
self.data = ""
self.read_data = False
self.push("220 Mailserver terrorist.at. Nutzung ohne vorige Erlaubnis verboten!\n")
def collect_incoming_data(self, data):
if len(self.data) > 0:
self.data += "\n"
self.data += data
self.server.logger.debug("Read: " + data.strip())
if self.data.__len__() > 16384:
self.server.logger.error("too much data, shutdown")
self.close_when_done()
def push(self,data):
self.server.logger.debug("Write: " + data)
asynchat.async_chat.push(self,data)
def found_terminator(self):
try:
if self.read_data:
if self.data.endswith(".") or self.data.endswith(".\r"):
self.read_data = False
self.push("250 Ok: queued as 12345\n")
mail = email.message_from_string(self.data)
key=self.server.maildir.add(mail)
self.server.logger.info("New Mail: %s" % key)
self.server.maildir.flush()
self.data = ""
else:
pass
elif self.data.startswith("EHLO") \
or self.data.startswith("HELO"):
self.push("250 Mailserver terrorist.at. Nutzung ohne vorige Erlaubnis verboten!\n")
self.data = ""
elif self.data.startswith("DATA"):
self.push("354 End data with <CR><LF>.<CR><LF>\n")
self.read_data = True
self.data=""
elif self.data.startswith("QUIT"):
self.data = ""
self.push("221 Bye\n")
self.close_when_done()
else:
self.push("250 OK\n")
self.data = ""
except Exception,e:
self.server.logger.error(str(e))
class SMTPServer(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
self.port = 25
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(("", self.port))
self.listen(5)
self.maildir = mailbox.Maildir("Maildir", create=True)
self.logger = logging.getLogger('MyLogger')
self.logger.setLevel(logging.DEBUG)
handler = logging.handlers.TimedRotatingFileHandler("log/smtp.log", "D", 1)
self.logger.addHandler(handler)
def handle_accept(self):
conn, addr = self.accept()
self.logger.info("New Client %s:%s" % conn.getpeername())
try:
SMTPChannel(self, conn, addr)
except Exception,e:
self.logger.error(str(e))
if __name__ == '__main__':
s = SMTPServer()
#user change
pwinfo = pwd.getpwnam('nobody')
os.setregid(pwinfo[3],pwinfo[3])
os.setreuid(pwinfo[2],pwinfo[2])
#"Robustly turn into a UNIX daemon, running in our_home_dir."
# First fork
try:
if os.fork() > 0:
sys.exit(0) # kill off parent
except OSError, e:
sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))
sys.exit(1)
os.setsid()
os.chdir('/')
os.umask(0)
# Second fork
try:
pid = os.fork()
if pid > 0:
os._exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))
os._exit(1)
si = open('/dev/null', 'r')
so = open('/dev/null', 'a+', 0)
se = open('/dev/null', 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# Set custom file descriptors so that they get proper buffering.
sys.stdout, sys.stderr = so, se
#"""
s.logger.info("Startup; pid=%s" % os.getpid())
asyncore.loop()
|