Advertisement
Guest User

Untitled

a guest
Feb 25th, 2018
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.67 KB | None | 0 0
  1. """pypopper: a file-based pop3 server
  2.  
  3. Useage:
  4. python pypopper.py <port> <path_to_message_file>
  5. """
  6. import logging
  7. import os
  8. import socket
  9. import sys
  10. import traceback
  11.  
  12. logging.basicConfig(format="%(name)s %(levelname)s - %(message)s")
  13. log = logging.getLogger("pypopper")
  14. log.setLevel(logging.INFO)
  15.  
  16. class ChatterboxConnection(object):
  17. END = "\r\n"
  18. def __init__(self, conn):
  19. self.conn = conn
  20. def __getattr__(self, name):
  21. return getattr(self.conn, name)
  22. def sendall(self, data, END=END):
  23. if len(data) < 50:
  24. log.debug("send: %r", data)
  25. else:
  26. log.debug("send: %r...", data[:50])
  27. data += END
  28. self.conn.sendall(data)
  29. def recvall(self, END=END):
  30. data = []
  31. while True:
  32. chunk = self.conn.recv(4096)
  33. if END in chunk:
  34. data.append(chunk[:chunk.index(END)])
  35. break
  36. data.append(chunk)
  37. if len(data) > 1:
  38. pair = data[-2] + data[-1]
  39. if END in pair:
  40. data[-2] = pair[:pair.index(END)]
  41. data.pop()
  42. break
  43. log.debug("recv: %r", "".join(data))
  44. return "".join(data)
  45.  
  46.  
  47. class Message(object):
  48. def __init__(self, filename):
  49. msg = open(filename, "r")
  50. try:
  51. self.data = data = msg.read()
  52. self.size = len(data)
  53. self.top, bot = data.split("\r\n\r\n", 1)
  54. self.bot = bot.split("\r\n")
  55. finally:
  56. msg.close()
  57.  
  58.  
  59. def handleUser(data, msg):
  60. return "+OK user accepted"
  61.  
  62. def handlePass(data, msg):
  63. return "+OK pass accepted"
  64.  
  65. def handleStat(data, msg):
  66. return "+OK 1 %i" % msg.size
  67.  
  68. def handleList(data, msg):
  69. return "+OK 1 messages (%i octets)\r\n1 %i\r\n." % (msg.size, msg.size)
  70.  
  71. def handleTop(data, msg):
  72. cmd, num, lines = data.split()
  73. assert num == "1", "unknown message number: %s" % num
  74. lines = int(lines)
  75. text = msg.top + "\r\n\r\n" + "\r\n".join(msg.bot[:lines])
  76. return "+OK top of message follows\r\n%s\r\n." % text
  77.  
  78. def handleRetr(data, msg):
  79. log.info("message sent")
  80. return "+OK %i octets\r\n%s\r\n." % (msg.size, msg.data)
  81.  
  82. def handleDele(data, msg):
  83. return "+OK message 1 deleted"
  84.  
  85. def handleNoop(data, msg):
  86. return "+OK"
  87.  
  88. def handleQuit(data, msg):
  89. return "+OK pypopper POP3 server signing off"
  90.  
  91. dispatch = dict(
  92. USER=handleUser,
  93. PASS=handlePass,
  94. STAT=handleStat,
  95. LIST=handleList,
  96. TOP=handleTop,
  97. RETR=handleRetr,
  98. DELE=handleDele,
  99. NOOP=handleNoop,
  100. QUIT=handleQuit,
  101. )
  102.  
  103. def serve(host, port, filename):
  104. assert os.path.exists(filename)
  105. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  106. sock.bind((host, port))
  107. try:
  108. if host:
  109. hostname = host
  110. else:
  111. hostname = "localhost"
  112. log.info("pypopper POP3 serving '%s' on %s:%s", filename, hostname, port)
  113. while True:
  114. sock.listen(1)
  115. conn, addr = sock.accept()
  116. log.debug('Connected by %s', addr)
  117. try:
  118. msg = Message(filename)
  119. conn = ChatterboxConnection(conn)
  120. conn.sendall("+OK pypopper file-based pop3 server ready")
  121. while True:
  122. data = conn.recvall()
  123. command = data.split(None, 1)[0]
  124. try:
  125. cmd = dispatch[command]
  126. except KeyError:
  127. conn.sendall("-ERR unknown command")
  128. else:
  129. conn.sendall(cmd(data, msg))
  130. if cmd is handleQuit:
  131. break
  132. finally:
  133. conn.close()
  134. msg = None
  135. except (SystemExit, KeyboardInterrupt):
  136. log.info("pypopper stopped")
  137. except Exception, ex:
  138. log.critical("fatal error", exc_info=ex)
  139. finally:
  140. sock.shutdown(socket.SHUT_RDWR)
  141. sock.close()
  142.  
  143. if __name__ == "__main__":
  144. if len(sys.argv) != 3:
  145. print "USAGE: [<host>:]<port> <path_to_message_file>"
  146. else:
  147. _, port, filename = sys.argv
  148. if ":" in port:
  149. host = port[:port.index(":")]
  150. port = port[port.index(":") + 1:]
  151. else:
  152. host = ""
  153. try:
  154. port = int(port)
  155. except Exception:
  156. print "Unknown port:", port
  157. else:
  158. if os.path.exists(filename):
  159. serve(host, port, filename)
  160. else:
  161. print "File not found:", filename
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement