Changeset 67

Show
Ignore:
Timestamp:
11/07/07 09:23:09 (1 year ago)
Author:
alberto
Message:

Applied reindent.py an all .py files to switch from tabs to 4 spaces. Closes #66

Location:
trunk
Files:
13 modified

Legend:

Unmodified
Added
Removed
  • trunk/setup.py

    r16 r67  
    1313 
    1414setup( 
    15                 name="TurboMail", 
    16                 version=version, 
    17          
    18                 description=description, 
    19                 long_description=long_description, 
    20                 author=author, 
    21                 author_email=email, 
    22                 url=url, 
    23                 download_url=download_url, 
    24                 license=license, 
    25          
    26                 install_requires = ["TurboGears >= 0.9a9dev-r2003"], 
    27                 zip_safe=True, 
    28                 packages=find_packages(), 
    29                 package_data = find_package_data(where='turbomail', package='turbomail'), 
    30                 keywords = ["turbogears.extension"], 
    31                 classifiers = [ 
    32                         'Development Status :: 5 - Production/Stable', 
    33                         'Framework :: TurboGears', 
    34                         'Intended Audience :: Developers', 
    35                         'License :: OSI Approved :: MIT License', 
    36                         'Operating System :: OS Independent', 
    37                         'Programming Language :: Python', 
    38                         'Topic :: Communications :: Email', 
    39                         'Topic :: Software Development :: Libraries :: Python Modules', 
    40                 ], 
    41                 test_suite = 'nose.collector', 
    42                 entry_points = { 
    43 #                               'paste.paster_create_template': ["turbomail = turbomail.startup:MailTemplate"] 
    44                                 'turbogears.extensions': ["turbomail = turbomail"] 
    45                         } 
    46         ) 
    47          
     15                name="TurboMail", 
     16                version=version, 
     17 
     18                description=description, 
     19                long_description=long_description, 
     20                author=author, 
     21                author_email=email, 
     22                url=url, 
     23                download_url=download_url, 
     24                license=license, 
     25 
     26                install_requires = ["TurboGears >= 0.9a9dev-r2003"], 
     27                zip_safe=True, 
     28                packages=find_packages(), 
     29                package_data = find_package_data(where='turbomail', package='turbomail'), 
     30                keywords = ["turbogears.extension"], 
     31                classifiers = [ 
     32                        'Development Status :: 5 - Production/Stable', 
     33                        'Framework :: TurboGears', 
     34                        'Intended Audience :: Developers', 
     35                        'License :: OSI Approved :: MIT License', 
     36                        'Operating System :: OS Independent', 
     37                        'Programming Language :: Python', 
     38                        'Topic :: Communications :: Email', 
     39                        'Topic :: Software Development :: Libraries :: Python Modules', 
     40                ], 
     41                test_suite = 'nose.collector', 
     42                entry_points = { 
     43#                               'paste.paster_create_template': ["turbomail = turbomail.startup:MailTemplate"] 
     44                                'turbogears.extensions': ["turbomail = turbomail"] 
     45                        } 
     46        ) 
  • trunk/tests/basic_tests.py

    r47 r67  
    66# This code is placed under the MIT license: 
    77# 
    8 # Permission is hereby granted, free of charge, to any person obtaining a copy  
    9 # of this software and associated documentation files (the "Software"), to deal  
    10 # in the Software without restriction, including without limitation the rights  
    11 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
    12 # copies of the Software, and to permit persons to whom the Software is  
     8# Permission is hereby granted, free of charge, to any person obtaining a copy 
     9# of this software and associated documentation files (the "Software"), to deal 
     10# in the Software without restriction, including without limitation the rights 
     11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
     12# copies of the Software, and to permit persons to whom the Software is 
    1313# furnished to do so, subject to the following conditions: 
    1414# 
    15 # The above copyright notice and this permission notice shall be included in  
     15# The above copyright notice and this permission notice shall be included in 
    1616# all copies or substantial portions of the Software. 
    1717# 
    18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
    19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
    20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
    21 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
    22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
    23 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
     18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
     19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
     20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
     21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
     22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
     23# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    2424# SOFTWARE. 
    2525 
     
    3838 
    3939class TestBasicTests(unittest.TestCase): 
    40         "Basic test cases for TurboMail." 
     40    "Basic test cases for TurboMail." 
    4141 
    42         def setUp(self): 
    43                 server_port = 42042 
    44                  
    45                 test_config = {'mail.on': True, 'mail.timeout': 1, 
    46                                            'mail.server': 'localhost:%d' % server_port} 
    47                 self._original_config = save_config(test_config.keys()) 
    48                 turbogears.config.update(test_config) 
    49                  
    50                 self.sink = SMTPMailsink(host='localhost', port=server_port) 
    51                 self.sink.start() 
    52                  
    53                 turbomail.start_extension() 
     42    def setUp(self): 
     43        server_port = 42042 
     44 
     45        test_config = {'mail.on': True, 'mail.timeout': 1, 
     46                                   'mail.server': 'localhost:%d' % server_port} 
     47        self._original_config = save_config(test_config.keys()) 
     48        turbogears.config.update(test_config) 
     49 
     50        self.sink = SMTPMailsink(host='localhost', port=server_port) 
     51        self.sink.start() 
     52 
     53        turbomail.start_extension() 
    5454 
    5555 
    56         def tearDown(self): 
    57                 turbomail.shutdown_extension() 
    58                 turbogears.config.update(self._original_config) 
    59                 self.sink.stop() 
     56    def tearDown(self): 
     57        turbomail.shutdown_extension() 
     58        turbogears.config.update(self._original_config) 
     59        self.sink.stop() 
    6060 
    6161 
    62         def test_simple(self): 
    63                 "Test that sending a simple mail with turbomail.Message works." 
    64                 sender = 'sender@foo.example' 
    65                 recipient = 'recipient@foo.example' 
    66                 subject = 'foo bar' 
    67                 message = turbomail.Message(sender, recipient, subject) 
    68                 message.plain = 'Hello World!'             
    69                 turbomail.enqueue(message) 
     62    def test_simple(self): 
     63        "Test that sending a simple mail with turbomail.Message works." 
     64        sender = 'sender@foo.example' 
     65        recipient = 'recipient@foo.example' 
     66        subject = 'foo bar' 
     67        message = turbomail.Message(sender, recipient, subject) 
     68        message.plain = 'Hello World!' 
     69        turbomail.enqueue(message) 
    7070 
    71                 msginfo = get_received_mail(self.sink) 
    72                 self.assertEqual(sender, msginfo['from']) 
    73                 self.assertEqual([recipient], msginfo['recipients']) 
    74                 msg = email.message_from_string(msginfo['mail'])  
    75                 self.failIf(msg.has_key('Old-Return-Path')) 
    76                 self.failIf(msg.has_key('Return-Path')) 
    77                 assert 'Hello World' in msg.get_payload()  
     71        msginfo = get_received_mail(self.sink) 
     72        self.assertEqual(sender, msginfo['from']) 
     73        self.assertEqual([recipient], msginfo['recipients']) 
     74        msg = email.message_from_string(msginfo['mail']) 
     75        self.failIf(msg.has_key('Old-Return-Path')) 
     76        self.failIf(msg.has_key('Return-Path')) 
     77        assert 'Hello World' in msg.get_payload() 
    7878 
    79         def test_smtpfrom(self): 
    80                 "Test that smtpfrom is being honored and used as envelope sender." 
    81                 sender = 'sender@foo.example' 
    82                 recipient = 'recipient@foo.example' 
    83                 subject = 'foo bar' 
    84                 smtpfrom = 'devnull@foo.example' 
    85                 message = turbomail.Message(sender, recipient, subject,  
    86                                                                         smtpfrom=smtpfrom) 
    87                 message.plain = 'Hello World!'             
    88                 turbomail.enqueue(message) 
    89                 msginfo = get_received_mail(self.sink) 
    90                 self.assertEqual(smtpfrom, msginfo['from']) 
    91                 self.assertEqual([recipient], msginfo['recipients']) 
     79    def test_smtpfrom(self): 
     80        "Test that smtpfrom is being honored and used as envelope sender." 
     81        sender = 'sender@foo.example' 
     82        recipient = 'recipient@foo.example' 
     83        subject = 'foo bar' 
     84        smtpfrom = 'devnull@foo.example' 
     85        message = turbomail.Message(sender, recipient, subject, 
     86                                                                smtpfrom=smtpfrom) 
     87        message.plain = 'Hello World!' 
     88        turbomail.enqueue(message) 
     89        msginfo = get_received_mail(self.sink) 
     90        self.assertEqual(smtpfrom, msginfo['from']) 
     91        self.assertEqual([recipient], msginfo['recipients']) 
    9292 
    93         def test_add_custom_headers_dict(self): 
    94                 "Test that custom headers (dict type) can be attached." 
    95                 extra_headers = {'Precendence': 'bulk', 'X-User': 'Alice'} 
    96                 message = turbomail.Message('sender@foo.example',  
    97                                                                         'recipient@foo.example', 'foo bar') 
    98                 message.plain = 'Hello World!' 
    99                 message.headers = extra_headers 
    100                 turbomail.enqueue(message) 
    101                 msginfo = get_received_mail(self.sink) 
    102                 msg = email.message_from_string(msginfo['mail'])  
    103                 for header_name in extra_headers.keys(): 
    104                         self.failUnless(msg.has_key(header_name)) 
    105                         self.assertEquals(extra_headers[header_name], msg[header_name]) 
     93    def test_add_custom_headers_dict(self): 
     94        "Test that custom headers (dict type) can be attached." 
     95        extra_headers = {'Precendence': 'bulk', 'X-User': 'Alice'} 
     96        message = turbomail.Message('sender@foo.example', 
     97                                                                'recipient@foo.example', 'foo bar') 
     98        message.plain = 'Hello World!' 
     99        message.headers = extra_headers 
     100        turbomail.enqueue(message) 
     101        msginfo = get_received_mail(self.sink) 
     102        msg = email.message_from_string(msginfo['mail']) 
     103        for header_name in extra_headers.keys(): 
     104            self.failUnless(msg.has_key(header_name)) 
     105            self.assertEquals(extra_headers[header_name], msg[header_name]) 
    106106 
    107         def test_add_custom_headers_tuple(self): 
    108                 "Test that a custom header (tuple type) can be attached." 
    109                 extra_headers = (('Precendence', 'bulk'), ('X-User', 'Alice')) 
    110                 message = turbomail.Message('sender@foo.example',  
    111                                                                         'recipient@foo.example', 'foo bar') 
    112                 message.plain = 'Hello World!' 
    113                 message.headers = extra_headers 
    114                 turbomail.enqueue(message) 
    115                 msginfo = get_received_mail(self.sink) 
    116                 msg = email.message_from_string(msginfo['mail'])  
    117                 for name, value in extra_headers: 
    118                         self.failUnless(msg.has_key(name)) 
    119                         self.assertEquals(value, msg[name]) 
     107    def test_add_custom_headers_tuple(self): 
     108        "Test that a custom header (tuple type) can be attached." 
     109        extra_headers = (('Precendence', 'bulk'), ('X-User', 'Alice')) 
     110        message = turbomail.Message('sender@foo.example', 
     111                                                                'recipient@foo.example', 'foo bar') 
     112        message.plain = 'Hello World!' 
     113        message.headers = extra_headers 
     114        turbomail.enqueue(message) 
     115        msginfo = get_received_mail(self.sink) 
     116        msg = email.message_from_string(msginfo['mail']) 
     117        for name, value in extra_headers: 
     118            self.failUnless(msg.has_key(name)) 
     119            self.assertEquals(value, msg[name]) 
    120120 
    121         def test_add_custom_headers_list(self): 
    122                 "Test that a custom header (list type) can be attached." 
    123                 extra_headers = [('Precendence', 'bulk'), ('X-User', 'Alice')] 
    124                 message = turbomail.Message('sender@foo.example',  
    125                                                                         'recipient@foo.example', 'foo bar') 
    126                 message.plain = 'Hello World!' 
    127                 message.headers = extra_headers 
    128                 turbomail.enqueue(message) 
    129                 msginfo = get_received_mail(self.sink) 
    130                 msg = email.message_from_string(msginfo['mail'])  
    131                 for name, value in extra_headers: 
    132                         self.failUnless(msg.has_key(name)) 
    133                         self.assertEquals(value, msg[name]) 
    134  
     121    def test_add_custom_headers_list(self): 
     122        "Test that a custom header (list type) can be attached." 
     123        extra_headers = [('Precendence', 'bulk'), ('X-User', 'Alice')] 
     124        message = turbomail.Message('sender@foo.example', 
     125                                                                'recipient@foo.example', 'foo bar') 
     126        message.plain = 'Hello World!' 
     127        message.headers = extra_headers 
     128        turbomail.enqueue(message) 
     129        msginfo = get_received_mail(self.sink) 
     130        msg = email.message_from_string(msginfo['mail']) 
     131        for name, value in extra_headers: 
     132            self.failUnless(msg.has_key(name)) 
     133            self.assertEquals(value, msg[name]) 
  • trunk/tests/lib/smtp_mailsink.py

    r53 r67  
    11# -*- coding: UTF-8 -*- 
    2 """A library which implements a SMTP mail sink (dummy SMTP server) in order  
     2"""A library which implements a SMTP mail sink (dummy SMTP server) in order 
    33to test correct sending of emails.""" 
    44 
     
    1717# You should have received a copy of the GNU Lesser General Public 
    1818# License along with this library; if not, write to the Free Software 
    19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301      USA  
     19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301      USA 
    2020 
    2121 
    22 # This coded is based on code published on  
    23 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440690/ but was  
     22# This coded is based on code published on 
     23# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440690/ but was 
    2424# heavily modified for easier usage and Python 2.3 compatibility. 
    2525# 
     
    2727# Written by Adam Feuer, Matt Branthwaite, and Troy Frever 
    2828# Published under the Python License (http://www.python.org/license). 
    29   
     29 
    3030# Example usage: 
    31 #  
     31# 
    3232# #!/usr/bin/env python 
    3333# # -*- coding: UTF-8 -*- 
    3434# "Wait until a single message was received on localhost/port 10026" 
    35 #  
     35# 
    3636# from smtp_mailsink import SMTPMailsink 
    3737# sink = SMTPMailsink(host='localhost', port=10026) 
    3838# sink.start() 
    3939# while not sink.has_message(): 
    40 #         time.sleep(1) 
     40#         time.sleep(1) 
    4141# print "received message: " + str(sink.get_messages()) 
    4242# sink.stop() 
     
    5252 
    5353class SMTPMailsinkServer(smtpd.SMTPServer): 
    54         """This is the actual mailsink server which stores all received messages in 
    55         an internal queue. Do not access the queue directly. All accessor methods 
    56         in this object are sufficiently guarded against race conditions.""" 
    57          
    58         def __init__( self, *args, **kwargs): 
    59                 smtpd.SMTPServer.__init__( self, *args, **kwargs ) 
    60                 self.queued_mails = [] 
    61                 self.lock = threading.Lock() 
     54    """This is the actual mailsink server which stores all received messages in 
     55    an internal queue. Do not access the queue directly. All accessor methods 
     56    in this object are sufficiently guarded against race conditions.""" 
    6257 
    63         def has_message(self): 
    64                 """Return True if at least one message was received successfully. The  
    65                 access to the internal queue is synchronized so the caller will be  
    66                 blocked until the necessary lock was aquired.""" 
    67                 self.lock.acquire() 
    68                 number_messages = len(self.queued_mails) 
    69                 self.lock.release() 
    70                 return number_messages > 0 
     58    def __init__( self, *args, **kwargs): 
     59        smtpd.SMTPServer.__init__( self, *args, **kwargs ) 
     60        self.queued_mails = [] 
     61        self.lock = threading.Lock() 
    7162 
    72         def get_messages(self): 
    73                 """Return a copy of the internal queue with all received messages. The  
    74                 access to the internal queue is synchronized so the caller will be  
    75                 blocked until the necessary lock was aquired.""" 
    76                 self.lock.acquire() 
    77                 messages = copy.copy(self.queued_mails) 
    78                 self.lock.release() 
    79                 return messages 
     63    def has_message(self): 
     64        """Return True if at least one message was received successfully. The 
     65        access to the internal queue is synchronized so the caller will be 
     66        blocked until the necessary lock was aquired.""" 
     67        self.lock.acquire() 
     68        number_messages = len(self.queued_mails) 
     69        self.lock.release() 
     70        return number_messages > 0 
    8071 
    81         def pop(self, index=None): 
    82                 """Return the index'th message in the queue (default=last) which is 
    83                 removed from the queue afterwards. Throws IndexError if index is bigger  
    84                 than the number of messages in the queue.""" 
    85                 item = None 
    86                 self.lock.acquire() 
    87                 if index == None: 
    88                         index = len(self.queued_mails) - 1 
    89                 try: 
    90                         item = self.queued_mails.pop(index) 
    91                 except Exception: 
    92                         print 'pop: before lock release' 
    93                         self.lock.release() 
    94                         raise 
    95                 self.lock.release() 
    96                 return item 
     72    def get_messages(self): 
     73        """Return a copy of the internal queue with all received messages. The 
     74        access to the internal queue is synchronized so the caller will be 
     75        blocked until the necessary lock was aquired.""" 
     76        self.lock.acquire() 
     77        messages = copy.copy(self.queued_mails) 
     78        self.lock.release() 
     79        return messages 
     80 
     81    def pop(self, index=None): 
     82        """Return the index'th message in the queue (default=last) which is 
     83        removed from the queue afterwards. Throws IndexError if index is bigger 
     84        than the number of messages in the queue.""" 
     85        item = None 
     86        self.lock.acquire() 
     87        if index == None: 
     88            index = len(self.queued_mails) - 1 
     89        try: 
     90            item = self.queued_mails.pop(index) 
     91        except Exception: 
     92            print 'pop: before lock release' 
     93            self.lock.release() 
     94            raise 
     95        self.lock.release() 
     96        return item 
    9797 
    9898 
    99         def process_message(self, peer, mailfrom, rcpttos, data): 
    100                 "Store a received message in the internal queue. For internal use only!" 
    101                 msg = {'client': peer, 'from': mailfrom, 'recipients': rcpttos,  
    102                            'mail': data} 
    103                 self.lock.acquire() 
    104                 self.queued_mails.append(msg) 
    105                 self.lock.release() 
     99    def process_message(self, peer, mailfrom, rcpttos, data): 
     100        "Store a received message in the internal queue. For internal use only!" 
     101        msg = {'client': peer, 'from': mailfrom, 'recipients': rcpttos, 
     102                   'mail': data} 
     103        self.lock.acquire() 
     104        self.queued_mails.append(msg) 
     105        self.lock.release() 
    106106 
    107107 
    108108class SMTPMailsink(threading.Thread): 
    109         """This class is responsible for controlling the actual mailsink server  
    110         class."""        
     109    """This class is responsible for controlling the actual mailsink server 
     110    class.""" 
    111111 
    112         def __init__(self, host='localhost', port=25): 
    113                 threading.Thread.__init__(self) 
    114                 self.stop_event = threading.Event() 
    115                 self.server = SMTPMailsinkServer((host, port), None) 
     112    def __init__(self, host='localhost', port=25): 
     113        threading.Thread.__init__(self) 
     114        self.stop_event = threading.Event() 
     115        self.server = SMTPMailsinkServer((host, port), None) 
    116116 
    117         def run(self): 
    118                 "Just run in a loop until stop() is called." 
    119                 while not self.stop_event.isSet(): 
    120                         try: 
    121                                 asyncore.loop(timeout=0.1) 
    122                         except select.error, e: 
    123                                 if e.args[0] != errno.EBADF: 
    124                                         raise 
     117    def run(self): 
     118        "Just run in a loop until stop() is called." 
     119        while not self.stop_event.isSet(): 
     120            try: 
     121                asyncore.loop(timeout=0.1) 
     122            except select.error, e: 
     123                if e.args[0] != errno.EBADF: 
     124                    raise 
    125125 
    126         def stop(self, timeout_seconds=5.0): 
    127                 """Stop the mailsink and shut down this thread. timeout_seconds  
    128                 specifies how long the caller should wait for the mailsink server to  
    129                 close down (default: 5 seconds). If the server did not stop in time, a 
    130                 warning message is printed.""" 
    131                 self.stop_event.set() 
    132                 self.server.close() 
    133                 threading.Thread.join(self, timeout=timeout_seconds) 
    134                 if self.isAlive(): 
    135                         print "WARNING: Thread still alive. Timeout while waiting for " + \ 
    136                                   "termination!" 
    137                  
    138         def has_message(self): 
    139                 "Return True if at least one message was received successfully." 
    140                 return self.server.has_message() 
    141                  
    142         def get_messages(self): 
    143                 "Return a copy of the internal queue with all received messages." 
    144                 return self.server.get_messages() 
     126    def stop(self, timeout_seconds=5.0): 
     127        """Stop the mailsink and shut down this thread. timeout_seconds 
     128        specifies how long the caller should wait for the mailsink server to 
     129        close down (default: 5 seconds). If the server did not stop in time, a 
     130        warning message is printed.""" 
     131        self.stop_event.set() 
     132        self.server.close() 
     133        threading.Thread.join(self, timeout=timeout_seconds) 
     134        if self.isAlive(): 
     135            print "WARNING: Thread still alive. Timeout while waiting for " + \ 
     136                      "termination!" 
    145137 
    146         def pop(self, index=None): 
    147                 """Return the index'th message in the queue (default=last) which is 
    148                 removed from the queue afterwards. Throws IndexError if index is bigger  
    149                 than the number of messages in the queue.""" 
    150                 return self.server.pop(index) 
     138    def has_message(self): 
     139        "Return True if at least one message was received successfully." 
     140        return self.server.has_message() 
     141 
     142    def get_messages(self): 
     143        "Return a copy of the internal queue with all received messages." 
     144        return self.server.get_messages() 
     145 
     146    def pop(self, index=None): 
     147        """Return the index'th message in the queue (default=last) which is 
     148        removed from the queue afterwards. Throws IndexError if index is bigger 
     149        than the number of messages in the queue.""" 
     150        return self.server.pop(index) 
  • trunk/tests/lib/utils.py

    r47 r67  
    55# This code is placed under the MIT license: 
    66# 
    7 # Permission is hereby granted, free of charge, to any person obtaining a copy  
    8 # of this software and associated documentation files (the "Software"), to deal  
    9 # in the Software without restriction, including without limitation the rights  
    10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
    11 # copies of the Software, and to permit persons to whom the Software is  
     7# Permission is hereby granted, free of charge, to any person obtaining a copy 
     8# of this software and associated documentation files (the "Software"), to deal 
     9# in the Software without restriction, including without limitation the rights 
     10# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
     11# copies of the Software, and to permit persons to whom the Software is 
    1212# furnished to do so, subject to the following conditions: 
    1313# 
    14 # The above copyright notice and this permission notice shall be included in  
     14# The above copyright notice and this permission notice shall be included in 
    1515# all copies or substantial portions of the Software. 
    1616# 
    17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
    18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
    19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
    20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
    21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
    22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
     17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
     18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
     19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
     20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
     21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
     22# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    2323# SOFTWARE. 
    2424 
     
    2929 
    3030class TimeoutException(Exception): 
    31         "A timeout occured!" 
    32         pass 
     31    "A timeout occured!" 
     32    pass 
    3333 
    3434 
    3535def get_received_mail(sink): 
    36         """Return the first mail received (which is removed from the TurboMail 
    37         queue) in the following format {'client': ...., 'from': ...,  
    38         'recipients': ..., 'mail': ...}. Blocks the caller until a message was  
    39         received but no longer than 10 seconds (in this case, a TimeoutException 
    40         is thrown).""" 
    41         for i in range(10 * 10): 
    42                 if not sink.has_message(): 
    43                         time.sleep(0.1) 
    44                 else: 
    45                         break 
    46         if not sink.has_message(): 
    47                 raise TimeoutException() 
    48         return sink.pop(index=0) 
     36    """Return the first mail received (which is removed from the TurboMail 
     37    queue) in the following format {'client': ...., 'from': ..., 
     38    'recipients': ..., 'mail': ...}. Blocks the caller until a message was 
     39    received but no longer than 10 seconds (in this case, a TimeoutException 
     40    is thrown)."""