view tests/dummysmtpd.py @ 32395:24245b54aa8a

match: replace match class by match function (API) The matcher class is getting hard to understand. It will be easier to follow if we can break it up into simpler matchers that we then compose. I'm hoping to have one matcher that accepts regular (non-include) patterns, one for exact file matches, one that always matches (and maybe one that never does) and then compose them by intersection and difference. This patch takes a simple but important step towards that goal by making match.match() a function (and renaming the matcher class itself from "match" to "matcher"). The new function will eventually be responsible for creating the simple matchers and composing them. icasefsmatcher similarly gets a factory function (called "icasefsmatch"). I also moved the other factory functions nearby.
author Martin von Zweigbergk <martinvonz@google.com>
date Fri, 12 May 2017 23:11:41 -0700
parents d83ca854fa21
children 75bae69747f0
line wrap: on
line source

#!/usr/bin/env python

"""dummy SMTP server for use in tests"""

from __future__ import absolute_import

import asyncore
import optparse
import smtpd
import ssl
import sys

from mercurial import (
    server,
    sslutil,
    ui as uimod,
)

def log(msg):
    sys.stdout.write(msg)
    sys.stdout.flush()

class dummysmtpserver(smtpd.SMTPServer):
    def __init__(self, localaddr):
        smtpd.SMTPServer.__init__(self, localaddr, remoteaddr=None)

    def process_message(self, peer, mailfrom, rcpttos, data):
        log('%s from=%s to=%s\n' % (peer[0], mailfrom, ', '.join(rcpttos)))

class dummysmtpsecureserver(dummysmtpserver):
    def __init__(self, localaddr, certfile):
        dummysmtpserver.__init__(self, localaddr)
        self._certfile = certfile

    def handle_accept(self):
        pair = self.accept()
        if not pair:
            return
        conn, addr = pair
        ui = uimod.ui.load()
        try:
            # wrap_socket() would block, but we don't care
            conn = sslutil.wrapserversocket(conn, ui, certfile=self._certfile)
        except ssl.SSLError:
            log('%s ssl error\n' % addr[0])
            conn.close()
            return
        smtpd.SMTPChannel(self, conn, addr)

def run():
    try:
        asyncore.loop()
    except KeyboardInterrupt:
        pass

def main():
    op = optparse.OptionParser()
    op.add_option('-d', '--daemon', action='store_true')
    op.add_option('--daemon-postexec', action='append')
    op.add_option('-p', '--port', type=int, default=8025)
    op.add_option('-a', '--address', default='localhost')
    op.add_option('--pid-file', metavar='FILE')
    op.add_option('--tls', choices=['none', 'smtps'], default='none')
    op.add_option('--certificate', metavar='FILE')

    opts, args = op.parse_args()
    if opts.tls == 'smtps' and not opts.certificate:
        op.error('--certificate must be specified')

    addr = (opts.address, opts.port)
    def init():
        if opts.tls == 'none':
            dummysmtpserver(addr)
        else:
            dummysmtpsecureserver(addr, opts.certificate)
        log('listening at %s:%d\n' % addr)

    server.runservice(vars(opts), initfn=init, runfn=run,
                      runargs=[sys.executable, __file__] + sys.argv[1:])

if __name__ == '__main__':
    main()