diff -Nru twisted-mail-10.1.0/bin/mailmail twisted-mail-12.0.0/bin/mailmail --- twisted-mail-10.1.0/bin/mailmail 2009-04-08 21:56:55.000000000 +0000 +++ twisted-mail-12.0.0/bin/mailmail 2011-06-30 12:57:11.000000000 +0000 @@ -1,24 +1,19 @@ #!/usr/bin/env python - -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - """ This script attempts to send some email. """ -### Twisted Preamble -# This makes sure that users don't have to set up their environment -# specially in order to run these programs from bin/. import sys, os -path = os.path.abspath(sys.argv[0]) -while os.path.dirname(path) != path: - if os.path.basename(path).startswith('Twisted'): - sys.path.insert(0, path) - break - path = os.path.dirname(path) -### end of preamble +extra = os.path.dirname(os.path.dirname(sys.argv[0])) +sys.path.insert(0, extra) +try: + import _preamble +except ImportError: + sys.exc_clear() +sys.path.remove(extra) from twisted.mail.scripts import mailmail mailmail.run() diff -Nru twisted-mail-10.1.0/debian/changelog twisted-mail-12.0.0/debian/changelog --- twisted-mail-10.1.0/debian/changelog 2012-02-17 20:25:01.000000000 +0000 +++ twisted-mail-12.0.0/debian/changelog 2012-02-17 01:23:29.000000000 +0000 @@ -1,3 +1,35 @@ +twisted-mail (12.0.0-1~ppa1~maverick1) maverick; urgency=low + + * New upstream version. + * Rebuild package for use in PPA. + + -- Jessica McKellar Wed, 15 Feb 2012 20:27:31 -0500 + +twisted-mail (11.1.0-1) unstable; urgency=low + + * New upstream release. + + -- Matthias Klose Wed, 21 Dec 2011 12:53:22 +0100 + +twisted-mail (11.0.0-1) unstable; urgency=low + + * New upstream release. + + -- Matthias Klose Mon, 18 Apr 2011 22:43:28 +0200 + +twisted-mail (10.2.0-1.1) unstable; urgency=low + + * Non-maintainer upload. + * Rebuild to add Python 2.7 and drop Python 2.5 support + + -- Piotr Ożarowski Sun, 17 Apr 2011 22:02:55 +0200 + +twisted-mail (10.2.0-1) unstable; urgency=low + + * New upstream release. + + -- Matthias Klose Thu, 24 Feb 2011 12:02:13 +0100 + twisted-mail (10.1.0-1) unstable; urgency=low * New upstream release. diff -Nru twisted-mail-10.1.0/debian/compat twisted-mail-12.0.0/debian/compat --- twisted-mail-10.1.0/debian/compat 2012-02-17 20:25:01.000000000 +0000 +++ twisted-mail-12.0.0/debian/compat 2012-02-16 01:25:11.000000000 +0000 @@ -1 +1 @@ -5 +7 diff -Nru twisted-mail-10.1.0/debian/control twisted-mail-12.0.0/debian/control --- twisted-mail-10.1.0/debian/control 2012-02-17 20:25:01.000000000 +0000 +++ twisted-mail-12.0.0/debian/control 2012-02-17 02:02:01.000000000 +0000 @@ -3,18 +3,17 @@ Priority: optional Maintainer: Matthias Klose Uploaders: Free Ekanayaka -Build-Depends: debhelper (>= 5.0.37.1), python-all (>= 2.6.5-9~), python-twisted-core (>= 10.1), patch +Build-Depends: debhelper (>=7.0.50~), python-all (>= 2.6.5-9~), python-twisted-core (>= 12.0), patch XS-Python-Version: all -Standards-Version: 3.9.0 +Standards-Version: 3.9.2 Package: python-twisted-mail Architecture: all -Depends: ${python:Depends}, python-twisted-core (>= 10.1), python-openssl, ${misc:Depends} +Depends: ${python:Depends}, python-twisted-core (>= 12.0), python-openssl, ${misc:Depends} Recommends: python-twisted-names Conflicts: python-twisted (<< 2.1), python2.3-twisted-mail, python2.4-twisted-mail Replaces: python-twisted (<< 2.1), python2.3-twisted-mail, python2.4-twisted-mail -XB-Python-Version: ${python:Versions} -Description: An SMTP, IMAP and POP protocol implementation +Description: SMTP, IMAP and POP protocol implementation Twisted Mail contains high-level, efficient protocol implementations for both clients and servers of SMTP, POP3, and IMAP4. Additionally, it contains an "out of the box" combination SMTP/POP3 virtual-hosting diff -Nru twisted-mail-10.1.0/debian/rules twisted-mail-12.0.0/debian/rules --- twisted-mail-10.1.0/debian/rules 2012-02-17 20:25:01.000000000 +0000 +++ twisted-mail-12.0.0/debian/rules 2012-02-16 01:26:54.000000000 +0000 @@ -7,6 +7,8 @@ VER := $(shell /usr/bin/python -c 'import sys; print sys.version[:3]') build: build-stamp +build-arch: build-stamp +build-indep: build-stamp build-stamp: $(PYVERS:%=build-python%) touch $@ build-python%: @@ -25,7 +27,7 @@ install-prereq: build-stamp dh_testdir dh_testroot - dh_clean -k + dh_prep install-python%: install-prereq : # python-twisted-mail diff -Nru twisted-mail-10.1.0/debian/source/format twisted-mail-12.0.0/debian/source/format --- twisted-mail-10.1.0/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ twisted-mail-12.0.0/debian/source/format 2012-02-17 20:25:01.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru twisted-mail-10.1.0/debian/watch twisted-mail-12.0.0/debian/watch --- twisted-mail-10.1.0/debian/watch 2012-02-17 20:25:01.000000000 +0000 +++ twisted-mail-12.0.0/debian/watch 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -version=3 -http://tmrc.mit.edu/mirror/twisted/Mail/(\d\.\d)/ TwistedMail-([\d\.]*)\.tar\.bz2 diff -Nru twisted-mail-10.1.0/doc/examples/emailserver.tac twisted-mail-12.0.0/doc/examples/emailserver.tac --- twisted-mail-10.1.0/doc/examples/emailserver.tac 2006-07-02 03:53:32.000000000 +0000 +++ twisted-mail-12.0.0/doc/examples/emailserver.tac 2011-02-14 04:45:15.000000000 +0000 @@ -1,11 +1,9 @@ - -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # You can run this module directly with: # twistd -ny emailserver.tac - """ A toy email server. """ @@ -14,16 +12,25 @@ from twisted.internet import defer from twisted.mail import smtp +from twisted.mail.imap4 import LOGINCredentials, PLAINCredentials + +from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse +from twisted.cred.portal import IRealm +from twisted.cred.portal import Portal + + class ConsoleMessageDelivery: implements(smtp.IMessageDelivery) def receivedHeader(self, helo, origin, recipients): return "Received: ConsoleMessageDelivery" + def validateFrom(self, helo, origin): # All addresses are accepted return origin + def validateTo(self, user): # Only messages directed to the "console" user are accepted. @@ -31,41 +38,69 @@ return lambda: ConsoleMessage() raise smtp.SMTPBadRcpt(user) + + class ConsoleMessage: implements(smtp.IMessage) def __init__(self): self.lines = [] + def lineReceived(self, line): self.lines.append(line) + def eomReceived(self): print "New message received:" print "\n".join(self.lines) self.lines = None return defer.succeed(None) + def connectionLost(self): # There was an error, throw away the stored lines self.lines = None + + class ConsoleSMTPFactory(smtp.SMTPFactory): + protocol = smtp.ESMTP + def __init__(self, *a, **kw): smtp.SMTPFactory.__init__(self, *a, **kw) self.delivery = ConsoleMessageDelivery() + def buildProtocol(self, addr): p = smtp.SMTPFactory.buildProtocol(self, addr) p.delivery = self.delivery + p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials} return p + + +class SimpleRealm: + implements(IRealm) + + def requestAvatar(self, avatarId, mind, *interfaces): + if smtp.IMessageDelivery in interfaces: + return smtp.IMessageDelivery, ConsoleMessageDelivery(), lambda: None + raise NotImplementedError() + + + def main(): from twisted.application import internet - from twisted.application import service + from twisted.application import service + + portal = Portal(SimpleRealm()) + checker = InMemoryUsernamePasswordDatabaseDontUse() + checker.addUser("guest", "password") + portal.registerChecker(checker) a = service.Application("Console SMTP Server") - internet.TCPServer(2500, ConsoleSMTPFactory()).setServiceParent(a) + internet.TCPServer(2500, ConsoleSMTPFactory(portal)).setServiceParent(a) return a diff -Nru twisted-mail-10.1.0/doc/examples/imap4client.py twisted-mail-12.0.0/doc/examples/imap4client.py --- twisted-mail-10.1.0/doc/examples/imap4client.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-mail-12.0.0/doc/examples/imap4client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/doc/examples/index.html twisted-mail-12.0.0/doc/examples/index.html --- twisted-mail-10.1.0/doc/examples/index.html 2010-07-03 14:55:46.000000000 +0000 +++ twisted-mail-12.0.0/doc/examples/index.html 2012-02-10 16:32:47.000000000 +0000 @@ -1,22 +1,23 @@ -Twisted Documentation: Twisted.Mail code examples +Twisted Documentation: Twisted Mail code examples -

Twisted.Mail code examples

+

Twisted Mail code examples

SMTP servers

SMTP clients

@@ -30,6 +31,6 @@

Index

- Version: 10.1.0 + Version: 12.0.0 \ No newline at end of file diff -Nru twisted-mail-10.1.0/doc/examples/smtpclient_simple.py twisted-mail-12.0.0/doc/examples/smtpclient_simple.py --- twisted-mail-10.1.0/doc/examples/smtpclient_simple.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-mail-12.0.0/doc/examples/smtpclient_simple.py 2011-02-14 04:45:15.000000000 +0000 @@ -0,0 +1,47 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Demonstrate sending mail via SMTP. +""" + +import sys +from email.mime.text import MIMEText + +from twisted.python import log +from twisted.mail.smtp import sendmail +from twisted.internet import reactor + + +def send(message, subject, sender, recipients, host): + """ + Send email to one or more addresses. + """ + msg = MIMEText(message) + msg['Subject'] = subject + msg['From'] = sender + msg['To'] = ', '.join(recipients) + + dfr = sendmail(host, sender, recipients, msg.as_string()) + def success(r): + reactor.stop() + def error(e): + print e + reactor.stop() + dfr.addCallback(success) + dfr.addErrback(error) + + reactor.run() + + +if __name__ == '__main__': + msg = 'This is the message body' + subject = 'This is the message subject' + + host = 'smtp.example.com' + sender = 'sender@example.com' + recipients = ['recipient@example.com'] + + log.startLogging(sys.stdout) + send(msg, subject, sender, recipients, host) + diff -Nru twisted-mail-10.1.0/doc/index.html twisted-mail-12.0.0/doc/index.html --- twisted-mail-10.1.0/doc/index.html 2010-07-03 14:55:46.000000000 +0000 +++ twisted-mail-12.0.0/doc/index.html 2012-02-10 16:32:47.000000000 +0000 @@ -20,6 +20,6 @@

Index

- Version: 10.1.0 + Version: 12.0.0 \ No newline at end of file diff -Nru twisted-mail-10.1.0/doc/man/mailmail-man.html twisted-mail-12.0.0/doc/man/mailmail-man.html --- twisted-mail-10.1.0/doc/man/mailmail-man.html 2010-07-03 14:55:46.000000000 +0000 +++ twisted-mail-12.0.0/doc/man/mailmail-man.html 2012-02-10 16:32:47.000000000 +0000 @@ -50,6 +50,6 @@

Index

- Version: 10.1.0 + Version: 12.0.0 \ No newline at end of file diff -Nru twisted-mail-10.1.0/doc/tutorial/smtpclient/smtpclient.html twisted-mail-12.0.0/doc/tutorial/smtpclient/smtpclient.html --- twisted-mail-10.1.0/doc/tutorial/smtpclient/smtpclient.html 2010-07-03 14:55:46.000000000 +0000 +++ twisted-mail-12.0.0/doc/tutorial/smtpclient/smtpclient.html 2012-02-10 16:32:47.000000000 +0000 @@ -29,18 +29,17 @@

SMTP Client 1

The first step is to create the most -minimal .tac file possible for use by -twistd.

+minimal .tac file possible for use by twistd .

1

from twisted.application import service
-

The first line of the .tac file imports -twisted.application.service, a module which contains many -of the basic service classes and helper functions available -in Twisted. In particular, we will be using the -Application function to create a new application +

The first line of the .tac file +imports twisted.application.service, a module which +contains many of the basic service classes and helper +functions available in Twisted. In particular, we will be using +the Application function to create a new application service. An application service simply acts as a central object on which to store certain kinds of deployment configuration.

@@ -49,18 +48,19 @@

application = service.Application("SMTP Client Tutorial") -

The second line of the .tac file creates a new -application service and binds it to the local name -application. twistd requires this local -name in each .tac file it runs. It uses various pieces -of configuration on the object to determine its behavior. For +

The second line of the .tac file creates a +new application service and binds it to the local +name application. twistd requires this +local name in each .tac file it runs. It uses various +pieces of configuration on the object to determine its behavior. For example, "SMTP Client Tutorial" will be used as the name of the .tap file into which to serialize application state, should it be necessary to do so.

-

That does it for the first example. We now have enough of a -.tac file to pass to twistd. If we run smtpclient-1.tac using the -twistd command line:

+

That does it for the first example. We now have enough of +a .tac file to pass to twistd. If we +run smtpclient-1.tac using +the twistd command line:

1

twistd -ny smtpclient-1.tac @@ -100,13 +100,13 @@ from twisted.internet import protocol
-

twisted.application.internet is another -application service module. It provides services for +

twisted.application.internet is +another application service module. It provides services for establishing outgoing connections (as well as creating network -servers, though we are not interested in those parts for the moment). -twisted.internet.protocol provides base implementations -of many of the core Twisted concepts, such as factories and -protocols.

+servers, though we are not interested in those parts for the +moment). twisted.internet.protocol provides base +implementations of many of the core Twisted concepts, such +as factories and protocols.

The next line of smtpclient-2.tac instantiates a new client factory.

@@ -115,12 +115,12 @@

smtpClientFactory = protocol.ClientFactory() -

Client factories are responsible for constructing -protocol instances whenever connections are established. -They may be required to create just one instance, or many instances if -many different connections are established, or they may never be -required to create one at all, if no connection ever manages to be -established.

+

Client factories are responsible for +constructing protocol instances whenever connections are +established. They may be required to create just one instance, or +many instances if many different connections are established, or they +may never be required to create one at all, if no connection ever +manages to be established.

Now that we have a client factory, we'll need to hook it up to the network somehow. The next line of smtpclient-2.tac does @@ -130,16 +130,16 @@

smtpClientService = internet.TCPClient(None, None, smtpClientFactory) -

We'll ignore the first two arguments to -internet.TCPClient for the moment and instead focus on +

We'll ignore the first two arguments +to internet.TCPClient for the moment and instead focus on the third. TCPClient is one of those application service classes. It creates TCP connections to a specified address and then uses its third argument, a client factory, to get a protocol instance. It then associates the TCP connection with the protocol instance and gets out of the way.

-

We can try to run smtpclient-2.tac the same way we ran -smtpclient-1.tac, but the results might be a little +

We can try to run smtpclient-2.tac the same way we +ran smtpclient-1.tac, but the results might be a little disappointing:

@@ -197,10 +197,11 @@
 

smtpClientService = internet.TCPClient('localhost', 25, smtpClientFactory)
-

This directs the client to connect to localhost on port -25. This isn't the address we want ultimately, but it's a -good place-holder for the time being. We can run smtpclient-3.tac and see what this change -gets us:

+

This directs the client to connect to localhost on +port 25. This isn't the address we want ultimately, but it's +a good place-holder for the time being. We can +run smtpclient-3.tac and see what this +change gets us:

 exarkun@boson:~/mail/tutorial/smtpclient$ twistd -ny smtpclient-3.tac
@@ -244,9 +245,9 @@
 

A meagre amount of progress, but the service still raises an -exception. This time, it's because we haven't specified a -protocol class for the factory to use. We'll do that in the -next example.

+exception. This time, it's because we haven't specified +a protocol class for the factory to use. We'll do that in +the next example.

SMTP Client 4

@@ -285,25 +286,26 @@ exarkun@boson:~/doc/mail/tutorial/smtpclient$ -

But what does this mean? -twisted.internet.protocol.Protocol is the base -protocol implementation. For those familiar with the classic -UNIX network services, it is equivalent to the discard -service. It never produces any output and it discards all its input. -Not terribly useful, and certainly nothing like an SMTP client. Let's -see how we can improve this in the next example.

+

But what does this +mean? twisted.internet.protocol.Protocol is the +base protocol implementation. For those familiar with the +classic UNIX network services, it is equivalent to +the discard service. It never produces any output and it +discards all its input. Not terribly useful, and certainly nothing +like an SMTP client. Let's see how we can improve this in the next +example.

SMTP Client 5

In smtpclient-5.tac, we will begin to use Twisted's SMTP protocol implementation for the first time. -We'll make the obvious change, simply swapping out -twisted.internet.protocol.Protocol in favor of -twisted.mail.smtp.ESMTPClient. Don't worry about the -E in ESMTP. It indicates we're actually using a -newer version of the SMTP protocol. There is an -SMTPClient in Twisted, but there's essentially no reason -to ever use it.

+We'll make the obvious change, simply swapping +out twisted.internet.protocol.Protocol in favor +of twisted.mail.smtp.ESMTPClient. Don't worry about +the E in ESMTP. It indicates we're actually using a +newer version of the SMTP protocol. There is +an SMTPClient in Twisted, but there's essentially no +reason to ever use it.

smtpclient-5.tac adds a new import:

@@ -311,10 +313,10 @@

from twisted.mail import smtp -

All of the mail related code in Twisted exists beneath the -twisted.mail package. More specifically, everything -having to do with the SMTP protocol implementation is defined in the -twisted.mail.smtp module.

+

All of the mail related code in Twisted exists beneath +the twisted.mail package. More specifically, everything +having to do with the SMTP protocol implementation is defined in +the twisted.mail.smtp module.

Next we remove a line we added in smtpclient-4.tac:

@@ -376,17 +378,17 @@

Oops, back to getting a traceback. This time, the default implementation of buildProtocol seems no longer to be -sufficient. It instantiates the protocol with no arguments, but -ESMTPClient wants at least one argument. In the next +sufficient. It instantiates the protocol with no arguments, +but ESMTPClient wants at least one argument. In the next version of the client, we'll override buildProtocol to fix this problem.

SMTP Client 6

-

smtpclient-6.tac introduces a -twisted.internet.protocol.ClientFactory subclass with an -overridden buildProtocol method to overcome the problem -encountered in the previous example.

+

smtpclient-6.tac introduces +a twisted.internet.protocol.ClientFactory subclass with +an overridden buildProtocol method to overcome the +problem encountered in the previous example.

1 2 @@ -422,8 +424,8 @@

smtpClientFactory = SMTPClientFactory()
-

Running this version of the code, we observe that the code -still isn't quite traceback-free.

+

Running this version of the code, we observe that the +code still isn't quite traceback-free.

 exarkun@boson:~/doc/mail/tutorial/smtpclient$ twistd -ny smtpclient-6.tac
@@ -485,10 +487,11 @@
 actually includes message data to transmit.  For simplicity's sake,
 the message is defined as part of a new class.  In a useful program
 which sent email, message data might be pulled in from the filesystem,
-a database, or be generated based on user-input.  smtpclient-7.tac, however, defines a new
-class, SMTPTutorialClient, with three class attributes
-(mailFrom, mailTo, and
-mailData):

+a database, or be generated based on +user-input. smtpclient-7.tac, however, +defines a new class, SMTPTutorialClient, with three class +attributes (mailFrom, mailTo, +and mailData):

1 2 @@ -516,7 +519,7 @@

This statically defined data is accessed later in the class definition by three of the methods which are part of the -SMTPClient callback API. Twisted expects each of the three + SMTPClient callback API. Twisted expects each of the three methods below to be defined and to return an object with a particular meaning. First, getMailFrom:

@@ -551,7 +554,7 @@

getMailTo is similar to getMailFrom. It returns one or more RFC 2821 addresses (this time a -forward-path, or envelope to). Since SMTP allows + forward-path, or envelope to). Since SMTP allows multiple recipients, getMailTo returns a list of these addresses. The list must contain at least one address, and even if there is exactly one recipient, it must still be in a list.

@@ -566,14 +569,14 @@

This one is quite simple as well: it returns a file or a file-like -object which contains the message contents. In our case, we return a -StringIO since we already have a string containing our -message. If the contents of the file returned by -getMailData span multiple lines (as email messages often -do), the lines should be \n delimited (as they would be -when opening a text file in the "rt" mode): necessary -newline translation will be performed by SMTPClient -automatically.

+object which contains the message contents. In our case, we return +a StringIO since we already have a string containing our +message. If the contents of the file returned +by getMailData span multiple lines (as email messages +often do), the lines should be \n delimited (as they +would be when opening a text file in the "rt" mode): +necessary newline translation will be performed +by SMTPClient automatically.

There is one more new callback method defined in smtpclient-7.tac. This one isn't for providing information about the messages to @@ -602,8 +605,8 @@ data, and disconnects. Notably missing, however, is application shutdown. Hitting ^C is fine during development, but it's not exactly a long-term solution. Fortunately, programmatic shutdown is extremely -simple. smtpclient-8.tac extends -sentMail with these two lines:

+simple. smtpclient-8.tac +extends sentMail with these two lines:

1 2 @@ -685,11 +688,11 @@ return defer.succeed('localhost')

-

defer.succeed is a function which creates a new -Deferred which already has a result, in this case -'localhost'. Now we need to adjust our -TCPClient-constructing code to expect and properly handle -this Deferred:

+

defer.succeed is a function which creates a +new Deferred which already has a result, in this +case 'localhost'. Now we need to adjust +our TCPClient-constructing code to expect and properly +handle this Deferred:

1 2 @@ -711,18 +714,18 @@ scope of this document. For such a look, see the Deferred Reference. However, in brief, what this version of the code does is to delay the -creation of the TCPClient until the -Deferred returned by getMailExchange fires. -Once it does, we proceed normally through the creation of our -SMTPClientFactory and TCPClient, as well as -set the TCPClient's service parent, just as we did in the -previous examples.

+creation of the TCPClient until the Deferred +returned by getMailExchange fires. Once it does, we +proceed normally through the creation of +our SMTPClientFactory and TCPClient, as well +as set the TCPClient's service parent, just as we did in +the previous examples.

SMTP Client 11

At last we're ready to perform the mail exchange lookup. We do -this by calling on an object provided specifically for this task, -twisted.mail.relaymanager.MXCalculator:

+this by calling on an object provided specifically for this +task, twisted.mail.relaymanager.MXCalculator:

1 2 @@ -737,16 +740,18 @@

Because getMX returns a Record_MX object rather than a string, we do a little bit of post-processing to get the results we want. We have already converted the rest of the tutorial -application to expect a Deferred from -getMailExchange, so no further changes are required. smtpclient-11.tac completes this tutorial -by being able to both look up the mail exchange host for the recipient -domain, connect to it, complete an SMTP transaction, report its -results, and finally shut down the reactor.

+application to expect a Deferred +from getMailExchange, so no further changes are +required. smtpclient-11.tac completes +this tutorial by being able to both look up the mail exchange host for +the recipient domain, connect to it, complete an SMTP transaction, +report its results, and finally shut down the reactor.

+

Index

- Version: 10.1.0 + Version: 12.0.0 \ No newline at end of file diff -Nru twisted-mail-10.1.0/LICENSE twisted-mail-12.0.0/LICENSE --- twisted-mail-10.1.0/LICENSE 2010-01-17 00:03:58.000000000 +0000 +++ twisted-mail-12.0.0/LICENSE 2012-01-23 13:19:44.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2001-2010 +Copyright (c) 2001-2012 Allen Short Andy Gayton Andrew Bennetts @@ -12,7 +12,7 @@ Donovan Preston Eric Mangold Eyal Lotem -Itamar Shtull-Trauring +Itamar Turner-Trauring James Knight Jason A. Mobarak Jean-Paul Calderone diff -Nru twisted-mail-10.1.0/NEWS twisted-mail-12.0.0/NEWS --- twisted-mail-10.1.0/NEWS 2010-06-27 11:23:16.000000000 +0000 +++ twisted-mail-12.0.0/NEWS 2012-02-10 14:56:39.000000000 +0000 @@ -1,6 +1,76 @@ Ticket numbers in this file can be looked up by visiting http://twistedmatrix.com/trac/ticket/ +Twisted Mail 12.0.0 (2012-02-10) +================================ + +No significant changes have been made for this release. + + +Twisted Mail 11.1.0 (2011-11-15) +================================ + +Features +-------- + - twisted.mail.smtp.LOGINCredentials now generates challenges with + ":" instead of "\0" for interoperability with Microsoft Outlook. + (#4692) + +Bugfixes +-------- + - When run from an unpacked source tarball or a VCS checkout, + bin/mail/mailmail will now use the version of Twisted it is part + of. (#3526) + +Other +----- + - #4796, #5006 + + +Twisted Mail 11.0.0 (2011-04-01) +================================ + +Features +-------- + - The `twistd mail` command line now accepts endpoint descriptions + for POP3 and SMTP servers. (#4739) + - The twistd mail plugin now accepts new authentication options via + strcred.AuthOptionMixin. These include --auth, --auth-help, and + authentication type-specific help options. (#4740) + +Bugfixes +-------- + - twisted.mail.imap4.IMAP4Server now generates INTERNALDATE strings + which do not consider the locale. (#4937) + +Improved Documentation +---------------------- + - Added a simple SMTP example, showing how to use sendmail. (#4042) + +Other +----- + + - #4162 + + +Twisted Mail 10.2.0 (2010-11-29) +================================ + +Improved Documentation +---------------------- + - The email server example now demonstrates how to set up + authentication and authorization using twisted.cred. (#4609) + +Deprecations and Removals +------------------------- + - twisted.mail.smtp.sendEmail, deprecated since mid 2003 (before + Twisted 2.0), has been removed. (#4529) + +Other +----- + - #4038, #4572 + + Twisted Mail 10.1.0 (2010-06-27) ================================ diff -Nru twisted-mail-10.1.0/README twisted-mail-12.0.0/README --- twisted-mail-10.1.0/README 2010-06-27 11:23:16.000000000 +0000 +++ twisted-mail-12.0.0/README 2012-02-10 14:56:39.000000000 +0000 @@ -1,3 +1,6 @@ -Twisted Mail 10.1.0 +Twisted Mail 12.0.0 -Twisted Mail depends on Twisted and (sometimes) Twisted Names. +Twisted Mail depends on Twisted Core and (sometimes) Twisted Names. For TLS +support, pyOpenSSL () is also required. Aside +from protocol implementations, much of Twisted Mail also only runs on POSIX +platforms. diff -Nru twisted-mail-10.1.0/setup.py twisted-mail-12.0.0/setup.py --- twisted-mail-10.1.0/setup.py 2008-10-26 21:37:04.000000000 +0000 +++ twisted-mail-12.0.0/setup.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import sys diff -Nru twisted-mail-10.1.0/twisted/mail/alias.py twisted-mail-12.0.0/twisted/mail/alias.py --- twisted-mail-10.1.0/twisted/mail/alias.py 2008-07-29 20:13:54.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/alias.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- # -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/bounce.py twisted-mail-12.0.0/twisted/mail/bounce.py --- twisted-mail-10.1.0/twisted/mail/bounce.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/bounce.py 2011-04-06 02:17:35.000000000 +0000 @@ -1,12 +1,11 @@ # -*- test-case-name: twisted.mail.test.test_bounce -*- # -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import StringIO import rfc822 -import string import time import os @@ -40,7 +39,7 @@ boundary = "%s_%s_%s" % (time.time(), os.getpid(), 'XXXXX') failedAddress = rfc822.AddressList(failedTo)[0][1] - failedDomain = string.split(failedAddress, '@', 1)[1] + failedDomain = failedAddress.split('@', 1)[1] messageID = smtp.messageid(uniq='bounce') ctime = time.ctime(time.time()) diff -Nru twisted-mail-10.1.0/twisted/mail/imap4.py twisted-mail-12.0.0/twisted/mail/imap4.py --- twisted-mail-10.1.0/twisted/mail/imap4.py 2010-04-10 14:34:47.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/imap4.py 2011-04-06 02:17:35.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_imap -*- -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -49,6 +49,11 @@ import twisted.cred.credentials +# locale-independent month names to use instead of strftime's +_MONTH_NAMES = dict(zip( + range(1, 13), + "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split())) + class MessageSet(object): """ @@ -1904,7 +1909,9 @@ log.msg("%d:%r: unpareseable internaldate: %r" % (id, msg, idate)) raise IMAP4Exception("Internal failure generating INTERNALDATE") - odate = time.strftime("%d-%b-%Y %H:%M:%S ", ttup[:9]) + # need to specify the month manually, as strftime depends on locale + strdate = time.strftime("%d-%%s-%Y %H:%M:%S ", ttup[:9]) + odate = strdate % (_MONTH_NAMES[ttup[1]],) if ttup[9] is None: odate = odate + "+0000" else: @@ -1912,7 +1919,7 @@ sign = "+" else: sign = "-" - odate = odate + sign + string.zfill(str(((abs(ttup[9]) / 3600) * 100 + (abs(ttup[9]) % 3600) / 60)), 4) + odate = odate + sign + str(((abs(ttup[9]) / 3600) * 100 + (abs(ttup[9]) % 3600) / 60)).zfill(4) _w('INTERNALDATE ' + _quote(odate)) def spew_rfc822header(self, id, msg, _w=None, _f=None): diff -Nru twisted-mail-10.1.0/twisted/mail/__init__.py twisted-mail-12.0.0/twisted/mail/__init__.py --- twisted-mail-10.1.0/twisted/mail/__init__.py 2008-07-29 20:13:54.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/__init__.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/maildir.py twisted-mail-12.0.0/twisted/mail/maildir.py --- twisted-mail-10.1.0/twisted/mail/maildir.py 2010-05-31 22:40:00.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/maildir.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -27,12 +27,8 @@ from twisted.python.hashlib import md5 from twisted.mail import mail from twisted.internet import interfaces, defer, reactor - -from twisted import cred -import twisted.cred.portal -import twisted.cred.credentials -import twisted.cred.checkers -import twisted.cred.error +from twisted.cred import portal, credentials, checkers +from twisted.cred.error import UnauthorizedLogin INTERNAL_ERROR = '''\ From: Twisted.mail Internals @@ -433,7 +429,7 @@ """A Maildir Domain where membership is checked by a dirdbm file """ - implements(cred.portal.IRealm, mail.IAliasableDomain) + implements(portal.IRealm, mail.IAliasableDomain) portal = None _credcheckers = None @@ -493,7 +489,7 @@ def requestAvatar(self, avatarId, mind, *interfaces): if pop3.IMailbox not in interfaces: raise NotImplementedError("No interface") - if avatarId == cred.checkers.ANONYMOUS: + if avatarId == checkers.ANONYMOUS: mbox = StringListMailbox([INTERNAL_ERROR]) else: mbox = MaildirMailbox(os.path.join(self.root, avatarId)) @@ -505,11 +501,11 @@ ) class DirdbmDatabase: - implements(cred.checkers.ICredentialsChecker) + implements(checkers.ICredentialsChecker) credentialInterfaces = ( - cred.credentials.IUsernamePassword, - cred.credentials.IUsernameHashedPassword + credentials.IUsernamePassword, + credentials.IUsernameHashedPassword ) def __init__(self, dbm): @@ -519,4 +515,4 @@ if c.username in self.dirdbm: if c.checkPassword(self.dirdbm[c.username]): return c.username - raise cred.error.UnauthorizedLogin() + raise UnauthorizedLogin() diff -Nru twisted-mail-10.1.0/twisted/mail/mail.py twisted-mail-12.0.0/twisted/mail/mail.py --- twisted-mail-10.1.0/twisted/mail/mail.py 2008-02-22 10:13:08.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/mail.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/pb.py twisted-mail-12.0.0/twisted/mail/pb.py --- twisted-mail-10.1.0/twisted/mail/pb.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/pb.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/pop3client.py twisted-mail-12.0.0/twisted/mail/pop3client.py --- twisted-mail-10.1.0/twisted/mail/pop3client.py 2008-11-19 19:56:50.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/pop3client.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.mail.test.test_pop3client -*- # Copyright (c) 2001-2004 Divmod Inc. -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-mail-10.1.0/twisted/mail/pop3.py twisted-mail-12.0.0/twisted/mail/pop3.py --- twisted-mail-10.1.0/twisted/mail/pop3.py 2008-11-19 19:56:50.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/pop3.py 2011-04-06 02:17:35.000000000 +0000 @@ -1,6 +1,6 @@ # -*- test-case-name: twisted.mail.test.test_pop3 -*- # -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -11,7 +11,6 @@ @author: Jp Calderone """ -import string import base64 import binascii import warnings @@ -351,7 +350,7 @@ self.blocked.append((command, args)) return - command = string.upper(command) + command = command.upper() authCmd = command in self.AUTH_CMDS if not self.mbox and not authCmd: raise POP3Error("not authenticated yet: cannot do " + command) diff -Nru twisted-mail-10.1.0/twisted/mail/protocols.py twisted-mail-12.0.0/twisted/mail/protocols.py --- twisted-mail-10.1.0/twisted/mail/protocols.py 2006-07-01 16:08:17.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/protocols.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/relaymanager.py twisted-mail-12.0.0/twisted/mail/relaymanager.py --- twisted-mail-10.1.0/twisted/mail/relaymanager.py 2008-01-20 13:34:51.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/relaymanager.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-mail-10.1.0/twisted/mail/relay.py twisted-mail-12.0.0/twisted/mail/relay.py --- twisted-mail-10.1.0/twisted/mail/relay.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/relay.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mail -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-mail-10.1.0/twisted/mail/scripts/mailmail.py twisted-mail-12.0.0/twisted/mail/scripts/mailmail.py --- twisted-mail-10.1.0/twisted/mail/scripts/mailmail.py 2008-07-10 15:07:15.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/scripts/mailmail.py 2011-06-30 12:57:11.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_mailmail -*- -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -17,6 +17,7 @@ except: import StringIO +from twisted.copyright import version from twisted.internet import reactor from twisted.mail import smtp @@ -67,6 +68,11 @@ # Skip -bm -- it is the default + # Add a non-standard option for querying the version of this tool. + if '--version' in argv: + print 'mailmail version:', version + raise SystemExit() + # -bp lists queue information. Screw that. if '-bp' in argv: raise _unsupportedOption diff -Nru twisted-mail-10.1.0/twisted/mail/smtp.py twisted-mail-12.0.0/twisted/mail/smtp.py --- twisted-mail-10.1.0/twisted/mail/smtp.py 2009-12-18 15:59:52.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/smtp.py 2011-08-05 23:41:33.000000000 +0000 @@ -1,14 +1,12 @@ # -*- test-case-name: twisted.mail.test.test_smtp -*- -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Simple Mail Transfer Protocol implementation. """ -import time, re, base64, types, socket, os, random, hmac -import MimeWriter, tempfile, rfc822 -import warnings +import time, re, base64, types, socket, os, random, rfc822 import binascii from email.base64MIME import encode as encode_base64 @@ -24,11 +22,8 @@ from twisted.internet.interfaces import ITLSTransport from twisted.python import log from twisted.python import util -from twisted.python import failure from twisted import cred -import twisted.cred.checkers -import twisted.cred.credentials from twisted.python.runtime import platform try: @@ -45,7 +40,7 @@ DNSNAME = socket.getfqdn() # Used for fast success code lookup -SUCCESS = dict(map(None, range(200, 300), [])) +SUCCESS = dict.fromkeys(xrange(200,300)) class IMessageDelivery(Interface): def receivedHeader(helo, origin, recipients): @@ -1402,7 +1397,7 @@ self._failresponse = self.esmtpAUTHDeclined try: challenge = base64.decodestring(challenge) - except binascii.Error, e: + except binascii.Error: # Illegal challenge, give up, then quit self.sendLine('*') self._okresponse = self.esmtpAUTHMalformedChallenge @@ -1738,6 +1733,22 @@ from twisted.mail.imap4 import IClientAuthentication from twisted.mail.imap4 import CramMD5ClientAuthenticator, LOGINAuthenticator +from twisted.mail.imap4 import LOGINCredentials as _lcredentials + +class LOGINCredentials(_lcredentials): + """ + L{LOGINCredentials} generates challenges for I{LOGIN} authentication. + + For interoperability with Outlook, the challenge generated does not exactly + match the one defined in the + U{draft specification}. + """ + + def __init__(self): + _lcredentials.__init__(self) + self.challenges = ['Password:', 'Username:'] + + class PLAINAuthenticator: implements(IClientAuthentication) @@ -1750,9 +1761,9 @@ def challengeResponse(self, secret, chal=1): if chal == 1: - return "%s\0%s\0%s" % (self.user, self.user, secret) + return "%s\0%s\0%s" % (self.user, self.user, secret) else: - return "%s\0%s" % (self.user, secret) + return "%s\0%s" % (self.user, secret) @@ -1874,96 +1885,7 @@ return d -def sendEmail(smtphost, fromEmail, toEmail, content, headers = None, attachments = None, multipartbody = "mixed"): - """Send an email, optionally with attachments. - - @type smtphost: str - @param smtphost: hostname of SMTP server to which to connect - - @type fromEmail: str - @param fromEmail: email address to indicate this email is from - - @type toEmail: str - @param toEmail: email address to which to send this email - - @type content: str - @param content: The body if this email. - - @type headers: dict - @param headers: Dictionary of headers to include in the email - - @type attachments: list of 3-tuples - @param attachments: Each 3-tuple should consist of the name of the - attachment, the mime-type of the attachment, and a string that is - the attachment itself. - - @type multipartbody: str - @param multipartbody: The type of MIME multi-part body. Generally - either "mixed" (as in text and images) or "alternative" (html email - with a fallback to text/plain). - - @rtype: Deferred - @return: The returned Deferred has its callback or errback invoked when - the mail is successfully sent or when an error occurs, respectively. - """ - warnings.warn("smtp.sendEmail may go away in the future.\n" - " Consider revising your code to use the email module\n" - " and smtp.sendmail.", - category=DeprecationWarning, stacklevel=2) - f = tempfile.TemporaryFile() - writer = MimeWriter.MimeWriter(f) - - writer.addheader("Mime-Version", "1.0") - if headers: - # Setup the mail headers - for (header, value) in headers.items(): - writer.addheader(header, value) - - headkeys = [k.lower() for k in headers.keys()] - else: - headkeys = () - - # Add required headers if not present - if "message-id" not in headkeys: - writer.addheader("Message-ID", messageid()) - if "date" not in headkeys: - writer.addheader("Date", rfc822date()) - if "from" not in headkeys and "sender" not in headkeys: - writer.addheader("From", fromEmail) - if "to" not in headkeys and "cc" not in headkeys and "bcc" not in headkeys: - writer.addheader("To", toEmail) - - writer.startmultipartbody(multipartbody) - - # message body - part = writer.nextpart() - body = part.startbody("text/plain") - body.write(content) - - if attachments is not None: - # add attachments - for (file, mime, attachment) in attachments: - part = writer.nextpart() - if mime.startswith('text'): - encoding = "7bit" - else: - attachment = base64.encodestring(attachment) - encoding = "base64" - part.addheader("Content-Transfer-Encoding", encoding) - body = part.startbody("%s; name=%s" % (mime, file)) - body.write(attachment) - - # finish - writer.lastpart() - - # send message - f.seek(0, 0) - d = defer.Deferred() - factory = SMTPSenderFactory(fromEmail, toEmail, f, d) - reactor.connectTCP(smtphost, 25, factory) - - return d ## ## Yerg. Codecs! @@ -1980,7 +1902,7 @@ return (''.join(r), len(s)) -def _slowXTextDecode(s, errors=None): +def xtext_decode(s, errors=None): """ Decode the xtext-encoded string C{s}. """ @@ -1998,17 +1920,6 @@ i += 1 return (''.join(r), len(s)) -try: - from twisted.protocols._c_urlarg import unquote as _helper_unquote -except ImportError: - xtext_decode = _slowXTextDecode -else: - def xtext_decode(s, errors=None): - """ - Decode the xtext-encoded string C{s} using a fast extension function. - """ - return (_helper_unquote(s, '+'), len(s)) - class xtextStreamReader(codecs.StreamReader): def decode(self, s, errors='strict'): return xtext_decode(s) diff -Nru twisted-mail-10.1.0/twisted/mail/tap.py twisted-mail-12.0.0/twisted/mail/tap.py --- twisted-mail-10.1.0/twisted/mail/tap.py 2008-10-28 20:12:14.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/tap.py 2011-10-18 10:31:11.000000000 +0000 @@ -1,13 +1,14 @@ # -*- test-case-name: twisted.mail.test.test_options -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. -"""I am the support module for creating mail servers with twistd +""" +I am the support module for creating mail servers with twistd """ import os -import sys +import warnings from twisted.mail import mail from twisted.mail import maildir @@ -15,31 +16,59 @@ from twisted.mail import relaymanager from twisted.mail import alias +from twisted.mail.protocols import SSLContextFactory + +from twisted.internet import endpoints + from twisted.python import usage +from twisted.python import deprecate +from twisted.python import versions from twisted.cred import checkers +from twisted.cred import strcred + from twisted.application import internet -class Options(usage.Options): +class Options(usage.Options, strcred.AuthOptionMixin): synopsis = "[options]" optParameters = [ - ["pop3", "p", 8110, "Port to start the POP3 server on (0 to disable).", usage.portCoerce], - ["pop3s", "S", 0, "Port to start the POP3-over-SSL server on (0 to disable).", usage.portCoerce], - ["smtp", "s", 8025, "Port to start the SMTP server on (0 to disable).", usage.portCoerce], - ["certificate", "c", None, "Certificate file to use for SSL connections"], + ["pop3s", "S", 0, + "Port to start the POP3-over-SSL server on (0 to disable). " + "DEPRECATED: use " + "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'"], + + ["certificate", "c", None, + "Certificate file to use for SSL connections. " + "DEPRECATED: use " + "'--pop3 ssl:port:privateKey=pkey.pem:certKey=cert.pem'"], + ["relay", "R", None, - "Relay messages according to their envelope 'To', using the given" - "path as a queue directory."], - ["hostname", "H", None, "The hostname by which to identify this server."], + "Relay messages according to their envelope 'To', using " + "the given path as a queue directory."], + + ["hostname", "H", None, + "The hostname by which to identify this server."], ] optFlags = [ ["esmtp", "E", "Use RFC 1425/1869 SMTP extensions"], - ["disable-anonymous", None, "Disallow non-authenticated SMTP connections"], + ["disable-anonymous", None, + "Disallow non-authenticated SMTP connections"], + ["no-pop3", None, "Disable the default POP3 server."], + ["no-smtp", None, "Disable the default SMTP server."], ] - zsh_actions = {"hostname" : "_hosts"} + + _protoDefaults = { + "pop3": 8110, + "smtp": 8025, + } + + compData = usage.Completions( + optActions={"hostname" : usage.CompleteHostnames(), + "certificate" : usage.CompleteFiles("*.pem")} + ) longdesc = "This creates a mail.tap file that can be used by twistd." @@ -47,13 +76,55 @@ usage.Options.__init__(self) self.service = mail.MailService() self.last_domain = None + for service in self._protoDefaults: + self[service] = [] + + + def addEndpoint(self, service, description, certificate=None): + """ + Given a 'service' (pop3 or smtp), add an endpoint. + """ + self[service].append( + _toEndpoint(description, certificate=certificate)) + + + def opt_pop3(self, description): + """ + Add a pop3 port listener on the specified endpoint. You can listen on + multiple ports by specifying multiple --pop3 options. For backwards + compatibility, a bare TCP port number can be specified, but this is + deprecated. [SSL Example: ssl:8995:privateKey=mycert.pem] [default: + tcp:8110] + """ + self.addEndpoint('pop3', description) + opt_p = opt_pop3 + + + def opt_smtp(self, description): + """ + Add an smtp port listener on the specified endpoint. You can listen on + multiple ports by specifying multiple --smtp options For backwards + compatibility, a bare TCP port number can be specified, but this is + deprecated. [SSL Example: ssl:8465:privateKey=mycert.pem] [default: + tcp:8025] + """ + self.addEndpoint('smtp', description) + opt_s = opt_smtp + def opt_passwordfile(self, filename): - """Specify a file containing username:password login info for authenticated ESMTP connections.""" + """ + Specify a file containing username:password login info for authenticated + ESMTP connections. (DEPRECATED; see --help-auth instead) + """ ch = checkers.OnDiskUsernamePasswordDatabase(filename) self.service.smtpPortal.registerChecker(ch) + msg = deprecate.getDeprecationWarningString( + self.opt_passwordfile, versions.Version('twisted.mail', 11, 0, 0)) + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) opt_P = opt_passwordfile + def opt_default(self): """Make the most recently specified domain the default domain.""" if self.last_domain: @@ -62,6 +133,7 @@ raise usage.UsageError("Specify a domain before specifying using --default") opt_D = opt_default + def opt_maildirdbmdomain(self, domain): """generate an SMTP/POP3 virtual domain which saves to \"path\" """ @@ -113,7 +185,47 @@ raise usage.UsageError("Specify a domain before specifying aliases") opt_A = opt_aliases + def _getEndpoints(self, reactor, service): + """ + Return a list of endpoints for the specified service, constructing + defaults if necessary. + + @param reactor: If any endpoints are created, this is the reactor with + which they are created. + + @param service: A key into self indicating the type of service to + retrieve endpoints for. This is either C{"pop3"} or C{"smtp"}. + + @return: A C{list} of C{IServerStreamEndpoint} providers corresponding + to the command line parameters that were specified for C{service}. + If none were and the protocol was not explicitly disabled with a + I{--no-*} option, a default endpoint for the service is created + using C{self._protoDefaults}. + """ + if service == 'pop3' and self['pop3s'] and len(self[service]) == 1: + # The single endpoint here is the POP3S service we added in + # postOptions. Include the default endpoint alongside it. + return self[service] + [ + endpoints.TCP4ServerEndpoint( + reactor, self._protoDefaults[service])] + elif self[service]: + # For any non-POP3S case, if there are any services set up, just + # return those. + return self[service] + elif self['no-' + service]: + # If there are no services, but the service was explicitly disabled, + # return nothing. + return [] + else: + # Otherwise, return the old default service. + return [ + endpoints.TCP4ServerEndpoint( + reactor, self._protoDefaults[service])] + + def postOptions(self): + from twisted.internet import reactor + if self['pop3s']: if not self['certificate']: raise usage.UsageError("Cannot specify --pop3s without " @@ -121,13 +233,27 @@ elif not os.path.exists(self['certificate']): raise usage.UsageError("Certificate file %r does not exist." % self['certificate']) + else: + self.addEndpoint( + 'pop3', self['pop3s'], certificate=self['certificate']) + + if self['esmtp'] and self['hostname'] is None: + raise usage.UsageError("--esmtp requires --hostname") if not self['disable-anonymous']: self.service.smtpPortal.registerChecker(checkers.AllowAnonymousAccess()) - if not (self['pop3'] or self['smtp'] or self['pop3s']): + anything = False + for service in self._protoDefaults: + self[service] = self._getEndpoints(reactor, service) + if self[service]: + anything = True + + if not anything: raise usage.UsageError("You cannot disable all protocols") + + class AliasUpdater: def __init__(self, domains, domain): self.domains = domains @@ -135,7 +261,44 @@ def __call__(self, new): self.domain.setAliasGroup(alias.loadAliasFile(self.domains, new)) + +def _toEndpoint(description, certificate=None): + """ + Tries to guess whether a description is a bare TCP port or a endpoint. If a + bare port is specified and a certificate file is present, returns an + SSL4ServerEndpoint and otherwise returns a TCP4ServerEndpoint. + """ + from twisted.internet import reactor + try: + port = int(description) + except ValueError: + return endpoints.serverFromString(reactor, description) + + warnings.warn( + "Specifying plain ports and/or a certificate is deprecated since " + "Twisted 11.0; use endpoint descriptions instead.", + category=DeprecationWarning, stacklevel=3) + + if certificate: + ctx = SSLContextFactory(certificate) + return endpoints.SSL4ServerEndpoint(reactor, port, ctx) + return endpoints.TCP4ServerEndpoint(reactor, port) + + def makeService(config): + """ + Construct a service for operating a mail server. + + The returned service may include POP3 servers or SMTP servers (or both), + depending on the configuration passed in. If there are multiple servers, + they will share all of their non-network state (eg, the same user accounts + are available on all of them). + + @param config: An L{Options} instance specifying what servers to include in + the returned service and where they should keep mail data. + + @return: An L{IService} provider which contains the requested mail servers. + """ if config['esmtp']: rmType = relaymanager.SmartHostESMTPRelayingManager smtpFactory = config.service.getESMTPFactory @@ -160,26 +323,21 @@ helper.setServiceParent(config.service) config.service.domains.setDefaultDomain(default) - ctx = None - if config['certificate']: - from twisted.mail.protocols import SSLContextFactory - ctx = SSLContextFactory(config['certificate']) - if config['pop3']: - s = internet.TCPServer(config['pop3'], config.service.getPOP3Factory()) - s.setServiceParent(config.service) - if config['pop3s']: - s = internet.SSLServer(config['pop3s'], - config.service.getPOP3Factory(), ctx) - s.setServiceParent(config.service) + f = config.service.getPOP3Factory() + for endpoint in config['pop3']: + svc = internet.StreamServerEndpointService(endpoint, f) + svc.setServiceParent(config.service) + if config['smtp']: f = smtpFactory() - f.context = ctx if config['hostname']: f.domain = config['hostname'] f.fArgs = (f.domain,) if config['esmtp']: f.fArgs = (None, None) + f.fArgs - s = internet.TCPServer(config['smtp'], f) - s.setServiceParent(config.service) + for endpoint in config['smtp']: + svc = internet.StreamServerEndpointService(endpoint, f) + svc.setServiceParent(config.service) + return config.service diff -Nru twisted-mail-10.1.0/twisted/mail/test/pop3testserver.py twisted-mail-12.0.0/twisted/mail/test/pop3testserver.py --- twisted-mail-10.1.0/twisted/mail/test/pop3testserver.py 2009-04-08 21:56:55.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/pop3testserver.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- test-case-name: twisted.mail.test.test_pop3client -*- -# Copyright (c) 2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.internet.protocol import Factory diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_bounce.py twisted-mail-12.0.0/twisted/mail/test/test_bounce.py --- twisted-mail-10.1.0/twisted/mail/test/test_bounce.py 2004-08-25 08:36:30.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_bounce.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -21,12 +21,12 @@ Subject: test '''), 'moshez@example.com', 'nonexistant@example.org') - self.assertEquals(from_, '') - self.assertEquals(to, 'moshez@example.com') + self.assertEqual(from_, '') + self.assertEqual(to, 'moshez@example.com') mess = rfc822.Message(cStringIO.StringIO(s)) - self.assertEquals(mess['To'], 'moshez@example.com') - self.assertEquals(mess['From'], 'postmaster@example.org') - self.assertEquals(mess['subject'], 'Returned Mail: see transcript for details') + self.assertEqual(mess['To'], 'moshez@example.com') + self.assertEqual(mess['From'], 'postmaster@example.org') + self.assertEqual(mess['subject'], 'Returned Mail: see transcript for details') def testBounceMIME(self): pass diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_imap.py twisted-mail-12.0.0/twisted/mail/test/test_imap.py --- twisted-mail-10.1.0/twisted/mail/test/test_imap.py 2010-04-10 14:34:47.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_imap.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.mail.test.test_imap -*- -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -12,9 +12,10 @@ except ImportError: from StringIO import StringIO +import codecs +import locale import os import types -import codecs from zope.interface import implements @@ -94,7 +95,7 @@ reader class. """ reader = codecs.getreader('imap4-utf-7')(StringIO('Hello&AP8-world')) - self.assertEquals(reader.read(), u'Hello\xffworld') + self.assertEqual(reader.read(), u'Hello\xffworld') def test_getwriter(self): @@ -105,7 +106,7 @@ output = StringIO() writer = codecs.getwriter('imap4-utf-7')(output) writer.write(u'Hello\xffworld') - self.assertEquals(output.getvalue(), 'Hello&AP8-world') + self.assertEqual(output.getvalue(), 'Hello&AP8-world') def test_encode(self): @@ -114,7 +115,7 @@ string according to the IMAP4 modified UTF-7 encoding rules. """ for (input, output) in self.tests: - self.assertEquals(input.encode('imap4-utf-7'), output) + self.assertEqual(input.encode('imap4-utf-7'), output) def test_decode(self): @@ -123,7 +124,7 @@ string according to the IMAP4 modified UTF-7 encoding rules. """ for (input, output) in self.tests: - self.assertEquals(input, output.decode('imap4-utf-7')) + self.assertEqual(input, output.decode('imap4-utf-7')) def test_printableSingletons(self): @@ -133,10 +134,10 @@ """ # All printables represent themselves for o in range(0x20, 0x26) + range(0x27, 0x7f): - self.failUnlessEqual(chr(o), chr(o).encode('imap4-utf-7')) - self.failUnlessEqual(chr(o), chr(o).decode('imap4-utf-7')) - self.failUnlessEqual('&'.encode('imap4-utf-7'), '&-') - self.failUnlessEqual('&-'.decode('imap4-utf-7'), '&') + self.assertEqual(chr(o), chr(o).encode('imap4-utf-7')) + self.assertEqual(chr(o), chr(o).decode('imap4-utf-7')) + self.assertEqual('&'.encode('imap4-utf-7'), '&-') + self.assertEqual('&-'.decode('imap4-utf-7'), '&') @@ -173,7 +174,7 @@ def cbProduced(result): self.assertIdentical(result, p) - self.assertEquals( + self.assertEqual( ''.join(c.buffer), '{119}\r\n' @@ -210,7 +211,7 @@ def cbProduced(result): self.failUnlessIdentical(result, p) - self.assertEquals( + self.assertEqual( ''.join(c.buffer), '{239}\r\n' @@ -258,7 +259,7 @@ def cbProduced(result): self.failUnlessIdentical(result, p) - self.assertEquals( + self.assertEqual( ''.join(c.buffer), '{354}\r\n' @@ -297,7 +298,7 @@ def cbProduced(result): self.failUnlessIdentical(result, p) - self.assertEquals( + self.assertEqual( ('{%d}\r\n' % len(b))+ b, ''.join(c.buffer)) return d.addCallback(cbProduced) @@ -353,22 +354,22 @@ ] for (input, output) in cases: - self.assertEquals(imap4._formatHeaders(input), output) + self.assertEqual(imap4._formatHeaders(input), output) def test_messageSet(self): m1 = MessageSet() m2 = MessageSet() - self.assertEquals(m1, m2) + self.assertEqual(m1, m2) m1 = m1 + (1, 3) - self.assertEquals(len(m1), 3) - self.assertEquals(list(m1), [1, 2, 3]) + self.assertEqual(len(m1), 3) + self.assertEqual(list(m1), [1, 2, 3]) m2 = m2 + (1, 3) - self.assertEquals(m1, m2) - self.assertEquals(list(m1 + m2), [1, 2, 3]) + self.assertEqual(m1, m2) + self.assertEqual(list(m1 + m2), [1, 2, 3]) def test_messageSetStringRepresentationWithWildcards(self): @@ -389,7 +390,7 @@ ] for i, o in zip(inputs, outputs): - self.assertEquals(str(i), o) + self.assertEqual(str(i), o) def test_messageSetStringRepresentationWithInversion(self): @@ -409,7 +410,7 @@ ] for i, o in zip(inputs, outputs): - self.assertEquals(str(i), o) + self.assertEqual(str(i), o) def test_quotedSplitter(self): @@ -469,7 +470,7 @@ self.assertRaises(imap4.MismatchedQuoting, imap4.splitQuoted, s) for (case, expected) in zip(cases, answers): - self.assertEquals(imap4.splitQuoted(case), expected) + self.assertEqual(imap4.splitQuoted(case), expected) def test_stringCollapser(self): @@ -494,7 +495,7 @@ ] for (case, expected) in zip(cases, answers): - self.assertEquals(imap4.collapseStrings(case), expected) + self.assertEqual(imap4.collapseStrings(case), expected) def test_parenParser(self): @@ -560,7 +561,7 @@ ] for (case, expected) in zip(cases, answers): - self.assertEquals(imap4.parseNestedParens(case), [expected]) + self.assertEqual(imap4.parseNestedParens(case), [expected]) # XXX This code used to work, but changes occurred within the # imap4.py module which made it no longer necessary for *all* of it @@ -571,7 +572,7 @@ # # for (case, expected) in zip(answers, cases): -# self.assertEquals('(' + imap4.collapseNestedLists(case) + ')', expected) +# self.assertEqual('(' + imap4.collapseNestedLists(case) + ')', expected) def test_fetchParserSimple(self): @@ -590,7 +591,7 @@ for (inp, outp) in cases: p = imap4._FetchParser() p.parseString(inp) - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], getattr(p, outp))) @@ -604,11 +605,11 @@ for (inp, outp) in cases: p = imap4._FetchParser() p.parseString(inp) - self.assertEquals(len(p.result), outp[0]) + self.assertEqual(len(p.result), outp[0]) p = [str(p).lower() for p in p.result] p.sort() outp[1].sort() - self.assertEquals(p, outp[1]) + self.assertEqual(p, outp[1]) def test_fetchParserBody(self): @@ -616,105 +617,105 @@ p = P() p.parseString('BODY') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, False) - self.assertEquals(p.result[0].header, None) - self.assertEquals(str(p.result[0]), 'BODY') + self.assertEqual(p.result[0].peek, False) + self.assertEqual(p.result[0].header, None) + self.assertEqual(str(p.result[0]), 'BODY') p = P() p.parseString('BODY.PEEK') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, True) - self.assertEquals(str(p.result[0]), 'BODY') + self.assertEqual(p.result[0].peek, True) + self.assertEqual(str(p.result[0]), 'BODY') p = P() p.parseString('BODY[]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].empty, True) - self.assertEquals(str(p.result[0]), 'BODY[]') + self.assertEqual(p.result[0].empty, True) + self.assertEqual(str(p.result[0]), 'BODY[]') p = P() p.parseString('BODY[HEADER]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, False) + self.assertEqual(p.result[0].peek, False) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].header.negate, True) - self.assertEquals(p.result[0].header.fields, ()) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[HEADER]') + self.assertEqual(p.result[0].header.negate, True) + self.assertEqual(p.result[0].header.fields, ()) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[HEADER]') p = P() p.parseString('BODY.PEEK[HEADER]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, True) + self.assertEqual(p.result[0].peek, True) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].header.negate, True) - self.assertEquals(p.result[0].header.fields, ()) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[HEADER]') + self.assertEqual(p.result[0].header.negate, True) + self.assertEqual(p.result[0].header.fields, ()) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[HEADER]') p = P() p.parseString('BODY[HEADER.FIELDS (Subject Cc Message-Id)]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, False) + self.assertEqual(p.result[0].peek, False) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].header.negate, False) - self.assertEquals(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[HEADER.FIELDS (Subject Cc Message-Id)]') + self.assertEqual(p.result[0].header.negate, False) + self.assertEqual(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[HEADER.FIELDS (Subject Cc Message-Id)]') p = P() p.parseString('BODY.PEEK[HEADER.FIELDS (Subject Cc Message-Id)]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, True) + self.assertEqual(p.result[0].peek, True) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].header.negate, False) - self.assertEquals(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[HEADER.FIELDS (Subject Cc Message-Id)]') + self.assertEqual(p.result[0].header.negate, False) + self.assertEqual(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[HEADER.FIELDS (Subject Cc Message-Id)]') p = P() p.parseString('BODY.PEEK[HEADER.FIELDS.NOT (Subject Cc Message-Id)]') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, True) + self.assertEqual(p.result[0].peek, True) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].header.negate, True) - self.assertEquals(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[HEADER.FIELDS.NOT (Subject Cc Message-Id)]') + self.assertEqual(p.result[0].header.negate, True) + self.assertEqual(p.result[0].header.fields, ['SUBJECT', 'CC', 'MESSAGE-ID']) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[HEADER.FIELDS.NOT (Subject Cc Message-Id)]') p = P() p.parseString('BODY[1.MIME]<10.50>') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, False) + self.assertEqual(p.result[0].peek, False) self.failUnless(isinstance(p.result[0].mime, p.MIME)) - self.assertEquals(p.result[0].part, (0,)) - self.assertEquals(p.result[0].partialBegin, 10) - self.assertEquals(p.result[0].partialLength, 50) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[1.MIME]<10.50>') + self.assertEqual(p.result[0].part, (0,)) + self.assertEqual(p.result[0].partialBegin, 10) + self.assertEqual(p.result[0].partialLength, 50) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[1.MIME]<10.50>') p = P() p.parseString('BODY.PEEK[1.3.9.11.HEADER.FIELDS.NOT (Message-Id Date)]<103.69>') - self.assertEquals(len(p.result), 1) + self.assertEqual(len(p.result), 1) self.failUnless(isinstance(p.result[0], p.Body)) - self.assertEquals(p.result[0].peek, True) + self.assertEqual(p.result[0].peek, True) self.failUnless(isinstance(p.result[0].header, p.Header)) - self.assertEquals(p.result[0].part, (0, 2, 8, 10)) - self.assertEquals(p.result[0].header.fields, ['MESSAGE-ID', 'DATE']) - self.assertEquals(p.result[0].partialBegin, 103) - self.assertEquals(p.result[0].partialLength, 69) - self.assertEquals(p.result[0].empty, False) - self.assertEquals(str(p.result[0]), 'BODY[1.3.9.11.HEADER.FIELDS.NOT (Message-Id Date)]<103.69>') + self.assertEqual(p.result[0].part, (0, 2, 8, 10)) + self.assertEqual(p.result[0].header.fields, ['MESSAGE-ID', 'DATE']) + self.assertEqual(p.result[0].partialBegin, 103) + self.assertEqual(p.result[0].partialLength, 69) + self.assertEqual(p.result[0].empty, False) + self.assertEqual(str(p.result[0]), 'BODY[1.3.9.11.HEADER.FIELDS.NOT (Message-Id Date)]<103.69>') def test_files(self): @@ -724,7 +725,7 @@ output = '"foo" "bar" "baz" {16}\r\nthis is a file\r\n "buz"' - self.assertEquals(imap4.collapseNestedLists(inputStructure), output) + self.assertEqual(imap4.collapseNestedLists(inputStructure), output) def test_quoteAvoider(self): @@ -735,7 +736,7 @@ output = '"foo" bar "baz" {16}\r\nthis is a file\r\n buz ""' - self.assertEquals(imap4.collapseNestedLists(input), output) + self.assertEqual(imap4.collapseNestedLists(input), output) def test_literals(self): @@ -744,7 +745,7 @@ ] for (case, expected) in cases: - self.assertEquals(imap4.parseNestedParens(case), expected) + self.assertEqual(imap4.parseNestedParens(case), expected) def test_queryBuilder(self): @@ -788,7 +789,7 @@ ] for (query, expected) in zip(inputs, outputs): - self.assertEquals(query, expected) + self.assertEqual(query, expected) def test_invalidIdListParser(self): @@ -874,14 +875,14 @@ ] for (input, expected) in zip(inputs, outputs): - self.assertEquals(imap4.parseIdList(input), expected) + self.assertEqual(imap4.parseIdList(input), expected) for (input, expected) in zip(inputs, lengths): if expected is None: self.assertRaises(TypeError, len, imap4.parseIdList(input)) else: L = len(imap4.parseIdList(input)) - self.assertEquals(L, expected, + self.assertEqual(L, expected, "len(%r) = %r != %r" % (input, L, expected)) class SimpleMailbox: @@ -1060,7 +1061,7 @@ d1 = self.connected.addCallback(strip(getCaps)).addErrback(self._ebGeneral) d = defer.gatherResults([self.loopback(), d1]) expected = {'IMAP4rev1': None, 'NAMESPACE': None, 'IDLE': None} - return d.addCallback(lambda _: self.assertEquals(expected, caps)) + return d.addCallback(lambda _: self.assertEqual(expected, caps)) def testCapabilityWithAuth(self): caps = {} @@ -1076,7 +1077,7 @@ expCap = {'IMAP4rev1': None, 'NAMESPACE': None, 'IDLE': None, 'AUTH': ['CRAM-MD5']} - return d.addCallback(lambda _: self.assertEquals(expCap, caps)) + return d.addCallback(lambda _: self.assertEqual(expCap, caps)) def testLogout(self): self.loggedOut = 0 @@ -1086,7 +1087,7 @@ self.client.logout().addCallback(strip(setLoggedOut)) self.connected.addCallback(strip(logout)).addErrback(self._ebGeneral) d = self.loopback() - return d.addCallback(lambda _: self.assertEquals(self.loggedOut, 1)) + return d.addCallback(lambda _: self.assertEqual(self.loggedOut, 1)) def testNoop(self): self.responses = None @@ -1097,7 +1098,7 @@ self.client.noop().addCallback(setResponses) self.connected.addCallback(strip(noop)).addErrback(self._ebGeneral) d = self.loopback() - return d.addCallback(lambda _: self.assertEquals(self.responses, [])) + return d.addCallback(lambda _: self.assertEqual(self.responses, [])) def testLogin(self): def login(): @@ -1108,8 +1109,8 @@ return d.addCallback(self._cbTestLogin) def _cbTestLogin(self, ignored): - self.assertEquals(self.server.account, SimpleServer.theAccount) - self.assertEquals(self.server.state, 'auth') + self.assertEqual(self.server.account, SimpleServer.theAccount) + self.assertEqual(self.server.state, 'auth') def testFailedLogin(self): def login(): @@ -1122,8 +1123,8 @@ return d.addCallback(self._cbTestFailedLogin) def _cbTestFailedLogin(self, ignored): - self.assertEquals(self.server.account, None) - self.assertEquals(self.server.state, 'unauth') + self.assertEqual(self.server.account, None) + self.assertEqual(self.server.state, 'unauth') def testLoginRequiringQuoting(self): @@ -1139,8 +1140,8 @@ return d.addCallback(self._cbTestLoginRequiringQuoting) def _cbTestLoginRequiringQuoting(self, ignored): - self.assertEquals(self.server.account, SimpleServer.theAccount) - self.assertEquals(self.server.state, 'auth') + self.assertEqual(self.server.account, SimpleServer.theAccount) + self.assertEqual(self.server.state, 'auth') def testNamespace(self): @@ -1158,7 +1159,7 @@ d1.addErrback(self._ebGeneral) d2 = self.loopback() d = defer.gatherResults([d1, d2]) - d.addCallback(lambda _: self.assertEquals(self.namespaceArgs, + d.addCallback(lambda _: self.assertEqual(self.namespaceArgs, [[['', '/']], [], []])) return d @@ -1183,8 +1184,8 @@ def _cbTestSelect(self, ignored): mbox = SimpleServer.theAccount.mailboxes['TEST-MAILBOX'] - self.assertEquals(self.server.mbox, mbox) - self.assertEquals(self.selectedArgs, { + self.assertEqual(self.server.mbox, mbox) + self.assertEqual(self.selectedArgs, { 'EXISTS': 9, 'RECENT': 3, 'UIDVALIDITY': 42, 'FLAGS': ('\\Flag1', 'Flag2', '\\AnotherSysFlag', 'LastFlag'), 'READ-WRITE': 1 @@ -1228,8 +1229,8 @@ def _cbTestExamine(self, ignored): mbox = SimpleServer.theAccount.mailboxes['TEST-MAILBOX'] - self.assertEquals(self.server.mbox, mbox) - self.assertEquals(self.examinedArgs, { + self.assertEqual(self.server.mbox, mbox) + self.assertEqual(self.examinedArgs, { 'EXISTS': 9, 'RECENT': 3, 'UIDVALIDITY': 42, 'FLAGS': ('\\Flag1', 'Flag2', '\\AnotherSysFlag', 'LastFlag'), 'READ-WRITE': False}) @@ -1257,12 +1258,12 @@ return d.addCallback(self._cbTestCreate, succeed, fail) def _cbTestCreate(self, ignored, succeed, fail): - self.assertEquals(self.result, [1] * len(succeed) + [0] * len(fail)) + self.assertEqual(self.result, [1] * len(succeed) + [0] * len(fail)) mbox = SimpleServer.theAccount.mailboxes.keys() answers = ['inbox', 'testbox', 'test/box', 'test', 'test/box/box'] mbox.sort() answers.sort() - self.assertEquals(mbox, [a.upper() for a in answers]) + self.assertEqual(mbox, [a.upper() for a in answers]) def testDelete(self): SimpleServer.theAccount.addMailbox('delete/me') @@ -1277,7 +1278,7 @@ d2 = self.loopback() d = defer.gatherResults([d1, d2]) d.addCallback(lambda _: - self.assertEquals(SimpleServer.theAccount.mailboxes.keys(), [])) + self.assertEqual(SimpleServer.theAccount.mailboxes.keys(), [])) return d def testIllegalInboxDelete(self): @@ -1314,7 +1315,7 @@ d1.addCallbacks(self._cbStopClient, self._ebGeneral) d2 = self.loopback() d = defer.gatherResults([d1, d2]) - d.addCallback(lambda _: self.assertEquals(str(self.failure.value), + d.addCallback(lambda _: self.assertEqual(str(self.failure.value), 'No such mailbox')) return d @@ -1340,7 +1341,7 @@ d = defer.gatherResults([d1, d2]) expected = "Hierarchically inferior mailboxes exist and \\Noselect is set" d.addCallback(lambda _: - self.assertEquals(str(self.failure.value), expected)) + self.assertEqual(str(self.failure.value), expected)) return d def testRename(self): @@ -1356,7 +1357,7 @@ d2 = self.loopback() d = defer.gatherResults([d1, d2]) d.addCallback(lambda _: - self.assertEquals(SimpleServer.theAccount.mailboxes.keys(), + self.assertEqual(SimpleServer.theAccount.mailboxes.keys(), ['NEWNAME'])) return d @@ -1398,7 +1399,7 @@ mboxes = SimpleServer.theAccount.mailboxes.keys() expected = ['newname', 'newname/m1', 'newname/m2'] mboxes.sort() - self.assertEquals(mboxes, [s.upper() for s in expected]) + self.assertEqual(mboxes, [s.upper() for s in expected]) def testSubscribe(self): def login(): @@ -1412,7 +1413,7 @@ d2 = self.loopback() d = defer.gatherResults([d1, d2]) d.addCallback(lambda _: - self.assertEquals(SimpleServer.theAccount.subscriptions, + self.assertEqual(SimpleServer.theAccount.subscriptions, ['THIS/MBOX'])) return d @@ -1429,7 +1430,7 @@ d2 = self.loopback() d = defer.gatherResults([d1, d2]) d.addCallback(lambda _: - self.assertEquals(SimpleServer.theAccount.subscriptions, + self.assertEqual(SimpleServer.theAccount.subscriptions, ['THAT/MBOX'])) return d @@ -1455,7 +1456,7 @@ def list(): return self.client.list('root', '%') d = self._listSetup(list) - d.addCallback(lambda listed: self.assertEquals( + d.addCallback(lambda listed: self.assertEqual( sortNest(listed), sortNest([ (SimpleMailbox.flags, "/", "ROOT/SUBTHING"), @@ -1469,7 +1470,7 @@ def lsub(): return self.client.lsub('root', '%') d = self._listSetup(lsub) - d.addCallback(self.assertEquals, + d.addCallback(self.assertEqual, [(SimpleMailbox.flags, "/", "ROOT/SUBTHING")]) return d @@ -1489,7 +1490,7 @@ d1.addCallbacks(self._cbStopClient, self._ebGeneral) d2 = self.loopback() d = defer.gatherResults([d1, d2]) - d.addCallback(lambda _: self.assertEquals( + d.addCallback(lambda _: self.assertEqual( self.statused, {'MESSAGES': 9, 'UIDNEXT': '10', 'UNSEEN': 4} )) @@ -1514,10 +1515,10 @@ return defer.gatherResults([d1, d2]).addCallback(self._cbTestFailedStatus) def _cbTestFailedStatus(self, ignored): - self.assertEquals( + self.assertEqual( self.statused, None ) - self.assertEquals( + self.assertEqual( self.failure.value.args, ('Could not open mailbox',) ) @@ -1545,12 +1546,12 @@ def _cbTestFullAppend(self, ignored, infile): mb = SimpleServer.theAccount.mailboxes['ROOT/SUBTHING'] - self.assertEquals(1, len(mb.messages)) - self.assertEquals( + self.assertEqual(1, len(mb.messages)) + self.assertEqual( (['\\SEEN', '\\DELETED'], 'Tue, 17 Jun 2003 11:22:16 -0600 (MDT)', 0), mb.messages[0][1:] ) - self.assertEquals(open(infile).read(), mb.messages[0][0].getvalue()) + self.assertEqual(open(infile).read(), mb.messages[0][0].getvalue()) def testPartialAppend(self): infile = util.sibpath(__file__, 'rfc822.message') @@ -1576,12 +1577,12 @@ def _cbTestPartialAppend(self, ignored, infile): mb = SimpleServer.theAccount.mailboxes['PARTIAL/SUBTHING'] - self.assertEquals(1, len(mb.messages)) - self.assertEquals( + self.assertEqual(1, len(mb.messages)) + self.assertEqual( (['\\SEEN'], 'Right now', 0), mb.messages[0][1:] ) - self.assertEquals(open(infile).read(), mb.messages[0][0].getvalue()) + self.assertEqual(open(infile).read(), mb.messages[0][0].getvalue()) def testCheck(self): SimpleServer.theAccount.addMailbox('root/subthing') @@ -1623,8 +1624,8 @@ return defer.gatherResults([d, d2]).addCallback(self._cbTestClose, m) def _cbTestClose(self, ignored, m): - self.assertEquals(len(m.messages), 1) - self.assertEquals(m.messages[0], ('Message 2', ('AnotherFlag',), None, 1)) + self.assertEqual(len(m.messages), 1) + self.assertEqual(m.messages[0], ('Message 2', ('AnotherFlag',), None, 1)) self.failUnless(m.closed) def testExpunge(self): @@ -1656,10 +1657,10 @@ return d.addCallback(self._cbTestExpunge, m) def _cbTestExpunge(self, ignored, m): - self.assertEquals(len(m.messages), 1) - self.assertEquals(m.messages[0], ('Message 2', ('AnotherFlag',), None, 1)) + self.assertEqual(len(m.messages), 1) + self.assertEqual(m.messages[0], ('Message 2', ('AnotherFlag',), None, 1)) - self.assertEquals(self.results, [0, 2]) + self.assertEqual(self.results, [0, 2]) @@ -1714,7 +1715,7 @@ the same as the query date. """ msgset = imap4.parseIdList('4:2') - self.assertEquals(list(msgset), [2, 3, 4]) + self.assertEqual(list(msgset), [2, 3, 4]) def test_searchSentOn(self): """ @@ -1832,8 +1833,8 @@ return d.addCallback(self._cbTestCramMD5) def _cbTestCramMD5(self, ignored): - self.assertEquals(self.authenticated, 1) - self.assertEquals(self.server.account, self.account) + self.assertEqual(self.authenticated, 1) + self.assertEqual(self.server.account, self.account) def testFailedCramMD5(self): self.server.challengers['CRAM-MD5'] = cred.credentials.CramMD5Credentials @@ -1854,8 +1855,8 @@ return d.addCallback(self._cbTestFailedCramMD5) def _cbTestFailedCramMD5(self, ignored): - self.assertEquals(self.authenticated, -1) - self.assertEquals(self.server.account, None) + self.assertEqual(self.authenticated, -1) + self.assertEqual(self.server.account, None) def testLOGIN(self): self.server.challengers['LOGIN'] = imap4.LOGINCredentials @@ -1874,8 +1875,8 @@ return d.addCallback(self._cbTestLOGIN) def _cbTestLOGIN(self, ignored): - self.assertEquals(self.authenticated, 1) - self.assertEquals(self.server.account, self.account) + self.assertEqual(self.authenticated, 1) + self.assertEqual(self.server.account, self.account) def testFailedLOGIN(self): self.server.challengers['LOGIN'] = imap4.LOGINCredentials @@ -1896,8 +1897,8 @@ return d.addCallback(self._cbTestFailedLOGIN) def _cbTestFailedLOGIN(self, ignored): - self.assertEquals(self.authenticated, -1) - self.assertEquals(self.server.account, None) + self.assertEqual(self.authenticated, -1) + self.assertEqual(self.server.account, None) def testPLAIN(self): self.server.challengers['PLAIN'] = imap4.PLAINCredentials @@ -1916,8 +1917,8 @@ return d.addCallback(self._cbTestPLAIN) def _cbTestPLAIN(self, ignored): - self.assertEquals(self.authenticated, 1) - self.assertEquals(self.server.account, self.account) + self.assertEqual(self.authenticated, 1) + self.assertEqual(self.server.account, self.account) def testFailedPLAIN(self): self.server.challengers['PLAIN'] = imap4.PLAINCredentials @@ -1938,8 +1939,8 @@ return d.addCallback(self._cbTestFailedPLAIN) def _cbTestFailedPLAIN(self, ignored): - self.assertEquals(self.authenticated, -1) - self.assertEquals(self.server.account, None) + self.assertEqual(self.authenticated, -1) + self.assertEqual(self.server.account, None) @@ -1963,7 +1964,7 @@ chal = 'challenge' cAuth = imap4.PLAINAuthenticator(username) response = cAuth.challengeResponse(secret, chal) - self.assertEquals(response, '\0%s\0%s' % (username, secret)) + self.assertEqual(response, '\0%s\0%s' % (username, secret)) def test_credentialsSetResponse(self): @@ -1975,8 +1976,8 @@ """ cred = imap4.PLAINCredentials() cred.setResponse('\0testuser\0secret') - self.assertEquals(cred.username, 'testuser') - self.assertEquals(cred.password, 'secret') + self.assertEqual(cred.username, 'testuser') + self.assertEqual(cred.password, 'secret') def test_credentialsInvalidResponse(self): @@ -2009,7 +2010,7 @@ def _cbTestReadWrite(self, ignored): E = self.client.events - self.assertEquals(E, [['modeChanged', 1]]) + self.assertEqual(E, [['modeChanged', 1]]) def testReadOnly(self): def login(): @@ -2024,7 +2025,7 @@ def _cbTestReadOnly(self, ignored): E = self.client.events - self.assertEquals(E, [['modeChanged', 0]]) + self.assertEqual(E, [['modeChanged', 0]]) def testFlagChange(self): flags = { @@ -2047,7 +2048,7 @@ expect = [['flagsChanged', {x[0]: x[1]}] for x in flags.items()] E.sort() expect.sort() - self.assertEquals(E, expect) + self.assertEqual(E, expect) def testNewMessages(self): def login(): @@ -2062,7 +2063,7 @@ def _cbTestNewMessages(self, ignored): E = self.client.events - self.assertEquals(E, [['newMessages', 10, None]]) + self.assertEqual(E, [['newMessages', 10, None]]) def testNewRecentMessages(self): def login(): @@ -2077,7 +2078,7 @@ def _cbTestNewRecentMessages(self, ignored): E = self.client.events - self.assertEquals(E, [['newMessages', None, 10]]) + self.assertEqual(E, [['newMessages', None, 10]]) def testNewMessagesAndRecent(self): def login(): @@ -2092,7 +2093,7 @@ def _cbTestNewMessagesAndRecent(self, ignored): E = self.client.events - self.assertEquals(E, [['newMessages', 20, None], ['newMessages', None, 10]]) + self.assertEqual(E, [['newMessages', 20, None], ['newMessages', None, 10]]) class ClientCapabilityTests(unittest.TestCase): @@ -2215,16 +2216,16 @@ transport.clear() self.server.dataReceived("01 LOGIN {8}\r\n") - self.assertEquals(transport.value(), "+ Ready for 8 octets of text\r\n") + self.assertEqual(transport.value(), "+ Ready for 8 octets of text\r\n") transport.clear() self.server.dataReceived("testuser {13}\r\n") - self.assertEquals(transport.value(), "+ Ready for 13 octets of text\r\n") + self.assertEqual(transport.value(), "+ Ready for 13 octets of text\r\n") transport.clear() self.server.dataReceived("password-test\r\n") - self.assertEquals(transport.value(), "01 OK LOGIN succeeded\r\n") - self.assertEquals(self.server.state, 'auth') + self.assertEqual(transport.value(), "01 OK LOGIN succeeded\r\n") + self.assertEqual(self.server.state, 'auth') self.server.connectionLost(error.ConnectionDone("Connection done.")) @@ -2266,14 +2267,14 @@ c.dataReceived('0003 OK FETCH completed\r\n') return d def test(res): - self.assertEquals(res, { + self.assertEqual(res, { 1: [['BODY', ['HEADER.FIELDS', ['SUBJECT']], 'Subject: Suprise for your woman...\r\n\r\n']], 2: [['BODY', ['HEADER.FIELDS', ['SUBJECT']], 'Subject: What you been doing. Order your meds here . ,. handcuff madsen\r\n\r\n']] }) - self.assertEquals(c.flags, {1: ['\\Seen']}) + self.assertEqual(c.flags, {1: ['\\Seen']}) return login( ).addCallback(strip(select) @@ -2389,14 +2390,14 @@ return d def test(res): - self.assertEquals(res, { + self.assertEqual(res, { 1: [['BODY', ['HEADER.FIELDS', ['SUBJECT']], 'Subject: subject one\r\n']], 2: [['BODY', ['HEADER.FIELDS', ['SUBJECT']], 'Subject: subject two\r\n']] }) - self.assertEquals(c.flags, {1: ['\\Recent'], 2: ['\\Seen']}) + self.assertEqual(c.flags, {1: ['\\Recent'], 2: ['\\Seen']}) return login( ).addCallback(strip(select) @@ -2436,11 +2437,11 @@ return d def test(res): - self.assertEquals(res, { + self.assertEqual(res, { 1: {'RFC822': 'Subject: first subject\r\n'}, 2: {'RFC822': 'Subject: second subject\r\n'}}) - self.assertEquals( + self.assertEqual( c.flags, {1: ['\\Seen'], 2: ['\\Recent', '\\Seen']}) return login( @@ -2502,7 +2503,7 @@ called. """ d = getattr(self.client, self.method)('foobox') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 %s foobox\r\n' % (self.command,)) return d @@ -2528,7 +2529,7 @@ """ d = self._examineOrSelect() self._response('* 3 EXISTS') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False, 'EXISTS': 3}) @@ -2555,7 +2556,7 @@ """ d = self._examineOrSelect() self._response('* 5 RECENT') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False, 'RECENT': 5}) @@ -2582,7 +2583,7 @@ """ d = self._examineOrSelect() self._response('* OK [UNSEEN 8] Message 8 is first unseen') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False, 'UNSEEN': 8}) @@ -2609,7 +2610,7 @@ """ d = self._examineOrSelect() self._response('* OK [UIDVALIDITY 12345] UIDs valid') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False, 'UIDVALIDITY': 12345}) @@ -2636,7 +2637,7 @@ """ d = self._examineOrSelect() self._response('* OK [UIDNEXT 4392] Predicted next UID') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False, 'UIDNEXT': 4392}) @@ -2664,7 +2665,7 @@ d = self._examineOrSelect() self._response( '* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), { 'READ-WRITE': False, 'FLAGS': ('\\Answered', '\\Flagged', '\\Deleted', '\\Seen', @@ -2682,7 +2683,7 @@ self._response( '* OK [PERMANENTFLAGS (\\Starred)] Just one permanent flag in ' 'that list up there') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), { 'READ-WRITE': False, 'PERMANENTFLAGS': ('\\Starred',)}) @@ -2698,7 +2699,7 @@ '* OK [X-MADE-UP] I just made this response text up.') # The value won't show up in the result. It would be okay if it did # someday, perhaps. This shouldn't ever happen, though. - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False}) @@ -2709,7 +2710,7 @@ """ d = self._examineOrSelect() self._response('* OK') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {'READ-WRITE': False}) @@ -2771,7 +2772,7 @@ """ def _expunge(self): d = self.client.expunge() - self.assertEquals(self.transport.value(), '0001 EXPUNGE\r\n') + self.assertEqual(self.transport.value(), '0001 EXPUNGE\r\n') self.transport.clear() return d @@ -2790,7 +2791,7 @@ """ d = self._expunge() self._response([3, 3, 5, 8]) - self.assertEquals(self._extractDeferredResult(d), [3, 3, 5, 8]) + self.assertEqual(self._extractDeferredResult(d), [3, 3, 5, 8]) def test_nonIntegerExpunged(self): @@ -2825,7 +2826,7 @@ """ def _search(self): d = self.client.search(imap4.Query(text="ABCDEF")) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 SEARCH (TEXT "ABCDEF")\r\n') return d @@ -2844,7 +2845,7 @@ """ d = self._search() self._response([2, 5, 10]) - self.assertEquals(self._extractDeferredResult(d), [2, 5, 10]) + self.assertEqual(self._extractDeferredResult(d), [2, 5, 10]) def test_nonIntegerFound(self): @@ -2874,13 +2875,13 @@ response. """ d = self.client.fetchUID('1:7') - self.assertEquals(self.transport.value(), '0001 FETCH 1:7 (UID)\r\n') + self.assertEqual(self.transport.value(), '0001 FETCH 1:7 (UID)\r\n') self.client.lineReceived('* 2 FETCH (UID 22)') self.client.lineReceived('* 3 FETCH (UID 23)') self.client.lineReceived('* 4 FETCH (UID 24)') self.client.lineReceived('* 5 FETCH (UID 25)') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), { 2: {'UID': '22'}, 3: {'UID': '23'}, @@ -2895,7 +2896,7 @@ fails with L{IllegalServerResponse}. """ d = self.client.fetchUID('1') - self.assertEquals(self.transport.value(), '0001 FETCH 1 (UID)\r\n') + self.assertEqual(self.transport.value(), '0001 FETCH 1 (UID)\r\n') self.client.lineReceived('* foo FETCH (UID 22)') self.client.lineReceived('0001 OK FETCH completed') self.assertRaises( @@ -2909,7 +2910,7 @@ L{IllegalServerResponse}. """ d = self.client.fetchUID('1:7') - self.assertEquals(self.transport.value(), '0001 FETCH 1:7 (UID)\r\n') + self.assertEqual(self.transport.value(), '0001 FETCH 1:7 (UID)\r\n') self.client.lineReceived('* 2 FETCH (UID 22)') self.client.lineReceived('* 3 FETCH (UID)') self.client.lineReceived('* 4 FETCH (UID 24)') @@ -2926,11 +2927,11 @@ the server's response. """ d = self.client.fetchBody('3') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 3 (RFC822.TEXT)\r\n') self.client.lineReceived('* 3 FETCH (RFC822.TEXT "Message text")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {3: {'RFC822.TEXT': 'Message text'}}) @@ -2944,11 +2945,11 @@ response. """ d = self.client.fetchSpecific('7') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 7 BODY[]\r\n') self.client.lineReceived('* 7 FETCH (BODY[] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {7: [['BODY', [], "Some body"]]}) @@ -2958,12 +2959,12 @@ C{True} for the C{peek} parameter. """ d = self.client.fetchSpecific('6', peek=True) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 6 BODY.PEEK[]\r\n') # BODY.PEEK responses are just BODY self.client.lineReceived('* 6 FETCH (BODY[] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {6: [['BODY', [], "Some body"]]}) @@ -2976,11 +2977,11 @@ response. """ d = self.client.fetchSpecific('7', headerNumber=(1, 2, 3)) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 7 BODY[1.2.3]\r\n') self.client.lineReceived('* 7 FETCH (BODY[1.2.3] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {7: [['BODY', ['1.2.3'], "Some body"]]}) @@ -2993,11 +2994,11 @@ corresponding message data given by the server's response. """ d = self.client.fetchSpecific('8', headerType='TEXT') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 8 BODY[TEXT]\r\n') self.client.lineReceived('* 8 FETCH (BODY[TEXT] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {8: [['BODY', ['TEXT'], "Some body"]]}) @@ -3011,11 +3012,11 @@ given by the server's response. """ d = self.client.fetchSpecific('4', headerType='TEXT', headerNumber=7) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 4 BODY[7.TEXT]\r\n') self.client.lineReceived('* 4 FETCH (BODY[7.TEXT] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {4: [['BODY', ['7.TEXT'], "Some body"]]}) @@ -3028,7 +3029,7 @@ L{IllegalServerResponse}. """ d = self.client.fetchSpecific('8', headerType='TEXT') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 8 BODY[TEXT]\r\n') self.client.lineReceived('* 8 FETCH (BODY[TEXT])') self.client.lineReceived('0001 OK FETCH completed') @@ -3044,11 +3045,11 @@ corresponding message data given by the server's response. """ d = self.client.fetchSpecific('8', headerType='MIME') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 8 BODY[MIME]\r\n') self.client.lineReceived('* 8 FETCH (BODY[MIME] "Some body")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {8: [['BODY', ['MIME'], "Some body"]]}) @@ -3063,11 +3064,11 @@ """ d = self.client.fetchSpecific( '9', headerType='TEXT', offset=17, length=3) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 9 BODY[TEXT]<17.3>\r\n') self.client.lineReceived('* 9 FETCH (BODY[TEXT]<17> "foo")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {9: [['BODY', ['TEXT'], '<17>', 'foo']]}) @@ -3080,7 +3081,7 @@ L{IllegalServerResponse}. """ d = self.client.fetchSpecific('8', headerType='TEXT') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 8 BODY[TEXT]\r\n') self.client.lineReceived('* 8 FETCH (BODY[TEXT]<17>)') self.client.lineReceived('0001 OK FETCH completed') @@ -3097,11 +3098,11 @@ body). """ d = self.client.fetchSpecific('7') - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 FETCH 7 BODY[]\r\n') self.client.lineReceived('* 7 FETCH (BODY[] "test")') self.client.lineReceived('0001 OK FETCH completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {7: [['BODY', [], "test"]]}) @@ -3132,12 +3133,12 @@ @param item: The data item which is expected to be specified. """ d = getattr(self.client, method)('3', ('\\Read', '\\Seen'), False) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 STORE 3 ' + item + ' (\\Read \\Seen)\r\n') self.client.lineReceived('* 3 FETCH (FLAGS (\\Read \\Seen))') self.client.lineReceived('0001 OK STORE completed') - self.assertEquals( + self.assertEqual( self._extractDeferredResult(d), {3: {'FLAGS': ['\\Read', '\\Seen']}}) @@ -3152,11 +3153,11 @@ @param item: The data item which is expected to be specified. """ d = getattr(self.client, method)('3', ('\\Read', '\\Seen'), True) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 STORE 3 ' + item + ' (\\Read \\Seen)\r\n') self.client.lineReceived('0001 OK STORE completed') - self.assertEquals(self._extractDeferredResult(d), {}) + self.assertEqual(self._extractDeferredResult(d), {}) def _flagsSilentlyWithUnsolicitedDataTest(self, method, item): @@ -3170,13 +3171,13 @@ @param item: The data item which is expected to be specified. """ d = getattr(self.client, method)('3', ('\\Read', '\\Seen'), True) - self.assertEquals( + self.assertEqual( self.transport.value(), '0001 STORE 3 ' + item + ' (\\Read \\Seen)\r\n') self.client.lineReceived('* 2 FETCH (FLAGS (\\Read \\Seen))') self.client.lineReceived('0001 OK STORE completed') - self.assertEquals(self._extractDeferredResult(d), {}) - self.assertEquals(self.client.flags, {2: ['\\Read', '\\Seen']}) + self.assertEqual(self._extractDeferredResult(d), {}) + self.assertEqual(self.client.flags, {2: ['\\Read', '\\Seen']}) def test_setFlags(self): @@ -3341,8 +3342,8 @@ ).addErrback(self._ebGeneral) def check(ignored): - self.assertEquals(self.result, self.expected) - self.assertEquals(self.storeArgs, self.expectedArgs) + self.assertEqual(self.result, self.expected) + self.assertEqual(self.storeArgs, self.expectedArgs) d = loopback.loopbackTCP(self.server, self.client, noisy=False) d.addCallback(check) return d @@ -3406,7 +3407,7 @@ ).addErrback(self._ebGeneral) d = loopback.loopbackTCP(self.server, self.client, noisy=False) - d.addCallback(lambda x : self.assertEquals(self.result, self.expected)) + d.addCallback(lambda x : self.assertEqual(self.result, self.expected)) return d def testFetchUID(self): @@ -3461,6 +3462,32 @@ def testFetchInternalDateUID(self): return self.testFetchInternalDate(1) + + def test_fetchInternalDateLocaleIndependent(self): + """ + The month name in the date is locale independent. + """ + # Fake that we're in a language where December is not Dec + currentLocale = locale.setlocale(locale.LC_ALL, None) + locale.setlocale(locale.LC_ALL, "es_AR.UTF8") + self.addCleanup(locale.setlocale, locale.LC_ALL, currentLocale) + return self.testFetchInternalDate(1) + + # if alternate locale is not available, the previous test will be skipped, + # please install this locale for it to run. Avoid using locale.getlocale to + # learn the current locale; its values don't round-trip well on all + # platforms. Fortunately setlocale returns a value which does round-trip + # well. + currentLocale = locale.setlocale(locale.LC_ALL, None) + try: + locale.setlocale(locale.LC_ALL, "es_AR.UTF8") + except locale.Error: + test_fetchInternalDateLocaleIndependent.skip = ( + "The es_AR.UTF8 locale is not installed.") + else: + locale.setlocale(locale.LC_ALL, currentLocale) + + def testFetchEnvelope(self, uid=0): self.function = self.client.fetchEnvelope self.messages = '15' @@ -3647,7 +3674,7 @@ self.connected.addErrback(self._ebGeneral) d = loopback.loopbackTCP(self.server, self.client, noisy=False) - d.addCallback(lambda ign: self.assertEquals(self.result, self.expected)) + d.addCallback(lambda ign: self.assertEqual(self.result, self.expected)) return d @@ -3682,7 +3709,7 @@ self.connected.addErrback(self._ebGeneral) d = loopback.loopbackTCP(self.server, self.client, noisy=False) - d.addCallback(lambda ign: self.assertEquals(self.result, self.expected)) + d.addCallback(lambda ign: self.assertEqual(self.result, self.expected)) return d @@ -3812,7 +3839,7 @@ d = self.connected.addCallback(strip(search)) def searched(results): - self.assertEquals(results, expectedMessages) + self.assertEqual(results, expectedMessages) d.addCallback(searched) d.addCallback(self._cbStopClient) d.addErrback(self._ebGeneral) @@ -3966,9 +3993,9 @@ # Ensure no short-circuiting wierdness is going on self.failIf(self.result is self.expected) - self.assertEquals(self.result, self.expected) - self.assertEquals(self.uid, self.server_received_uid) - self.assertEquals( + self.assertEqual(self.result, self.expected) + self.assertEqual(self.uid, self.server_received_uid) + self.assertEqual( imap4.parseNestedParens(self.query), self.server_received_query ) @@ -4027,10 +4054,10 @@ for (k, v) in self.expected.items(): v['UID'] = str(k) - self.assertEquals(self.result, self.expected) - self.assertEquals(self.uid, self.server_received_uid) - self.assertEquals(self.parts, self.server_received_parts) - self.assertEquals(imap4.parseIdList(self.messages), + self.assertEqual(self.result, self.expected) + self.assertEqual(self.uid, self.server_received_uid) + self.assertEqual(self.parts, self.server_received_parts) + self.assertEqual(imap4.parseIdList(self.messages), imap4.parseIdList(self.server_received_messages)) d = loopback.loopbackTCP(self.server, self.client, noisy=False) @@ -4087,13 +4114,13 @@ def cbCopy(results): for a in m.args: - self.assertEquals(a[0].read(), "open") - self.assertEquals(a[1], "flags") - self.assertEquals(a[2], "internaldate") + self.assertEqual(a[0].read(), "open") + self.assertEqual(a[1], "flags") + self.assertEqual(a[2], "internaldate") for (status, result) in results: self.failUnless(status) - self.assertEquals(result, None) + self.assertEqual(result, None) return d.addCallback(cbCopy) @@ -4112,17 +4139,17 @@ seen = [] for a in m.args: seen.append(a[0].read()) - self.assertEquals(a[1], ()) - self.assertEquals(a[2], "Date") + self.assertEqual(a[1], ()) + self.assertEqual(a[2], "Date") seen.sort() exp = ["Header-Counter: %d\r\n\r\nBody %d" % (i, i) for i in range(1, 11)] exp.sort() - self.assertEquals(seen, exp) + self.assertEqual(seen, exp) for (status, result) in results: self.failUnless(status) - self.assertEquals(result, None) + self.assertEqual(result, None) return d.addCallback(cbCopy) @@ -4137,7 +4164,7 @@ d = f([im for im in zip(range(1, 11), msgs)], 'tag', m) def cbCopy(results): - self.assertEquals(results, zip([1] * 10, range(1, 11))) + self.assertEqual(results, zip([1] * 10, range(1, 11))) for (orig, new) in zip(msgs, m.msgs): self.assertIdentical(orig, new) @@ -4176,9 +4203,9 @@ map(self.connected.addCallback, map(strip, methods)) self.connected.addCallbacks(self._cbStopClient, self._ebGeneral) def check(ignored): - self.assertEquals(self.server.startedTLS, True) - self.assertEquals(self.client.startedTLS, True) - self.assertEquals(len(called), len(methods)) + self.assertEqual(self.server.startedTLS, True) + self.assertEqual(self.client.startedTLS, True) + self.assertEqual(len(called), len(methods)) d = self.loopback() d.addCallback(check) return d @@ -4196,7 +4223,7 @@ ).addErrback(self._ebGeneral) d = self.loopback() - d.addCallback(lambda x : self.assertEquals(len(success), 1)) + d.addCallback(lambda x : self.assertEqual(len(success), 1)) return d @@ -4443,7 +4470,7 @@ # call resumeProducing on its producer). It doesn't matter: just # make sure the surrounding structure is okay, and that no # exceptions occurred. - self.assertEquals( + self.assertEqual( self.transport.value(), '* 1 FETCH (BODY[] )\r\n' '01 OK FETCH completed\r\n' diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_mailmail.py twisted-mail-12.0.0/twisted/mail/test/test_mailmail.py --- twisted-mail-10.1.0/twisted/mail/test/test_mailmail.py 2008-07-10 15:07:15.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_mailmail.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_mail.py twisted-mail-12.0.0/twisted/mail/test/test_mail.py --- twisted-mail-10.1.0/twisted/mail/test/test_mail.py 2010-05-31 22:40:00.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_mail.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -56,57 +56,57 @@ d = dict([(x, x + 10) for x in range(10)]) d = mail.mail.DomainWithDefaultDict(d, 'Default') - self.assertEquals(len(d), 10) - self.assertEquals(list(iter(d)), range(10)) - self.assertEquals(list(d.iterkeys()), list(iter(d))) + self.assertEqual(len(d), 10) + self.assertEqual(list(iter(d)), range(10)) + self.assertEqual(list(d.iterkeys()), list(iter(d))) items = list(d.iteritems()) items.sort() - self.assertEquals(items, [(x, x + 10) for x in range(10)]) + self.assertEqual(items, [(x, x + 10) for x in range(10)]) values = list(d.itervalues()) values.sort() - self.assertEquals(values, range(10, 20)) + self.assertEqual(values, range(10, 20)) items = d.items() items.sort() - self.assertEquals(items, [(x, x + 10) for x in range(10)]) + self.assertEqual(items, [(x, x + 10) for x in range(10)]) values = d.values() values.sort() - self.assertEquals(values, range(10, 20)) + self.assertEqual(values, range(10, 20)) for x in range(10): - self.assertEquals(d[x], x + 10) - self.assertEquals(d.get(x), x + 10) + self.assertEqual(d[x], x + 10) + self.assertEqual(d.get(x), x + 10) self.failUnless(x in d) self.failUnless(d.has_key(x)) del d[2], d[4], d[6] - self.assertEquals(len(d), 7) - self.assertEquals(d[2], 'Default') - self.assertEquals(d[4], 'Default') - self.assertEquals(d[6], 'Default') + self.assertEqual(len(d), 7) + self.assertEqual(d[2], 'Default') + self.assertEqual(d[4], 'Default') + self.assertEqual(d[6], 'Default') d.update({'a': None, 'b': (), 'c': '*'}) - self.assertEquals(len(d), 10) - self.assertEquals(d['a'], None) - self.assertEquals(d['b'], ()) - self.assertEquals(d['c'], '*') + self.assertEqual(len(d), 10) + self.assertEqual(d['a'], None) + self.assertEqual(d['b'], ()) + self.assertEqual(d['c'], '*') d.clear() - self.assertEquals(len(d), 0) + self.assertEqual(len(d), 0) - self.assertEquals(d.setdefault('key', 'value'), 'value') - self.assertEquals(d['key'], 'value') + self.assertEqual(d.setdefault('key', 'value'), 'value') + self.assertEqual(d['key'], 'value') - self.assertEquals(d.popitem(), ('key', 'value')) - self.assertEquals(len(d), 0) + self.assertEqual(d.popitem(), ('key', 'value')) + self.assertEqual(len(d), 0) dcopy = d.copy() - self.assertEquals(d.domains, dcopy.domains) - self.assertEquals(d.default, dcopy.default) + self.assertEqual(d.domains, dcopy.domains) + self.assertEqual(d.default, dcopy.default) def _stringificationTest(self, stringifier): @@ -150,7 +150,7 @@ self.assertRaises(smtp.AddressError, self.domain.exists, "any user") def testRelay(self): - self.assertEquals( + self.assertEqual( self.domain.willRelay("random q emailer", "protocol"), False ) @@ -187,7 +187,7 @@ return self.fp.eomReceived().addCallback(self._cbFinalName) def _cbFinalName(self, result): - self.assertEquals(result, self.final) + self.assertEqual(result, self.final) self.failUnless(self.f.closed) self.failIf(os.path.exists(self.name)) @@ -196,7 +196,7 @@ for line in contents.splitlines(): self.fp.lineReceived(line) self.fp.eomReceived() - self.assertEquals(file(self.final).read(), contents) + self.assertEqual(file(self.final).read(), contents) def testInterrupted(self): contents = "first line\nsecond line\n" @@ -411,7 +411,7 @@ mbox.AppendFactory = FailingMaildirMailboxAppendMessageTask d = self._appendMessages(mbox, ["X" * i for i in range(1, 11)]) - d.addCallback(self.assertEquals, [None] * 10) + d.addCallback(self.assertEqual, [None] * 10) d.addCallback(self._cbTestAppend, mbox) return d @@ -422,8 +422,8 @@ and that each has the expected contents, and that they are in the same order as that in which they were appended. """ - self.assertEquals(len(mbox.listMessages()), 10) - self.assertEquals( + self.assertEqual(len(mbox.listMessages()), 10) + self.assertEqual( [len(mbox.getMessage(i).read()) for i in range(10)], range(1, 11)) # test in the right order: last to first error location. @@ -472,8 +472,8 @@ and that each has the expected contents, and that they are in the same order as that in which they were appended. """ - self.assertEquals(len(mbox.listMessages()), 10) - self.assertEquals( + self.assertEqual(len(mbox.listMessages()), 10) + self.assertEqual( [len(mbox.getMessage(i).read()) for i in range(10)], range(1, 11)) @@ -543,12 +543,12 @@ i = i + 1 mb = mail.maildir.MaildirMailbox(self.d) - self.assertEquals(mb.listMessages(), range(1, 11)) - self.assertEquals(mb.listMessages(1), 2) - self.assertEquals(mb.listMessages(5), 6) + self.assertEqual(mb.listMessages(), range(1, 11)) + self.assertEqual(mb.listMessages(1), 2) + self.assertEqual(mb.listMessages(5), 6) - self.assertEquals(mb.getMessage(6).read(), 'x' * 7) - self.assertEquals(mb.getMessage(1).read(), 'x' * 2) + self.assertEqual(mb.getMessage(6).read(), 'x' * 7) + self.assertEqual(mb.getMessage(1).read(), 'x' * 2) d = {} for i in range(10): @@ -559,12 +559,12 @@ p, f = os.path.split(msgs[5]) mb.deleteMessage(5) - self.assertEquals(mb.listMessages(5), 0) + self.assertEqual(mb.listMessages(5), 0) self.failUnless(os.path.exists(j(self.d, '.Trash', 'cur', f))) self.failIf(os.path.exists(j(self.d, msgs[5]))) mb.undeleteMessages() - self.assertEquals(mb.listMessages(5), 6) + self.assertEqual(mb.listMessages(5), 6) self.failIf(os.path.exists(j(self.d, '.Trash', 'cur', f))) self.failUnless(os.path.exists(j(self.d, msgs[5]))) @@ -584,13 +584,13 @@ for (u, p) in toAdd: self.failUnless(u in self.D.dbm) - self.assertEquals(self.D.dbm[u], p) + self.assertEqual(self.D.dbm[u], p) self.failUnless(os.path.exists(os.path.join(self.P, u))) def testCredentials(self): creds = self.D.getCredentialsCheckers() - self.assertEquals(len(creds), 1) + self.assertEqual(len(creds), 1) self.failUnless(cred.checkers.ICredentialsChecker.providedBy(creds[0])) self.failUnless(cred.credentials.IUsernamePassword in creds[0].credentialInterfaces) @@ -605,7 +605,7 @@ ) t = self.D.requestAvatar('user', None, pop3.IMailbox) - self.assertEquals(len(t), 3) + self.assertEqual(len(t), 3) self.failUnless(t[0] is pop3.IMailbox) self.failUnless(pop3.IMailbox.providedBy(t[1])) @@ -622,7 +622,7 @@ ) creds = cred.credentials.UsernamePassword('user', 'password') - self.assertEquals(database.requestAvatarId(creds), 'user') + self.assertEqual(database.requestAvatarId(creds), 'user') class StubAliasableDomain(object): @@ -701,7 +701,7 @@ ) fp = StringIO.StringIO(hdr) m = rfc822.Message(fp) - self.assertEquals(len(m.items()), 1) + self.assertEqual(len(m.items()), 1) self.failUnless(m.has_key('Received')) def testValidateTo(self): @@ -769,8 +769,8 @@ ) def _cbAuthenticateAPOP(self, result): - self.assertEquals(len(result), 3) - self.assertEquals(result[0], pop3.IMailbox) + self.assertEqual(len(result), 3) + self.assertEqual(result[0], pop3.IMailbox) self.failUnless(pop3.IMailbox.providedBy(result[1])) result[2]() @@ -792,8 +792,8 @@ ) def _cbAuthenticatePASS(self, result): - self.assertEquals(len(result), 3) - self.assertEquals(result[0], pop3.IMailbox) + self.assertEqual(len(result), 3) + self.assertEqual(result[0], pop3.IMailbox) self.failUnless(pop3.IMailbox.providedBy(result[1])) result[2]() @@ -870,22 +870,22 @@ def testMailFrom(self): for i in range(10): - self.assertEquals(self.R.getMailFrom(), 'from-%d' % (i,)) + self.assertEqual(self.R.getMailFrom(), 'from-%d' % (i,)) self.R.sentMail(250, None, None, None, None) - self.assertEquals(self.R.getMailFrom(), None) + self.assertEqual(self.R.getMailFrom(), None) def testMailTo(self): for i in range(10): - self.assertEquals(self.R.getMailTo(), ['to-%d' % (i,)]) + self.assertEqual(self.R.getMailTo(), ['to-%d' % (i,)]) self.R.sentMail(250, None, None, None, None) - self.assertEquals(self.R.getMailTo(), None) + self.assertEqual(self.R.getMailTo(), None) def testMailData(self): for i in range(10): name = os.path.join(self.tmpdir, 'body-%d' % (i,)) - self.assertEquals(self.R.getMailData().read(), name) + self.assertEqual(self.R.getMailData().read(), name) self.R.sentMail(250, None, None, None, None) - self.assertEquals(self.R.getMailData(), None) + self.assertEqual(self.R.getMailData(), None) class Manager: def __init__(self): @@ -916,7 +916,7 @@ for i in self.messages: self.relay.sentMail(250, None, None, None, None) - self.assertEquals( + self.assertEqual( self.manager.success, [(self.factory, m) for m in self.messages] ) @@ -925,14 +925,14 @@ for i in self.messages: self.relay.sentMail(550, None, None, None, None) - self.assertEquals( + self.assertEqual( self.manager.failure, [(self.factory, m) for m in self.messages] ) def testConnectionLost(self): self.relay.connectionLost(failure.Failure(Exception())) - self.assertEquals(self.manager.done, [self.factory]) + self.assertEqual(self.manager.done, [self.factory]) class DirectoryQueueTestCase(unittest.TestCase): def setUp(self): @@ -954,19 +954,19 @@ def testWaiting(self): self.failUnless(self.queue.hasWaiting()) - self.assertEquals(len(self.queue.getWaiting()), 25) + self.assertEqual(len(self.queue.getWaiting()), 25) waiting = self.queue.getWaiting() self.queue.setRelaying(waiting[0]) - self.assertEquals(len(self.queue.getWaiting()), 24) + self.assertEqual(len(self.queue.getWaiting()), 24) self.queue.setWaiting(waiting[0]) - self.assertEquals(len(self.queue.getWaiting()), 25) + self.assertEqual(len(self.queue.getWaiting()), 25) def testRelaying(self): for m in self.queue.getWaiting(): self.queue.setRelaying(m) - self.assertEquals( + self.assertEqual( len(self.queue.getRelayed()), 25 - len(self.queue.getWaiting()) ) @@ -975,16 +975,16 @@ relayed = self.queue.getRelayed() self.queue.setWaiting(relayed[0]) - self.assertEquals(len(self.queue.getWaiting()), 1) - self.assertEquals(len(self.queue.getRelayed()), 24) + self.assertEqual(len(self.queue.getWaiting()), 1) + self.assertEqual(len(self.queue.getRelayed()), 24) def testDone(self): msg = self.queue.getWaiting()[0] self.queue.setRelaying(msg) self.queue.done(msg) - self.assertEquals(len(self.queue.getWaiting()), 24) - self.assertEquals(len(self.queue.getRelayed()), 0) + self.assertEqual(len(self.queue.getWaiting()), 24) + self.assertEqual(len(self.queue.getRelayed()), 0) self.failIf(msg in self.queue.getWaiting()) self.failIf(msg in self.queue.getRelayed()) @@ -997,7 +997,7 @@ envelopes.sort() for i in range(25): - self.assertEquals( + self.assertEqual( envelopes.pop(0), ['header', i] ) @@ -1078,8 +1078,8 @@ return self.mx.getMX('test.domain').addCallback(self._cbSimpleSuccess) def _cbSimpleSuccess(self, mx): - self.assertEquals(mx.preference, 0) - self.assertEquals(str(mx.name), 'the.email.test.domain') + self.assertEqual(mx.preference, 0) + self.assertEqual(str(mx.name), 'the.email.test.domain') def testSimpleFailure(self): self.mx.fallbackToDomain = False @@ -1636,35 +1636,35 @@ for l in lines: mail.alias.handle(result, l, 'TestCase', None) - self.assertEquals(result['user'], ['another@host', 'me@again']) - self.assertEquals(result['nextuser'], ['|/bin/program']) - self.assertEquals(result['moreusers'], [':/etc/include/filename']) - self.assertEquals(result['multiuser'], ['first@host', 'second@host', 'last@anotherhost']) + self.assertEqual(result['user'], ['another@host', 'me@again']) + self.assertEqual(result['nextuser'], ['|/bin/program']) + self.assertEqual(result['moreusers'], [':/etc/include/filename']) + self.assertEqual(result['multiuser'], ['first@host', 'second@host', 'last@anotherhost']) def testFileLoader(self): domains = {'': object()} result = mail.alias.loadAliasFile(domains, fp=aliasFile) - self.assertEquals(len(result), 3) + self.assertEqual(len(result), 3) group = result['testuser'] s = str(group) for a in ('address1', 'address2', 'address3', 'continuation@address', '/bin/process/this'): self.failIfEqual(s.find(a), -1) - self.assertEquals(len(group), 5) + self.assertEqual(len(group), 5) group = result['usertwo'] s = str(group) for a in ('thisaddress', 'thataddress', 'lastaddress'): self.failIfEqual(s.find(a), -1) - self.assertEquals(len(group), 3) + self.assertEqual(len(group), 3) group = result['lastuser'] s = str(group) - self.failUnlessEqual(s.find('/includable'), -1) + self.assertEqual(s.find('/includable'), -1) for a in ('/filename', 'program', 'address'): self.failIfEqual(s.find(a), -1, '%s not found' % a) - self.assertEquals(len(group), 3) + self.assertEqual(len(group), 3) def testMultiWrapper(self): msgs = LineBufferMessage(), LineBufferMessage(), LineBufferMessage() @@ -1678,7 +1678,7 @@ for m in msgs: self.failUnless(m.eom) self.failIf(m.lost) - self.assertEquals(self.lines, m.lines) + self.assertEqual(self.lines, m.lines) def testFileAlias(self): tmpfile = self.mktemp() @@ -1691,7 +1691,7 @@ def _cbTestFileAlias(self, ignored, tmpfile): lines = file(tmpfile).readlines() - self.assertEquals([L[:-1] for L in lines], self.lines) + self.assertEqual([L[:-1] for L in lines], self.lines) @@ -1843,7 +1843,7 @@ def _cbProcessAlias(ignored): lines = file('process.alias.out').readlines() - self.assertEquals([L[:-1] for L in lines], self.lines) + self.assertEqual([L[:-1] for L in lines], self.lines) return m.eomReceived().addCallback(_cbProcessAlias) @@ -1951,7 +1951,7 @@ mail.alias.FileWrapper('/file'), ]) expected.sort() - self.assertEquals(r1, expected) + self.assertEqual(r1, expected) res2 = A2.resolve(aliases) r2 = map(str, res2.objs) @@ -1961,7 +1961,7 @@ mail.alias.AddressAlias('user3', None, None) ]) expected.sort() - self.assertEquals(r2, expected) + self.assertEqual(r2, expected) res3 = A3.resolve(aliases) r3 = map(str, res3.objs) @@ -1972,7 +1972,7 @@ mail.alias.FileWrapper('/file'), ]) expected.sort() - self.assertEquals(r3, expected) + self.assertEqual(r3, expected) def test_cyclicAlias(self): @@ -1990,9 +1990,9 @@ 'alias3': A3 }) - self.assertEquals(aliases['alias1'].resolve(aliases), None) - self.assertEquals(aliases['alias2'].resolve(aliases), None) - self.assertEquals(aliases['alias3'].resolve(aliases), None) + self.assertEqual(aliases['alias1'].resolve(aliases), None) + self.assertEqual(aliases['alias2'].resolve(aliases), None) + self.assertEqual(aliases['alias3'].resolve(aliases), None) A4 = MockAliasGroup(['|echo', 'alias1'], domain, 'alias4') aliases['alias4'] = A4 @@ -2004,7 +2004,7 @@ mail.alias.MessageWrapper(DummyProcess(), 'echo') ]) expected.sort() - self.assertEquals(r, expected) + self.assertEqual(r, expected) diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_options.py twisted-mail-12.0.0/twisted/mail/test/test_options.py --- twisted-mail-10.1.0/twisted/mail/test/test_options.py 2008-10-28 20:12:14.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_options.py 2011-08-08 20:58:28.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -8,12 +8,16 @@ from twisted.trial.unittest import TestCase from twisted.python.usage import UsageError -from twisted.mail.tap import Options +from twisted.mail import protocols +from twisted.mail.tap import Options, makeService +from twisted.python import deprecate, versions +from twisted.python.filepath import FilePath +from twisted.internet import endpoints, defer class OptionsTestCase(TestCase): """ - Tests for the command line option parser used for C{twistd mail}. + Tests for the command line option parser used for I{twistd mail}. """ def setUp(self): self.aliasFilename = self.mktemp() @@ -42,3 +46,196 @@ '--maildirdbmdomain', 'example.com=example.com', '--aliases', self.aliasFilename]) + + def testPasswordfileDeprecation(self): + """ + Test that the --passwordfile option will emit a correct warning. + """ + passwd = FilePath(self.mktemp()) + passwd.setContent("") + options = Options() + options.opt_passwordfile(passwd.path) + warnings = self.flushWarnings([self.testPasswordfileDeprecation]) + self.assertEqual(warnings[0]['category'], DeprecationWarning) + self.assertEqual(len(warnings), 1) + msg = deprecate.getDeprecationWarningString(options.opt_passwordfile, + versions.Version('twisted.mail', 11, 0, 0)) + self.assertEqual(warnings[0]['message'], msg) + + + def test_barePort(self): + """ + A bare port passed to I{--pop3} results in deprecation warning in + addition to a TCP4ServerEndpoint. + """ + options = Options() + options.parseOptions(['--pop3', '8110']) + self.assertEqual(len(options['pop3']), 1) + self.assertIsInstance( + options['pop3'][0], endpoints.TCP4ServerEndpoint) + warnings = self.flushWarnings([options.opt_pop3]) + self.assertEqual(len(warnings), 1) + self.assertEqual(warnings[0]['category'], DeprecationWarning) + self.assertEqual( + warnings[0]['message'], + "Specifying plain ports and/or a certificate is deprecated since " + "Twisted 11.0; use endpoint descriptions instead.") + + + def _endpointTest(self, service): + """ + Use L{Options} to parse a single service configuration parameter and + verify that an endpoint of the correct type is added to the list for + that service. + """ + options = Options() + options.parseOptions(['--' + service, 'tcp:1234']) + self.assertEqual(len(options[service]), 1) + self.assertIsInstance( + options[service][0], endpoints.TCP4ServerEndpoint) + + + def test_endpointSMTP(self): + """ + When I{--smtp} is given a TCP endpoint description as an argument, a + TCPServerEndpoint is added to the list of SMTP endpoints. + """ + self._endpointTest('smtp') + + + def test_endpointPOP3(self): + """ + When I{--pop3} is given a TCP endpoint description as an argument, a + TCPServerEndpoint is added to the list of POP3 endpoints. + """ + self._endpointTest('pop3') + + + def test_protoDefaults(self): + """ + POP3 and SMTP each listen on a TCP4ServerEndpoint by default. + """ + options = Options() + options.parseOptions([]) + + self.assertEqual(len(options['pop3']), 1) + self.assertIsInstance( + options['pop3'][0], endpoints.TCP4ServerEndpoint) + + self.assertEqual(len(options['smtp']), 1) + self.assertIsInstance( + options['smtp'][0], endpoints.TCP4ServerEndpoint) + + + def test_protoDisable(self): + """ + The I{--no-pop3} and I{--no-smtp} options disable POP3 and SMTP + respectively. + """ + options = Options() + options.parseOptions(['--no-pop3']) + self.assertEqual(options._getEndpoints(None, 'pop3'), []) + self.assertNotEquals(options._getEndpoints(None, 'smtp'), []) + + options = Options() + options.parseOptions(['--no-smtp']) + self.assertNotEquals(options._getEndpoints(None, 'pop3'), []) + self.assertEqual(options._getEndpoints(None, 'smtp'), []) + + + def test_allProtosDisabledError(self): + """ + If all protocols are disabled, L{UsageError} is raised. + """ + options = Options() + self.assertRaises( + UsageError, options.parseOptions, (['--no-pop3', '--no-smtp'])) + + + def test_pop3sBackwardCompatibility(self): + """ + The deprecated I{--pop3s} and I{--certificate} options set up a POP3 SSL + server. + """ + cert = FilePath(self.mktemp()) + cert.setContent("") + options = Options() + options.parseOptions(['--pop3s', '8995', + '--certificate', cert.path]) + self.assertEqual(len(options['pop3']), 2) + self.assertIsInstance( + options['pop3'][0], endpoints.SSL4ServerEndpoint) + self.assertIsInstance( + options['pop3'][1], endpoints.TCP4ServerEndpoint) + + warnings = self.flushWarnings([options.postOptions]) + self.assertEqual(len(warnings), 1) + self.assertEqual(warnings[0]['category'], DeprecationWarning) + self.assertEqual( + warnings[0]['message'], + "Specifying plain ports and/or a certificate is deprecated since " + "Twisted 11.0; use endpoint descriptions instead.") + + + def test_esmtpWithoutHostname(self): + """ + If I{--esmtp} is given without I{--hostname}, L{Options.parseOptions} + raises L{UsageError}. + """ + options = Options() + exc = self.assertRaises(UsageError, options.parseOptions, ['--esmtp']) + self.assertEqual("--esmtp requires --hostname", str(exc)) + + + +class SpyEndpoint(object): + """ + SpyEndpoint remembers what factory it is told to listen with. + """ + listeningWith = None + def listen(self, factory): + self.listeningWith = factory + return defer.succeed(None) + + + +class MakeServiceTests(TestCase): + """ + Tests for L{twisted.mail.tap.makeService} + """ + def _endpointServerTest(self, key, factoryClass): + """ + Configure a service with two endpoints for the protocol associated with + C{key} and verify that when the service is started a factory of type + C{factoryClass} is used to listen on each of them. + """ + cleartext = SpyEndpoint() + secure = SpyEndpoint() + config = Options() + config[key] = [cleartext, secure] + service = makeService(config) + service.privilegedStartService() + service.startService() + self.addCleanup(service.stopService) + self.assertIsInstance(cleartext.listeningWith, factoryClass) + self.assertIsInstance(secure.listeningWith, factoryClass) + + + def test_pop3(self): + """ + If one or more endpoints is included in the configuration passed to + L{makeService} for the C{"pop3"} key, a service for starting a POP3 + server is constructed for each of them and attached to the returned + service. + """ + self._endpointServerTest("pop3", protocols.POP3Factory) + + + def test_smtp(self): + """ + If one or more endpoints is included in the configuration passed to + L{makeService} for the C{"smtp"} key, a service for starting an SMTP + server is constructed for each of them and attached to the returned + service. + """ + self._endpointServerTest("smtp", protocols.SMTPFactory) diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_pop3client.py twisted-mail-12.0.0/twisted/mail/test/test_pop3client.py --- twisted-mail-10.1.0/twisted/mail/test/test_pop3client.py 2006-08-13 22:34:25.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_pop3client.py 2011-07-14 19:05:14.000000000 +0000 @@ -57,48 +57,48 @@ p.dataReceived('-ERR Offline for maintenance\r\n') return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "Offline for maintenance")) + lambda exc: self.assertEqual(exc.args[0], "Offline for maintenance")) def testOkUser(self): p, t = setUp() d = p.user("username") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") p.dataReceived("+OK send password\r\n") return d.addCallback(self.assertEqual, "send password") def testBadUser(self): p, t = setUp() d = p.user("username") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") p.dataReceived("-ERR account suspended\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "account suspended")) + lambda exc: self.assertEqual(exc.args[0], "account suspended")) def testOkPass(self): p, t = setUp() d = p.password("password") - self.assertEquals(t.value(), "PASS password\r\n") + self.assertEqual(t.value(), "PASS password\r\n") p.dataReceived("+OK you're in!\r\n") return d.addCallback(self.assertEqual, "you're in!") def testBadPass(self): p, t = setUp() d = p.password("password") - self.assertEquals(t.value(), "PASS password\r\n") + self.assertEqual(t.value(), "PASS password\r\n") p.dataReceived("-ERR go away\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "go away")) + lambda exc: self.assertEqual(exc.args[0], "go away")) def testOkLogin(self): p, t = setUp() p.allowInsecureLogin = True d = p.login("username", "password") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") p.dataReceived("+OK go ahead\r\n") - self.assertEquals(t.value(), "USER username\r\nPASS password\r\n") + self.assertEqual(t.value(), "USER username\r\nPASS password\r\n") p.dataReceived("+OK password accepted\r\n") return d.addCallback(self.assertEqual, "password accepted") @@ -106,39 +106,39 @@ p, t = setUp() p.allowInsecureLogin = True d = p.login("username", "password") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") p.dataReceived("+OK waiting on you\r\n") - self.assertEquals(t.value(), "USER username\r\nPASS password\r\n") + self.assertEqual(t.value(), "USER username\r\nPASS password\r\n") p.dataReceived("-ERR bogus login\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "bogus login")) + lambda exc: self.assertEqual(exc.args[0], "bogus login")) def testBadUsernameLogin(self): p, t = setUp() p.allowInsecureLogin = True d = p.login("username", "password") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") p.dataReceived("-ERR bogus login\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "bogus login")) + lambda exc: self.assertEqual(exc.args[0], "bogus login")) def testServerGreeting(self): p, t = setUp(greet=False) p.dataReceived("+OK lalala this has no challenge\r\n") - self.assertEquals(p.serverChallenge, None) + self.assertEqual(p.serverChallenge, None) def testServerGreetingWithChallenge(self): p, t = setUp(greet=False) p.dataReceived("+OK \r\n") - self.assertEquals(p.serverChallenge, "") + self.assertEqual(p.serverChallenge, "") def testAPOP(self): p, t = setUp(greet=False) p.dataReceived("+OK \r\n") d = p.login("username", "password") - self.assertEquals(t.value(), "APOP username f34f1e464d0d7927607753129cabe39a\r\n") + self.assertEqual(t.value(), "APOP username f34f1e464d0d7927607753129cabe39a\r\n") p.dataReceived("+OK Welcome!\r\n") return d.addCallback(self.assertEqual, "Welcome!") @@ -161,10 +161,10 @@ directlyProvides(t, interfaces.ISSLTransport) p.dataReceived("+OK Howdy\r\n") d = p.login("username", "password") - self.assertEquals(t.value(), "USER username\r\n") + self.assertEqual(t.value(), "USER username\r\n") t.clear() p.dataReceived("+OK\r\n") - self.assertEquals(t.value(), "PASS password\r\n") + self.assertEqual(t.value(), "PASS password\r\n") p.dataReceived("+OK\r\n") return d @@ -188,7 +188,7 @@ def testListSize(self): p, t = setUp() d = p.listSize() - self.assertEquals(t.value(), "LIST\r\n") + self.assertEqual(t.value(), "LIST\r\n") p.dataReceived("+OK Here it comes\r\n") p.dataReceived("1 3\r\n2 2\r\n3 1\r\n.\r\n") return d.addCallback(self.assertEqual, [3, 2, 1]) @@ -198,28 +198,28 @@ c = ListConsumer() f = c.consume d = p.listSize(f) - self.assertEquals(t.value(), "LIST\r\n") + self.assertEqual(t.value(), "LIST\r\n") p.dataReceived("+OK Here it comes\r\n") p.dataReceived("1 3\r\n2 2\r\n3 1\r\n") - self.assertEquals(c.data, {0: [3], 1: [2], 2: [1]}) + self.assertEqual(c.data, {0: [3], 1: [2], 2: [1]}) p.dataReceived("5 3\r\n6 2\r\n7 1\r\n") - self.assertEquals(c.data, {0: [3], 1: [2], 2: [1], 4: [3], 5: [2], 6: [1]}) + self.assertEqual(c.data, {0: [3], 1: [2], 2: [1], 4: [3], 5: [2], 6: [1]}) p.dataReceived(".\r\n") return d.addCallback(self.assertIdentical, f) def testFailedListSize(self): p, t = setUp() d = p.listSize() - self.assertEquals(t.value(), "LIST\r\n") + self.assertEqual(t.value(), "LIST\r\n") p.dataReceived("-ERR Fatal doom server exploded\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "Fatal doom server exploded")) + lambda exc: self.assertEqual(exc.args[0], "Fatal doom server exploded")) def testListUID(self): p, t = setUp() d = p.listUID() - self.assertEquals(t.value(), "UIDL\r\n") + self.assertEqual(t.value(), "UIDL\r\n") p.dataReceived("+OK Here it comes\r\n") p.dataReceived("1 abc\r\n2 def\r\n3 ghi\r\n.\r\n") return d.addCallback(self.assertEqual, ["abc", "def", "ghi"]) @@ -229,27 +229,27 @@ c = ListConsumer() f = c.consume d = p.listUID(f) - self.assertEquals(t.value(), "UIDL\r\n") + self.assertEqual(t.value(), "UIDL\r\n") p.dataReceived("+OK Here it comes\r\n") p.dataReceived("1 xyz\r\n2 abc\r\n5 mno\r\n") - self.assertEquals(c.data, {0: ["xyz"], 1: ["abc"], 4: ["mno"]}) + self.assertEqual(c.data, {0: ["xyz"], 1: ["abc"], 4: ["mno"]}) p.dataReceived(".\r\n") return d.addCallback(self.assertIdentical, f) def testFailedListUID(self): p, t = setUp() d = p.listUID() - self.assertEquals(t.value(), "UIDL\r\n") + self.assertEqual(t.value(), "UIDL\r\n") p.dataReceived("-ERR Fatal doom server exploded\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "Fatal doom server exploded")) + lambda exc: self.assertEqual(exc.args[0], "Fatal doom server exploded")) class POP3ClientMessageTestCase(unittest.TestCase): def testRetrieve(self): p, t = setUp() d = p.retrieve(7) - self.assertEquals(t.value(), "RETR 8\r\n") + self.assertEqual(t.value(), "RETR 8\r\n") p.dataReceived("+OK Message incoming\r\n") p.dataReceived("La la la here is message text\r\n") p.dataReceived("..Further message text tra la la\r\n") @@ -264,7 +264,7 @@ c = MessageConsumer() f = c.consume d = p.retrieve(7, f) - self.assertEquals(t.value(), "RETR 8\r\n") + self.assertEqual(t.value(), "RETR 8\r\n") p.dataReceived("+OK Message incoming\r\n") p.dataReceived("La la la here is message text\r\n") p.dataReceived("..Further message text\r\n.\r\n") @@ -272,13 +272,13 @@ def _cbTestRetrieveWithConsumer(self, result, f, c): self.assertIdentical(result, f) - self.assertEquals(c.data, ["La la la here is message text", + self.assertEqual(c.data, ["La la la here is message text", ".Further message text"]) def testPartialRetrieve(self): p, t = setUp() d = p.retrieve(7, lines=2) - self.assertEquals(t.value(), "TOP 8 2\r\n") + self.assertEqual(t.value(), "TOP 8 2\r\n") p.dataReceived("+OK 2 lines on the way\r\n") p.dataReceived("Line the first! Woop\r\n") p.dataReceived("Line the last! Bye\r\n") @@ -293,7 +293,7 @@ c = MessageConsumer() f = c.consume d = p.retrieve(7, f, lines=2) - self.assertEquals(t.value(), "TOP 8 2\r\n") + self.assertEqual(t.value(), "TOP 8 2\r\n") p.dataReceived("+OK 2 lines on the way\r\n") p.dataReceived("Line the first! Woop\r\n") p.dataReceived("Line the last! Bye\r\n") @@ -302,17 +302,17 @@ def _cbTestPartialRetrieveWithConsumer(self, result, f, c): self.assertIdentical(result, f) - self.assertEquals(c.data, ["Line the first! Woop", + self.assertEqual(c.data, ["Line the first! Woop", "Line the last! Bye"]) def testFailedRetrieve(self): p, t = setUp() d = p.retrieve(0) - self.assertEquals(t.value(), "RETR 1\r\n") + self.assertEqual(t.value(), "RETR 1\r\n") p.dataReceived("-ERR Fatal doom server exploded\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "Fatal doom server exploded")) + lambda exc: self.assertEqual(exc.args[0], "Fatal doom server exploded")) def test_concurrentRetrieves(self): @@ -323,19 +323,19 @@ p, t = setUp() messages = [ p.retrieve(i).addCallback( - self.assertEquals, + self.assertEqual, ["First line of %d." % (i + 1,), "Second line of %d." % (i + 1,)]) for i in range(3)] for i in range(1, 4): - self.assertEquals(t.value(), "RETR %d\r\n" % (i,)) + self.assertEqual(t.value(), "RETR %d\r\n" % (i,)) t.clear() p.dataReceived("+OK 2 lines on the way\r\n") p.dataReceived("First line of %d.\r\n" % (i,)) p.dataReceived("Second line of %d.\r\n" % (i,)) - self.assertEquals(t.value(), "") + self.assertEqual(t.value(), "") p.dataReceived(".\r\n") return defer.DeferredList(messages, fireOnOneErrback=True) @@ -346,7 +346,7 @@ def testCapability(self): p, t = setUp() d = p.capabilities(useCache=0) - self.assertEquals(t.value(), "CAPA\r\n") + self.assertEqual(t.value(), "CAPA\r\n") p.dataReceived("+OK Capabilities on the way\r\n") p.dataReceived("X\r\nY\r\nZ\r\nA 1 2 3\r\nB 1 2\r\nC 1\r\n.\r\n") return d.addCallback( @@ -359,73 +359,73 @@ def testCapabilityError(self): p, t = setUp() d = p.capabilities(useCache=0) - self.assertEquals(t.value(), "CAPA\r\n") + self.assertEqual(t.value(), "CAPA\r\n") p.dataReceived("-ERR This server is lame!\r\n") - return d.addCallback(self.assertEquals, {}) + return d.addCallback(self.assertEqual, {}) def testStat(self): p, t = setUp() d = p.stat() - self.assertEquals(t.value(), "STAT\r\n") + self.assertEqual(t.value(), "STAT\r\n") p.dataReceived("+OK 1 1212\r\n") return d.addCallback(self.assertEqual, (1, 1212)) def testStatError(self): p, t = setUp() d = p.stat() - self.assertEquals(t.value(), "STAT\r\n") + self.assertEqual(t.value(), "STAT\r\n") p.dataReceived("-ERR This server is lame!\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "This server is lame!")) + lambda exc: self.assertEqual(exc.args[0], "This server is lame!")) def testNoop(self): p, t = setUp() d = p.noop() - self.assertEquals(t.value(), "NOOP\r\n") + self.assertEqual(t.value(), "NOOP\r\n") p.dataReceived("+OK No-op to you too!\r\n") return d.addCallback(self.assertEqual, "No-op to you too!") def testNoopError(self): p, t = setUp() d = p.noop() - self.assertEquals(t.value(), "NOOP\r\n") + self.assertEqual(t.value(), "NOOP\r\n") p.dataReceived("-ERR This server is lame!\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "This server is lame!")) + lambda exc: self.assertEqual(exc.args[0], "This server is lame!")) def testRset(self): p, t = setUp() d = p.reset() - self.assertEquals(t.value(), "RSET\r\n") + self.assertEqual(t.value(), "RSET\r\n") p.dataReceived("+OK Reset state\r\n") return d.addCallback(self.assertEqual, "Reset state") def testRsetError(self): p, t = setUp() d = p.reset() - self.assertEquals(t.value(), "RSET\r\n") + self.assertEqual(t.value(), "RSET\r\n") p.dataReceived("-ERR This server is lame!\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "This server is lame!")) + lambda exc: self.assertEqual(exc.args[0], "This server is lame!")) def testDelete(self): p, t = setUp() d = p.delete(3) - self.assertEquals(t.value(), "DELE 4\r\n") + self.assertEqual(t.value(), "DELE 4\r\n") p.dataReceived("+OK Hasta la vista\r\n") return d.addCallback(self.assertEqual, "Hasta la vista") def testDeleteError(self): p, t = setUp() d = p.delete(3) - self.assertEquals(t.value(), "DELE 4\r\n") + self.assertEqual(t.value(), "DELE 4\r\n") p.dataReceived("-ERR Winner is not you.\r\n") return self.assertFailure( d, ServerErrorResponse).addCallback( - lambda exc: self.assertEquals(exc.args[0], "Winner is not you.")) + lambda exc: self.assertEqual(exc.args[0], "Winner is not you.")) class SimpleClient(POP3Client): @@ -480,7 +480,15 @@ class POP3TLSTestCase(unittest.TestCase): - def testStartTLS(self): + """ + Tests for POP3Client's support for TLS connections. + """ + + def test_startTLS(self): + """ + POP3Client.startTLS starts a TLS session over its existing TCP + connection. + """ sf = TLSServerFactory() sf.protocol.output = [ ['+OK'], # Server greeting @@ -491,10 +499,16 @@ ] sf.protocol.context = ServerTLSContext() port = reactor.listenTCP(0, sf, interface='127.0.0.1') + self.addCleanup(port.stopListening) H = port.getHost().host P = port.getHost().port + connLostDeferred = defer.Deferred() cp = SimpleClient(defer.Deferred(), ClientTLSContext()) + def connectionLost(reason): + SimpleClient.connectionLost(cp, reason) + connLostDeferred.callback(None) + cp.connectionLost = connectionLost cf = protocol.ClientFactory() cf.protocol = lambda: cp @@ -510,19 +524,14 @@ def cbDisconnected(ign): log.msg("Disconnected; asserting correct input received") - self.assertEquals( + self.assertEqual( sf.input, ['CAPA', 'STLS', 'CAPA', 'QUIT']) def cleanup(result): log.msg("Asserted correct input; disconnecting client and shutting down server") conn.disconnect() - - def cbShutdown(ignored): - log.msg("Shut down server") - return result - - return defer.maybeDeferred(port.stopListening).addCallback(cbShutdown) + return connLostDeferred cp.deferred.addCallback(cbConnected) cp.deferred.addCallback(cbStartedTLS) diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_pop3.py twisted-mail-12.0.0/twisted/mail/test/test_pop3.py --- twisted-mail-10.1.0/twisted/mail/test/test_pop3.py 2008-06-21 22:04:53.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_pop3.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -48,16 +48,16 @@ input = iter(itertools.cycle(['012', '345', '6', '7', '8', '9'])) c = pop3._IteratorBuffer(output.extend, input, 6) i = iter(c) - self.assertEquals(output, []) # nothing is buffer + self.assertEqual(output, []) # nothing is buffer i.next() - self.assertEquals(output, []) # '012' is buffered + self.assertEqual(output, []) # '012' is buffered i.next() - self.assertEquals(output, []) # '012345' is buffered + self.assertEqual(output, []) # '012345' is buffered i.next() - self.assertEquals(output, ['012', '345', '6']) # nothing is buffered + self.assertEqual(output, ['012', '345', '6']) # nothing is buffered for n in range(5): i.next() - self.assertEquals(output, ['012', '345', '6', '7', '8', '9', '012', '345']) + self.assertEqual(output, ['012', '345', '6', '7', '8', '9', '012', '345']) def testFinishLineBuffering(self): @@ -70,7 +70,7 @@ c = pop3._IteratorBuffer(output.extend, input, 5) for i in c: pass - self.assertEquals(output, ['a', 'b', 'c']) + self.assertEqual(output, ['a', 'b', 'c']) def testSuccessResponseFormatter(self): @@ -78,7 +78,7 @@ Test that the thing that spits out POP3 'success responses' works right. """ - self.assertEquals( + self.assertEqual( pop3.successResponse('Great.'), '+OK Great.\r\n') @@ -88,10 +88,10 @@ Test that the function which formats stat lines does so appropriately. """ statLine = list(pop3.formatStatResponse([]))[-1] - self.assertEquals(statLine, '+OK 0 0\r\n') + self.assertEqual(statLine, '+OK 0 0\r\n') statLine = list(pop3.formatStatResponse([10, 31, 0, 10101]))[-1] - self.assertEquals(statLine, '+OK 4 10142\r\n') + self.assertEqual(statLine, '+OK 4 10142\r\n') def testListLineFormatter(self): @@ -100,12 +100,12 @@ command does so appropriately. """ listLines = list(pop3.formatListResponse([])) - self.assertEquals( + self.assertEqual( listLines, ['+OK 0\r\n', '.\r\n']) listLines = list(pop3.formatListResponse([1, 2, 3, 100])) - self.assertEquals( + self.assertEqual( listLines, ['+OK 4\r\n', '1 1\r\n', '2 2\r\n', '3 3\r\n', '4 100\r\n', '.\r\n']) @@ -118,17 +118,17 @@ """ UIDs = ['abc', 'def', 'ghi'] listLines = list(pop3.formatUIDListResponse([], UIDs.__getitem__)) - self.assertEquals( + self.assertEqual( listLines, ['+OK \r\n', '.\r\n']) listLines = list(pop3.formatUIDListResponse([123, 431, 591], UIDs.__getitem__)) - self.assertEquals( + self.assertEqual( listLines, ['+OK \r\n', '1 abc\r\n', '2 def\r\n', '3 ghi\r\n', '.\r\n']) listLines = list(pop3.formatUIDListResponse([0, None, 591], UIDs.__getitem__)) - self.assertEquals( + self.assertEqual( listLines, ['+OK \r\n', '1 abc\r\n', '3 ghi\r\n', '.\r\n']) @@ -247,7 +247,7 @@ server.service = self.factory def check(ignored): output = '\r\n'.join(client.response) + '\r\n' - self.assertEquals(output, self.expectedOutput) + self.assertEqual(output, self.expectedOutput) return loopback.loopbackTCP(server, client).addCallback(check) def testLoopback(self): @@ -255,7 +255,7 @@ protocol.service = self.factory clientProtocol = MyPOP3Downloader() def check(ignored): - self.failUnlessEqual(clientProtocol.message, self.message) + self.assertEqual(clientProtocol.message, self.message) protocol.connectionLost( failure.Failure(Exception("Test harness disconnect"))) d = loopback.loopbackAsync(protocol, clientProtocol) @@ -310,7 +310,7 @@ def _cbRunTest(self, ignored, client, dummy, expectedOutput): - self.failUnlessEqual('\r\n'.join(expectedOutput), + self.assertEqual('\r\n'.join(expectedOutput), '\r\n'.join(client.response)) dummy.connectionLost(failure.Failure(Exception("Test harness disconnect"))) return ignored @@ -382,7 +382,7 @@ def _cbTestAuthListing(self, ignored, client): self.failUnless(client.response[1].startswith('+OK')) - self.assertEquals(client.response[2:6], + self.assertEqual(client.response[2:6], ["AUTH1", "SECONDAUTH", "AUTHLAST", "."]) def testIllegalPASS(self): @@ -396,7 +396,7 @@ def _cbTestIllegalPASS(self, ignored, client, dummy): expected_output = '+OK \r\n-ERR USER required before PASS\r\n+OK \r\n' - self.failUnlessEqual(expected_output, '\r\n'.join(client.response) + '\r\n') + self.assertEqual(expected_output, '\r\n'.join(client.response) + '\r\n') dummy.connectionLost(failure.Failure(Exception("Test harness disconnect"))) def testEmptyPASS(self): @@ -410,7 +410,7 @@ def _cbTestEmptyPASS(self, ignored, client, dummy): expected_output = '+OK \r\n-ERR USER required before PASS\r\n+OK \r\n' - self.failUnlessEqual(expected_output, '\r\n'.join(client.response) + '\r\n') + self.assertEqual(expected_output, '\r\n'.join(client.response) + '\r\n') dummy.connectionLost(failure.Failure(Exception("Test harness disconnect"))) @@ -625,12 +625,12 @@ p.lineReceived("LIST 1") self._flush() - self.assertEquals(s.getvalue(), "+OK 1 44\r\n") + self.assertEqual(s.getvalue(), "+OK 1 44\r\n") s.truncate(0) p.lineReceived("LIST") self._flush() - self.assertEquals(s.getvalue(), "+OK 1\r\n1 44\r\n.\r\n") + self.assertEqual(s.getvalue(), "+OK 1\r\n1 44\r\n.\r\n") def testLISTWithBadArgument(self): @@ -642,19 +642,19 @@ s = self.pop3Transport p.lineReceived("LIST a") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Invalid message-number: 'a'\r\n") s.truncate(0) p.lineReceived("LIST 0") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Invalid message-number: 0\r\n") s.truncate(0) p.lineReceived("LIST 2") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Invalid message-number: 2\r\n") s.truncate(0) @@ -669,12 +669,12 @@ s = self.pop3Transport p.lineReceived("UIDL 1") - self.assertEquals(s.getvalue(), "+OK 0\r\n") + self.assertEqual(s.getvalue(), "+OK 0\r\n") s.truncate(0) p.lineReceived("UIDL") self._flush() - self.assertEquals(s.getvalue(), "+OK \r\n1 0\r\n.\r\n") + self.assertEqual(s.getvalue(), "+OK \r\n1 0\r\n.\r\n") def testUIDLWithBadArgument(self): @@ -686,19 +686,19 @@ s = self.pop3Transport p.lineReceived("UIDL a") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("UIDL 0") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("UIDL 2") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) @@ -714,7 +714,7 @@ p.lineReceived("STAT") self._flush() - self.assertEquals(s.getvalue(), "+OK 1 44\r\n") + self.assertEqual(s.getvalue(), "+OK 1 44\r\n") def testRETR(self): @@ -726,7 +726,7 @@ p.lineReceived("RETR 1") self._flush() - self.assertEquals( + self.assertEqual( s.getvalue(), "+OK 44\r\n" "From: moshe\r\n" @@ -747,19 +747,19 @@ s = self.pop3Transport p.lineReceived("RETR a") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("RETR 0") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("RETR 2") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) @@ -775,7 +775,7 @@ p.lineReceived("TOP 1 0") self._flush() - self.assertEquals( + self.assertEqual( s.getvalue(), "+OK Top of message follows\r\n" "From: moshe\r\n" @@ -796,31 +796,31 @@ p.mbox.messages.append(self.extraMessage) p.lineReceived("TOP 1 a") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad line count argument\r\n") s.truncate(0) p.lineReceived("TOP 1 -1") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad line count argument\r\n") s.truncate(0) p.lineReceived("TOP a 1") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("TOP 0 1") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) p.lineReceived("TOP 3 1") - self.assertEquals( + self.assertEqual( s.getvalue(), "-ERR Bad message number argument\r\n") s.truncate(0) @@ -836,7 +836,7 @@ p.mbox.messages.append(self.extraMessage) p.lineReceived('LAST') - self.assertEquals( + self.assertEqual( s.getvalue(), "+OK 0\r\n") s.truncate(0) @@ -854,7 +854,7 @@ self._flush() s.truncate(0) p.lineReceived('LAST') - self.assertEquals( + self.assertEqual( s.getvalue(), '+OK 2\r\n') s.truncate(0) @@ -872,7 +872,7 @@ self._flush() s.truncate(0) p.lineReceived('LAST') - self.assertEquals( + self.assertEqual( s.getvalue(), '+OK 2\r\n') @@ -892,7 +892,7 @@ self._flush() s.truncate(0) p.lineReceived('LAST') - self.assertEquals( + self.assertEqual( s.getvalue(), '+OK 2\r\n') @@ -910,7 +910,7 @@ p.lineReceived('RSET') s.truncate(0) p.lineReceived('LAST') - self.assertEquals( + self.assertEqual( s.getvalue(), '+OK 0\r\n') diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_scripts.py twisted-mail-12.0.0/twisted/mail/test/test_scripts.py --- twisted-mail-10.1.0/twisted/mail/test/test_scripts.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_scripts.py 2011-06-30 12:57:11.000000000 +0000 @@ -0,0 +1,18 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for the command-line mailer tool provided by Twisted Mail. +""" + +from twisted.trial.unittest import TestCase +from twisted.scripts.test.test_scripts import ScriptTestsMixin + + + +class ScriptTests(TestCase, ScriptTestsMixin): + """ + Tests for all one of mail's scripts. + """ + def test_mailmail(self): + self.scriptTest("mail/mailmail") diff -Nru twisted-mail-10.1.0/twisted/mail/test/test_smtp.py twisted-mail-12.0.0/twisted/mail/test/test_smtp.py --- twisted-mail-10.1.0/twisted/mail/test/test_smtp.py 2009-12-18 15:59:52.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/test/test_smtp.py 2011-08-05 23:41:33.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2009 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ @@ -308,7 +308,7 @@ server = FakeSMTPServer() d = self.loopback(server, client) d.addCallback(lambda x : - self.assertEquals(server.buffer, self.expected_output)) + self.assertEqual(server.buffer, self.expected_output)) return d @@ -514,7 +514,7 @@ for recip in msgdata[2]: expected = list(msgdata[:]) expected[2] = [recip] - self.assertEquals( + self.assertEqual( a.message[(recip,)], tuple(expected) ) @@ -602,7 +602,7 @@ client.registerAuthenticator(cAuth) d = self.loopback(server, client) - d.addCallback(lambda x : self.assertEquals(server.authenticated, 1)) + d.addCallback(lambda x : self.assertEqual(server.authenticated, 1)) return d @@ -639,12 +639,7 @@ p = cred.portal.Portal(realm) p.registerChecker(DummyChecker()) - class WeirdLOGIN(imap4.LOGINCredentials): - def __init__(self): - imap4.LOGINCredentials.__init__(self) - self.challenges[1] = 'Username:' - - server = DummyESMTP({'LOGIN': WeirdLOGIN}) + server = DummyESMTP({'LOGIN': smtp.LOGINCredentials}) server.portal = p client = MyESMTPClient('testpassword') @@ -675,11 +670,11 @@ ] for (c, e) in cases: - self.assertEquals(smtp.quoteaddr(c), e) + self.assertEqual(smtp.quoteaddr(c), e) def testUser(self): u = smtp.User('user@host', 'helo.host.name', None, None) - self.assertEquals(str(u), 'user@host') + self.assertEqual(str(u), 'user@host') def testXtextEncoding(self): cases = [ @@ -691,10 +686,10 @@ for (case, expected) in cases: self.assertEqual(smtp.xtext_encode(case), (expected, len(case))) - self.assertEquals(case.encode('xtext'), expected) + self.assertEqual(case.encode('xtext'), expected) self.assertEqual( smtp.xtext_decode(expected), (case, len(expected))) - self.assertEquals(expected.decode('xtext'), case) + self.assertEqual(expected.decode('xtext'), case) def test_encodeWithErrors(self): @@ -718,11 +713,6 @@ """ bytes = 'Hello world' self.assertEqual( - smtp._slowXTextDecode(bytes, 'strict'), - (bytes.decode('xtext'), len(bytes))) - # This might be the same as _slowXTextDecode, but it might also be the - # fast version instead. - self.assertEqual( smtp.xtext_decode(bytes, 'strict'), (bytes.decode('xtext'), len(bytes))) self.assertEqual( @@ -747,8 +737,8 @@ server = DummyESMTP(contextFactory=serverCTX) def check(ignored): - self.assertEquals(client.tls, True) - self.assertEquals(server.startedTLS, True) + self.assertEqual(client.tls, True) + self.assertEqual(server.startedTLS, True) return self.loopback(server, client).addCallback(check) @@ -773,9 +763,9 @@ proto.setTimeout(None) out = transport.value().splitlines() - self.assertEquals(len(out), 2) + self.assertEqual(len(out), 2) self.failUnless(out[0].startswith('220')) - self.assertEquals(out[1], "500 Error: bad syntax") + self.assertEqual(out[1], "500 Error: bad syntax") @@ -796,7 +786,7 @@ client.makeConnection(t) t.protocol = client def check(ign): - self.assertEquals(clock.seconds(), 0.5) + self.assertEqual(clock.seconds(), 0.5) d = self.assertFailure(onDone, smtp.SMTPTimeoutError ).addCallback(check) # The first call should not trigger the timeout @@ -983,7 +973,7 @@ Verify that the message was successfully delivered and flush the error which caused the first attempt to fail. """ - self.assertEquals( + self.assertEqual( domain.messages, {recipient: ["\n%s\n" % (message,)]}) # Flush the RuntimeError that BrokenMessage caused to be logged. @@ -1454,11 +1444,11 @@ d, credentials, mind, interfaces = loginArgs.pop() d.errback(RuntimeError("Something wrong with the server")) - self.assertEquals( + self.assertEqual( '451 Requested action aborted: local error in processing\r\n', self.transport.value()) - self.assertEquals(len(self.flushLoggedErrors(RuntimeError)), 1) + self.assertEqual(len(self.flushLoggedErrors(RuntimeError)), 1) @@ -1472,7 +1462,7 @@ the response code and response string. """ err = smtp.SMTPClientError(123, "some text") - self.assertEquals(str(err), "123 some text") + self.assertEqual(str(err), "123 some text") def test_strWithNegativeCode(self): @@ -1481,7 +1471,7 @@ is excluded from the string representation. """ err = smtp.SMTPClientError(-1, "foo bar") - self.assertEquals(str(err), "foo bar") + self.assertEqual(str(err), "foo bar") def test_strWithLog(self): @@ -1493,7 +1483,7 @@ log.append("testlog") log.append("secondline") err = smtp.SMTPClientError(100, "test error", log=log.str()) - self.assertEquals( + self.assertEqual( str(err), "100 test error\n" "testlog\n" @@ -1512,7 +1502,7 @@ SMTP response codes to the log passed to the factory's errback. """ onDone = self.assertFailure(defer.Deferred(), smtp.SMTPDeliveryError) - onDone.addCallback(lambda e: self.assertEquals( + onDone.addCallback(lambda e: self.assertEqual( e.log, "bob@example.com: 199 Error in sending.\n")) clientFactory = smtp.SMTPSenderFactory( diff -Nru twisted-mail-10.1.0/twisted/mail/_version.py twisted-mail-12.0.0/twisted/mail/_version.py --- twisted-mail-10.1.0/twisted/mail/_version.py 2010-06-27 11:23:16.000000000 +0000 +++ twisted-mail-12.0.0/twisted/mail/_version.py 2012-02-10 14:56:39.000000000 +0000 @@ -1,3 +1,3 @@ # This is an auto-generated file. Do not edit it. from twisted.python import versions -version = versions.Version('twisted.mail', 10, 1, 0) +version = versions.Version('twisted.mail', 12, 0, 0) diff -Nru twisted-mail-10.1.0/twisted/plugins/twisted_mail.py twisted-mail-12.0.0/twisted/plugins/twisted_mail.py --- twisted-mail-10.1.0/twisted/plugins/twisted_mail.py 2008-04-08 15:53:14.000000000 +0000 +++ twisted-mail-12.0.0/twisted/plugins/twisted_mail.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application.service import ServiceMaker