Script arguments localhost:localport and remotehost:remoteport are now

optional, and default to `localhost' and ports 8025 and 25
respectively.

SMTPChannel.__init__(): Calculate __fqdn using socket.getfqdn()
instead of gethostby*() and friends.  This allows us to run this
script even if we don't have access to dns (assuming the localhost is
configured properly).

Also, restore my precious page breaks.  Hands off, oh Whitespace
Normalizer!
This commit is contained in:
Barry Warsaw 2001-10-04 16:27:04 +00:00
parent a645b30294
commit 0e8427e4f2
1 changed files with 28 additions and 18 deletions

View File

@ -1,7 +1,7 @@
#! /usr/bin/env python #! /usr/bin/env python
"""An RFC 2821 smtp proxy. """An RFC 2821 smtp proxy.
Usage: %(program)s [options] localhost:port remotehost:port Usage: %(program)s [options] [localhost:localport [remotehost:remoteport]]
Options: Options:
@ -30,8 +30,12 @@ Options:
Version: %(__version__)s Version: %(__version__)s
If localhost is not given then `localhost' is used, and if localport is not
given then 8025 is used. If remotehost is not given then `localhost' is used,
and if remoteport is not given, then 25 is used.
""" """
# Overview: # Overview:
# #
# This file implements the minimal SMTP protocol as defined in RFC 821. It # This file implements the minimal SMTP protocol as defined in RFC 821. It
@ -89,9 +93,10 @@ class Devnull:
DEBUGSTREAM = Devnull() DEBUGSTREAM = Devnull()
NEWLINE = '\n' NEWLINE = '\n'
EMPTYSTRING = '' EMPTYSTRING = ''
COMMASPACE = ', '
def usage(code, msg=''): def usage(code, msg=''):
print >> sys.stderr, __doc__ % globals() print >> sys.stderr, __doc__ % globals()
if msg: if msg:
@ -99,7 +104,7 @@ def usage(code, msg=''):
sys.exit(code) sys.exit(code)
class SMTPChannel(asynchat.async_chat): class SMTPChannel(asynchat.async_chat):
COMMAND = 0 COMMAND = 0
DATA = 1 DATA = 1
@ -115,8 +120,7 @@ class SMTPChannel(asynchat.async_chat):
self.__mailfrom = None self.__mailfrom = None
self.__rcpttos = [] self.__rcpttos = []
self.__data = '' self.__data = ''
self.__fqdn = socket.gethostbyaddr( self.__fqdn = socket.getfqdn()
socket.gethostbyname(socket.gethostname()))[0]
self.__peer = conn.getpeername() self.__peer = conn.getpeername()
print >> DEBUGSTREAM, 'Peer:', repr(self.__peer) print >> DEBUGSTREAM, 'Peer:', repr(self.__peer)
self.push('220 %s %s' % (self.__fqdn, __version__)) self.push('220 %s %s' % (self.__fqdn, __version__))
@ -265,7 +269,7 @@ class SMTPChannel(asynchat.async_chat):
self.push('354 End data with <CR><LF>.<CR><LF>') self.push('354 End data with <CR><LF>.<CR><LF>')
class SMTPServer(asyncore.dispatcher): class SMTPServer(asyncore.dispatcher):
def __init__(self, localaddr, remoteaddr): def __init__(self, localaddr, remoteaddr):
self._localaddr = localaddr self._localaddr = localaddr
@ -313,6 +317,7 @@ class SMTPServer(asyncore.dispatcher):
raise NotImplementedError raise NotImplementedError
class DebuggingServer(SMTPServer): class DebuggingServer(SMTPServer):
# Do something with the gathered message # Do something with the gathered message
def process_message(self, peer, mailfrom, rcpttos, data): def process_message(self, peer, mailfrom, rcpttos, data):
@ -328,7 +333,7 @@ class DebuggingServer(SMTPServer):
print '------------ END MESSAGE ------------' print '------------ END MESSAGE ------------'
class PureProxy(SMTPServer): class PureProxy(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data): def process_message(self, peer, mailfrom, rcpttos, data):
lines = data.split('\n') lines = data.split('\n')
@ -369,7 +374,7 @@ class PureProxy(SMTPServer):
return refused return refused
class MailmanProxy(PureProxy): class MailmanProxy(PureProxy):
def process_message(self, peer, mailfrom, rcpttos, data): def process_message(self, peer, mailfrom, rcpttos, data):
from cStringIO import StringIO from cStringIO import StringIO
@ -448,12 +453,13 @@ class MailmanProxy(PureProxy):
msg.Enqueue(mlist, torequest=1) msg.Enqueue(mlist, torequest=1)
class Options: class Options:
setuid = 1 setuid = 1
classname = 'PureProxy' classname = 'PureProxy'
def parseargs(): def parseargs():
global DEBUGSTREAM global DEBUGSTREAM
try: try:
@ -478,32 +484,36 @@ def parseargs():
DEBUGSTREAM = sys.stderr DEBUGSTREAM = sys.stderr
# parse the rest of the arguments # parse the rest of the arguments
try: if len(args) < 1:
localspec = 'localhost:8025'
remotespec = 'localhost:25'
elif len(args) < 2:
localspec = args[0] localspec = args[0]
remotespec = args[1] remotespec = 'localhost:25'
except IndexError: else:
usage(1, 'Not enough arguments') usage(1, 'Invalid arguments: %s' % COMMASPACE.join(args))
# split into host/port pairs # split into host/port pairs
i = localspec.find(':') i = localspec.find(':')
if i < 0: if i < 0:
usage(1, 'Bad local spec: "%s"' % localspec) usage(1, 'Bad local spec: %s' % localspec)
options.localhost = localspec[:i] options.localhost = localspec[:i]
try: try:
options.localport = int(localspec[i+1:]) options.localport = int(localspec[i+1:])
except ValueError: except ValueError:
usage(1, 'Bad local port: "%s"' % localspec) usage(1, 'Bad local port: %s' % localspec)
i = remotespec.find(':') i = remotespec.find(':')
if i < 0: if i < 0:
usage(1, 'Bad remote spec: "%s"' % remotespec) usage(1, 'Bad remote spec: %s' % remotespec)
options.remotehost = remotespec[:i] options.remotehost = remotespec[:i]
try: try:
options.remoteport = int(remotespec[i+1:]) options.remoteport = int(remotespec[i+1:])
except ValueError: except ValueError:
usage(1, 'Bad remote port: "%s"' % remotespec) usage(1, 'Bad remote port: %s' % remotespec)
return options return options
if __name__ == '__main__': if __name__ == '__main__':
options = parseargs() options = parseargs()
# Become nobody # Become nobody