##// END OF EJS Templates
tests: fix dummysmtpd argument check
Mads Kiilerich -
r51624:8823e4d4 stable
parent child Browse files
Show More
@@ -1,125 +1,125 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 """dummy SMTP server for use in tests"""
3 """dummy SMTP server for use in tests"""
4
4
5
5
6 import asyncore
6 import asyncore
7 import optparse
7 import optparse
8 import smtpd
8 import smtpd
9 import ssl
9 import ssl
10 import sys
10 import sys
11 import traceback
11 import traceback
12
12
13 from mercurial import (
13 from mercurial import (
14 pycompat,
14 pycompat,
15 server,
15 server,
16 sslutil,
16 sslutil,
17 ui as uimod,
17 ui as uimod,
18 )
18 )
19
19
20
20
21 def log(msg):
21 def log(msg):
22 sys.stdout.write(msg)
22 sys.stdout.write(msg)
23 sys.stdout.flush()
23 sys.stdout.flush()
24
24
25
25
26 class dummysmtpserver(smtpd.SMTPServer):
26 class dummysmtpserver(smtpd.SMTPServer):
27 def __init__(self, localaddr):
27 def __init__(self, localaddr):
28 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None)
28 smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None)
29
29
30 def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
30 def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
31 log(
31 log(
32 '%s from=%s to=%s\n%s\n'
32 '%s from=%s to=%s\n%s\n'
33 % (peer[0], mailfrom, ', '.join(rcpttos), data.decode())
33 % (peer[0], mailfrom, ', '.join(rcpttos), data.decode())
34 )
34 )
35
35
36 def handle_error(self):
36 def handle_error(self):
37 # On Windows, a bad SSL connection sometimes generates a WSAECONNRESET.
37 # On Windows, a bad SSL connection sometimes generates a WSAECONNRESET.
38 # The default handler will shutdown this server, and then both the
38 # The default handler will shutdown this server, and then both the
39 # current connection and subsequent ones fail on the client side with
39 # current connection and subsequent ones fail on the client side with
40 # "No connection could be made because the target machine actively
40 # "No connection could be made because the target machine actively
41 # refused it". If we eat the error, then the client properly aborts in
41 # refused it". If we eat the error, then the client properly aborts in
42 # the expected way, and the server is available for subsequent requests.
42 # the expected way, and the server is available for subsequent requests.
43 traceback.print_exc()
43 traceback.print_exc()
44
44
45
45
46 class dummysmtpsecureserver(dummysmtpserver):
46 class dummysmtpsecureserver(dummysmtpserver):
47 def __init__(self, localaddr, certfile):
47 def __init__(self, localaddr, certfile):
48 dummysmtpserver.__init__(self, localaddr)
48 dummysmtpserver.__init__(self, localaddr)
49 self._certfile = certfile
49 self._certfile = certfile
50
50
51 def handle_accept(self):
51 def handle_accept(self):
52 pair = self.accept()
52 pair = self.accept()
53 if not pair:
53 if not pair:
54 return
54 return
55 conn, addr = pair
55 conn, addr = pair
56 ui = uimod.ui.load()
56 ui = uimod.ui.load()
57 try:
57 try:
58 # wrap_socket() would block, but we don't care
58 # wrap_socket() would block, but we don't care
59 conn = sslutil.wrapserversocket(conn, ui, certfile=self._certfile)
59 conn = sslutil.wrapserversocket(conn, ui, certfile=self._certfile)
60 except ssl.SSLError as e:
60 except ssl.SSLError as e:
61 log('%s ssl error: %s\n' % (addr[0], e))
61 log('%s ssl error: %s\n' % (addr[0], e))
62 conn.close()
62 conn.close()
63 return
63 return
64 smtpd.SMTPChannel(self, conn, addr)
64 smtpd.SMTPChannel(self, conn, addr)
65
65
66
66
67 def run():
67 def run():
68 try:
68 try:
69 asyncore.loop()
69 asyncore.loop()
70 except KeyboardInterrupt:
70 except KeyboardInterrupt:
71 pass
71 pass
72
72
73
73
74 def _encodestrsonly(v):
74 def _encodestrsonly(v):
75 if isinstance(v, type(u'')):
75 if isinstance(v, type(u'')):
76 return v.encode('ascii')
76 return v.encode('ascii')
77 return v
77 return v
78
78
79
79
80 def bytesvars(obj):
80 def bytesvars(obj):
81 unidict = vars(obj)
81 unidict = vars(obj)
82 bd = {k.encode('ascii'): _encodestrsonly(v) for k, v in unidict.items()}
82 bd = {k.encode('ascii'): _encodestrsonly(v) for k, v in unidict.items()}
83 if bd[b'daemon_postexec'] is not None:
83 if bd[b'daemon_postexec'] is not None:
84 bd[b'daemon_postexec'] = [
84 bd[b'daemon_postexec'] = [
85 _encodestrsonly(v) for v in bd[b'daemon_postexec']
85 _encodestrsonly(v) for v in bd[b'daemon_postexec']
86 ]
86 ]
87 return bd
87 return bd
88
88
89
89
90 def main():
90 def main():
91 op = optparse.OptionParser()
91 op = optparse.OptionParser()
92 op.add_option('-d', '--daemon', action='store_true')
92 op.add_option('-d', '--daemon', action='store_true')
93 op.add_option('--daemon-postexec', action='append')
93 op.add_option('--daemon-postexec', action='append')
94 op.add_option('-p', '--port', type=int, default=8025)
94 op.add_option('-p', '--port', type=int, default=8025)
95 op.add_option('-a', '--address', default='localhost')
95 op.add_option('-a', '--address', default='localhost')
96 op.add_option('--pid-file', metavar='FILE')
96 op.add_option('--pid-file', metavar='FILE')
97 op.add_option('--tls', choices=['none', 'smtps'], default='none')
97 op.add_option('--tls', choices=['none', 'smtps'], default='none')
98 op.add_option('--certificate', metavar='FILE')
98 op.add_option('--certificate', metavar='FILE')
99 op.add_option('--logfile', metavar='FILE')
99 op.add_option('--logfile', metavar='FILE')
100
100
101 opts, args = op.parse_args()
101 opts, args = op.parse_args()
102 if opts.tls == 'smtps' and not opts.certificate:
102 if (opts.tls == 'smtps') != bool(opts.certificate):
103 op.error('--certificate must be specified')
103 op.error('--certificate must be specified with --tls=smtps')
104
104
105 addr = (opts.address, opts.port)
105 addr = (opts.address, opts.port)
106
106
107 def init():
107 def init():
108 if opts.tls == 'none':
108 if opts.tls == 'none':
109 dummysmtpserver(addr)
109 dummysmtpserver(addr)
110 else:
110 else:
111 dummysmtpsecureserver(addr, opts.certificate)
111 dummysmtpsecureserver(addr, opts.certificate)
112 log('listening at %s:%d\n' % addr)
112 log('listening at %s:%d\n' % addr)
113
113
114 server.runservice(
114 server.runservice(
115 bytesvars(opts),
115 bytesvars(opts),
116 initfn=init,
116 initfn=init,
117 runfn=run,
117 runfn=run,
118 runargs=[pycompat.sysexecutable, pycompat.fsencode(__file__)]
118 runargs=[pycompat.sysexecutable, pycompat.fsencode(__file__)]
119 + pycompat.sysargv[1:],
119 + pycompat.sysargv[1:],
120 logfile=opts.logfile,
120 logfile=opts.logfile,
121 )
121 )
122
122
123
123
124 if __name__ == '__main__':
124 if __name__ == '__main__':
125 main()
125 main()
General Comments 0
You need to be logged in to leave comments. Login now