[Zope3-checkins] CVS: Zope3/src/zope/app/mail/tests - test_event.py:1.2 test_mailer.py:1.2 test_service.py:1.2 test_directives.py:1.4 test_asyncmailservice.py:NONE test_batchmailer.py:NONE test_mailevents.py:NONE test_simplemailer.py:NONE

Albertas Agejevas alga@codeworks.lt
Mon, 23 Jun 2003 11:45:41 -0400


Update of /cvs-repository/Zope3/src/zope/app/mail/tests
In directory cvs.zope.org:/tmp/cvs-serv32331/src/zope/app/mail/tests

Modified Files:
	test_directives.py 
Added Files:
	test_event.py test_mailer.py test_service.py 
Removed Files:
	test_asyncmailservice.py test_batchmailer.py 
	test_mailevents.py test_simplemailer.py 
Log Message:
Transactionaly safe QueuedMailService merged into head.
If you want to play with it, uncomment the example tag in
zope/app/mail/configure.zcml .


=== Zope3/src/zope/app/mail/tests/test_event.py 1.1 => 1.2 ===
--- /dev/null	Mon Jun 23 11:45:41 2003
+++ Zope3/src/zope/app/mail/tests/test_event.py	Mon Jun 23 11:45:40 2003
@@ -0,0 +1,47 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""MailService Implementation
+
+Simple implementation of the MailService, Mailers and MailEvents.
+
+$Id$
+"""
+from unittest import TestCase, TestSuite, makeSuite
+from zope.interface.verify import verifyObject
+from zope.app.interfaces.mail import IMailSentEvent, IMailErrorEvent
+
+
+class TestMailEvents(TestCase):
+
+    def testMailSendEvent(self):
+        from zope.app.mail.event import MailSentEvent
+        msgid = '<1234@example.com>'
+        m = MailSentEvent(msgid)
+        verifyObject(IMailSentEvent, m)
+        self.assertEquals(m.messageId, msgid)
+
+    def testMailErrorEvent(self):
+        from zope.app.mail.event import MailErrorEvent
+        msgid = '<1234@example.com>'
+        error = '550 Relay access denied'
+        m = MailErrorEvent(msgid, error)
+        verifyObject(IMailErrorEvent, m)
+        self.assertEquals(m.messageId, msgid)
+        self.assertEquals(m.errorMessage, error)
+
+
+def test_suite():
+    return TestSuite((
+        makeSuite(TestMailEvents),
+        ))


=== Zope3/src/zope/app/mail/tests/test_mailer.py 1.1 => 1.2 ===
--- /dev/null	Mon Jun 23 11:45:41 2003
+++ Zope3/src/zope/app/mail/tests/test_mailer.py	Mon Jun 23 11:45:40 2003
@@ -0,0 +1,131 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for mailers.
+
+$Id$
+"""
+
+import unittest
+from StringIO import StringIO
+from zope.interface.verify import verifyObject
+from zope.app.interfaces.mail import ISendmailMailer, ISMTPMailer
+
+
+class TestSendmailMailer(unittest.TestCase):
+
+    def setUp(self):
+        from zope.app.mail.mailer import SendmailMailer
+
+        class ShtringIO(StringIO):
+            def close(self):
+                pass
+        self.input = ShtringIO()
+        def popen(cmd, mode):
+            self.cmd_arg = cmd
+            self.mode_arg = mode
+            return self.input
+        self.mailer = SendmailMailer()
+        self.mailer.popen = popen
+
+    def test_interface(self):
+        verifyObject(ISendmailMailer, self.mailer)
+
+    def test_send(self):
+        msgtext = 'Headers: headers\n\nbodybodybody\n-- \nsig\n'
+        self.mailer.send('me@example.com', ('you@example.com', 'him@example.com'),
+                         msgtext)
+        self.assertEquals(self.input.getvalue(), msgtext)
+        self.assertEquals(self.cmd_arg, "/usr/lib/sendmail -oem -oi"
+                          " -f me@example.com you@example.com him@example.com")
+        self.assertEquals(self.mode_arg, "w")
+
+
+class TestSMTPMailer(unittest.TestCase):
+
+    def setUp(self, port=None):
+        from zope.app.mail.mailer import SMTPMailer
+
+        class SMTP:
+
+            def __init__(myself, h, p):
+                myself.hostname = h
+                myself.port = p
+                if type(p) == type(u""):
+                    import socket
+                    raise socket.error("Int or String expected")
+                self.smtp = myself
+
+            def sendmail(self, f, t, m):
+                self.fromaddr = f
+                self.toaddrs = t
+                self.msgtext = m
+
+            def login(self, username, password):
+                self.username = username
+                self.password = password
+
+            def quit(self):
+                self.quit = True
+
+        if port is None:
+            self.mailer = SMTPMailer()
+        else:
+            self.mailer = SMTPMailer(u'localhost', port)
+        self.mailer.smtp = SMTP
+
+    def test_interface(self):
+        verifyObject(ISMTPMailer, self.mailer)
+
+    def test_send(self):
+        for run in (1,2):
+            if run == 2:
+                self.setUp(u'25')
+            fromaddr = 'me@example.com'
+            toaddrs = ('you@example.com', 'him@example.com')
+            msgtext = 'Headers: headers\n\nbodybodybody\n-- \nsig\n'
+            self.mailer.send(fromaddr, toaddrs, msgtext)
+            self.assertEquals(self.smtp.fromaddr, fromaddr)
+            self.assertEquals(self.smtp.toaddrs, toaddrs)
+            self.assertEquals(self.smtp.msgtext, msgtext)
+            self.assert_(self.smtp.quit)
+
+    def test_send_auth(self):
+        fromaddr = 'me@example.com'
+        toaddrs = ('you@example.com', 'him@example.com')
+        msgtext = 'Headers: headers\n\nbodybodybody\n-- \nsig\n'
+        self.mailer.username = 'foo'
+        self.mailer.password = 'evil'
+        self.mailer.hostname = 'spamrelay'
+        self.mailer.port = 31337
+        self.mailer.send(fromaddr, toaddrs, msgtext)
+        self.assertEquals(self.smtp.username, 'foo')
+        self.assertEquals(self.smtp.password, 'evil')
+        self.assertEquals(self.smtp.hostname, 'spamrelay')
+        self.assertEquals(self.smtp.port, '31337')
+        self.assertEquals(self.smtp.fromaddr, fromaddr)
+        self.assertEquals(self.smtp.toaddrs, toaddrs)
+        self.assertEquals(self.smtp.msgtext, msgtext)
+        self.assert_(self.smtp.quit)
+
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(TestSendmailMailer))
+    suite.addTest(unittest.makeSuite(TestSMTPMailer))
+    return suite
+
+
+if __name__ == '__main__':
+    unittest.main()


=== Zope3/src/zope/app/mail/tests/test_service.py 1.1 => 1.2 ===
--- /dev/null	Mon Jun 23 11:45:41 2003
+++ Zope3/src/zope/app/mail/tests/test_service.py	Mon Jun 23 11:45:40 2003
@@ -0,0 +1,304 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""MailService Implementation
+
+Simple implementation of the MailService, Mailers and MailEvents.
+
+$Id$
+"""
+from unittest import TestCase, TestSuite, makeSuite
+from zope.interface import implements
+from zope.interface.verify import verifyObject
+from zope.app.interfaces.mail import IMailer
+from transaction import get_transaction
+from os import mkdir, rmdir, unlink, getpid, listdir
+from tempfile import mktemp
+import os.path
+
+__metaclass__ = type
+
+
+class MailerStub:
+
+    implements(IMailer)
+    def __init__(self, *args, **kw):
+        self.sent_messages = []
+
+    def send(self, fromaddr, toaddrs, message):
+        self.sent_messages.append((fromaddr, toaddrs, message))
+
+
+class TestMailDataManager(TestCase):
+
+    def testInterface(self):
+        from transaction.interfaces import IDataManager
+        from zope.app.mail.service import MailDataManager
+        manager = MailDataManager(object, (1, 2))
+        verifyObject(IDataManager, manager)
+        self.assertEqual(manager.callable, object)
+        self.assertEqual(manager.args, (1, 2))
+
+
+class TestDirectMailService(TestCase):
+
+    def testInterface(self):
+        from zope.app.interfaces.mail import IDirectMailService
+        from zope.app.mail.service import DirectMailService
+        mailer = MailerStub()
+        service = DirectMailService(mailer)
+        verifyObject(IDirectMailService, service)
+        self.assertEqual(service.mailer, mailer)
+
+    def testSend(self):
+        from zope.app.mail.service import DirectMailService
+        mailer = MailerStub()
+        service = DirectMailService(mailer)
+        fromaddr = 'Jim <jim@example.com'
+        toaddrs = ('Guido <guido@example.com>',
+                   'Steve <steve@examplecom>')
+        opt_headers = ('From: Jim <jim@example.org>\n'
+                       'To: some-zope-coders:;\n'
+                       'Date: Mon, 19 May 2003 10:17:36 -0400\n'
+                       'Message-Id: <20030519.1234@example.org>\n')
+        message =     ('Subject: example\n'
+                       '\n'
+                       'This is just an example\n')
+
+        msgid = service.send(fromaddr, toaddrs, opt_headers + message)
+        self.assertEquals(msgid, '20030519.1234@example.org')
+        self.assertEquals(mailer.sent_messages, [])
+        get_transaction().commit()
+        self.assertEquals(mailer.sent_messages,
+                          [(fromaddr, toaddrs, opt_headers + message)])
+
+        mailer.sent_messages = []
+        msgid = service.send(fromaddr, toaddrs, message)
+        self.assert_('@' in msgid)
+        self.assertEquals(mailer.sent_messages, [])
+        get_transaction().commit()
+        self.assertEquals(len(mailer.sent_messages), 1)
+        self.assertEquals(mailer.sent_messages[0][0], fromaddr)
+        self.assertEquals(mailer.sent_messages[0][1], toaddrs)
+        self.assert_(mailer.sent_messages[0][2].endswith(message))
+        new_headers = mailer.sent_messages[0][2][:-len(message)]
+        self.assert_(new_headers.find('Message-Id: <%s>' % msgid) != -1)
+
+        mailer.sent_messages = []
+        msgid = service.send(fromaddr, toaddrs, opt_headers + message)
+        self.assertEquals(mailer.sent_messages, [])
+        get_transaction().abort()
+        self.assertEquals(mailer.sent_messages, [])
+
+
+class MaildirWriterStub:
+
+    data = ''
+    commited_messages = []  # this list is shared among all instances
+    aborted_messages = []   # this one too
+
+    def write(self, str):
+        self.data += str
+
+    def writelines(self, seq):
+        self.data += ''.join(seq)
+
+    def commit(self):
+        self._commited = True
+        self.commited_messages.append(self.data)
+
+    def abort(self):
+        self._aborted = True
+        self.aborted_messages.append(self.data)
+
+
+class MaildirStub:
+
+    def __init__(self, path, create=False):
+        self.path = path
+        self.create = create
+        self.msgs = []
+        self.files = []
+
+    def __iter__(self):
+        return iter(self.files)
+
+    def newMessage(self):
+        m = MaildirWriterStub()
+        self.msgs.append(m)
+        return m
+
+class LoggerStub:
+
+    def __init__(self):
+        self.infos = []
+        self.errors = []
+
+    def getLogger(name):
+        return self
+
+    def error(self, msg, *args, **kwargs):
+        self.errors.append((msg, args, kwargs))
+
+    def info(self, msg, *args, **kwargs):
+        self.infos.append((msg, args, kwargs))
+
+class BizzarreMailError(IOError):
+    pass
+
+class BrokenMailerStub:
+
+    implements(IMailer)
+    def __init__(self, *args, **kw):
+        pass
+
+    def send(self, fromaddr, toaddrs, message):
+        raise BizzarreMailError("bad things happened while sending mail")
+
+class TestQueuedMailService(TestCase):
+
+    def setUp(self):
+        import zope.app.mail.service as mail_service_module
+        self.mail_service_module = mail_service_module
+        self.old_Maildir = mail_service_module.Maildir
+        mail_service_module.Maildir = MaildirStub
+
+    def tearDown(self):
+        self.mail_service_module.Maildir = self.old_Maildir
+
+    def testInterface(self):
+        from zope.app.interfaces.mail import IQueuedMailService
+        from zope.app.mail.service import QueuedMailService
+        service = QueuedMailService('/path/to/mailbox')
+        verifyObject(IQueuedMailService, service)
+        self.assertEqual(service.queuePath, '/path/to/mailbox')
+
+    def testSend(self):
+        from zope.app.mail.service import QueuedMailService
+        service = QueuedMailService('/path/to/mailbox')
+        fromaddr = 'jim@example.com'
+        toaddrs = ('guido@example.com',
+                   'steve@examplecom')
+        zope_headers = ('X-Zope-From: jim@example.com\n'
+                       'X-Zope-To: guido@example.com, steve@examplecom\n')
+        opt_headers = ('From: Jim <jim@example.org>\n'
+                       'To: some-zope-coders:;\n'
+                       'Date: Mon, 19 May 2003 10:17:36 -0400\n'
+                       'Message-Id: <20030519.1234@example.org>\n')
+        message =     ('Subject: example\n'
+                       '\n'
+                       'This is just an example\n')
+
+        msgid = service.send(fromaddr, toaddrs, opt_headers + message)
+        self.assertEquals(msgid, '20030519.1234@example.org')
+        self.assertEquals(MaildirWriterStub.commited_messages, [])
+        self.assertEquals(MaildirWriterStub.aborted_messages, [])
+        get_transaction().commit()
+        self.assertEquals(MaildirWriterStub.commited_messages,
+                          [zope_headers + opt_headers + message])
+        self.assertEquals(MaildirWriterStub.aborted_messages, [])
+
+        MaildirWriterStub.commited_messages = []
+        msgid = service.send(fromaddr, toaddrs, message)
+        self.assert_('@' in msgid)
+        self.assertEquals(MaildirWriterStub.commited_messages, [])
+        self.assertEquals(MaildirWriterStub.aborted_messages, [])
+        get_transaction().commit()
+        self.assertEquals(len(MaildirWriterStub.commited_messages), 1)
+        self.assert_(MaildirWriterStub.commited_messages[0].endswith(message))
+        new_headers = MaildirWriterStub.commited_messages[0][:-len(message)]
+        self.assert_(new_headers.find('Message-Id: <%s>' % msgid) != -1)
+        self.assert_(new_headers.find('X-Zope-From: %s' % fromaddr) != 1)
+        self.assert_(new_headers.find('X-Zope-To: %s' % ", ".join(toaddrs)) != 1)
+        self.assertEquals(MaildirWriterStub.aborted_messages, [])
+
+        MaildirWriterStub.commited_messages = []
+        msgid = service.send(fromaddr, toaddrs, opt_headers + message)
+        self.assertEquals(MaildirWriterStub.commited_messages, [])
+        self.assertEquals(MaildirWriterStub.aborted_messages, [])
+        get_transaction().abort()
+        self.assertEquals(MaildirWriterStub.commited_messages, [])
+        self.assertEquals(len(MaildirWriterStub.aborted_messages), 1)
+
+
+class TestQueueProcessorThread(TestCase):
+
+    def setUp(self):
+        from zope.app.mail.service import QueueProcessorThread
+        self.md = MaildirStub('/foo/bar/baz')
+        self.thread = QueueProcessorThread()
+        self.thread.setMaildir(self.md)
+        self.mailer = MailerStub()
+        self.thread.setMailer(self.mailer)
+        self.thread.log = LoggerStub()
+
+    def test_parseMessage(self):
+
+        hdr = ('X-Zope-From: foo@example.com\n'
+               'X-Zope-To: bar@example.com, baz@example.com\n')
+        msg = ('Header: value\n'
+               '\n'
+               'Body\n')
+
+
+        f, t, m = self.thread._parseMessage(hdr + msg)
+        self.assertEquals(f, 'foo@example.com')
+        self.assertEquals(t, ('bar@example.com', 'baz@example.com'))
+        self.assertEquals(m, msg)
+
+    def test_deliveration(self):
+        self.filename = mktemp()
+        temp = open(self.filename, "w+b")
+        temp.write('X-Zope-From: foo@example.com\n'
+                   'X-Zope-To: bar@example.com, baz@example.com\n'
+                   'Header: value\n\nBody\n')
+        temp.close()
+        self.md.files.append(self.filename)
+        self.thread.run(forever=False)
+        self.assertEquals(self.mailer.sent_messages,
+                          [('foo@example.com',
+                            ('bar@example.com', 'baz@example.com'),
+                            'Header: value\n\nBody\n')])
+        self.failIf(os.path.exists(self.filename), 'File exists')
+        self.assertEquals(self.thread.log.infos,
+                          [('Mail from %s to %s sent.',
+                            ('foo@example.com',
+                             'bar@example.com, baz@example.com'),
+                            {})])
+
+
+    def test_error_logging(self):
+        self.thread.setMailer(BrokenMailerStub())
+        self.filename = mktemp()
+        temp = open(self.filename, "w+b")
+        temp.write('X-Zope-From: foo@example.com\n'
+                   'X-Zope-To: bar@example.com, baz@example.com\n'
+                   'Header: value\n\nBody\n')
+        temp.close()
+        self.md.files.append(self.filename)
+        self.thread.run(forever=False)
+        self.assertEquals(self.thread.log.errors,
+                          [('Error while sending mail from %s to %s.',
+                            ('foo@example.com',
+                             'bar@example.com, baz@example.com'),
+                            {'exc_info': 1})])
+
+
+
+def test_suite():
+    return TestSuite((
+        makeSuite(TestMailDataManager),
+        makeSuite(TestDirectMailService),
+        makeSuite(TestQueuedMailService),
+        makeSuite(TestQueueProcessorThread),
+        ))


=== Zope3/src/zope/app/mail/tests/test_directives.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/mail/tests/test_directives.py:1.3	Mon May 19 06:03:37 2003
+++ Zope3/src/zope/app/mail/tests/test_directives.py	Mon Jun 23 11:45:40 2003
@@ -16,6 +16,7 @@
 $Id$
 """
 import unittest
+import threading
 
 from cStringIO import StringIO
 
@@ -26,6 +27,7 @@
 from zope.app.component.metaconfigure import managerHandler, provideInterface
 import zope.app.mail
 import zope.app.interfaces.mail
+from zope.app.mail.metaconfigure import provideMailer
 
 template = """<zopeConfigure
    xmlns='http://namespaces.zope.org/zope'
@@ -35,6 +37,20 @@
    </zopeConfigure>"""
 
 
+class MaildirStub:
+
+    def __init__(self, path, create=False):
+        self.path = path
+        self.create = create
+
+    def __iter__(self):
+        return iter(())
+
+    def newMessage(self):
+        return None
+
+
+
 class DirectivesTest(PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
@@ -45,40 +61,78 @@
                          zope.app.interfaces.mail.IMailService)
         XMLConfig('metameta.zcml', zope.configuration)()
         XMLConfig('meta.zcml', zope.app.mail)()
-
-    def test_mailservice(self):
+        from zope.app.mail import service
+        self.orig_maildir = service.Maildir
+        service.Maildir = MaildirStub
+
+    def tearDown(self):
+        from zope.app.mail import service
+        service.Maildir = self.orig_maildir
+
+    def testQueuedService(self):
+        threads = threading.activeCount()
+        provideMailer("smtp", object())
         xmlconfig(StringIO(template % (
             '''
-            <mail:mailservice name="Mail"
-               hostname="somehost" port="125"
-               username="foo" password="bar"
-               class=".mail.AsyncMailService"
+            <mail:queuedService name="Mail"
+               queuePath="/path/to/mailbox"
+               mailer="smtp"
                permission="zope.Public" />
             '''
             )), None, Context([], zope.app.mail))
         service = getService(None, 'Mail')
-        self.assertEqual('AsyncMailService', service.__class__.__name__)
-        self.assertEqual('somehost', service.hostname)
-        self.assertEqual(125, service.port)
-        self.assertEqual('foo', service.username)
-        self.assertEqual('bar', service.password)
-
-    def test_mailer(self):
+        self.assertEqual('QueuedMailService', service.__class__.__name__)
+        self.assertEqual('/path/to/mailbox', service.queuePath)
+        self.assertEqual(threading.activeCount(), threads + 1)
+
+    def testDirectService(self):
+        testMailer = object()
+        provideMailer('test.mailer', testMailer)
         xmlconfig(StringIO(template % (
             '''
-            <mail:mailservice class=".mail.AsyncMailService"
-                permission="zope.Public" />
+            <mail:directService name="Mail"
+               mailer="test.mailer"
+               permission="zope.Public" />
+            '''
+            )), None, Context([], zope.app.mail))
+        service = getService(None, 'Mail')
+        self.assertEqual('DirectMailService', service.__class__.__name__)
+        self.assert_(testMailer is service.mailer)
 
-            <mail:mailer name="TestSimpleMailer" class=".mailer.SimpleMailer"
-                serviceType="Mail" default="True" />
+
+    def testSendmailMailer(self):
+        from zope.app.interfaces.mail import ISendmailMailer
+        from zope.app.mail.metaconfigure import queryMailer
+        xmlconfig(StringIO(template % (
+            '''
+            <mail:sendmailMailer id="Sendmail"
+               command="/usr/lib/sendmail -oem -oi -f %(from)s %(to)s" />
             '''
             )), None, Context([], zope.app.mail))
+        self.assert_(ISendmailMailer.isImplementedBy(queryMailer("Sendmail")))
 
-        service = getService(None, "Mail")
-        self.assertEqual("TestSimpleMailer", service.getDefaultMailerName())
-        self.assertEqual(service._AsyncMailService__mailers['TestSimpleMailer'],
-                         service.createMailer('TestSimpleMailer').__class__)
+    def testSMTPMailer(self):
+        from zope.app.interfaces.mail import ISMTPMailer
+        from zope.app.mail.metaconfigure import queryMailer
+        xmlconfig(StringIO(template % (
+            '''
+            <mail:smtpMailer id="smtp"
+               hostname="localhost"
+               port="25"
+               username="zope3"
+               password="xyzzy"
+               />
+            '''
+            )), None, Context([], zope.app.mail))
 
+        xmlconfig(StringIO(template % (
+            '''
+            <mail:smtpMailer id="smtp2"
+              hostname="smarthost"
+            />
+            '''
+            )), None, Context([], zope.app.mail))
+        self.assert_(ISMTPMailer.isImplementedBy(queryMailer("smtp")))
 
 def test_suite():
     return unittest.makeSuite(DirectivesTest)

=== Removed File Zope3/src/zope/app/mail/tests/test_asyncmailservice.py ===

=== Removed File Zope3/src/zope/app/mail/tests/test_batchmailer.py ===

=== Removed File Zope3/src/zope/app/mail/tests/test_mailevents.py ===

=== Removed File Zope3/src/zope/app/mail/tests/test_simplemailer.py ===