comparison tests/dummysmtpd.py @ 29332:2bb0ddd8267b

tests: add dummy SMTP daemon for SSL tests Currently it only supports SMTP over SSL since SMTPS should be simpler than handling StartTLS. Since we don't need asynchronous server for our tests, it does TLS handshake in blocking way. But asyncore is required by Python smtpd module.
author Yuya Nishihara <yuya@tcha.org>
date Fri, 27 May 2016 22:43:47 +0900
parents
children 1b8b6adb2365
comparison
equal deleted inserted replaced
29331:1e02d9576194 29332:2bb0ddd8267b
1 #!/usr/bin/env python
2
3 """dummy SMTP server for use in tests"""
4
5 from __future__ import absolute_import
6
7 import asyncore
8 import optparse
9 import smtpd
10 import ssl
11 import sys
12
13 from mercurial import (
14 cmdutil,
15 )
16
17 def log(msg):
18 sys.stdout.write(msg)
19 sys.stdout.flush()
20
21 class dummysmtpserver(smtpd.SMTPServer):
22 def __init__(self, localaddr):
23 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None)
24
25 def process_message(self, peer, mailfrom, rcpttos, data):
26 log('%s from=%s to=%s\n' % (peer[0], mailfrom, ', '.join(rcpttos)))
27
28 class dummysmtpsecureserver(dummysmtpserver):
29 def __init__(self, localaddr, certfile):
30 dummysmtpserver.__init__(self, localaddr)
31 self._certfile = certfile
32
33 def handle_accept(self):
34 pair = self.accept()
35 if not pair:
36 return
37 conn, addr = pair
38 try:
39 # wrap_socket() would block, but we don't care
40 conn = ssl.wrap_socket(conn, server_side=True,
41 certfile=self._certfile,
42 ssl_version=ssl.PROTOCOL_TLSv1)
43 except ssl.SSLError:
44 log('%s ssl error\n' % addr[0])
45 conn.close()
46 return
47 smtpd.SMTPChannel(self, conn, addr)
48
49 def run():
50 try:
51 asyncore.loop()
52 except KeyboardInterrupt:
53 pass
54
55 def main():
56 op = optparse.OptionParser()
57 op.add_option('-d', '--daemon', action='store_true')
58 op.add_option('--daemon-postexec', action='append')
59 op.add_option('-p', '--port', type=int, default=8025)
60 op.add_option('-a', '--address', default='localhost')
61 op.add_option('--pid-file', metavar='FILE')
62 op.add_option('--tls', choices=['none', 'smtps'], default='none')
63 op.add_option('--certificate', metavar='FILE')
64
65 opts, args = op.parse_args()
66 if opts.tls == 'smtps' and not opts.certificate:
67 op.error('--certificate must be specified')
68
69 addr = (opts.address, opts.port)
70 def init():
71 if opts.tls == 'none':
72 dummysmtpserver(addr)
73 else:
74 dummysmtpsecureserver(addr, opts.certificate)
75 log('listening at %s:%d\n' % addr)
76
77 cmdutil.service(vars(opts), initfn=init, runfn=run,
78 runargs=[sys.executable, __file__] + sys.argv[1:])
79
80 if __name__ == '__main__':
81 main()