Ticket #6572: 6572-1.patch

File 6572-1.patch, 3.0 KB (added by Kai Zhang, 8 years ago)

Add cancellation support to twisted.mail.smtp.sendmail. Write test code with twisted.test.proto_helpers.MemoryReactor.

  • twisted/mail/test/test_smtp.py

     
    1313from twisted.mail import smtp
    1414from twisted.internet import defer, protocol, reactor, interfaces
    1515from twisted.internet import address, error, task
    16 from twisted.test.proto_helpers import StringTransport
     16from twisted.test.proto_helpers import MemoryReactor, StringTransport
    1717
    1818from twisted import cred
    1919import twisted.cred.error
     
    16491649            warningsShown[0]['message'],
    16501650            "tlsMode attribute of twisted.mail.smtp.ESMTPClient "
    16511651            "is deprecated since Twisted 13.0")
     1652
     1653
     1654
     1655class SendmailTestCase(unittest.TestCase):
     1656    """
     1657    Tests for L{twisted.mail.smtp.sendmail}.
     1658    """
     1659    def test_cancel(self):
     1660        """
     1661        A deferred returned by L{twisted.mail.smtp.sendmail} can be cancelled,
     1662        telling the L{twisted.mail.smtp.SMTPSenderFactory} not to
     1663        retry and disconnecting the L{twisted.internet.interfaces.IConnector}.
     1664        """
     1665        reactor = MemoryReactor()
     1666        d = smtp.sendmail("localhost", "source@address", "recipient@address",
     1667                          "message", _reactor=reactor)
     1668        factory = reactor.tcpClients[0][2]
     1669        connector = reactor.connectors[0]
     1670        d.cancel()
     1671        self.assertEqual(factory.sendFinished, 1)
     1672        self.assertEqual(connector._disconnected, True)
     1673        self.assertFailure(d, defer.CancelledError)
     1674        return d
  • twisted/mail/smtp.py

     
    18941894        p.timeout = self.timeout
    18951895        return p
    18961896
    1897 def sendmail(smtphost, from_addr, to_addrs, msg, senderDomainName=None, port=25):
     1897def sendmail(smtphost, from_addr, to_addrs, msg,
     1898             senderDomainName=None, port=25, _reactor=reactor):
    18981899    """Send an email
    18991900
    19001901    This interface is intended to be a direct replacement for
     
    19211922
    19221923    @param port: Remote port to which to connect.
    19231924
     1925    @param _reactor: The reactor used to connect to host.
     1926
    19241927    @rtype: L{Deferred}
    19251928    @returns: A L{Deferred}, its callback will be called if a message is sent
    19261929        to ANY address, the errback if no message is sent.
     
    19341937        # It's not a file
    19351938        msg = StringIO(str(msg))
    19361939
    1937     d = defer.Deferred()
     1940    def cancel(d):
     1941        """
     1942        Cancel the L{twisted.mail.smtp.sendmail} call.
     1943        """
     1944        factory.sendFinished = 1
     1945        connector.disconnect()
     1946    d = defer.Deferred(cancel)
    19381947    factory = SMTPSenderFactory(from_addr, to_addrs, msg, d)
    19391948
    19401949    if senderDomainName is not None:
    19411950        factory.domain = senderDomainName
    19421951
    1943     reactor.connectTCP(smtphost, port, factory)
     1952    connector = _reactor.connectTCP(smtphost, port, factory)
    19441953
    19451954    return d
    19461955