11#! /usr/bin/env python
22"""An RFC 2821 smtp proxy.
33
4- Usage: %(program)s [options] localhost:port remotehost:port
4+ Usage: %(program)s [options] [ localhost:localport [ remotehost:remoteport]]
55
66Options:
77
3030
3131Version: %(__version__)s
3232
33+ If localhost is not given then `localhost' is used, and if localport is not
34+ given then 8025 is used. If remotehost is not given then `localhost' is used,
35+ and if remoteport is not given, then 25 is used.
3336"""
3437
38+
3539# Overview:
3640#
3741# This file implements the minimal SMTP protocol as defined in RFC 821. It
@@ -89,17 +93,18 @@ def flush(self): pass
8993DEBUGSTREAM = Devnull ()
9094NEWLINE = '\n '
9195EMPTYSTRING = ''
96+ COMMASPACE = ', '
9297
9398
94-
99+
95100def usage (code , msg = '' ):
96101 print >> sys .stderr , __doc__ % globals ()
97102 if msg :
98103 print >> sys .stderr , msg
99104 sys .exit (code )
100105
101106
102-
107+
103108class SMTPChannel (asynchat .async_chat ):
104109 COMMAND = 0
105110 DATA = 1
@@ -115,8 +120,7 @@ def __init__(self, server, conn, addr):
115120 self .__mailfrom = None
116121 self .__rcpttos = []
117122 self .__data = ''
118- self .__fqdn = socket .gethostbyaddr (
119- socket .gethostbyname (socket .gethostname ()))[0 ]
123+ self .__fqdn = socket .getfqdn ()
120124 self .__peer = conn .getpeername ()
121125 print >> DEBUGSTREAM , 'Peer:' , repr (self .__peer )
122126 self .push ('220 %s %s' % (self .__fqdn , __version__ ))
@@ -265,7 +269,7 @@ def smtp_DATA(self, arg):
265269 self .push ('354 End data with <CR><LF>.<CR><LF>' )
266270
267271
268-
272+
269273class SMTPServer (asyncore .dispatcher ):
270274 def __init__ (self , localaddr , remoteaddr ):
271275 self ._localaddr = localaddr
@@ -313,6 +317,7 @@ def process_message(self, peer, mailfrom, rcpttos, data):
313317 raise NotImplementedError
314318
315319
320+
316321class DebuggingServer (SMTPServer ):
317322 # Do something with the gathered message
318323 def process_message (self , peer , mailfrom , rcpttos , data ):
@@ -328,7 +333,7 @@ def process_message(self, peer, mailfrom, rcpttos, data):
328333 print '------------ END MESSAGE ------------'
329334
330335
331-
336+
332337class PureProxy (SMTPServer ):
333338 def process_message (self , peer , mailfrom , rcpttos , data ):
334339 lines = data .split ('\n ' )
@@ -369,7 +374,7 @@ def _deliver(self, mailfrom, rcpttos, data):
369374 return refused
370375
371376
372-
377+
373378class MailmanProxy (PureProxy ):
374379 def process_message (self , peer , mailfrom , rcpttos , data ):
375380 from cStringIO import StringIO
@@ -448,12 +453,13 @@ def process_message(self, peer, mailfrom, rcpttos, data):
448453 msg .Enqueue (mlist , torequest = 1 )
449454
450455
451-
456+
452457class Options :
453458 setuid = 1
454459 classname = 'PureProxy'
455460
456461
462+
457463def parseargs ():
458464 global DEBUGSTREAM
459465 try :
@@ -478,32 +484,36 @@ def parseargs():
478484 DEBUGSTREAM = sys .stderr
479485
480486 # parse the rest of the arguments
481- try :
487+ if len (args ) < 1 :
488+ localspec = 'localhost:8025'
489+ remotespec = 'localhost:25'
490+ elif len (args ) < 2 :
482491 localspec = args [0 ]
483- remotespec = args [1 ]
484- except IndexError :
485- usage (1 , 'Not enough arguments' )
492+ remotespec = 'localhost:25'
493+ else :
494+ usage (1 , 'Invalid arguments: %s' % COMMASPACE .join (args ))
495+
486496 # split into host/port pairs
487497 i = localspec .find (':' )
488498 if i < 0 :
489- usage (1 , 'Bad local spec: "%s" ' % localspec )
499+ usage (1 , 'Bad local spec: %s ' % localspec )
490500 options .localhost = localspec [:i ]
491501 try :
492502 options .localport = int (localspec [i + 1 :])
493503 except ValueError :
494- usage (1 , 'Bad local port: "%s" ' % localspec )
504+ usage (1 , 'Bad local port: %s ' % localspec )
495505 i = remotespec .find (':' )
496506 if i < 0 :
497- usage (1 , 'Bad remote spec: "%s" ' % remotespec )
507+ usage (1 , 'Bad remote spec: %s ' % remotespec )
498508 options .remotehost = remotespec [:i ]
499509 try :
500510 options .remoteport = int (remotespec [i + 1 :])
501511 except ValueError :
502- usage (1 , 'Bad remote port: "%s" ' % remotespec )
512+ usage (1 , 'Bad remote port: %s ' % remotespec )
503513 return options
504514
505515
506-
516+
507517if __name__ == '__main__' :
508518 options = parseargs ()
509519 # Become nobody
0 commit comments