~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_email_message.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-28 06:58:22 UTC
  • mfrom: (2379.2.3 hpss-chroot)
  • Revision ID: pqm@pqm.ubuntu.com-20070328065822-999550a858a3ced3
(robertc) Fix chroot urls to not expose the url of the transport they are protecting, allowing regular url operations to work on them. (Robert Collins, Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2009, 2011, 2014, 2016 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
import sys
18
 
from email.Header import decode_header
19
 
 
20
 
from bzrlib import __version__ as _bzrlib_version
21
 
from bzrlib.email_message import EmailMessage
22
 
from bzrlib.errors import BzrBadParameterNotUnicode
23
 
from bzrlib.smtp_connection import SMTPConnection
24
 
from bzrlib import tests
25
 
 
26
 
EMPTY_MESSAGE = '''\
27
 
From: from@from.com
28
 
Subject: subject
29
 
To: to@to.com
30
 
User-Agent: Bazaar (%s)
31
 
 
32
 
''' % _bzrlib_version
33
 
 
34
 
_SIMPLE_MESSAGE = '''\
35
 
MIME-Version: 1.0
36
 
Content-Type: text/plain; charset="%%s"
37
 
Content-Transfer-Encoding: %%s
38
 
From: from@from.com
39
 
Subject: subject
40
 
To: to@to.com
41
 
User-Agent: Bazaar (%s)
42
 
 
43
 
%%s''' % _bzrlib_version
44
 
 
45
 
SIMPLE_MESSAGE_ASCII = _SIMPLE_MESSAGE % ('us-ascii', '7bit', 'body')
46
 
SIMPLE_MESSAGE_UTF8 = _SIMPLE_MESSAGE % ('utf-8', 'base64', 'YsOzZHk=\n')
47
 
SIMPLE_MESSAGE_8BIT = _SIMPLE_MESSAGE % ('8-bit', 'base64', 'YvRkeQ==\n')
48
 
 
49
 
 
50
 
BOUNDARY = '=====123456=='
51
 
 
52
 
_MULTIPART_HEAD = '''\
53
 
Content-Type: multipart/mixed; boundary="%(boundary)s"
54
 
MIME-Version: 1.0
55
 
From: from@from.com
56
 
Subject: subject
57
 
To: to@to.com
58
 
User-Agent: Bazaar (%(version)s)
59
 
 
60
 
--%(boundary)s
61
 
MIME-Version: 1.0
62
 
Content-Type: text/plain; charset="us-ascii"
63
 
Content-Transfer-Encoding: 7bit
64
 
Content-Disposition: inline
65
 
 
66
 
body
67
 
''' %  { 'version': _bzrlib_version, 'boundary': BOUNDARY }
68
 
 
69
 
 
70
 
def final_newline_or_not(msg):
71
 
    if sys.version_info >= (2, 7, 6):
72
 
        # Some internals of python's email module changed in an (minor)
73
 
        # incompatible way: a final newline is appended in 2.7.6...
74
 
       msg += '\n'
75
 
    return msg
76
 
 
77
 
 
78
 
def simple_multipart_message():
79
 
    msg = _MULTIPART_HEAD + '--%s--' % BOUNDARY
80
 
    return final_newline_or_not(msg)
81
 
 
82
 
 
83
 
def complex_multipart_message(typ):
84
 
    msg = _MULTIPART_HEAD + '''\
85
 
--%(boundary)s
86
 
MIME-Version: 1.0
87
 
Content-Type: text/%%s; charset="us-ascii"; name="lines.txt"
88
 
Content-Transfer-Encoding: 7bit
89
 
Content-Disposition: inline
90
 
 
91
 
a
92
 
b
93
 
c
94
 
d
95
 
e
96
 
 
97
 
--%(boundary)s--''' %  { 'boundary': BOUNDARY }
98
 
    msg = final_newline_or_not(msg)
99
 
    return msg % (typ,)
100
 
 
101
 
 
102
 
class TestEmailMessage(tests.TestCase):
103
 
 
104
 
    def test_empty_message(self):
105
 
        msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
106
 
        self.assertEqualDiff(EMPTY_MESSAGE , msg.as_string())
107
 
 
108
 
    def test_simple_message(self):
109
 
        pairs = {
110
 
            'body': SIMPLE_MESSAGE_ASCII,
111
 
            u'b\xf3dy': SIMPLE_MESSAGE_UTF8,
112
 
            'b\xc3\xb3dy': SIMPLE_MESSAGE_UTF8,
113
 
            'b\xf4dy': SIMPLE_MESSAGE_8BIT,
114
 
        }
115
 
        for body, expected in pairs.items():
116
 
            msg = EmailMessage('from@from.com', 'to@to.com', 'subject', body)
117
 
            self.assertEqualDiff(expected, msg.as_string())
118
 
 
119
 
    def test_multipart_message_simple(self):
120
 
        msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
121
 
        msg.add_inline_attachment('body')
122
 
        self.assertEqualDiff(simple_multipart_message(),
123
 
                             msg.as_string(BOUNDARY))
124
 
 
125
 
 
126
 
    def test_multipart_message_complex(self):
127
 
        msg = EmailMessage('from@from.com', 'to@to.com', 'subject', 'body')
128
 
        msg.add_inline_attachment(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-subtype')
129
 
        self.assertEqualDiff(complex_multipart_message('x-subtype'),
130
 
                             msg.as_string(BOUNDARY))
131
 
 
132
 
    def test_headers_accept_unicode_and_utf8(self):
133
 
        for user in [ u'Pepe P\xe9rez <pperez@ejemplo.com>',
134
 
                'Pepe P\xc3\xa9red <pperez@ejemplo.com>' ]:
135
 
            msg = EmailMessage(user, user, user) # no exception raised
136
 
 
137
 
            for header in ['From', 'To', 'Subject']:
138
 
                value = msg[header]
139
 
                str(value).decode('ascii') # no UnicodeDecodeError
140
 
 
141
 
    def test_headers_reject_8bit(self):
142
 
        for i in range(3): # from_address, to_address, subject
143
 
            x = [ '"J. Random Developer" <jrandom@example.com>' ] * 3
144
 
            x[i] = 'Pepe P\xe9rez <pperez@ejemplo.com>'
145
 
            self.assertRaises(BzrBadParameterNotUnicode, EmailMessage, *x)
146
 
 
147
 
    def test_multiple_destinations(self):
148
 
        to_addresses = [ 'to1@to.com', 'to2@to.com', 'to3@to.com' ]
149
 
        msg = EmailMessage('from@from.com', to_addresses, 'subject')
150
 
        self.assertContainsRe(msg.as_string(), 'To: ' +
151
 
                ', '.join(to_addresses)) # re.M can't be passed, so no ^$
152
 
 
153
 
    def test_retrieving_headers(self):
154
 
        msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
155
 
        for header, value in [('From', 'from@from.com'), ('To', 'to@to.com'),
156
 
                ('Subject', 'subject')]:
157
 
            self.assertEqual(value, msg.get(header))
158
 
            self.assertEqual(value, msg[header])
159
 
        self.assertEqual(None, msg.get('Does-Not-Exist'))
160
 
        self.assertEqual(None, msg['Does-Not-Exist'])
161
 
        self.assertEqual('None', msg.get('Does-Not-Exist', 'None'))
162
 
 
163
 
    def test_setting_headers(self):
164
 
        msg = EmailMessage('from@from.com', 'to@to.com', 'subject')
165
 
        msg['To'] = 'to2@to.com'
166
 
        msg['Cc'] = 'cc@cc.com'
167
 
        self.assertEqual('to2@to.com', msg['To'])
168
 
        self.assertEqual('cc@cc.com', msg['Cc'])
169
 
 
170
 
    def test_address_to_encoded_header(self):
171
 
        def decode(s):
172
 
            """Convert a RFC2047-encoded string to a unicode string."""
173
 
            return ' '.join([chunk.decode(encoding or 'ascii')
174
 
                             for chunk, encoding in decode_header(s)])
175
 
 
176
 
        address = 'jrandom@example.com'
177
 
        encoded = EmailMessage.address_to_encoded_header(address)
178
 
        self.assertEqual(address, encoded)
179
 
 
180
 
        address = 'J Random Developer <jrandom@example.com>'
181
 
        encoded = EmailMessage.address_to_encoded_header(address)
182
 
        self.assertEqual(address, encoded)
183
 
 
184
 
        address = '"J. Random Developer" <jrandom@example.com>'
185
 
        encoded = EmailMessage.address_to_encoded_header(address)
186
 
        self.assertEqual(address, encoded)
187
 
 
188
 
        address = u'Pepe P\xe9rez <pperez@ejemplo.com>' # unicode ok
189
 
        encoded = EmailMessage.address_to_encoded_header(address)
190
 
        self.assertTrue('pperez@ejemplo.com' in encoded) # addr must be unencoded
191
 
        self.assertEqual(address, decode(encoded))
192
 
 
193
 
        address = 'Pepe P\xc3\xa9red <pperez@ejemplo.com>' # UTF-8 ok
194
 
        encoded = EmailMessage.address_to_encoded_header(address)
195
 
        self.assertTrue('pperez@ejemplo.com' in encoded)
196
 
        self.assertEqual(address, decode(encoded).encode('utf-8'))
197
 
 
198
 
        address = 'Pepe P\xe9rez <pperez@ejemplo.com>' # ISO-8859-1 not ok
199
 
        self.assertRaises(BzrBadParameterNotUnicode,
200
 
                EmailMessage.address_to_encoded_header, address)
201
 
 
202
 
    def test_string_with_encoding(self):
203
 
        pairs = {
204
 
                u'Pepe':        ('Pepe', 'ascii'),
205
 
                u'P\xe9rez':    ('P\xc3\xa9rez', 'utf-8'),
206
 
                'Perez':         ('Perez', 'ascii'), # u'Pepe' == 'Pepe'
207
 
                'P\xc3\xa9rez': ('P\xc3\xa9rez', 'utf-8'),
208
 
                'P\xe8rez':     ('P\xe8rez', '8-bit'),
209
 
        }
210
 
        for string_, pair in pairs.items():
211
 
            self.assertEqual(pair, EmailMessage.string_with_encoding(string_))
212
 
 
213
 
 
214
 
class TestSend(tests.TestCase):
215
 
 
216
 
    def setUp(self):
217
 
        super(TestSend, self).setUp()
218
 
        self.messages = []
219
 
 
220
 
        def send_as_append(_self, msg):
221
 
            self.messages.append(msg.as_string(BOUNDARY))
222
 
 
223
 
        self.overrideAttr(SMTPConnection, 'send_email', send_as_append)
224
 
 
225
 
 
226
 
 
227
 
    def send_email(self, attachment=None, attachment_filename=None,
228
 
                   attachment_mime_subtype='plain'):
229
 
        class FakeConfig:
230
 
            def get(self, option):
231
 
                return None
232
 
 
233
 
        EmailMessage.send(FakeConfig(), 'from@from.com', 'to@to.com',
234
 
                          'subject', 'body',
235
 
                          attachment=attachment,
236
 
                          attachment_filename=attachment_filename,
237
 
                          attachment_mime_subtype=attachment_mime_subtype)
238
 
 
239
 
    def assertMessage(self, expected):
240
 
        self.assertLength(1, self.messages)
241
 
        self.assertEqualDiff(expected, self.messages[0])
242
 
 
243
 
    def test_send_plain(self):
244
 
        self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt')
245
 
        self.assertMessage(complex_multipart_message('plain'))
246
 
 
247
 
    def test_send_patch(self):
248
 
        self.send_email(u'a\nb\nc\nd\ne\n', 'lines.txt', 'x-patch')
249
 
        self.assertMessage(complex_multipart_message('x-patch'))
250
 
 
251
 
    def test_send_simple(self):
252
 
          self.send_email()
253
 
          self.assertMessage(SIMPLE_MESSAGE_ASCII)
254