Exemple #1
0
 def test_mail_with_compatible_smtputf8(self):
     handler = ReceivingHandler()
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     recipient = 'bart\[email protected]'
     sender = 'anne\[email protected]'
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         client.send(
             bytes('MAIL FROM: <' + sender + '> SMTPUTF8\r\n',
                   encoding='utf-8'))
         code, response = client.getreply()
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
         client.send(
             bytes('RCPT TO: <' + recipient + '>\r\n', encoding='utf-8'))
         code, response = client.getreply()
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
         code, response = client.data('')
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
     self.assertEqual(handler.box[0].rcpt_tos[0], recipient)
     self.assertEqual(handler.box[0].mail_from, sender)
Exemple #2
0
    def test_real_mail_aiosmtpd(self):
        """ Test sending messages with a real-world SMTPD server """
        if aiosmtpd is None:
            self.skipTest('aiosmtpd not available')

        # Start an smtp server
        mail_handler = StashingHandler()
        controller = Controller(mail_handler, loop=None,
                                hostname='localhost', port=self.smtpd_port)
        controller.start()

        # Give it time to settle
        sleep(0.5)

        # Initialize a Postman
        postman = Postman('*****@*****.**',
                          NoLoginSMTP('localhost', self.smtpd_port, None, None))

        # Send messages
        with postman.connect() as c:
            # Send plaintext message
            msg = Message(['*****@*****.**'], 'Subject', 'HTML message')
            c.sendmail(msg)

            # Send unicode message
            msg = Message(['*****@*****.**'], u'Håkon', u'Håkon')
            c.sendmail(msg)

        # Done
        controller.stop()

        # Test
        self.assertEqual(len(mail_handler.mail), 2)
async def amain(loop):
    """Instantiate a controller which runs the SMTP server in a separate thread with a dedicated event loop"""

    controller = Controller(MyHandler(),
                            hostname=SMTPSERVER_CFG['Server']['BINDADDR'],
                            port=SMTPSERVER_CFG['Server']['BINDPORT'])
    controller.start()
Exemple #4
0
 def test_hostname_empty(self):
     # WARNING: This test _always_ succeeds in Windows.
     cont = Controller(Sink(), hostname="")
     try:
         cont.start()
     finally:
         cont.stop()
Exemple #5
0
class SMTPHandler(rpc.AttrHandler):
    def __init__(self):
        self.inbox = Inbox()
        self.controller = Controller(self.inbox, port=0, ready_timeout=1)
        self.controller.start()

    @property
    def port(self):
        return self.controller.server.sockets[0].getsockname()[1]

    @property
    def running(self):
        return self.controller.thread.is_alive()

    @rpc.method
    def inboxcount(self):
        return self.inbox.count

    @rpc.method
    def stop(self):
        # TODO Call later is currently needed to let the RPC client recieve a
        #      response before the server exits.
        # See: https://github.com/aio-libs/aiozmq/issues/39
        loop = asyncio.get_event_loop()
        loop.call_later(0.01, self.controller.stop)
Exemple #6
0
 def setUp(self):
     self.stream = StringIO()
     handler = Debugging(self.stream)
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     self.address = (controller.hostname, controller.port)
Exemple #7
0
 def setUp(self):
     self.stream = StringIO()
     handler = Debugging(self.stream)
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     self.address = (controller.hostname, controller.port)
Exemple #8
0
    def setUp(self):
        # There are two controllers and two SMTPd's running here.  The
        # "upstream" one listens on port 9025 and is connected to a "data
        # handler" which captures the messages it receives.  The second -and
        # the one under test here- listens on port 9024 and proxies to the one
        # on port 9025.  Because we need to set the decode_data flag
        # differently for each different test, the controller of the proxy is
        # created in the individual tests, not in the setup.
        self.upstream = DataHandler()
        upstream_controller = Controller(self.upstream, port=9025)
        upstream_controller.start()
        self.addCleanup(upstream_controller.stop)
        self.proxy = Proxy(upstream_controller.hostname, 9025)
        self.source = """\
From: Anne Person <*****@*****.**>
To: Bart Person <*****@*****.**>
Subject: A test

Testing
"""
        # The upstream SMTPd will always receive the content as bytes
        # delimited with CRLF.
        self.expected = CRLF.join([
            'From: Anne Person <*****@*****.**>',
            'To: Bart Person <*****@*****.**>',
            'Subject: A test',
            'X-Peer: ::1',
            '',
            'Testing\r\n']).encode('ascii')
Exemple #9
0
def main(keywords, antivirus, in_port, server, port):
    in_port = in_port if in_port else IN_PORT
    server = server if server else MAIL_SERVER
    port = port if port else OUT_PORT

    filters = []
    # add keyword filters if specified
    if keywords:
        keywords = keywords.split(",")
        for k in keywords:
            if not isfile(abspath(k)):
                print("%s: keywords file does not exist" % k)
            else:
                filters.append(KeywordFilter(k))
    # add antivirus filter if specified
    if antivirus:
        filters.append(AntivirusFilter())

    # create a gateway object containing the filters, start the server
    gateway = Gateway(server, port, filters)
    controller = Controller(MailHandler(gateway),
                            hostname='localhost',
                            port=in_port)
    try:
        controller.start()
        while True:
            pass
    finally:
        controller.stop()
Exemple #10
0
 def test_mail_with_compatible_smtputf8(self):
     handler = ReceivingHandler()
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     recipient = 'bart\[email protected]'
     sender = 'anne\[email protected]'
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         client.send(bytes(
             'MAIL FROM: <' + sender + '> SMTPUTF8\r\n',
             encoding='utf-8'))
         code, response = client.getreply()
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
         client.send(bytes(
             'RCPT TO: <' + recipient + '>\r\n',
             encoding='utf-8'))
         code, response = client.getreply()
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
         code, response = client.data('')
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
     self.assertEqual(handler.box[0].rcpt_tos[0], recipient)
     self.assertEqual(handler.box[0].mail_from, sender)
Exemple #11
0
    def setUp(self):
        # There are two controllers and two SMTPd's running here.  The
        # "upstream" one listens on port 9025 and is connected to a "data
        # handler" which captures the messages it receives.  The second -and
        # the one under test here- listens on port 9024 and proxies to the one
        # on port 9025.  Because we need to set the decode_data flag
        # differently for each different test, the controller of the proxy is
        # created in the individual tests, not in the setup.
        self.upstream = DataHandler()
        upstream_controller = Controller(self.upstream, port=9025)
        upstream_controller.start()
        self.addCleanup(upstream_controller.stop)
        self.proxy = Proxy(upstream_controller.hostname, 9025)
        self.source = """\
From: Anne Person <*****@*****.**>
To: Bart Person <*****@*****.**>
Subject: A test

Testing
"""
        # The upstream SMTPd will always receive the content as bytes
        # delimited with CRLF.
        self.expected = CRLF.join([
            'From: Anne Person <*****@*****.**>',
            'To: Bart Person <*****@*****.**>',
            'Subject: A test',
            'X-Peer: ::1',
            '',
            'Testing']).encode('ascii')
Exemple #12
0
async def run_tests():
    with tempfile.TemporaryDirectory() as maildir:
        # create temporary mailbox
        for d in ['cur', 'new', 'tmp']:
            maildirdir = os.path.join(maildir, d)
            os.mkdir(maildirdir)
        mailbox = Maildir(maildir)

        # start smtp server
        handler = MessageHandler(maildir)
        controller = Controller(handler)
        controller.start()

        # run tests
        tests = filter(
            lambda f: f.startswith('test_'),
            globals().keys(),
        )
        for test in tests:
            print(test + '...', end=' ')
            try:
                await globals()[test](mailbox)
            except AssertionError:
                fail()
                continue
            succeed()
Exemple #13
0
 def _make_relay(code=OK_REPLY):
     port = unused_tcp_port_factory()
     handler = DataHandler(port, code)
     relay = Controller(handler, hostname='127.0.0.1', port=port)
     relay.start()
     relays.append(relay)
     return handler
Exemple #14
0
def startsmtp():
    """ async controller"""
    controller = Controller(SMTPHoney(),
                            hostname="0.0.0.0",
                            port=int(smtpport))
    # It calls the class below as my handler.
    controller.start()
Exemple #15
0
 def test_normal_situation(self):
     cont = Controller(Sink())
     try:
         cont.start()
         assert cont.smtpd is not None
         assert cont._thread_exception is None
     finally:
         cont.stop()
Exemple #16
0
 def test_reuse_loop(self, temp_event_loop):
     cont = Controller(Sink(), loop=temp_event_loop)
     assert cont.loop is temp_event_loop
     try:
         cont.start()
         assert cont.smtpd.loop is temp_event_loop
     finally:
         cont.stop()
Exemple #17
0
 def test_socket_error(self):
     # Testing starting a server with a port already in use
     s1 = Controller(Sink(), port=8025)
     s2 = Controller(Sink(), port=8025)
     self.addCleanup(s1.stop)
     self.addCleanup(s2.stop)
     s1.start()
     self.assertRaises(socket.error, s2.start)
Exemple #18
0
 def test_smtp_utf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.ehlo('example.com')
     self.assertEqual(code, 250)
     self.assertIn(b'SMTPUTF8', response.splitlines())
Exemple #19
0
async def amain(loop):
    #hostname is passed to your loop’s AbstractEventLoop.create_server() method as the host parameter,
    #except None (default) is translated to ‘::1’.
    #To bind dual-stack locally, use ‘localhost’. To bind dual-stack on all interfaces, use ''
    controller = Controller(ExampleHandler(),
                            hostname='',
                            port=os.environ.get("SMTP_PORT"))
    controller.start()
Exemple #20
0
 def test_helo_hook(self):
     controller = Controller(HELOHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.helo('me')
     self.assertEqual(code, 250)
     self.assertEqual(response, b'geddy.example.com')
Exemple #21
0
 def test_smtp_utf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.ehlo('example.com')
     self.assertEqual(code, 250)
     self.assertIn(b'SMTPUTF8', response.splitlines())
Exemple #22
0
 def test_socket_error(self):
     # Testing starting a server with a port already in use
     s1 = Controller(Sink(), port=8025)
     s2 = Controller(Sink(), port=8025)
     self.addCleanup(s1.stop)
     self.addCleanup(s2.stop)
     s1.start()
     self.assertRaises(socket.error, s2.start)
Exemple #23
0
 def test_helo_hook(self):
     controller = Controller(HELOHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.helo('me')
     self.assertEqual(code, 250)
     self.assertEqual(response, b'geddy.example.com')
Exemple #24
0
 def test_mail_with_unrequited_smtputf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd('MAIL FROM: <*****@*****.**>')
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
Exemple #25
0
 def setUp(self):
     self.tempdir = TemporaryDirectory()
     self.addCleanup(self.tempdir.cleanup)
     self.maildir_path = os.path.join(self.tempdir.name, 'maildir')
     self.handler = handler = Mailbox(self.maildir_path)
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     self.address = (controller.hostname, controller.port)
Exemple #26
0
 def test_server_attribute(self):
     controller = Controller(Sink())
     self.assertIsNone(controller.server)
     try:
         controller.start()
         self.assertIsNotNone(controller.server)
     finally:
         controller.stop()
         self.assertIsNone(controller.server)
Exemple #27
0
 def test_server_attribute(self):
     controller = Controller(Sink())
     self.assertIsNone(controller.server)
     try:
         controller.start()
         self.assertIsNotNone(controller.server)
     finally:
         controller.stop()
         self.assertIsNone(controller.server)
Exemple #28
0
 def test_mail_hook(self):
     controller = Controller(MAILHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.helo('me')
         code, response = client.mail('*****@*****.**')
     self.assertEqual(code, 250)
     self.assertEqual(response, b'Yeah, sure')
Exemple #29
0
 def test_mail_with_unrequited_smtputf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd('MAIL FROM: <*****@*****.**>')
         self.assertEqual(code, 250)
         self.assertEqual(response, b'OK')
Exemple #30
0
 def test_socket_error_dupe(self, plain_controller, client):
     contr2 = Controller(Sink(),
                         hostname=Global.SrvAddr.host,
                         port=Global.SrvAddr.port)
     try:
         with pytest.raises(socket.error):
             contr2.start()
     finally:
         contr2.stop()
Exemple #31
0
 def test_ehlo_hook(self):
     controller = Controller(EHLOHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.ehlo('me')
     self.assertEqual(code, 250)
     lines = response.decode('utf-8').splitlines()
     self.assertEqual(lines[-1], 'alex.example.com')
Exemple #32
0
 def test_default_greeting(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP() as client:
         code, msg = client.connect(controller.hostname, controller.port)
         self.assertEqual(code, 220)
         # The hostname prefix is unpredictable.
         self.assertEqual(msg[-len(GREETING):], bytes(GREETING, 'utf-8'))
Exemple #33
0
 def test_server_attribute(self):
     controller = Controller(Sink())
     assert controller.server is None
     try:
         controller.start()
         assert controller.server is not None
     finally:
         controller.stop()
     assert controller.server is None
Exemple #34
0
 def test_testconn_raises(self, mocker: MockFixture):
     mocker.patch("socket.socket.recv",
                  side_effect=RuntimeError("MockError"))
     cont = Controller(Sink(), hostname="")
     try:
         with pytest.raises(RuntimeError, match="MockError"):
             cont.start()
     finally:
         cont.stop()
Exemple #35
0
 def setUp(self):
     self.tempdir = TemporaryDirectory()
     self.addCleanup(self.tempdir.cleanup)
     self.maildir_path = os.path.join(self.tempdir.name, 'maildir')
     self.handler = handler = Mailbox(self.maildir_path)
     controller = Controller(handler)
     controller.start()
     self.addCleanup(controller.stop)
     self.address = (controller.hostname, controller.port)
Exemple #36
0
 def test_default_greeting(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP() as client:
         code, msg = client.connect(controller.hostname, controller.port)
         self.assertEqual(code, 220)
         # The hostname prefix is unpredictable.
         self.assertEqual(msg[-len(GREETING):], bytes(GREETING, 'utf-8'))
Exemple #37
0
 def test_mail_hook(self):
     controller = Controller(MAILHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.helo('me')
         code, response = client.mail('*****@*****.**')
     self.assertEqual(code, 250)
     self.assertEqual(response, b'Yeah, sure')
Exemple #38
0
 def test_ehlo_hook(self):
     controller = Controller(EHLOHandler())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         code, response = client.ehlo('me')
     self.assertEqual(code, 250)
     lines = response.decode('utf-8').splitlines()
     self.assertEqual(lines[-1], 'alex.example.com')
Exemple #39
0
 def test_mail_with_incompatible_smtputf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd(
             'MAIL FROM: <*****@*****.**> SMTPUTF8=YES')
         self.assertEqual(code, 501)
         self.assertEqual(response, b'Error: SMTPUTF8 takes no arguments')
Exemple #40
0
 def test_socket_error_dupe(self, plain_controller, client):
     contr2 = Controller(Sink(),
                         hostname=Global.SrvAddr.host,
                         port=Global.SrvAddr.port)
     expectedre = r"error while attempting to bind on address"
     try:
         with pytest.raises(socket.error, match=expectedre):
             contr2.start()
     finally:
         contr2.stop()
Exemple #41
0
 def test_mail_with_incompatible_smtputf8(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd(
             'MAIL FROM: <*****@*****.**> SMTPUTF8=YES')
         self.assertEqual(code, 501)
         self.assertEqual(response, b'Error: SMTPUTF8 takes no arguments')
Exemple #42
0
async def amain():
    handler = RelayHandler()
    cont = Controller(handler,
                      hostname='',
                      port=8025,
                      authenticator=Authenticator(DB_AUTH))
    try:
        cont.start()
    finally:
        cont.stop()
Exemple #43
0
 def test_mail_invalid_body(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd(
             'MAIL FROM: <*****@*****.**> BODY 9BIT')
         self.assertEqual(code, 501)
         self.assertEqual(response,
                          b'Error: BODY can only be one of 7BIT, 8BITMIME')
Exemple #44
0
async def amain(loop):
    try:
        controller = Controller(ExampleHandler(),
                                loop=None,
                                hostname=None,
                                port=8025)
        controller.start()
    except Exception:
        loop.stop()
        sys.exit(0)
        pass
Exemple #45
0
 def test_mail_invalid_body(self):
     controller = Controller(Sink())
     controller.start()
     self.addCleanup(controller.stop)
     with SMTP(controller.hostname, controller.port) as client:
         client.ehlo('example.com')
         code, response = client.docmd(
             'MAIL FROM: <*****@*****.**> BODY 9BIT')
         self.assertEqual(code, 501)
         self.assertEqual(response,
                          b'Error: BODY can only be one of 7BIT, 8BITMIME')
Exemple #46
0
 def test_deliver_bytes(self):
     with ExitStack() as resources:
         controller = Controller(self.proxy, port=9024)
         controller.start()
         resources.callback(controller.stop)
         client = resources.enter_context(
             SMTP(*(controller.hostname, controller.port)))
         client.sendmail(
             '*****@*****.**', ['*****@*****.**'], self.source)
         client.quit()
     self.assertEqual(self.upstream.content, self.expected)
     self.assertEqual(self.upstream.original_content, self.expected)
class CapturingAiosmtpdServer:
    """An async SMTP server / context manager for testing RPC effects."""

    def __init__(self):
        self.messages = []
        self.handler = CapturingAiosmtpdHandler(context=self)
        self.controller = Controller(
            handler=self.handler, hostname="localhost", port=10025)

    def __enter__(self):
        self.controller.start()
        return self

    def __exit__(self, *exc):
        self.controller.stop()
Exemple #48
0
    def test_data_hook(self):
        controller = Controller(DATAHandler())
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            with self.assertRaises(SMTPDataError) as cm:
                client.sendmail('*****@*****.**', ['*****@*****.**'], """\
From: [email protected]
To: [email protected]
Subject: Test

Yikes
""")
            self.assertEqual(cm.exception.smtp_code, 599)
            self.assertEqual(cm.exception.smtp_error, b'Not today')
Exemple #49
0
    def test_rcpt_hook(self):
        controller = Controller(RCPTHandler())
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            with self.assertRaises(SMTPRecipientsRefused) as cm:
                client.sendmail('*****@*****.**', ['*****@*****.**'], """\
From: [email protected]
To: [email protected]
Subject: Test

""")
            self.assertEqual(cm.exception.recipients, {
                '*****@*****.**': (550, b'Rejected'),
                })
Exemple #50
0
    def test_no_hooks(self):
        controller = Controller(NoHooksHandler())
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            client.helo('me')
            client.mail('*****@*****.**')
            client.rcpt(['*****@*****.**'])
            code, response = client.data("""\
From: [email protected]
To: [email protected]
Subject: Test

""")
            self.assertEqual(code, 250)
Exemple #51
0
    def test_process_message_error(self):
        controller = Controller(ErroringHandler())
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            code, response = client.ehlo('example.com')
            self.assertEqual(code, 250)
            with self.assertRaises(SMTPDataError) as cm:
                client.sendmail('*****@*****.**', ['*****@*****.**'], """\
From: [email protected]
To: [email protected]
Subject: A test

Testing
""")
            self.assertEqual(cm.exception.smtp_code, 499)
            self.assertEqual(cm.exception.smtp_error,
                             b'Could not accept the message')
Exemple #52
0
    def test_message(self):
        # In this test, the message content comes in as a bytes.
        handler = DataHandler()
        controller = Controller(handler)
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            client.sendmail('*****@*****.**', ['*****@*****.**'], """\
From: Anne Person <*****@*****.**>
To: Bart Person <*****@*****.**>
Subject: A test
Message-ID: <ant>

Testing
""")
        # The content is not converted, so it's bytes.
        self.assertEqual(handler.content, handler.original_content)
        self.assertIsInstance(handler.content, bytes)
        self.assertIsInstance(handler.original_content, bytes)
Exemple #53
0
    def test_message(self):
        # In this test, the message data comes in as bytes.
        controller = Controller(self.handler)
        controller.start()
        self.addCleanup(controller.stop)
        with SMTP(controller.hostname, controller.port) as client:
            client.sendmail('*****@*****.**', ['*****@*****.**'], """\
From: Anne Person <*****@*****.**>
To: Bart Person <*****@*****.**>
Subject: A test
Message-ID: <ant>

Testing
""")
        self.assertEqual(self.handled_message['subject'], 'A test')
        self.assertEqual(self.handled_message['message-id'], '<ant>')
        self.assertIsNotNone(self.handled_message['X-Peer'])
        self.assertEqual(
            self.handled_message['X-MailFrom'], '*****@*****.**')
        self.assertEqual(self.handled_message['X-RcptTo'], '*****@*****.**')
Exemple #54
0
async def amain(loop):
    cont = Controller(Sink(), hostname='::0', port=8025)
    cont.start()
Exemple #55
0
 async def smtpd_main(self, hostname, port):
     cont = Controller(self, hostname=hostname, port=port)
     cont.start()
Exemple #56
0
 def setUp(self):
     controller = Controller(Sink)
     controller.start()
     self.addCleanup(controller.stop)
     self.address = (controller.hostname, controller.port)