Changeset 32
- Timestamp:
- 10/16/07 03:51:19 (1 year ago)
- Location:
- branches/2.0.5
- Files:
-
- 6 modified
-
tests/basic_tests.py (modified) (1 diff)
-
tests/lib/smtp_mailsink.py (modified) (3 diffs)
-
tests/lib/utils.py (modified) (1 diff)
-
tests/test_message_as_string.py (modified) (2 diffs)
-
turbomail/dispatch.py (modified) (1 diff)
-
turbomail/message.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/2.0.5/tests/basic_tests.py
r31 r32 77 77 assert 'Hello World' in msg.get_payload() 78 78 79 def test_add_custom_headers_dict(self):80 "Test that custom headers (dict type) can be attached."81 extra_headers = {'Precendence': 'bulk', 'X-User': 'Alice'} 82 message = turbomail.Message('sender@foo.example', 83 'recipient@foo.example', 'foo bar') 84 message.plain = 'Hello World!'85 message.headers = extra_headers 86 turbomail.enqueue(message)87 msginfo = get_received_mail(self.sink) 88 msg = email.message_from_string(msginfo['mail']) 89 for header_name in extra_headers.keys(): 90 self.failUnless(msg.has_key(header_name))91 self.assertEquals(extra_headers[header_name], msg[header_name])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']) 92 92 93 def test_add_custom_headers_tuple(self):94 "Test that a custom header (tupletype) 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_headers100 turbomail.enqueue(message)101 msginfo = get_received_mail(self.sink)102 msg = email.message_from_string(msginfo['mail'])103 for name, value in extra_headers:104 self.failUnless(msg.has_key(name))105 self.assertEquals(value, msg[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]) 106 106 107 def test_add_custom_headers_list(self):108 "Test that a custom header (listtype) 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_headers114 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]) 120 120 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 -
branches/2.0.5/tests/lib/smtp_mailsink.py
r25 r32 18 18 # You should have received a copy of the GNU Lesser General Public 19 19 # License along with this library; if not, write to the Free Software 20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 21 22 22 … … 39 39 # sink.start() 40 40 # while not sink.has_message(): 41 # time.sleep(1)41 # time.sleep(1) 42 42 # print "received message: " + str(sink.get_messages()) 43 43 # sink.stop() … … 51 51 52 52 class SMTPMailsinkServer(smtpd.SMTPServer): 53 """This is the actual mailsink server which stores all received messages in54 an internal queue. Do not access the queue directly. All accessor methods55 in this object are sufficiently guarded against race conditions."""56 57 def __init__( self, *args, **kwargs):58 smtpd.SMTPServer.__init__( self, *args, **kwargs )59 self.queued_mails = []60 self.lock = threading.Lock()53 """This is the actual mailsink server which stores all received messages in 54 an internal queue. Do not access the queue directly. All accessor methods 55 in this object are sufficiently guarded against race conditions.""" 56 57 def __init__( self, *args, **kwargs): 58 smtpd.SMTPServer.__init__( self, *args, **kwargs ) 59 self.queued_mails = [] 60 self.lock = threading.Lock() 61 61 62 def has_message(self):63 """Return True if at least one message was received successfully. The64 access to the internal queue is synchronized so the caller will be65 blocked until the necessary lock was aquired."""66 self.lock.acquire()67 number_messages = len(self.queued_mails)68 self.lock.release()69 return number_messages > 062 def has_message(self): 63 """Return True if at least one message was received successfully. The 64 access to the internal queue is synchronized so the caller will be 65 blocked until the necessary lock was aquired.""" 66 self.lock.acquire() 67 number_messages = len(self.queued_mails) 68 self.lock.release() 69 return number_messages > 0 70 70 71 def get_messages(self):72 """Return a copy of the internal queue with all received messages. The73 access to the internal queue is synchronized so the caller will be74 blocked until the necessary lock was aquired."""75 self.lock.acquire()76 messages = copy.copy(self.queued_mails)77 self.lock.release()78 return messages71 def get_messages(self): 72 """Return a copy of the internal queue with all received messages. The 73 access to the internal queue is synchronized so the caller will be 74 blocked until the necessary lock was aquired.""" 75 self.lock.acquire() 76 messages = copy.copy(self.queued_mails) 77 self.lock.release() 78 return messages 79 79 80 def pop(self, index=None):81 """Return the index'th message in the queue (default=last) which is82 removed from the queue afterwards. Throws IndexError if index is bigger83 than the number of messages in the queue."""84 item = None85 self.lock.acquire()86 if index == None:87 index = len(self.queued_mails) - 188 try:89 item = self.queued_mails.pop(index)90 except Exception:91 print 'pop: before lock release'92 self.lock.release()93 raise94 self.lock.release()95 return item80 def pop(self, index=None): 81 """Return the index'th message in the queue (default=last) which is 82 removed from the queue afterwards. Throws IndexError if index is bigger 83 than the number of messages in the queue.""" 84 item = None 85 self.lock.acquire() 86 if index == None: 87 index = len(self.queued_mails) - 1 88 try: 89 item = self.queued_mails.pop(index) 90 except Exception: 91 print 'pop: before lock release' 92 self.lock.release() 93 raise 94 self.lock.release() 95 return item 96 96 97 97 98 def process_message(self, peer, mailfrom, rcpttos, data):99 "Store a received message in the internal queue. For internal use only!"100 msg = {'client': peer, 'from': mailfrom, 'recipients': rcpttos,101 'mail': data}102 self.lock.acquire()103 self.queued_mails.append(msg)104 self.lock.release()98 def process_message(self, peer, mailfrom, rcpttos, data): 99 "Store a received message in the internal queue. For internal use only!" 100 msg = {'client': peer, 'from': mailfrom, 'recipients': rcpttos, 101 'mail': data} 102 self.lock.acquire() 103 self.queued_mails.append(msg) 104 self.lock.release() 105 105 106 106 107 107 class SMTPMailsink(threading.Thread): 108 """This class is responsible for controlling the actual mailsink server109 class.""" 108 """This class is responsible for controlling the actual mailsink server 109 class.""" 110 110 111 def __init__(self, host='localhost', port=25):112 threading.Thread.__init__(self)113 self.stop_event = threading.Event()114 self.server = SMTPMailsinkServer((host, port), None)111 def __init__(self, host='localhost', port=25): 112 threading.Thread.__init__(self) 113 self.stop_event = threading.Event() 114 self.server = SMTPMailsinkServer((host, port), None) 115 115 116 def run(self):117 "Just run in a loop until stop() is called."118 while not self.stop_event.isSet():119 asyncore.loop(timeout=0.1)116 def run(self): 117 "Just run in a loop until stop() is called." 118 while not self.stop_event.isSet(): 119 asyncore.loop(timeout=0.1) 120 120 121 def stop(self, timeout_seconds=5.0):122 """Stop the mailsink and shut down this thread. timeout_seconds123 specifies how long the caller should wait for the mailsink server to124 close down (default: 5 seconds). If the server did not stop in time, a125 warning message is printed."""126 self.stop_event.set()127 self.server.close()128 threading.Thread.join(self, timeout=timeout_seconds)129 if self.isAlive():130 print "WARNING: Thread still alive. Timeout while waiting for " + \131 "termination!"132 133 def has_message(self):134 "Return True if at least one message was received successfully."135 return self.server.has_message()136 137 def get_messages(self):138 "Return a copy of the internal queue with all received messages."139 return self.server.get_messages()121 def stop(self, timeout_seconds=5.0): 122 """Stop the mailsink and shut down this thread. timeout_seconds 123 specifies how long the caller should wait for the mailsink server to 124 close down (default: 5 seconds). If the server did not stop in time, a 125 warning message is printed.""" 126 self.stop_event.set() 127 self.server.close() 128 threading.Thread.join(self, timeout=timeout_seconds) 129 if self.isAlive(): 130 print "WARNING: Thread still alive. Timeout while waiting for " + \ 131 "termination!" 132 133 def has_message(self): 134 "Return True if at least one message was received successfully." 135 return self.server.has_message() 136 137 def get_messages(self): 138 "Return a copy of the internal queue with all received messages." 139 return self.server.get_messages() 140 140 141 def pop(self, index=None):142 """Return the index'th message in the queue (default=last) which is143 removed from the queue afterwards. Throws IndexError if index is bigger144 than the number of messages in the queue."""145 return self.server.pop(index)141 def pop(self, index=None): 142 """Return the index'th message in the queue (default=last) which is 143 removed from the queue afterwards. Throws IndexError if index is bigger 144 than the number of messages in the queue.""" 145 return self.server.pop(index) -
branches/2.0.5/tests/lib/utils.py
r25 r32 29 29 30 30 class TimeoutException(Exception): 31 "A timeout occured!"32 pass31 "A timeout occured!" 32 pass 33 33 34 34 35 35 def get_received_mail(sink): 36 """Return the first mail received (which is removed from the TurboMail37 queue) in the following format {'client': ...., 'from': ...,38 'recipients': ..., 'mail': ...}. Blocks the caller until a message was39 received but no longer than 10 seconds (in this case, a TimeoutException40 is thrown)."""41 for i in range(10 * 10):42 if not sink.has_message():43 time.sleep(0.1)44 else:45 break46 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).""" 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) 49 49 50 50 51 51 def save_config(keys): 52 """Return a dictionary with the original configuration for the specified53 keys."""54 original_config = {}55 for key in keys:56 original_config[key] = turbogears.config.get(key)57 return original_config52 """Return a dictionary with the original configuration for the specified 53 keys.""" 54 original_config = {} 55 for key in keys: 56 original_config[key] = turbogears.config.get(key) 57 return original_config 58 58 59 59 -
branches/2.0.5/tests/test_message_as_string.py
r27 r32 38 38 39 39 class TestMessageAsString(unittest.TestCase): 40 "Test cases for sending emails as plain strings with TurboMail."40 "Test cases for sending emails as plain strings with TurboMail." 41 41 42 def setUp(self):43 server_port = 4204244 test_config = {'mail.on': True, 'mail.timeout': 1,45 'mail.server': 'localhost:%d' % server_port}46 self._original_config = save_config(test_config.keys())47 turbogears.config.update(test_config)48 49 self.sink = SMTPMailsink(host='localhost', port=server_port)50 self.sink.start()51 turbogears.startup.startTurboGears()42 def setUp(self): 43 server_port = 42042 44 test_config = {'mail.on': True, 'mail.timeout': 1, 45 'mail.server': 'localhost:%d' % server_port} 46 self._original_config = save_config(test_config.keys()) 47 turbogears.config.update(test_config) 48 49 self.sink = SMTPMailsink(host='localhost', port=server_port) 50 self.sink.start() 51 turbogears.startup.startTurboGears() 52 52 53 53 54 def tearDown(self):55 turbogears.startup.stopTurboGears()56 turbogears.config.update(self._original_config)57 self.sink.stop()54 def tearDown(self): 55 turbogears.startup.stopTurboGears() 56 turbogears.config.update(self._original_config) 57 self.sink.stop() 58 58 59 59 60 def test_message_string(self):61 """Test that a message can be submitted as string (not as62 turbomail.Message). This is important when existing (e.g. from a63 mailbox) or digitally signed messages should be sent through64 TurboMail."""65 msg_string = """From: bar@xams.example60 def test_message_string(self): 61 """Test that a message can be submitted as string (not as 62 turbomail.Message). This is important when existing (e.g. from a 63 mailbox) or digitally signed messages should be sent through 64 TurboMail.""" 65 msg_string = """From: bar@xams.example 66 66 To: foo@xams.example 67 67 Subject: foo bar … … 71 71 72 72 Hello World!""" 73 sender = 'sender@foobar.example'74 recipient = 'recipient@foo.example'75 msginfo = dict(sender=sender, recipients=[recipient], message=msg_string)76 turbomail.enqueue(msginfo)73 sender = 'sender@foobar.example' 74 recipient = 'recipient@foo.example' 75 msginfo = dict(sender=sender, recipients=[recipient], message=msg_string) 76 turbomail.enqueue(msginfo) 77 77 78 msginfo = get_received_mail(self.sink)79 self.assertEqual(sender, msginfo['from'])80 self.assertEqual([recipient], msginfo['recipients'])81 self.assertEqual(msg_string, msginfo['mail'])78 msginfo = get_received_mail(self.sink) 79 self.assertEqual(sender, msginfo['from']) 80 self.assertEqual([recipient], msginfo['recipients']) 81 self.assertEqual(msg_string, msginfo['mail']) 82 82 -
branches/2.0.5/turbomail/dispatch.py
r27 r32 148 148 packUpdate['smtpfrom'] = pack['sender'] 149 149 150 if 'smtpfrom' in pack :150 if 'smtpfrom' in pack and pack['smtpfrom'] != None: 151 151 if isinstance(pack['smtpfrom'], tuple): 152 152 packUpdate['smtpfrom'] = pack['smtpfrom'][1] -
branches/2.0.5/turbomail/message.py
r31 r32 354 354 return dict( 355 355 sender=self.sender, 356 smtpfrom = self.smtpfrom, 356 357 to=[[self.recipient], self.recipient][isinstance(self.recipient, list)], 357 358 recipients=[i[1] for i in recipients if isinstance(i, tuple)] + [i for i in recipients if not isinstance(i, tuple)],
