Skip to content

Instantly share code, notes, and snippets.

@h3ct0r
Created August 5, 2015 15:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save h3ct0r/c46a148949f894741c6b to your computer and use it in GitHub Desktop.
Save h3ct0r/c46a148949f894741c6b to your computer and use it in GitHub Desktop.
SMTP server for development on localhost written in python
#!/usr/bin/env python
# This a simple smtp server for testing on localhost
# The original version is on https://coderwall.com/p/ufjgwa/smtp-server-on-python-for-development-with-storing-emails
# This version is more verbose on what is doing, with more parameters and fail safe checks.
import argparse
import asyncore
import smtpd
import time
import os
SMTPD_MAIN_CLASSES = [
smtpd.DebuggingServer.__name__,
smtpd.PureProxy.__name__,
smtpd.MailmanProxy.__name__,
]
def storeproxy_factory(base_class, store_path, verbose):
class StoreProxy(base_class):
def process_message(self, peer, mailfrom, rcpttos, data):
filename = '%d_%s.eml' % (int(time.time()), '_'.join(rcpttos))
with open(os.path.join(store_path, filename), 'w') as f:
f.write(data)
if verbose:
print data
return StoreProxy
def get_argparser():
parser = argparse.ArgumentParser(description='Development SMTPd')
parser.add_argument(
'-c',
'--class',
choices=SMTPD_MAIN_CLASSES,
default=SMTPD_MAIN_CLASSES[0],
type=str,
dest='klass'
)
parser.add_argument(
'-l',
'--localaddr',
nargs=1,
default='127.0.0.1:1025',
type=str
)
parser.add_argument(
'-r',
'--remoteaddr',
nargs=1,
default='127.0.0.1:2525',
type=str
)
parser.add_argument(
'-s',
'--store',
nargs=1,
type=str
)
parser.add_argument(
'-v',
'--verbose',
action='store_true'
)
return parser
def normalize_addr(addr):
if isinstance(addr, list):
addr = addr[0]
if ':' in addr:
host, port = addr.split(':')
return (host, int(port))
return None
def main():
args = get_argparser().parse_args()
server_class = getattr(smtpd, args.klass)
if args.store:
if not os.path.isdir(args.store[0]):
raise AttributeError("The file specified does not exists or is not a folder")
print "Storing in folder:", args.store[0]
server_class = storeproxy_factory(server_class, args.store[0], args.verbose)
server = server_class(
normalize_addr(args.localaddr),
normalize_addr(args.remoteaddr)
)
print "Server:", server_class
print "Address:", args.localaddr
print "Remote address:", args.remoteaddr
print "Verbose:", args.verbose
try:
asyncore.loop()
except KeyboardInterrupt:
server.close()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment