root / trunk / tests / test_message.py

Revision 133, 8.4 kB (checked in by fs, 2 weeks ago)

date property in Message class can now deal with datetime objects too (#96)

Line 
1#!/usr/bin/env python
2# encoding: utf-8
3"""Test the TurboMail Message class."""
4
5from datetime import datetime, timedelta
6import email
7from email.Header import decode_header, Header
8try:
9    from email.mime.text import MIMEText
10except ImportError:
11    # Python < 2.5 has no email.mime module
12    from email.MIMEText import MIMEText
13from email.Utils import formatdate, parsedate
14
15import logging
16import re
17import time
18import unittest
19
20
21from turbomail.message import Message
22
23logging.disable(logging.WARNING)
24
25
26class TestBasicMessage(unittest.TestCase):
27    """Test the basic output of the Message class."""
28   
29    def setUp(self):
30        self.message = Message(
31                author=("Author", "author@example.com"),
32                to=("Recipient", "recipient@example.com"),
33                subject="Test message subject.",
34                plain="This is a test message plain text body."
35            )
36   
37    def test_message_properties(self):
38        self.assertEqual(self.message.author, [("Author", "author@example.com")])
39        self.assertEqual(str(self.message.author), "Author <author@example.com>")
40        self.failUnless(isinstance(self.message.mime, MIMEText))
41   
42    def test_message_string_with_basic(self):
43        message_string = str(self.message)
44        msg = email.message_from_string(message_string)
45        self.assertEqual('Author <author@example.com>', msg['From'])
46        self.assertEqual('Recipient <recipient@example.com>', msg['To'])
47        self.assertEqual('Test message subject.', msg['Subject'])
48        self.assertEqual('This is a test message plain text body.', msg.get_payload())
49   
50    def test_message_recipients_and_addresses(self):
51        self.message.cc = 'cc@example.com'
52        self.message.bcc = 'bcc@example.com'
53        self.message.sender = 'sender@example.com'
54        self.message.reply_to = 'replyto@example.com'
55        self.message.disposition = 'disposition@example.com'
56       
57        message_string = str(self.message)
58        msg = email.message_from_string(message_string)
59       
60        self.assertEqual('cc@example.com', msg['cc'])
61        # BCC must not be encoded in the message itself, it is only sent in the
62        # smtp envelope
63        self.assertEqual(None, msg['bcc'])
64        self.assertEqual('sender@example.com', msg['sender'])
65        self.assertEqual('replyto@example.com', msg['reply-to'])
66        self.assertEqual('disposition@example.com', msg['disposition-notification-to'])
67   
68    def test_mime_generation(self):
69        mime = self.message.mime
70        self.failUnless(self.message.mime is mime)
71        self.message.subject = "Test message subject."
72        self.failIf(self.message.mime is mime)
73   
74    def test_recipients_collection(self):
75        self.message.cc.append("copied@example.com")
76        self.assertEqual(["recipient@example.com", "copied@example.com"],
77                         self.message.recipients.addresses)
78   
79    def test_smtp_from_as_envelope(self):
80        self.message.smtp_from = 'devnull@example.com'
81        self.assertEqual('devnull@example.com', str(self.message.envelope_sender))
82   
83    def test_subject_with_umlaut(self):
84        subject_string = u"Test with ÀöÌ"
85        self.message.subject = subject_string
86        self.message.encoding = "UTF-8"
87       
88        msg = email.message_from_string(str(self.message))
89        encoded_subject = str(Header(subject_string, "UTF-8"))
90        self.assertEqual(encoded_subject, msg['Subject'])
91   
92    def test_from_with_umlaut(self):
93        from_name = u"Karl MÃŒller"
94        from_email = u"karl.mueller@example.com"
95       
96        self.message.author = [(from_name, from_email)]
97        self.message.encoding = "ISO-8859-1"
98       
99        msg = email.message_from_string(str(self.message))
100        encoded_name = "%s <%s>" % (str(Header(from_name, "ISO-8859-1")), from_email)
101        self.assertEqual(encoded_name, msg['From'])
102   
103    def test_multiple_authors(self):
104        """For better readability, provide a property 'authors' (alias for
105        author)."""
106        self.message.authors = 'foo@example.com'
107        self.assertEqual(self.message.authors, self.message.author)
108       
109        self.message.authors = ['bar@example.com', 'baz@example.com']
110        self.message.sender = 'foo@example.com'
111        msg = email.message_from_string(str(self.message))
112        from_addresses = re.split(r",\n?\s+", msg['From'])
113        self.assertEqual(['bar@example.com', 'baz@example.com'], from_addresses)
114   
115    def test_multiple_authors_require_sender(self):
116        self.message.authors = ['bar@example.com', 'baz@example.com']
117        self.assertRaises(ValueError, str, self.message)
118       
119        self.message.sender = 'bar@example.com'
120        str(self.message)
121   
122    def test_permit_one_sender_at_most(self):
123        self.message.sender = ['bar@example.com', 'baz@example.com']
124        self.assertRaises(ValueError, str, self.message)
125       
126        self.message.sender = 'bar@example.com'
127        str(self.message)
128   
129    def test_raise_error_for_unknown_kwargs_at_class_instantiation(self):
130        self.assertRaises(TypeError, Message, invalid_argument=True)
131
132    def test_add_custom_headers_dict(self):
133        "Test that custom headers (dict type) can be attached."
134        self.message.headers = {'Precedence': 'bulk', 'X-User': 'Alice'}
135        msg = email.message_from_string(str(self.message))
136        self.assertEqual('bulk', msg['Precedence'])
137        self.assertEqual('Alice', msg['X-User'])
138
139    def test_add_custom_headers_tuple(self):
140        "Test that a custom header (tuple type) can be attached."
141        self.message.headers = (('Precedence', 'bulk'), ('X-User', 'Alice'))
142       
143        msg = email.message_from_string(str(self.message))
144        self.assertEqual('bulk', msg['Precedence'])
145        self.assertEqual('Alice', msg['X-User'])
146
147    def test_add_custom_headers_list(self):
148        "Test that a custom header (list type) can be attached."
149        self.message.headers = [('Precedence', 'bulk'), ('X-User', 'Alice')]
150       
151        msg = email.message_from_string(str(self.message))
152        self.assertEqual('bulk', msg['Precedence'])
153        self.assertEqual('Alice', msg['X-User'])
154   
155    def test_no_sender_header_if_no_sender_required(self):
156        msg = email.message_from_string(str(self.message))
157        self.assertEqual(None, msg['Sender'])
158   
159    def _date_header_to_datetime(self, date_string):
160        """Converts a date_string from the Date header into a naive datetime
161        object."""
162        assert date_string != None
163        epoch_seconds = time.mktime(parsedate(date_string))
164        datetime_obj = datetime.fromtimestamp(epoch_seconds)
165        return datetime_obj
166   
167    def _almost_now(self, date_string):
168        """Returns True if the date_string represents a time which is 'almost
169        now'."""
170        delta = abs(datetime.now() - self._date_header_to_datetime(date_string))
171        return (delta < timedelta(seconds=1))
172   
173    def test_date_header_added_even_if_date_not_set_explicitely(self):
174        msg = email.message_from_string(str(self.message))
175        self.assertTrue(self._almost_now(msg['Date']))
176   
177    def test_date_can_be_set_as_string(self):
178        date_string = 'Fri, 26 Dec 2008 11:19:42 +0530'
179        self.message.date = date_string
180        msg = email.message_from_string(str(self.message))
181        self.assertEqual(date_string, msg['Date'])
182   
183    def test_date_can_be_set_as_float(self):
184        expected_date = datetime(2008, 12, 26, 12, 55)
185        expected_time = time.mktime(expected_date.timetuple())
186        self.message.date = expected_time
187        msg = email.message_from_string(str(self.message))
188        header_string = msg['Date']
189        header_date = self._date_header_to_datetime(header_string)
190        self.assertEqual(expected_date, header_date)
191        expected_datestring = formatdate(expected_time, localtime=True)
192        self.assertEqual(expected_datestring, header_string)
193   
194    def test_date_can_be_set_as_datetime(self):
195        expected_date = datetime(2008, 12, 26, 12, 55)
196        self.message.date = expected_date
197        msg = email.message_from_string(str(self.message))
198        header_date = self._date_header_to_datetime(msg['Date'])
199        self.assertEqual(expected_date, header_date)
200   
201    def test_date_header_is_set_even_if_reset_to_none(self):
202        self.message.date = None
203        msg = email.message_from_string(str(self.message))
204        self.assertTrue(self._almost_now(msg['Date']))
205
Note: See TracBrowser for help on using the browser.