From df5b30b3820d927cc761782f8d6edf5795e89e3d Mon Sep 17 00:00:00 2001 From: yvesf Date: Sat, 20 Feb 2010 20:14:56 +0100 Subject: import --- .gitignore | 1 + logs/_dummy | 0 smtp.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 .gitignore create mode 100644 logs/_dummy create mode 100644 smtp.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9424bf4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/Maildir diff --git a/logs/_dummy b/logs/_dummy new file mode 100644 index 0000000..e69de29 diff --git a/smtp.py b/smtp.py new file mode 100644 index 0000000..b1b2e67 --- /dev/null +++ b/smtp.py @@ -0,0 +1,105 @@ +import asynchat, asyncore, socket +import pwd, os, sys +import email +from mailbox import Maildir,MaildirMessage + +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 + + def collect_incoming_data(self, data): + if len(self.data) > 0: + self.data += "\n" + self.data += data + if self.data.__len__() > 16384: + print "too much data, shutdown" + self.close_when_done() + + def found_terminator(self): + print self.data + if self.read_data: + if self.data.endswith("\n."): + self.push("250 Ok: queued as 12345\n") + self.read_data = False + mail = email.message_from_string(self.data) + self.server.maildir.add(mail) + self.server.maildir.flush() + self.data = "" + + elif self.data.startswith("EHLO") \ + or self.data.startswith("HELO"): + self.push("HELO there\n") + self.data = "" + elif self.data.startswith("DATA"): + self.push("354 End data with .\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 = "" + + +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 = Maildir("Maildir", create=True) + + def handle_accept(self): + conn, addr = self.accept() + SMTPChannel(self, conn, addr) + + + +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: + pid = os.fork() + if pid > 0: + print "PID: %s" % pid + 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: + if os.fork() > 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 + + asyncore.loop() -- cgit v1.2.1