mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
166
third_party/python/Lib/test/test_email/__init__.py
vendored
Normal file
166
third_party/python/Lib/test/test_email/__init__.py
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
import os
|
||||
import unittest
|
||||
import collections
|
||||
import email
|
||||
from email.message import Message
|
||||
from email._policybase import compat32
|
||||
from test.support import load_package_tests
|
||||
from test.test_email import __file__ as landmark
|
||||
|
||||
# Load all tests in package
|
||||
def load_tests(*args):
|
||||
return load_package_tests(os.path.dirname(__file__), *args)
|
||||
|
||||
|
||||
# helper code used by a number of test modules.
|
||||
|
||||
def openfile(filename, *args, **kws):
|
||||
path = os.path.join(os.path.dirname(landmark), 'data', filename)
|
||||
return open(path, *args, **kws)
|
||||
|
||||
|
||||
# Base test class
|
||||
class TestEmailBase(unittest.TestCase):
|
||||
|
||||
maxDiff = None
|
||||
# Currently the default policy is compat32. By setting that as the default
|
||||
# here we make minimal changes in the test_email tests compared to their
|
||||
# pre-3.3 state.
|
||||
policy = compat32
|
||||
# Likewise, the default message object is Message.
|
||||
message = Message
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super().__init__(*args, **kw)
|
||||
self.addTypeEqualityFunc(bytes, self.assertBytesEqual)
|
||||
|
||||
# Backward compatibility to minimize test_email test changes.
|
||||
ndiffAssertEqual = unittest.TestCase.assertEqual
|
||||
|
||||
def _msgobj(self, filename):
|
||||
with openfile(filename) as fp:
|
||||
return email.message_from_file(fp, policy=self.policy)
|
||||
|
||||
def _str_msg(self, string, message=None, policy=None):
|
||||
if policy is None:
|
||||
policy = self.policy
|
||||
if message is None:
|
||||
message = self.message
|
||||
return email.message_from_string(string, message, policy=policy)
|
||||
|
||||
def _bytes_msg(self, bytestring, message=None, policy=None):
|
||||
if policy is None:
|
||||
policy = self.policy
|
||||
if message is None:
|
||||
message = self.message
|
||||
return email.message_from_bytes(bytestring, message, policy=policy)
|
||||
|
||||
def _make_message(self):
|
||||
return self.message(policy=self.policy)
|
||||
|
||||
def _bytes_repr(self, b):
|
||||
return [repr(x) for x in b.splitlines(keepends=True)]
|
||||
|
||||
def assertBytesEqual(self, first, second, msg):
|
||||
"""Our byte strings are really encoded strings; improve diff output"""
|
||||
self.assertEqual(self._bytes_repr(first), self._bytes_repr(second))
|
||||
|
||||
def assertDefectsEqual(self, actual, expected):
|
||||
self.assertEqual(len(actual), len(expected), actual)
|
||||
for i in range(len(actual)):
|
||||
self.assertIsInstance(actual[i], expected[i],
|
||||
'item {}'.format(i))
|
||||
|
||||
|
||||
def parameterize(cls):
|
||||
"""A test method parameterization class decorator.
|
||||
|
||||
Parameters are specified as the value of a class attribute that ends with
|
||||
the string '_params'. Call the portion before '_params' the prefix. Then
|
||||
a method to be parameterized must have the same prefix, the string
|
||||
'_as_', and an arbitrary suffix.
|
||||
|
||||
The value of the _params attribute may be either a dictionary or a list.
|
||||
The values in the dictionary and the elements of the list may either be
|
||||
single values, or a list. If single values, they are turned into single
|
||||
element tuples. However derived, the resulting sequence is passed via
|
||||
*args to the parameterized test function.
|
||||
|
||||
In a _params dictionary, the keys become part of the name of the generated
|
||||
tests. In a _params list, the values in the list are converted into a
|
||||
string by joining the string values of the elements of the tuple by '_' and
|
||||
converting any blanks into '_'s, and this become part of the name.
|
||||
The full name of a generated test is a 'test_' prefix, the portion of the
|
||||
test function name after the '_as_' separator, plus an '_', plus the name
|
||||
derived as explained above.
|
||||
|
||||
For example, if we have:
|
||||
|
||||
count_params = range(2)
|
||||
|
||||
def count_as_foo_arg(self, foo):
|
||||
self.assertEqual(foo+1, myfunc(foo))
|
||||
|
||||
we will get parameterized test methods named:
|
||||
test_foo_arg_0
|
||||
test_foo_arg_1
|
||||
test_foo_arg_2
|
||||
|
||||
Or we could have:
|
||||
|
||||
example_params = {'foo': ('bar', 1), 'bing': ('bang', 2)}
|
||||
|
||||
def example_as_myfunc_input(self, name, count):
|
||||
self.assertEqual(name+str(count), myfunc(name, count))
|
||||
|
||||
and get:
|
||||
test_myfunc_input_foo
|
||||
test_myfunc_input_bing
|
||||
|
||||
Note: if and only if the generated test name is a valid identifier can it
|
||||
be used to select the test individually from the unittest command line.
|
||||
|
||||
The values in the params dict can be a single value, a tuple, or a
|
||||
dict. If a single value of a tuple, it is passed to the test function
|
||||
as positional arguments. If a dict, it is a passed via **kw.
|
||||
|
||||
"""
|
||||
paramdicts = {}
|
||||
testers = collections.defaultdict(list)
|
||||
for name, attr in cls.__dict__.items():
|
||||
if name.endswith('_params'):
|
||||
if not hasattr(attr, 'keys'):
|
||||
d = {}
|
||||
for x in attr:
|
||||
if not hasattr(x, '__iter__'):
|
||||
x = (x,)
|
||||
n = '_'.join(str(v) for v in x).replace(' ', '_')
|
||||
d[n] = x
|
||||
attr = d
|
||||
paramdicts[name[:-7] + '_as_'] = attr
|
||||
if '_as_' in name:
|
||||
testers[name.split('_as_')[0] + '_as_'].append(name)
|
||||
testfuncs = {}
|
||||
for name in paramdicts:
|
||||
if name not in testers:
|
||||
raise ValueError("No tester found for {}".format(name))
|
||||
for name in testers:
|
||||
if name not in paramdicts:
|
||||
raise ValueError("No params found for {}".format(name))
|
||||
for name, attr in cls.__dict__.items():
|
||||
for paramsname, paramsdict in paramdicts.items():
|
||||
if name.startswith(paramsname):
|
||||
testnameroot = 'test_' + name[len(paramsname):]
|
||||
for paramname, params in paramsdict.items():
|
||||
if hasattr(params, 'keys'):
|
||||
test = (lambda self, name=name, params=params:
|
||||
getattr(self, name)(**params))
|
||||
else:
|
||||
test = (lambda self, name=name, params=params:
|
||||
getattr(self, name)(*params))
|
||||
testname = testnameroot + '_' + paramname
|
||||
test.__name__ = testname
|
||||
testfuncs[testname] = test
|
||||
for key, value in testfuncs.items():
|
||||
setattr(cls, key, value)
|
||||
return cls
|
4
third_party/python/Lib/test/test_email/__main__.py
vendored
Normal file
4
third_party/python/Lib/test/test_email/__main__.py
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
from test.test_email import load_tests
|
||||
import unittest
|
||||
|
||||
unittest.main()
|
BIN
third_party/python/Lib/test/test_email/data/PyBanner048.gif
vendored
Normal file
BIN
third_party/python/Lib/test/test_email/data/PyBanner048.gif
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 954 B |
BIN
third_party/python/Lib/test/test_email/data/audiotest.au
vendored
Normal file
BIN
third_party/python/Lib/test/test_email/data/audiotest.au
vendored
Normal file
Binary file not shown.
19
third_party/python/Lib/test/test_email/data/msg_01.txt
vendored
Normal file
19
third_party/python/Lib/test/test_email/data/msg_01.txt
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Return-Path: <bbb@zzz.org>
|
||||
Delivered-To: bbb@zzz.org
|
||||
Received: by mail.zzz.org (Postfix, from userid 889)
|
||||
id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15090.61304.110929.45684@aaa.zzz.org>
|
||||
From: bbb@ddd.com (John X. Doe)
|
||||
To: bbb@zzz.org
|
||||
Subject: This is a test message
|
||||
Date: Fri, 4 May 2001 14:05:44 -0400
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Do you like this message?
|
||||
|
||||
-Me
|
136
third_party/python/Lib/test/test_email/data/msg_02.txt
vendored
Normal file
136
third_party/python/Lib/test/test_email/data/msg_02.txt
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
MIME-version: 1.0
|
||||
From: ppp-request@zzz.org
|
||||
Sender: ppp-admin@zzz.org
|
||||
To: ppp@zzz.org
|
||||
Subject: Ppp digest, Vol 1 #2 - 5 msgs
|
||||
Date: Fri, 20 Apr 2001 20:18:00 -0400 (EDT)
|
||||
X-Mailer: Mailman v2.0.4
|
||||
X-Mailman-Version: 2.0.4
|
||||
Content-Type: multipart/mixed; boundary="192.168.1.2.889.32614.987812255.500.21814"
|
||||
|
||||
--192.168.1.2.889.32614.987812255.500.21814
|
||||
Content-type: text/plain; charset=us-ascii
|
||||
Content-description: Masthead (Ppp digest, Vol 1 #2)
|
||||
|
||||
Send Ppp mailing list submissions to
|
||||
ppp@zzz.org
|
||||
|
||||
To subscribe or unsubscribe via the World Wide Web, visit
|
||||
http://www.zzz.org/mailman/listinfo/ppp
|
||||
or, via email, send a message with subject or body 'help' to
|
||||
ppp-request@zzz.org
|
||||
|
||||
You can reach the person managing the list at
|
||||
ppp-admin@zzz.org
|
||||
|
||||
When replying, please edit your Subject line so it is more specific
|
||||
than "Re: Contents of Ppp digest..."
|
||||
|
||||
|
||||
--192.168.1.2.889.32614.987812255.500.21814
|
||||
Content-type: text/plain; charset=us-ascii
|
||||
Content-description: Today's Topics (5 msgs)
|
||||
|
||||
Today's Topics:
|
||||
|
||||
1. testing #1 (Barry A. Warsaw)
|
||||
2. testing #2 (Barry A. Warsaw)
|
||||
3. testing #3 (Barry A. Warsaw)
|
||||
4. testing #4 (Barry A. Warsaw)
|
||||
5. testing #5 (Barry A. Warsaw)
|
||||
|
||||
--192.168.1.2.889.32614.987812255.500.21814
|
||||
Content-Type: multipart/digest; boundary="__--__--"
|
||||
|
||||
--__--__--
|
||||
|
||||
Message: 1
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Date: Fri, 20 Apr 2001 20:16:13 -0400
|
||||
To: ppp@zzz.org
|
||||
From: barry@digicool.com (Barry A. Warsaw)
|
||||
Subject: [Ppp] testing #1
|
||||
Precedence: bulk
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
--__--__--
|
||||
|
||||
Message: 2
|
||||
Date: Fri, 20 Apr 2001 20:16:21 -0400
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
To: ppp@zzz.org
|
||||
From: barry@digicool.com (Barry A. Warsaw)
|
||||
Precedence: bulk
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
--__--__--
|
||||
|
||||
Message: 3
|
||||
Date: Fri, 20 Apr 2001 20:16:25 -0400
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
To: ppp@zzz.org
|
||||
From: barry@digicool.com (Barry A. Warsaw)
|
||||
Subject: [Ppp] testing #3
|
||||
Precedence: bulk
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
--__--__--
|
||||
|
||||
Message: 4
|
||||
Date: Fri, 20 Apr 2001 20:16:28 -0400
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
To: ppp@zzz.org
|
||||
From: barry@digicool.com (Barry A. Warsaw)
|
||||
Subject: [Ppp] testing #4
|
||||
Precedence: bulk
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
--__--__--
|
||||
|
||||
Message: 5
|
||||
Date: Fri, 20 Apr 2001 20:16:32 -0400
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
To: ppp@zzz.org
|
||||
From: barry@digicool.com (Barry A. Warsaw)
|
||||
Subject: [Ppp] testing #5
|
||||
Precedence: bulk
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
|
||||
|
||||
--__--__----
|
||||
|
||||
--192.168.1.2.889.32614.987812255.500.21814
|
||||
Content-type: text/plain; charset=us-ascii
|
||||
Content-description: Digest Footer
|
||||
|
||||
_______________________________________________
|
||||
Ppp mailing list
|
||||
Ppp@zzz.org
|
||||
http://www.zzz.org/mailman/listinfo/ppp
|
||||
|
||||
|
||||
--192.168.1.2.889.32614.987812255.500.21814--
|
||||
|
||||
End of Ppp Digest
|
||||
|
16
third_party/python/Lib/test/test_email/data/msg_03.txt
vendored
Normal file
16
third_party/python/Lib/test/test_email/data/msg_03.txt
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
Return-Path: <bbb@zzz.org>
|
||||
Delivered-To: bbb@zzz.org
|
||||
Received: by mail.zzz.org (Postfix, from userid 889)
|
||||
id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT)
|
||||
Message-ID: <15090.61304.110929.45684@aaa.zzz.org>
|
||||
From: bbb@ddd.com (John X. Doe)
|
||||
To: bbb@zzz.org
|
||||
Subject: This is a test message
|
||||
Date: Fri, 4 May 2001 14:05:44 -0400
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Do you like this message?
|
||||
|
||||
-Me
|
37
third_party/python/Lib/test/test_email/data/msg_04.txt
vendored
Normal file
37
third_party/python/Lib/test/test_email/data/msg_04.txt
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
Return-Path: <barry@python.org>
|
||||
Delivered-To: barry@python.org
|
||||
Received: by mail.python.org (Postfix, from userid 889)
|
||||
id C2BF0D37C6; Tue, 11 Sep 2001 00:05:05 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="h90VIIIKmx"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15261.36209.358846.118674@anthem.python.org>
|
||||
From: barry@python.org (Barry A. Warsaw)
|
||||
To: barry@python.org
|
||||
Subject: a simple multipart
|
||||
Date: Tue, 11 Sep 2001 00:05:05 -0400
|
||||
X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid
|
||||
X-Attribution: BAW
|
||||
X-Oblique-Strategy: Make a door into a window
|
||||
|
||||
|
||||
--h90VIIIKmx
|
||||
Content-Type: text/plain
|
||||
Content-Disposition: inline;
|
||||
filename="msg.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
a simple kind of mirror
|
||||
to reflect upon our own
|
||||
|
||||
--h90VIIIKmx
|
||||
Content-Type: text/plain
|
||||
Content-Disposition: inline;
|
||||
filename="msg.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
a simple kind of mirror
|
||||
to reflect upon our own
|
||||
|
||||
--h90VIIIKmx--
|
||||
|
28
third_party/python/Lib/test/test_email/data/msg_05.txt
vendored
Normal file
28
third_party/python/Lib/test/test_email/data/msg_05.txt
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
From: foo
|
||||
Subject: bar
|
||||
To: baz
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/report; report-type=delivery-status;
|
||||
boundary="D1690A7AC1.996856090/mail.example.com"
|
||||
Message-Id: <20010803162810.0CA8AA7ACC@mail.example.com>
|
||||
|
||||
This is a MIME-encapsulated message.
|
||||
|
||||
--D1690A7AC1.996856090/mail.example.com
|
||||
Content-Type: text/plain
|
||||
|
||||
Yadda yadda yadda
|
||||
|
||||
--D1690A7AC1.996856090/mail.example.com
|
||||
|
||||
Yadda yadda yadda
|
||||
|
||||
--D1690A7AC1.996856090/mail.example.com
|
||||
Content-Type: message/rfc822
|
||||
|
||||
From: nobody@python.org
|
||||
|
||||
Yadda yadda yadda
|
||||
|
||||
--D1690A7AC1.996856090/mail.example.com--
|
||||
|
33
third_party/python/Lib/test/test_email/data/msg_06.txt
vendored
Normal file
33
third_party/python/Lib/test/test_email/data/msg_06.txt
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
Return-Path: <barry@python.org>
|
||||
Delivered-To: barry@python.org
|
||||
MIME-Version: 1.0
|
||||
Content-Type: message/rfc822
|
||||
Content-Description: forwarded message
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15265.9482.641338.555352@python.org>
|
||||
From: barry@python.org (Barry A. Warsaw)
|
||||
Sender: barry@python.org
|
||||
To: barry@python.org
|
||||
Subject: forwarded message from Barry A. Warsaw
|
||||
Date: Thu, 13 Sep 2001 17:28:42 -0400
|
||||
X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid
|
||||
X-Attribution: BAW
|
||||
X-Oblique-Strategy: Be dirty
|
||||
X-Url: http://barry.wooz.org
|
||||
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Return-Path: <barry@python.org>
|
||||
Delivered-To: barry@python.org
|
||||
Message-ID: <15265.9468.713530.98441@python.org>
|
||||
From: barry@python.org (Barry A. Warsaw)
|
||||
Sender: barry@python.org
|
||||
To: barry@python.org
|
||||
Subject: testing
|
||||
Date: Thu, 13 Sep 2001 17:28:28 -0400
|
||||
X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid
|
||||
X-Attribution: BAW
|
||||
X-Oblique-Strategy: Spectrum analysis
|
||||
X-Url: http://barry.wooz.org
|
||||
|
||||
|
83
third_party/python/Lib/test/test_email/data/msg_07.txt
vendored
Normal file
83
third_party/python/Lib/test/test_email/data/msg_07.txt
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry <barry@digicool.com>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Here is your dingus fish
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
Hi there,
|
||||
|
||||
This is the dingus fish.
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: image/gif; name="dingusfish.gif"
|
||||
Content-Transfer-Encoding: base64
|
||||
content-disposition: attachment; filename="dingusfish.gif"
|
||||
|
||||
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
|
||||
|
||||
--BOUNDARY--
|
24
third_party/python/Lib/test/test_email/data/msg_08.txt
vendored
Normal file
24
third_party/python/Lib/test/test_email/data/msg_08.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry Warsaw <barry@python.org>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Lyrics
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/html; charset="iso-8859-1"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="iso-8859-2"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="koi8-r"
|
||||
|
||||
|
||||
--BOUNDARY--
|
24
third_party/python/Lib/test/test_email/data/msg_09.txt
vendored
Normal file
24
third_party/python/Lib/test/test_email/data/msg_09.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry Warsaw <barry@python.org>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Lyrics
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/html; charset="iso-8859-1"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="koi8-r"
|
||||
|
||||
|
||||
--BOUNDARY--
|
39
third_party/python/Lib/test/test_email/data/msg_10.txt
vendored
Normal file
39
third_party/python/Lib/test/test_email/data/msg_10.txt
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry Warsaw <barry@python.org>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Lyrics
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
This is a 7bit encoded message.
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/html; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: Quoted-Printable
|
||||
|
||||
=A1This is a Quoted Printable encoded message!
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: Base64
|
||||
|
||||
VGhpcyBpcyBhIEJhc2U2NCBlbmNvZGVkIG1lc3NhZ2Uu
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: Base64
|
||||
|
||||
VGhpcyBpcyBhIEJhc2U2NCBlbmNvZGVkIG1lc3NhZ2UuCg==
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
|
||||
This has no Content-Transfer-Encoding: header.
|
||||
|
||||
--BOUNDARY--
|
7
third_party/python/Lib/test/test_email/data/msg_11.txt
vendored
Normal file
7
third_party/python/Lib/test/test_email/data/msg_11.txt
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
Content-Type: message/rfc822
|
||||
MIME-Version: 1.0
|
||||
Subject: The enclosing message
|
||||
|
||||
Subject: An enclosed message
|
||||
|
||||
Here is the body of the message.
|
36
third_party/python/Lib/test/test_email/data/msg_12.txt
vendored
Normal file
36
third_party/python/Lib/test/test_email/data/msg_12.txt
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry Warsaw <barry@python.org>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Lyrics
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/html; charset="iso-8859-1"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: multipart/mixed; boundary="ANOTHER"
|
||||
|
||||
--ANOTHER
|
||||
Content-Type: text/plain; charset="iso-8859-2"
|
||||
|
||||
|
||||
--ANOTHER
|
||||
Content-Type: text/plain; charset="iso-8859-3"
|
||||
|
||||
--ANOTHER--
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="koi8-r"
|
||||
|
||||
|
||||
--BOUNDARY--
|
38
third_party/python/Lib/test/test_email/data/msg_12a.txt
vendored
Normal file
38
third_party/python/Lib/test/test_email/data/msg_12a.txt
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry Warsaw <barry@python.org>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Lyrics
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/html; charset="iso-8859-1"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: multipart/mixed; boundary="ANOTHER"
|
||||
|
||||
--ANOTHER
|
||||
Content-Type: text/plain; charset="iso-8859-2"
|
||||
|
||||
|
||||
--ANOTHER
|
||||
Content-Type: text/plain; charset="iso-8859-3"
|
||||
|
||||
|
||||
--ANOTHER--
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="koi8-r"
|
||||
|
||||
|
||||
--BOUNDARY--
|
94
third_party/python/Lib/test/test_email/data/msg_13.txt
vendored
Normal file
94
third_party/python/Lib/test/test_email/data/msg_13.txt
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry <barry@digicool.com>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Here is your dingus fish
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="OUTER"
|
||||
|
||||
--OUTER
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
A text/plain part
|
||||
|
||||
--OUTER
|
||||
Content-Type: multipart/mixed; boundary=BOUNDARY
|
||||
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
|
||||
Hi there,
|
||||
|
||||
This is the dingus fish.
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: image/gif; name="dingusfish.gif"
|
||||
Content-Transfer-Encoding: base64
|
||||
content-disposition: attachment; filename="dingusfish.gif"
|
||||
|
||||
R0lGODdhAAEAAfAAAP///wAAACwAAAAAAAEAAQAC/oSPqcvtD6OctNqLs968+w+G4kiW5omm6sq2
|
||||
7gvH8kzX9o3n+s73/g8MCofEovGITGICTKbyCV0FDNOo9SqpQqpOrJfXzTQj2vD3TGtqL+NtGQ2f
|
||||
qTXmxzuOd7WXdcc9DyjU53ewFni4s0fGhdiYaEhGBelICTNoV1j5NUnFcrmUqemjNifJVWpaOqaI
|
||||
oFq3SspZsSraE7sHq3jr1MZqWvi662vxV4tD+pvKW6aLDOCLyur8PDwbanyDeq0N3DctbQYeLDvR
|
||||
RY6t95m6UB0d3mwIrV7e2VGNvjjffukeJp4w7F65KecGFsTHQGAygOrgrWs1jt28Rc88KESYcGLA
|
||||
/obvTkH6p+CinWJiJmIMqXGQwH/y4qk0SYjgQTczT3ajKZGfuI0uJ4kkVI/DT5s3/ejkxI0aT4Y+
|
||||
YTYgWbImUaXk9nlLmnSh1qJiJFl0OpUqRK4oOy7NyRQtHWofhoYVxkwWXKUSn0YsS+fUV6lhqfYb
|
||||
6ayd3Z5qQdG1B7bvQzaJjwUV2lixMUZ7JVsOlfjWVr/3NB/uFvnySBN6Dcb6rGwaRM3wsormw5cC
|
||||
M9NxWy/bWdufudCvy8bOAjXjVVwta/uO21sE5RHBCzNFXtgq9ORtH4eYjVP4Yryo026nvkFmCeyA
|
||||
B29efV6ravCMK5JwWd5897Qrx7ll38o6iHDZ/rXPR//feevhF4l7wjUGX3xq1eeRfM4RSJGBIV1D
|
||||
z1gKPkfWag3mVBVvva1RlX5bAJTPR/2YqNtw/FkIYYEi/pIZiAdpcxpoHtmnYYoZtvhUftzdx5ZX
|
||||
JSKDW405zkGcZzzGZ6KEv4FI224oDmijlEf+xp6MJK5ojY/ASeVUR+wsKRuJ+XFZ5o7ZeEime8t1
|
||||
ouUsU6YjF5ZtUihhkGfCdFQLWQFJ3UXxmElfhQnR+eCdcDbkFZp6vTRmj56ApCihn5QGpaToNZmR
|
||||
n3NVSpZcQpZ2KEONusaiCsKAug0wkQbJSFO+PTSjneGxOuFjPlUk3ovWvdIerjUg9ZGIOtGq/qeX
|
||||
eCYrrCX+1UPsgTKGGRSbzd5q156d/gpfbJxe66eD5iQKrXj7RGgruGxs62qebBHUKS32CKluCiqZ
|
||||
qh+pmehmEb71noAUoe5e9Zm17S7773V10pjrtG4CmuurCV/n6zLK5turWNhqOvFXbjhZrMD0YhKe
|
||||
wR0zOyuvsh6MWrGoIuzvyWu5y1WIFAqmJselypxXh6dKLNOKEB98L88bS2rkNqqlKzCNJp9c0G0j
|
||||
Gzh0iRrCbHSXmPR643QS+4rWhgFmnSbSuXCjS0xAOWkU2UdLqyuUNfHSFdUouy3bm5i5GnDM3tG8
|
||||
doJ4r5tqu3pPbRSVfvs8uJzeNXhp3n4j/tZ42SwH7eaWUUOjc3qFV9453UHTXZfcLH+OeNs5g36x
|
||||
lBnHvTm7EbMbLeuaLncao8vWCXimfo1o+843Ak6y4ChNeGntvAYvfLK4ezmoyNIbNCLTCXO9ZV3A
|
||||
E8/s88RczPzDwI4Ob7XZyl7+9Miban29h+tJZPrE21wgvBphDfrrfPdCTPKJD/y98L1rZwHcV6Jq
|
||||
Zab0metpuNIX/qAFPoz171WUaUb4HAhBSzHuHfjzHb3kha/2Cctis/ORArVHNYfFyYRH2pYIRzic
|
||||
isVOfPWD1b6mRTqpCRBozzof6UZVvFXRxWIr3GGrEviGYgyPMfahheiSaLs/9QeFu7oZ/ndSY8DD
|
||||
ya9x+uPed+7mxN2IzIISBOMLFYWVqC3Pew1T2nFuuCiwZS5/v6II10i4t1OJcUH2U9zxKodHsGGv
|
||||
Oa+zkvNUYUOa/TCCRutF9MzDwdlUMJADTCGSbDQ5OV4PTamDoPEi6Ecc/RF5RWwkcdSXvSOaDWSn
|
||||
I9LlvubFTQpuc6JKXLcKeb+xdbKRBnwREemXyjg6ME65aJiOuBgrktzykfPLJBKR9ClMavJ62/Ff
|
||||
BlNIyod9yX9wcSXexnXFpvkrbXk64xsx5Db7wXKP5fSgsvwIMM/9631VLBfkmtbHRXpqmtei52hG
|
||||
pUwSlo+BASQoeILDOBgREECxBBh5/iYmNsQ9dIv5+OI++QkqdsJPc3uykz5fkM+OraeekcQF7X4n
|
||||
B5S67za5U967PmooGQhUXfF7afXyCD7ONdRe17QogYjVx38uLwtrS6nhTnm15LQUnu9E2uK6CNI/
|
||||
1HOABj0ESwOjut4FEpFQpdNAm4K2LHnDWHNcmKB2ioKBogysVZtMO2nSxUdZ8Yk2kJc7URioLVI0
|
||||
YgmtIwZj4LoeKemgnOnbUdGnzZ4Oa6scqiolBGqS6RgWNLu0RMhcaE6rhhU4hiuqFXPAG8fGwTPW
|
||||
FKeLMtdVmXLSs5YJGF/YeVm7rREMlY3UYE+yCxbaMXX8y15m5zVHq6GOKDMynzII/jdUHdyVqIy0
|
||||
ifX2+r/EgtZcvRzSb72gU9ui87M2VecjKildW/aFqaYhKoryUjfB/g4qtyVuc60xFDGmCxwjW+qu
|
||||
zjuwl2GkOWn66+3QiiEctvd04OVvcCVzjgT7lrkvjVGKKHmmlDUKowSeikb5kK/mJReuWOxONx+s
|
||||
ULsl+Lqb0CVn0SrVyJ6wt4t6yTeSCafhPhAf0OXn6L60UMxiLolFAtmN35S2Ob1lZpQ1r/n0Qb5D
|
||||
oQ1zJiRVDgF8N3Q8TYfbi3DyWCy3lT1nxyBs6FT3S2GOzWRlxwKvlRP0RPJA9SjxEy0UoEnkA+M4
|
||||
cnzLMJrBGWLFEaaUb5lvpqbq/loOaU5+DFuHPxo82/OZuM8FXG3oVNZhtWpMpb/0Xu5m/LfLhHZQ
|
||||
7yuVI0MqZ7NE43imC8jH3IwGZlbPm0xkJYs7+2U48hXTsFSMqgGDvai0kLxyynKNT/waj+q1c1tz
|
||||
GjOpPBgdCSq3UKZxCSsqFIY+O6JbAWGWcV1pwqLyj5sGqCF1xb1F3varUWqrJv6cN3PrUXzijtfZ
|
||||
FshpBL3Xwr4GIPvU2N8EjrJgS1zl21rbXQMXeXc5jjFyrhpCzijSv/RQtyPSzHCFMhlME95fHglt
|
||||
pRsX+dfSQjUeHAlpWzJ5iOo79Ldnaxai6bXTcGO3fp07ri7HLEmXXPlYi8bv/qVxvNcdra6m7Rlb
|
||||
6JBTb5fd66VhFRjGArh2n7R1rDW4P5NOT9K0I183T2scYkeZ3q/VFyLb09U9ajzXBS8Kgkhc4mBS
|
||||
kYY9cy3Vy9lUnuNJH8HGIclUilwnBtjUOH0gteGOZ4c/XNrhXLSYDyxfnD8z1pDy7rYRvDolhnbe
|
||||
UMzxCZUs40s6s7UIvBnLgc0+vKuOkIXeOrDymlp+Zxra4MZLBbVrqD/jTJ597pDmnw5c4+DbyB88
|
||||
9Cg9DodYcSuMZT/114pptqc/EuTjRPvH/z5slzI3tluOEBBLqOXLOX+0I5929tO97wkvl/atCz+y
|
||||
xJrdwteW2FNW/NSmBP+f/maYtVs/bYyBC7Ox3jsYZHL05CIrBa/nS+b3bHfiYm4Ueil1YZZSgAUI
|
||||
fFZ1dxUmeA2oQRQ3RuGXNGLFV9/XbGFGPV6kfzk1TBBCd+izc7q1H+OHMJwmaBX2IQNYVAKHYepV
|
||||
SSGCe6CnbYHHETKGNe43EDvFgZr0gB/nVHPHZ80VV1ojOiI3XDvYIkl4ayo4bxQIgrFXWTvBI0nH
|
||||
VElWMuw2aLUWCRHHf8ymVCHjFlJnOSojfevCYyyyZDH0IcvHhrsnQ5O1OsWzONuVVKIxSxiFZ/tR
|
||||
fKDAf6xFTnw4O9Qig2VCfW2hJQrmMOuHW0W3dLQmCMO2ccdUd/xyfflH/olTiHZVdGwb8nIwRzSE
|
||||
J15jFlOJuBZBZ4CiyHyd2IFylFlB+HgHhYabhWOGwYO1ZH/Og1dtQlFMk352CGRSIFTapnWQEUtN
|
||||
l4zv8S0aaCFDyGCBqDUxZYpxGHX01y/JuH1xhn7TOCnNCI4eKDs5WGX4R425F4vF1o3BJ4vO0otq
|
||||
I3rimI7jJY1jISqnBxknCIvruF83mF5wN4X7qGLIhR8A2Vg0yFERSIXn9Vv3GHy3Vj/WIkKddlYi
|
||||
yIMv2I/VMjTLpW7pt05SWIZR0RPyxpB4SIUM9lBPGBl0GC7oSEEwRYLe4pJpZY2P0zbI1n+Oc44w
|
||||
qY3PUnmF0ixjVpDD/mJ9wpOBGTVgXlaCaZiPcIWK5NiKBIiPdGaQ0TWGvAiG7nMchdZb7Vgf8zNi
|
||||
MuMyzRdy/lePe9iC4TRx7WhhOQI/QiSVNAmAa2lT/piFbuh7ofJoYSZzrSZ1bvmWw3eN2nKUPVky
|
||||
uPN5/VRfohRd0VYZoqhKIlU6TXYhJxmPUIloAwc1bPmHEpaZYZORHNlXUJM07hATwHR8MJYqkwWR
|
||||
WaIezFhxSFlc8/Fq82hEnpeRozg3ULhhr9lAGtVEkCg5ZNRuuVleBPaZadhG0ZgkyPmDOTOKzViM
|
||||
YgOcpukKqQcbjAWS0IleQ2ROjdh6A+md1qWdBRSX7iSYgFRTtRmBpJioieXJiHfJiMGIR9fJOn8I
|
||||
MSfXYhspn4ooSa2mSAj4n+8Bmg03fBJZoPOJgsVZRxu1oOMRPXYYjdqjihFaEoZpXBREanuJoRI6
|
||||
cibFinq4ngUKh/wQd/H5ofYCZ0HJXR62opZFaAT0iFIZo4DIiUojkjeqKiuoZirKo5Y1a7AWckGa
|
||||
BkuYoD5lpDK6eUs6CkDqpETwl1EqpfhJpVeKpVl6EgUAADs=
|
||||
|
||||
--BOUNDARY--
|
||||
|
||||
--OUTER--
|
23
third_party/python/Lib/test/test_email/data/msg_14.txt
vendored
Normal file
23
third_party/python/Lib/test/test_email/data/msg_14.txt
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Return-Path: <bbb@zzz.org>
|
||||
Delivered-To: bbb@zzz.org
|
||||
Received: by mail.zzz.org (Postfix, from userid 889)
|
||||
id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15090.61304.110929.45684@aaa.zzz.org>
|
||||
From: bbb@ddd.com (John X. Doe)
|
||||
To: bbb@zzz.org
|
||||
Subject: This is a test message
|
||||
Date: Fri, 4 May 2001 14:05:44 -0400
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
I'm sorry but I'm using a drainbread ISP, which although big and
|
||||
wealthy can't seem to generate standard compliant email. :(
|
||||
|
||||
This message has a Content-Type: header with no subtype. I hope you
|
||||
can still read it.
|
||||
|
||||
-Me
|
52
third_party/python/Lib/test/test_email/data/msg_15.txt
vendored
Normal file
52
third_party/python/Lib/test/test_email/data/msg_15.txt
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
Return-Path: <xx@xx.dk>
|
||||
Received: from fepD.post.tele.dk (195.41.46.149) by mail.groupcare.dk (LSMTP for Windows NT v1.1b) with SMTP id <0.0014F8A2@mail.groupcare.dk>; Mon, 30 Apr 2001 12:17:50 +0200
|
||||
User-Agent: Microsoft-Outlook-Express-Macintosh-Edition/5.02.2106
|
||||
Subject: XX
|
||||
From: xx@xx.dk
|
||||
To: XX
|
||||
Message-ID: <xxxx>
|
||||
Mime-version: 1.0
|
||||
Content-type: multipart/mixed;
|
||||
boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
|
||||
|
||||
> Denne meddelelse er i MIME-format. Da dit postl
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: multipart/alternative;
|
||||
boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
|
||||
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: text/plain; charset="ISO-8859-1"
|
||||
Content-transfer-encoding: quoted-printable
|
||||
|
||||
Some removed test.
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: text/html; charset="ISO-8859-1"
|
||||
Content-transfer-encoding: quoted-printable
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Some removed HTML</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
Some removed text.
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part--
|
||||
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: image/gif; name="xx.gif";
|
||||
x-mac-creator="6F676C65";
|
||||
x-mac-type="47494666"
|
||||
Content-disposition: attachment
|
||||
Content-transfer-encoding: base64
|
||||
|
||||
Some removed base64 encoded chars.
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part--
|
||||
|
123
third_party/python/Lib/test/test_email/data/msg_16.txt
vendored
Normal file
123
third_party/python/Lib/test/test_email/data/msg_16.txt
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
Return-Path: <>
|
||||
Delivered-To: scr-admin@socal-raves.org
|
||||
Received: from cougar.noc.ucla.edu (cougar.noc.ucla.edu [169.232.10.18])
|
||||
by babylon.socal-raves.org (Postfix) with ESMTP id CCC2C51B84
|
||||
for <scr-admin@socal-raves.org>; Sun, 23 Sep 2001 20:13:54 -0700 (PDT)
|
||||
Received: from sims-ms-daemon by cougar.noc.ucla.edu
|
||||
(Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10)
|
||||
id <0GK500B01D0B8Y@cougar.noc.ucla.edu> for scr-admin@socal-raves.org; Sun,
|
||||
23 Sep 2001 20:14:35 -0700 (PDT)
|
||||
Received: from cougar.noc.ucla.edu
|
||||
(Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10)
|
||||
id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT)
|
||||
Date: Sun, 23 Sep 2001 20:14:35 -0700 (PDT)
|
||||
From: Internet Mail Delivery <postmaster@ucla.edu>
|
||||
Subject: Delivery Notification: Delivery has failed
|
||||
To: scr-admin@socal-raves.org
|
||||
Message-id: <0GK500B04D0B8X@cougar.noc.ucla.edu>
|
||||
MIME-version: 1.0
|
||||
Sender: scr-owner@socal-raves.org
|
||||
Errors-To: scr-owner@socal-raves.org
|
||||
X-BeenThere: scr@socal-raves.org
|
||||
X-Mailman-Version: 2.1a3
|
||||
Precedence: bulk
|
||||
List-Help: <mailto:scr-request@socal-raves.org?subject=help>
|
||||
List-Post: <mailto:scr@socal-raves.org>
|
||||
List-Subscribe: <http://socal-raves.org/mailman/listinfo/scr>,
|
||||
<mailto:scr-request@socal-raves.org?subject=subscribe>
|
||||
List-Id: SoCal-Raves <scr.socal-raves.org>
|
||||
List-Unsubscribe: <http://socal-raves.org/mailman/listinfo/scr>,
|
||||
<mailto:scr-request@socal-raves.org?subject=unsubscribe>
|
||||
List-Archive: <http://socal-raves.org/mailman/private/scr/>
|
||||
Content-Type: multipart/report; boundary="Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)"
|
||||
|
||||
|
||||
--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)
|
||||
Content-type: text/plain; charset=ISO-8859-1
|
||||
|
||||
This report relates to a message you sent with the following header fields:
|
||||
|
||||
Message-id: <002001c144a6$8752e060$56104586@oxy.edu>
|
||||
Date: Sun, 23 Sep 2001 20:10:55 -0700
|
||||
From: "Ian T. Henry" <henryi@oxy.edu>
|
||||
To: SoCal Raves <scr@socal-raves.org>
|
||||
Subject: [scr] yeah for Ians!!
|
||||
|
||||
Your message cannot be delivered to the following recipients:
|
||||
|
||||
Recipient address: jangel1@cougar.noc.ucla.edu
|
||||
Reason: recipient reached disk quota
|
||||
|
||||
|
||||
--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)
|
||||
Content-type: message/DELIVERY-STATUS
|
||||
|
||||
Original-envelope-id: 0GK500B4HD0888@cougar.noc.ucla.edu
|
||||
Reporting-MTA: dns; cougar.noc.ucla.edu
|
||||
|
||||
Action: failed
|
||||
Status: 5.0.0 (recipient reached disk quota)
|
||||
Original-recipient: rfc822;jangel1@cougar.noc.ucla.edu
|
||||
Final-recipient: rfc822;jangel1@cougar.noc.ucla.edu
|
||||
|
||||
--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)
|
||||
Content-type: MESSAGE/RFC822
|
||||
|
||||
Return-path: scr-admin@socal-raves.org
|
||||
Received: from sims-ms-daemon by cougar.noc.ucla.edu
|
||||
(Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10)
|
||||
id <0GK500B01D0B8X@cougar.noc.ucla.edu>; Sun, 23 Sep 2001 20:14:35 -0700 (PDT)
|
||||
Received: from panther.noc.ucla.edu by cougar.noc.ucla.edu
|
||||
(Sun Internet Mail Server sims.3.5.2000.03.23.18.03.p10)
|
||||
with ESMTP id <0GK500B4GD0888@cougar.noc.ucla.edu> for jangel1@sims-ms-daemon;
|
||||
Sun, 23 Sep 2001 20:14:33 -0700 (PDT)
|
||||
Received: from babylon.socal-raves.org
|
||||
(ip-209-85-222-117.dreamhost.com [209.85.222.117])
|
||||
by panther.noc.ucla.edu (8.9.1a/8.9.1) with ESMTP id UAA09793 for
|
||||
<jangel1@ucla.edu>; Sun, 23 Sep 2001 20:14:32 -0700 (PDT)
|
||||
Received: from babylon (localhost [127.0.0.1]) by babylon.socal-raves.org
|
||||
(Postfix) with ESMTP id D3B2951B70; Sun, 23 Sep 2001 20:13:47 -0700 (PDT)
|
||||
Received: by babylon.socal-raves.org (Postfix, from userid 60001)
|
||||
id A611F51B82; Sun, 23 Sep 2001 20:13:46 -0700 (PDT)
|
||||
Received: from tiger.cc.oxy.edu (tiger.cc.oxy.edu [134.69.3.112])
|
||||
by babylon.socal-raves.org (Postfix) with ESMTP id ADA7351B70 for
|
||||
<scr@socal-raves.org>; Sun, 23 Sep 2001 20:13:44 -0700 (PDT)
|
||||
Received: from ent (n16h86.dhcp.oxy.edu [134.69.16.86])
|
||||
by tiger.cc.oxy.edu (8.8.8/8.8.8) with SMTP id UAA08100 for
|
||||
<scr@socal-raves.org>; Sun, 23 Sep 2001 20:14:24 -0700 (PDT)
|
||||
Date: Sun, 23 Sep 2001 20:10:55 -0700
|
||||
From: "Ian T. Henry" <henryi@oxy.edu>
|
||||
Subject: [scr] yeah for Ians!!
|
||||
Sender: scr-admin@socal-raves.org
|
||||
To: SoCal Raves <scr@socal-raves.org>
|
||||
Errors-to: scr-admin@socal-raves.org
|
||||
Message-id: <002001c144a6$8752e060$56104586@oxy.edu>
|
||||
MIME-version: 1.0
|
||||
X-Mailer: Microsoft Outlook Express 5.50.4522.1200
|
||||
Content-type: text/plain; charset=us-ascii
|
||||
Precedence: bulk
|
||||
Delivered-to: scr-post@babylon.socal-raves.org
|
||||
Delivered-to: scr@socal-raves.org
|
||||
X-Converted-To-Plain-Text: from multipart/alternative by demime 0.98e
|
||||
X-Converted-To-Plain-Text: Alternative section used was text/plain
|
||||
X-BeenThere: scr@socal-raves.org
|
||||
X-Mailman-Version: 2.1a3
|
||||
List-Help: <mailto:scr-request@socal-raves.org?subject=help>
|
||||
List-Post: <mailto:scr@socal-raves.org>
|
||||
List-Subscribe: <http://socal-raves.org/mailman/listinfo/scr>,
|
||||
<mailto:scr-request@socal-raves.org?subject=subscribe>
|
||||
List-Id: SoCal-Raves <scr.socal-raves.org>
|
||||
List-Unsubscribe: <http://socal-raves.org/mailman/listinfo/scr>,
|
||||
<mailto:scr-request@socal-raves.org?subject=unsubscribe>
|
||||
List-Archive: <http://socal-raves.org/mailman/private/scr/>
|
||||
|
||||
I always love to find more Ian's that are over 3 years old!!
|
||||
|
||||
Ian
|
||||
_______________________________________________
|
||||
For event info, list questions, or to unsubscribe, see http://www.socal-raves.org/
|
||||
|
||||
|
||||
|
||||
--Boundary_(ID_PGS2F2a+z+/jL7hupKgRhA)--
|
||||
|
12
third_party/python/Lib/test/test_email/data/msg_17.txt
vendored
Normal file
12
third_party/python/Lib/test/test_email/data/msg_17.txt
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
MIME-Version: 1.0
|
||||
From: Barry <barry@digicool.com>
|
||||
To: Dingus Lovers <cravindogs@cravindogs.com>
|
||||
Subject: Here is your dingus fish
|
||||
Date: Fri, 20 Apr 2001 19:35:02 -0400
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
Hi there,
|
||||
|
||||
This is the dingus fish.
|
||||
|
||||
[Non-text (image/gif) part of message omitted, filename dingusfish.gif]
|
6
third_party/python/Lib/test/test_email/data/msg_18.txt
vendored
Normal file
6
third_party/python/Lib/test/test_email/data/msg_18.txt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
Content-Type: text/plain; charset="us-ascii"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Foobar-Spoink-Defrobnit: wasnipoop; giraffes="very-long-necked-animals";
|
||||
spooge="yummy"; hippos="gargantuan"; marshmallows="gooey"
|
||||
|
43
third_party/python/Lib/test/test_email/data/msg_19.txt
vendored
Normal file
43
third_party/python/Lib/test/test_email/data/msg_19.txt
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
Send Ppp mailing list submissions to
|
||||
ppp@zzz.org
|
||||
|
||||
To subscribe or unsubscribe via the World Wide Web, visit
|
||||
http://www.zzz.org/mailman/listinfo/ppp
|
||||
or, via email, send a message with subject or body 'help' to
|
||||
ppp-request@zzz.org
|
||||
|
||||
You can reach the person managing the list at
|
||||
ppp-admin@zzz.org
|
||||
|
||||
When replying, please edit your Subject line so it is more specific
|
||||
than "Re: Contents of Ppp digest..."
|
||||
|
||||
Today's Topics:
|
||||
|
||||
1. testing #1 (Barry A. Warsaw)
|
||||
2. testing #2 (Barry A. Warsaw)
|
||||
3. testing #3 (Barry A. Warsaw)
|
||||
4. testing #4 (Barry A. Warsaw)
|
||||
5. testing #5 (Barry A. Warsaw)
|
||||
|
||||
hello
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
hello
|
||||
|
||||
|
||||
|
||||
_______________________________________________
|
||||
Ppp mailing list
|
||||
Ppp@zzz.org
|
||||
http://www.zzz.org/mailman/listinfo/ppp
|
||||
|
22
third_party/python/Lib/test/test_email/data/msg_20.txt
vendored
Normal file
22
third_party/python/Lib/test/test_email/data/msg_20.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Return-Path: <bbb@zzz.org>
|
||||
Delivered-To: bbb@zzz.org
|
||||
Received: by mail.zzz.org (Postfix, from userid 889)
|
||||
id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15090.61304.110929.45684@aaa.zzz.org>
|
||||
From: bbb@ddd.com (John X. Doe)
|
||||
To: bbb@zzz.org
|
||||
Cc: ccc@zzz.org
|
||||
CC: ddd@zzz.org
|
||||
cc: eee@zzz.org
|
||||
Subject: This is a test message
|
||||
Date: Fri, 4 May 2001 14:05:44 -0400
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Do you like this message?
|
||||
|
||||
-Me
|
20
third_party/python/Lib/test/test_email/data/msg_21.txt
vendored
Normal file
20
third_party/python/Lib/test/test_email/data/msg_21.txt
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
From: aperson@dom.ain
|
||||
To: bperson@dom.ain
|
||||
Subject: Test
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
MIME message
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
One
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Two
|
||||
--BOUNDARY--
|
||||
End of MIME message
|
46
third_party/python/Lib/test/test_email/data/msg_22.txt
vendored
Normal file
46
third_party/python/Lib/test/test_email/data/msg_22.txt
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
Mime-Version: 1.0
|
||||
Message-Id: <a05001902b7f1c33773e9@[134.84.183.138]>
|
||||
Date: Tue, 16 Oct 2001 13:59:25 +0300
|
||||
To: a@example.com
|
||||
From: b@example.com
|
||||
Content-Type: multipart/mixed; boundary="============_-1208892523==_============"
|
||||
|
||||
--============_-1208892523==_============
|
||||
Content-Type: text/plain; charset="us-ascii" ; format="flowed"
|
||||
|
||||
Text text text.
|
||||
--============_-1208892523==_============
|
||||
Content-Id: <a05001902b7f1c33773e9@[134.84.183.138].0.0>
|
||||
Content-Type: image/jpeg; name="wibble.JPG"
|
||||
; x-mac-type="4A504547"
|
||||
; x-mac-creator="474B4F4E"
|
||||
Content-Disposition: attachment; filename="wibble.JPG"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABIEBAREA
|
||||
g6bCjjw/pIZSjO6FWFpldjySOmCNrO7DBZibUXhTwtCixw+GtAijVdqxxaPp0aKvmGXa
|
||||
qrbBQvms0mAMeYS/3iTV1dG0hHaRNK01XblnWxtVdjkHLMIgTyqnk9VB7CrP2KzIINpa
|
||||
4O7I+zxYO9WV8jZg71Zlb+8rMDkEirAVQFAUAKAFAAAUAYAUDgADgY6DjpRtXj5RxjHA
|
||||
4wQRj0wQCMdCAewpaKKK/9k=
|
||||
--============_-1208892523==_============
|
||||
Content-Id: <a05001902b7f1c33773e9@[134.84.183.138].0.1>
|
||||
Content-Type: image/jpeg; name="wibble2.JPG"
|
||||
; x-mac-type="4A504547"
|
||||
; x-mac-creator="474B4F4E"
|
||||
Content-Disposition: attachment; filename="wibble2.JPG"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAALCAXABJ0BAREA
|
||||
/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
|
||||
W6NFJJBEkU10kKGTcWMDwxuU+0JHvk8qAtOpNwqSR0n8c3BlDyXHlqsUltHEiTvdXLxR
|
||||
7vMiGDNJAJWkAMk8ZkCFp5G2oo5W++INrbQtNfTQxJAuXlupz9oS4d5Y1W+E2XlWZJJE
|
||||
Y7LWYQxTLE1zuMbfBPxw8X2fibVdIbSbI6nLZxX635t9TjtYreWR7WGKJTLJFFKSlozO
|
||||
0ShxIXM43uC3/9k=
|
||||
--============_-1208892523==_============
|
||||
Content-Type: text/plain; charset="us-ascii" ; format="flowed"
|
||||
|
||||
Text text text.
|
||||
--============_-1208892523==_============--
|
||||
|
8
third_party/python/Lib/test/test_email/data/msg_23.txt
vendored
Normal file
8
third_party/python/Lib/test/test_email/data/msg_23.txt
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
From: aperson@dom.ain
|
||||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain
|
||||
|
||||
A message part
|
||||
--BOUNDARY--
|
10
third_party/python/Lib/test/test_email/data/msg_24.txt
vendored
Normal file
10
third_party/python/Lib/test/test_email/data/msg_24.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
Content-Type: multipart/mixed; boundary="BOUNDARY"
|
||||
MIME-Version: 1.0
|
||||
Subject: A subject
|
||||
To: aperson@dom.ain
|
||||
From: bperson@dom.ain
|
||||
|
||||
--BOUNDARY
|
||||
|
||||
|
||||
--BOUNDARY--
|
117
third_party/python/Lib/test/test_email/data/msg_25.txt
vendored
Normal file
117
third_party/python/Lib/test/test_email/data/msg_25.txt
vendored
Normal file
|
@ -0,0 +1,117 @@
|
|||
From MAILER-DAEMON Fri Apr 06 16:46:09 2001
|
||||
Received: from [204.245.199.98] (helo=zinfandel.lacita.com)
|
||||
by www.linux.org.uk with esmtp (Exim 3.13 #1)
|
||||
id 14lYR6-0008Iv-00
|
||||
for linuxuser-admin@www.linux.org.uk; Fri, 06 Apr 2001 16:46:09 +0100
|
||||
Received: from localhost (localhost) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with internal id JAB03225; Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800)
|
||||
Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800)
|
||||
From: Mail Delivery Subsystem <MAILER-DAEMON@zinfandel.lacita.com>
|
||||
Subject: Returned mail: Too many hops 19 (17 max): from <linuxuser-admin@www.linux.org.uk> via [199.164.235.226], to <scoffman@wellpartner.com>
|
||||
Message-Id: <200104061723.JAB03225@zinfandel.lacita.com>
|
||||
To: <linuxuser-admin@www.linux.org.uk>
|
||||
To: postmaster@zinfandel.lacita.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/report; report-type=delivery-status;
|
||||
bo
|
||||
Auto-Submitted: auto-generated (failure)
|
||||
|
||||
This is a MIME-encapsulated message
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com
|
||||
|
||||
The original message was received at Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800)
|
||||
from [199.164.235.226]
|
||||
|
||||
----- The following addresses have delivery notifications -----
|
||||
<scoffman@wellpartner.com> (unrecoverable error)
|
||||
|
||||
----- Transcript of session follows -----
|
||||
554 Too many hops 19 (17 max): from <linuxuser-admin@www.linux.org.uk> via [199.164.235.226], to <scoffman@wellpartner.com>
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com
|
||||
Content-Type: message/delivery-status
|
||||
|
||||
Reporting-MTA: dns; zinfandel.lacita.com
|
||||
Received-From-MTA: dns; [199.164.235.226]
|
||||
Arrival-Date: Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800)
|
||||
|
||||
Final-Recipient: rfc822; scoffman@wellpartner.com
|
||||
Action: failed
|
||||
Status: 5.4.6
|
||||
Last-Attempt-Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800)
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com
|
||||
Content-Type: text/rfc822-headers
|
||||
|
||||
Return-Path: linuxuser-admin@www.linux.org.uk
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03225 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:23:03 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03221 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:22:18 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03217 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:21:37 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03213 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:20:56 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03209 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:20:15 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03205 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:19:33 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03201 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:18:52 -0800 (GMT-0800)
|
||||
Received: from zinfandel.lacita.com ([204.245.199.98])
|
||||
by
|
||||
fo
|
||||
Received: from ns1.wellpartner.net ([199.164.235.226]) by zinfandel.lacita.com (8.7.3/8.6.10-MT4.00) with ESMTP id JAA03197 for <scoffman@wellpartner.com>; Fri, 6 Apr 2001 09:17:54 -0800 (GMT-0800)
|
||||
Received: from www.linux.org.uk (parcelfarce.linux.theplanet.co.uk [195.92.249.252])
|
||||
by
|
||||
fo
|
||||
Received: from localhost.localdomain
|
||||
([
|
||||
by
|
||||
id
|
||||
Received: from [212.1.130.11] (helo=s1.uklinux.net ident=root)
|
||||
by
|
||||
id
|
||||
fo
|
||||
Received: from server (ppp-2-22.cvx4.telinco.net [212.1.149.22])
|
||||
by
|
||||
fo
|
||||
From: Daniel James <daniel@linuxuser.co.uk>
|
||||
Organization: LinuxUser
|
||||
To: linuxuser@www.linux.org.uk
|
||||
X-Mailer: KMail [version 1.1.99]
|
||||
Content-Type: text/plain;
|
||||
c
|
||||
MIME-Version: 1.0
|
||||
Message-Id: <01040616033903.00962@server>
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Subject: [LinuxUser] bulletin no. 45
|
||||
Sender: linuxuser-admin@www.linux.org.uk
|
||||
Errors-To: linuxuser-admin@www.linux.org.uk
|
||||
X-BeenThere: linuxuser@www.linux.org.uk
|
||||
X-Mailman-Version: 2.0.3
|
||||
Precedence: bulk
|
||||
List-Help: <mailto:linuxuser-request@www.linux.org.uk?subject=help>
|
||||
List-Post: <mailto:linuxuser@www.linux.org.uk>
|
||||
List-Subscribe: <http://www.linux.org.uk/mailman/listinfo/linuxuser>,
|
||||
<m
|
||||
List-Id: bulletins from LinuxUser magazine <linuxuser.www.linux.org.uk>
|
||||
List-Unsubscribe: <http://www.linux.org.uk/mailman/listinfo/linuxuser>,
|
||||
<m
|
||||
List-Archive: <http://www.linux.org.uk/pipermail/linuxuser/>
|
||||
Date: Fri, 6 Apr 2001 16:03:39 +0100
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com--
|
||||
|
||||
|
46
third_party/python/Lib/test/test_email/data/msg_26.txt
vendored
Normal file
46
third_party/python/Lib/test/test_email/data/msg_26.txt
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
Received: from xcar [192.168.0.2] by jeeves.wooster.local
|
||||
(SMTPD32-7.07 EVAL) id AFF92F0214; Sun, 12 May 2002 08:55:37 +0100
|
||||
Date: Sun, 12 May 2002 08:56:15 +0100
|
||||
From: Father Time <father.time@xcar.wooster.local>
|
||||
To: timbo@jeeves.wooster.local
|
||||
Subject: IMAP file test
|
||||
Message-ID: <6df65d354b.father.time@rpc.wooster.local>
|
||||
X-Organization: Home
|
||||
User-Agent: Messenger-Pro/2.50a (MsgServe/1.50) (RISC-OS/4.02) POPstar/2.03
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="1618492860--2051301190--113853680"
|
||||
Status: R
|
||||
X-UIDL: 319998302
|
||||
|
||||
This message is in MIME format which your mailer apparently does not support.
|
||||
You either require a newer version of your software which supports MIME, or
|
||||
a separate MIME decoding utility. Alternatively, ask the sender of this
|
||||
message to resend it in a different format.
|
||||
|
||||
--1618492860--2051301190--113853680
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
|
||||
Simple email with attachment.
|
||||
|
||||
|
||||
--1618492860--2051301190--113853680
|
||||
Content-Type: application/riscos; name="clock.bmp,69c"; type=BMP;
|
||||
load=&fff69c4b; exec=&355dd4d1; access=&03
|
||||
Content-Disposition: attachment; filename="clock.bmp"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
Qk12AgAAAAAAAHYAAAAoAAAAIAAAACAAAAABAAQAAAAAAAAAAADXDQAA1w0AAAAAAAAA
|
||||
AAAAAAAAAAAAiAAAiAAAAIiIAIgAAACIAIgAiIgAALu7uwCIiIgAERHdACLuIgAz//8A
|
||||
zAAAAN0R3QDu7iIA////AAAAAAAAAAAAAAAAAAAAAAAAAAi3AAAAAAAAADeAAAAAAAAA
|
||||
C3ADMzMzMANwAAAAAAAAAAAHMAAAAANwAAAAAAAAAACAMAd3zPfwAwgAAAAAAAAIAwd/
|
||||
f8x/f3AwgAAAAAAAgDB0x/f3//zPAwgAAAAAAAcHfM9////8z/AwAAAAAAiwd/f3////
|
||||
////A4AAAAAAcEx/f///////zAMAAAAAiwfM9////3///8zwOAAAAAcHf3////B/////
|
||||
8DAAAAALB/f3///wd3d3//AwAAAABwTPf//wCQAAD/zAMAAAAAsEx/f///B////8wDAA
|
||||
AAAHB39////wf/////AwAAAACwf39///8H/////wMAAAAIcHfM9///B////M8DgAAAAA
|
||||
sHTH///wf///xAMAAAAACHB3f3//8H////cDgAAAAAALB3zH//D//M9wMAAAAAAAgLB0
|
||||
z39///xHAwgAAAAAAAgLB3d3RHd3cDCAAAAAAAAAgLAHd0R3cAMIAAAAAAAAgAgLcAAA
|
||||
AAMwgAgAAAAACDAAAAu7t7cwAAgDgAAAAABzcIAAAAAAAAgDMwAAAAAAN7uwgAAAAAgH
|
||||
MzMAAAAACH97tzAAAAALu3c3gAAAAAAL+7tzDABAu7f7cAAAAAAACA+3MA7EQAv/sIAA
|
||||
AAAAAAAIAAAAAAAAAIAAAAAA
|
||||
|
||||
--1618492860--2051301190--113853680--
|
15
third_party/python/Lib/test/test_email/data/msg_27.txt
vendored
Normal file
15
third_party/python/Lib/test/test_email/data/msg_27.txt
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
Return-Path: <aperson@dom.ain>
|
||||
Received: by mail.dom.ain (Postfix, from userid 889)
|
||||
id B9D0AD35DB; Tue, 4 Jun 2002 21:46:59 -0400 (EDT)
|
||||
Message-ID: <15613.28051.707126.569693@dom.ain>
|
||||
Date: Tue, 4 Jun 2002 21:46:59 -0400
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: bug demonstration
|
||||
12345678911234567892123456789312345678941234567895123456789612345678971234567898112345678911234567892123456789112345678911234567892123456789
|
||||
more text
|
||||
From: aperson@dom.ain (Anne P. Erson)
|
||||
To: bperson@dom.ain (Barney P. Erson)
|
||||
|
||||
test
|
25
third_party/python/Lib/test/test_email/data/msg_28.txt
vendored
Normal file
25
third_party/python/Lib/test/test_email/data/msg_28.txt
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
From: aperson@dom.ain
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/digest; boundary=BOUNDARY
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: message/rfc822
|
||||
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
To: aa@bb.org
|
||||
From: cc@dd.org
|
||||
Subject: ee
|
||||
|
||||
message 1
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: message/rfc822
|
||||
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
To: aa@bb.org
|
||||
From: cc@dd.org
|
||||
Subject: ee
|
||||
|
||||
message 2
|
||||
|
||||
--BOUNDARY--
|
22
third_party/python/Lib/test/test_email/data/msg_29.txt
vendored
Normal file
22
third_party/python/Lib/test/test_email/data/msg_29.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Return-Path: <bbb@zzz.org>
|
||||
Delivered-To: bbb@zzz.org
|
||||
Received: by mail.zzz.org (Postfix, from userid 889)
|
||||
id 27CEAD38CC; Fri, 4 May 2001 14:05:44 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii;
|
||||
title*0*="us-ascii'en'This%20is%20even%20more%20";
|
||||
title*1*="%2A%2A%2Afun%2A%2A%2A%20";
|
||||
title*2="isn't it!"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15090.61304.110929.45684@aaa.zzz.org>
|
||||
From: bbb@ddd.com (John X. Doe)
|
||||
To: bbb@zzz.org
|
||||
Subject: This is a test message
|
||||
Date: Fri, 4 May 2001 14:05:44 -0400
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Do you like this message?
|
||||
|
||||
-Me
|
23
third_party/python/Lib/test/test_email/data/msg_30.txt
vendored
Normal file
23
third_party/python/Lib/test/test_email/data/msg_30.txt
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
From: aperson@dom.ain
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/digest; boundary=BOUNDARY
|
||||
|
||||
--BOUNDARY
|
||||
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
To: aa@bb.org
|
||||
From: cc@dd.org
|
||||
Subject: ee
|
||||
|
||||
message 1
|
||||
|
||||
--BOUNDARY
|
||||
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
To: aa@bb.org
|
||||
From: cc@dd.org
|
||||
Subject: ee
|
||||
|
||||
message 2
|
||||
|
||||
--BOUNDARY--
|
15
third_party/python/Lib/test/test_email/data/msg_31.txt
vendored
Normal file
15
third_party/python/Lib/test/test_email/data/msg_31.txt
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
From: aperson@dom.ain
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=BOUNDARY_
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain
|
||||
|
||||
message 1
|
||||
|
||||
--BOUNDARY
|
||||
Content-Type: text/plain
|
||||
|
||||
message 2
|
||||
|
||||
--BOUNDARY--
|
14
third_party/python/Lib/test/test_email/data/msg_32.txt
vendored
Normal file
14
third_party/python/Lib/test/test_email/data/msg_32.txt
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
Delivered-To: freebsd-isp@freebsd.org
|
||||
Date: Tue, 26 Sep 2000 12:23:03 -0500
|
||||
From: Anne Person <aperson@example.com>
|
||||
To: Barney Dude <bdude@example.com>
|
||||
Subject: Re: Limiting Perl CPU Utilization...
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii
|
||||
Content-Disposition: inline
|
||||
User-Agent: Mutt/1.3.8i
|
||||
Sender: owner-freebsd-isp@FreeBSD.ORG
|
||||
Precedence: bulk
|
||||
X-Loop: FreeBSD.org
|
||||
|
||||
Some message.
|
29
third_party/python/Lib/test/test_email/data/msg_33.txt
vendored
Normal file
29
third_party/python/Lib/test/test_email/data/msg_33.txt
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
Delivered-To: freebsd-isp@freebsd.org
|
||||
Date: Wed, 27 Sep 2000 11:11:09 -0500
|
||||
From: Anne Person <aperson@example.com>
|
||||
To: Barney Dude <bdude@example.com>
|
||||
Subject: Re: Limiting Perl CPU Utilization...
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/signed; micalg*=ansi-x3.4-1968''pgp-md5;
|
||||
protocol*=ansi-x3.4-1968''application%2Fpgp-signature;
|
||||
boundary*="ansi-x3.4-1968''EeQfGwPcQSOJBaQU"
|
||||
Content-Disposition: inline
|
||||
Sender: owner-freebsd-isp@FreeBSD.ORG
|
||||
Precedence: bulk
|
||||
X-Loop: FreeBSD.org
|
||||
|
||||
|
||||
--EeQfGwPcQSOJBaQU
|
||||
Content-Type: text/plain; charset*=ansi-x3.4-1968''us-ascii
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
part 1
|
||||
|
||||
--EeQfGwPcQSOJBaQU
|
||||
Content-Type: text/plain
|
||||
Content-Disposition: inline
|
||||
|
||||
part 2
|
||||
|
||||
--EeQfGwPcQSOJBaQU--
|
19
third_party/python/Lib/test/test_email/data/msg_34.txt
vendored
Normal file
19
third_party/python/Lib/test/test_email/data/msg_34.txt
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
From: aperson@dom.ain
|
||||
To: bperson@dom.ain
|
||||
Content-Type: multipart/digest; boundary=XYZ
|
||||
|
||||
--XYZ
|
||||
Content-Type: text/plain
|
||||
|
||||
|
||||
This is a text plain part that is counter to recommended practice in
|
||||
RFC 2046, $5.1.5, but is not illegal
|
||||
|
||||
--XYZ
|
||||
|
||||
From: cperson@dom.ain
|
||||
To: dperson@dom.ain
|
||||
|
||||
A submessage
|
||||
|
||||
--XYZ--
|
4
third_party/python/Lib/test/test_email/data/msg_35.txt
vendored
Normal file
4
third_party/python/Lib/test/test_email/data/msg_35.txt
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
From: aperson@dom.ain
|
||||
To: bperson@dom.ain
|
||||
Subject: here's something interesting
|
||||
counter to RFC 2822, there's no separating newline here
|
40
third_party/python/Lib/test/test_email/data/msg_36.txt
vendored
Normal file
40
third_party/python/Lib/test/test_email/data/msg_36.txt
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
Mime-Version: 1.0
|
||||
Content-Type: Multipart/Mixed; Boundary="NextPart"
|
||||
To: IETF-Announce:;
|
||||
From: Internet-Drafts@ietf.org
|
||||
Subject: I-D ACTION:draft-ietf-mboned-mix-00.txt
|
||||
Date: Tue, 22 Dec 1998 16:55:06 -0500
|
||||
|
||||
--NextPart
|
||||
|
||||
Blah blah blah
|
||||
|
||||
--NextPart
|
||||
Content-Type: Multipart/Alternative; Boundary="OtherAccess"
|
||||
|
||||
--OtherAccess
|
||||
Content-Type: Message/External-body;
|
||||
access-type="mail-server";
|
||||
server="mailserv@ietf.org"
|
||||
|
||||
Content-Type: text/plain
|
||||
Content-ID: <19981222151406.I-D@ietf.org>
|
||||
|
||||
ENCODING mime
|
||||
FILE /internet-drafts/draft-ietf-mboned-mix-00.txt
|
||||
|
||||
--OtherAccess
|
||||
Content-Type: Message/External-body;
|
||||
name="draft-ietf-mboned-mix-00.txt";
|
||||
site="ftp.ietf.org";
|
||||
access-type="anon-ftp";
|
||||
directory="internet-drafts"
|
||||
|
||||
Content-Type: text/plain
|
||||
Content-ID: <19981222151406.I-D@ietf.org>
|
||||
|
||||
|
||||
--OtherAccess--
|
||||
|
||||
--NextPart--
|
||||
|
22
third_party/python/Lib/test/test_email/data/msg_37.txt
vendored
Normal file
22
third_party/python/Lib/test/test_email/data/msg_37.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Content-Type: multipart/mixed; boundary=ABCDE
|
||||
|
||||
--ABCDE
|
||||
Content-Type: text/x-one
|
||||
|
||||
Blah
|
||||
|
||||
--ABCDE
|
||||
--ABCDE
|
||||
Content-Type: text/x-two
|
||||
|
||||
Blah
|
||||
|
||||
--ABCDE
|
||||
--ABCDE
|
||||
--ABCDE
|
||||
--ABCDE
|
||||
Content-Type: text/x-two
|
||||
|
||||
Blah
|
||||
|
||||
--ABCDE--
|
101
third_party/python/Lib/test/test_email/data/msg_38.txt
vendored
Normal file
101
third_party/python/Lib/test/test_email/data/msg_38.txt
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
|
||||
|
||||
------- =_aaaaaaaaaa0
|
||||
Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa1"
|
||||
Content-ID: <20592.1022586929.1@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa2"
|
||||
Content-ID: <20592.1022586929.2@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa2
|
||||
Content-Type: text/plain
|
||||
Content-ID: <20592.1022586929.3@example.com>
|
||||
Content-Description: very tricky
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
Unlike the test test_nested-multiples-with-internal-boundary, this
|
||||
piece of text not only contains the outer boundary tags
|
||||
------- =_aaaaaaaaaa1
|
||||
and
|
||||
------- =_aaaaaaaaaa0
|
||||
but puts them at the start of a line! And, to be even nastier, it
|
||||
even includes a couple of end tags, such as this one:
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
and this one, which is from a multipart we haven't even seen yet!
|
||||
|
||||
------- =_aaaaaaaaaa4--
|
||||
|
||||
This will, I'm sure, cause much breakage of MIME parsers. But, as
|
||||
far as I can tell, it's perfectly legal. I have not yet ever seen
|
||||
a case of this in the wild, but I've seen *similar* things.
|
||||
|
||||
|
||||
------- =_aaaaaaaaaa2
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.4@example.com>
|
||||
Content-Description: patch2
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa2--
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa3"
|
||||
Content-ID: <20592.1022586929.6@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa3
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.7@example.com>
|
||||
Content-Description: patch3
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa3
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.8@example.com>
|
||||
Content-Description: patch4
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa3--
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa4"
|
||||
Content-ID: <20592.1022586929.10@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa4
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.11@example.com>
|
||||
Content-Description: patch5
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa4
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.12@example.com>
|
||||
Content-Description: patch6
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa4--
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
------- =_aaaaaaaaaa0
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
Content-ID: <20592.1022586929.15@example.com>
|
||||
|
||||
--
|
||||
It's never too late to have a happy childhood.
|
||||
|
||||
------- =_aaaaaaaaaa0--
|
83
third_party/python/Lib/test/test_email/data/msg_39.txt
vendored
Normal file
83
third_party/python/Lib/test/test_email/data/msg_39.txt
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0"
|
||||
|
||||
------- =_aaaaaaaaaa0
|
||||
Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa1"
|
||||
Content-ID: <20592.1022586929.1@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1"
|
||||
Content-ID: <20592.1022586929.2@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.3@example.com>
|
||||
Content-Description: patch1
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.4@example.com>
|
||||
Content-Description: patch2
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1"
|
||||
Content-ID: <20592.1022586929.6@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.7@example.com>
|
||||
Content-Description: patch3
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.8@example.com>
|
||||
Content-Description: patch4
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1"
|
||||
Content-ID: <20592.1022586929.10@example.com>
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.11@example.com>
|
||||
Content-Description: patch5
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1
|
||||
Content-Type: application/octet-stream
|
||||
Content-ID: <20592.1022586929.12@example.com>
|
||||
Content-Description: patch6
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
XXX
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
------- =_aaaaaaaaaa1--
|
||||
|
||||
------- =_aaaaaaaaaa0
|
||||
Content-Type: text/plain; charset="us-ascii"
|
||||
Content-ID: <20592.1022586929.15@example.com>
|
||||
|
||||
--
|
||||
It's never too late to have a happy childhood.
|
||||
|
||||
------- =_aaaaaaaaaa0--
|
10
third_party/python/Lib/test/test_email/data/msg_40.txt
vendored
Normal file
10
third_party/python/Lib/test/test_email/data/msg_40.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
MIME-Version: 1.0
|
||||
Content-Type: text/html; boundary="--961284236552522269"
|
||||
|
||||
----961284236552522269
|
||||
Content-Type: text/html;
|
||||
Content-Transfer-Encoding: 7Bit
|
||||
|
||||
<html></html>
|
||||
|
||||
----961284236552522269--
|
8
third_party/python/Lib/test/test_email/data/msg_41.txt
vendored
Normal file
8
third_party/python/Lib/test/test_email/data/msg_41.txt
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
From: "Allison Dunlap" <xxx@example.com>
|
||||
To: yyy@example.com
|
||||
Subject: 64423
|
||||
Date: Sun, 11 Jul 2004 16:09:27 -0300
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
|
||||
Blah blah blah
|
20
third_party/python/Lib/test/test_email/data/msg_42.txt
vendored
Normal file
20
third_party/python/Lib/test/test_email/data/msg_42.txt
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
Content-Type: multipart/mixed; boundary="AAA"
|
||||
From: Mail Delivery Subsystem <xxx@example.com>
|
||||
To: yyy@example.com
|
||||
|
||||
This is a MIME-encapsulated message
|
||||
|
||||
--AAA
|
||||
|
||||
Stuff
|
||||
|
||||
--AAA
|
||||
Content-Type: message/rfc822
|
||||
|
||||
From: webmaster@python.org
|
||||
To: zzz@example.com
|
||||
Content-Type: multipart/mixed; boundary="BBB"
|
||||
|
||||
--BBB--
|
||||
|
||||
--AAA--
|
217
third_party/python/Lib/test/test_email/data/msg_43.txt
vendored
Normal file
217
third_party/python/Lib/test/test_email/data/msg_43.txt
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
From SRS0=aO/p=ON=bag.python.org=None@bounce2.pobox.com Fri Nov 26 21:40:36 2004
|
||||
X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
|
||||
[nil nil nil nil nil nil nil "MAILER DAEMON <>" "MAILER DAEMON <>" nil nil "Banned file: auto__mail.python.bat in mail from you" "^From:" nil nil nil nil "Banned file: auto__mail.python.bat in mail from you" nil nil nil nil nil nil nil]
|
||||
nil)
|
||||
MIME-Version: 1.0
|
||||
Message-Id: <edab.7804f5cb8070@python.org>
|
||||
Content-Type: multipart/report; report-type=delivery-status;
|
||||
charset=utf-8;
|
||||
boundary="----------=_1101526904-1956-5"
|
||||
X-Virus-Scanned: by XS4ALL Virus Scanner
|
||||
X-UIDL: 4\G!!!<c"!UV["!M7C!!
|
||||
From: MAILER DAEMON <>
|
||||
To: <webmaster@python.org>
|
||||
Subject: Banned file: auto__mail.python.bat in mail from you
|
||||
Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
This is a multi-part message in MIME format...
|
||||
|
||||
------------=_1101526904-1956-5
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
BANNED FILENAME ALERT
|
||||
|
||||
Your message to: xxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxx@dot.ca.gov, xxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxx@dot.ca.gov, xxxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxx@dot.ca.gov, xxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxx@dot.ca.gov, xxxx@dot.ca.gov, xxxxxxxx@dot.ca.gov, xxxxxxxxxx@dot.ca.gov, xxxxxxxxxxxxxxxxxx@dot.ca.gov
|
||||
was blocked by our Spam Firewall. The email you sent with the following subject has NOT BEEN DELIVERED:
|
||||
|
||||
Subject: Delivery_failure_notice
|
||||
|
||||
An attachment in that mail was of a file type that the Spam Firewall is set to block.
|
||||
|
||||
|
||||
|
||||
------------=_1101526904-1956-5
|
||||
Content-Type: message/delivery-status
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Description: Delivery error report
|
||||
|
||||
Reporting-MTA: dns; sacspam01.dot.ca.gov
|
||||
Received-From-MTA: smtp; sacspam01.dot.ca.gov ([127.0.0.1])
|
||||
Arrival-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
Final-Recipient: rfc822; xxxxxxx@dot.ca.gov
|
||||
Action: failed
|
||||
Status: 5.7.1
|
||||
Diagnostic-Code: smtp; 550 5.7.1 Message content rejected, id=01956-02-2 - BANNED: auto__mail.python.bat
|
||||
Last-Attempt-Date: Fri, 26 Nov 2004 19:41:44 -0800 (PST)
|
||||
|
||||
------------=_1101526904-1956-5
|
||||
Content-Type: text/rfc822-headers
|
||||
Content-Disposition: inline
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Description: Undelivered-message headers
|
||||
|
||||
Received: from kgsav.org (ppp-70-242-162-63.dsl.spfdmo.swbell.net [70.242.162.63])
|
||||
by sacspam01.dot.ca.gov (Spam Firewall) with SMTP
|
||||
id A232AD03DE3A; Fri, 26 Nov 2004 19:41:35 -0800 (PST)
|
||||
From: webmaster@python.org
|
||||
To: xxxxx@dot.ca.gov
|
||||
Date: Sat, 27 Nov 2004 03:35:30 UTC
|
||||
Subject: Delivery_failure_notice
|
||||
Importance: Normal
|
||||
X-Priority: 3 (Normal)
|
||||
X-MSMail-Priority: Normal
|
||||
Message-ID: <edab.7804f5cb8070@python.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="====67bd2b7a5.f99f7"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
------------=_1101526904-1956-5--
|
||||
|
33
third_party/python/Lib/test/test_email/data/msg_44.txt
vendored
Normal file
33
third_party/python/Lib/test/test_email/data/msg_44.txt
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
Return-Path: <barry@python.org>
|
||||
Delivered-To: barry@python.org
|
||||
Received: by mail.python.org (Postfix, from userid 889)
|
||||
id C2BF0D37C6; Tue, 11 Sep 2001 00:05:05 -0400 (EDT)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="h90VIIIKmx"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Message-ID: <15261.36209.358846.118674@anthem.python.org>
|
||||
From: barry@python.org (Barry A. Warsaw)
|
||||
To: barry@python.org
|
||||
Subject: a simple multipart
|
||||
Date: Tue, 11 Sep 2001 00:05:05 -0400
|
||||
X-Mailer: VM 6.95 under 21.4 (patch 4) "Artificial Intelligence" XEmacs Lucid
|
||||
X-Attribution: BAW
|
||||
X-Oblique-Strategy: Make a door into a window
|
||||
|
||||
|
||||
--h90VIIIKmx
|
||||
Content-Type: text/plain; name="msg.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
a simple kind of mirror
|
||||
to reflect upon our own
|
||||
|
||||
--h90VIIIKmx
|
||||
Content-Type: text/plain; name="msg.txt"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
a simple kind of mirror
|
||||
to reflect upon our own
|
||||
|
||||
--h90VIIIKmx--
|
||||
|
33
third_party/python/Lib/test/test_email/data/msg_45.txt
vendored
Normal file
33
third_party/python/Lib/test/test_email/data/msg_45.txt
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
From: <foo@bar.baz>
|
||||
To: <baz@bar.foo>
|
||||
Subject: test
|
||||
X-Long-Line: Some really long line contains a lot of text and thus has to be rewrapped because it is some
|
||||
really long
|
||||
line
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/signed; boundary="borderline";
|
||||
protocol="application/pgp-signature"; micalg=pgp-sha1
|
||||
|
||||
This is an OpenPGP/MIME signed message (RFC 2440 and 3156)
|
||||
--borderline
|
||||
Content-Type: text/plain
|
||||
X-Long-Line: Another really long line contains a lot of text and thus has to be rewrapped because it is another
|
||||
really long
|
||||
line
|
||||
|
||||
This is the signed contents.
|
||||
|
||||
--borderline
|
||||
Content-Type: application/pgp-signature; name="signature.asc"
|
||||
Content-Description: OpenPGP digital signature
|
||||
Content-Disposition: attachment; filename="signature.asc"
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v2.0.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFG03voRhp6o4m9dFsRApSZAKCCAN3IkJlVRg6NvAiMHlvvIuMGPQCeLZtj
|
||||
FGwfnRHFBFO/S4/DKysm0lI=
|
||||
=t7+s
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
--borderline--
|
23
third_party/python/Lib/test/test_email/data/msg_46.txt
vendored
Normal file
23
third_party/python/Lib/test/test_email/data/msg_46.txt
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Return-Path: <sender@example.net>
|
||||
Delivery-Date: Mon, 08 Feb 2010 14:05:16 +0100
|
||||
Received: from example.org (example.org [64.5.53.58])
|
||||
by example.net (node=mxbap2) with ESMTP (Nemesis)
|
||||
id UNIQUE for someone@example.com; Mon, 08 Feb 2010 14:05:16 +0100
|
||||
Date: Mon, 01 Feb 2010 12:21:16 +0100
|
||||
From: "Sender" <sender@example.net>
|
||||
To: <someone@example.com>
|
||||
Subject: GroupwiseForwardingTest
|
||||
Mime-Version: 1.0
|
||||
Content-Type: message/rfc822
|
||||
|
||||
Return-path: <sender@example.net>
|
||||
Message-ID: <4B66B890.4070408@teconcept.de>
|
||||
Date: Mon, 01 Feb 2010 12:18:40 +0100
|
||||
From: "Dr. Sender" <sender@example.net>
|
||||
MIME-Version: 1.0
|
||||
To: "Recipient" <recipient@example.com>
|
||||
Subject: GroupwiseForwardingTest
|
||||
Content-Type: text/plain; charset=ISO-8859-15
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Testing email forwarding with Groupwise 1.2.2010
|
198
third_party/python/Lib/test/test_email/test__encoded_words.py
vendored
Normal file
198
third_party/python/Lib/test/test_email/test__encoded_words.py
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
import unittest
|
||||
from email import _encoded_words as _ew
|
||||
from email import errors
|
||||
from test.test_email import TestEmailBase
|
||||
|
||||
|
||||
class TestDecodeQ(TestEmailBase):
|
||||
|
||||
def _test(self, source, ex_result, ex_defects=[]):
|
||||
result, defects = _ew.decode_q(source)
|
||||
self.assertEqual(result, ex_result)
|
||||
self.assertDefectsEqual(defects, ex_defects)
|
||||
|
||||
def test_no_encoded(self):
|
||||
self._test(b'foobar', b'foobar')
|
||||
|
||||
def test_spaces(self):
|
||||
self._test(b'foo=20bar=20', b'foo bar ')
|
||||
self._test(b'foo_bar_', b'foo bar ')
|
||||
|
||||
def test_run_of_encoded(self):
|
||||
self._test(b'foo=20=20=21=2Cbar', b'foo !,bar')
|
||||
|
||||
|
||||
class TestDecodeB(TestEmailBase):
|
||||
|
||||
def _test(self, source, ex_result, ex_defects=[]):
|
||||
result, defects = _ew.decode_b(source)
|
||||
self.assertEqual(result, ex_result)
|
||||
self.assertDefectsEqual(defects, ex_defects)
|
||||
|
||||
def test_simple(self):
|
||||
self._test(b'Zm9v', b'foo')
|
||||
|
||||
def test_missing_padding(self):
|
||||
# 1 missing padding character
|
||||
self._test(b'dmk', b'vi', [errors.InvalidBase64PaddingDefect])
|
||||
# 2 missing padding characters
|
||||
self._test(b'dg', b'v', [errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_invalid_character(self):
|
||||
self._test(b'dm\x01k===', b'vi', [errors.InvalidBase64CharactersDefect])
|
||||
|
||||
def test_invalid_character_and_bad_padding(self):
|
||||
self._test(b'dm\x01k', b'vi', [errors.InvalidBase64CharactersDefect,
|
||||
errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_invalid_length(self):
|
||||
self._test(b'abcde', b'abcde', [errors.InvalidBase64LengthDefect])
|
||||
|
||||
|
||||
class TestDecode(TestEmailBase):
|
||||
|
||||
def test_wrong_format_input_raises(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_ew.decode('=?badone?=')
|
||||
with self.assertRaises(ValueError):
|
||||
_ew.decode('=?')
|
||||
with self.assertRaises(ValueError):
|
||||
_ew.decode('')
|
||||
|
||||
def _test(self, source, result, charset='us-ascii', lang='', defects=[]):
|
||||
res, char, l, d = _ew.decode(source)
|
||||
self.assertEqual(res, result)
|
||||
self.assertEqual(char, charset)
|
||||
self.assertEqual(l, lang)
|
||||
self.assertDefectsEqual(d, defects)
|
||||
|
||||
def test_simple_q(self):
|
||||
self._test('=?us-ascii?q?foo?=', 'foo')
|
||||
|
||||
def test_simple_b(self):
|
||||
self._test('=?us-ascii?b?dmk=?=', 'vi')
|
||||
|
||||
def test_q_case_ignored(self):
|
||||
self._test('=?us-ascii?Q?foo?=', 'foo')
|
||||
|
||||
def test_b_case_ignored(self):
|
||||
self._test('=?us-ascii?B?dmk=?=', 'vi')
|
||||
|
||||
def test_non_trivial_q(self):
|
||||
self._test('=?latin-1?q?=20F=fcr=20Elise=20?=', ' Für Elise ', 'latin-1')
|
||||
|
||||
def test_q_escaped_bytes_preserved(self):
|
||||
self._test(b'=?us-ascii?q?=20\xACfoo?='.decode('us-ascii',
|
||||
'surrogateescape'),
|
||||
' \uDCACfoo',
|
||||
defects = [errors.UndecodableBytesDefect])
|
||||
|
||||
def test_b_undecodable_bytes_ignored_with_defect(self):
|
||||
self._test(b'=?us-ascii?b?dm\xACk?='.decode('us-ascii',
|
||||
'surrogateescape'),
|
||||
'vi',
|
||||
defects = [
|
||||
errors.InvalidBase64CharactersDefect,
|
||||
errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_b_invalid_bytes_ignored_with_defect(self):
|
||||
self._test('=?us-ascii?b?dm\x01k===?=',
|
||||
'vi',
|
||||
defects = [errors.InvalidBase64CharactersDefect])
|
||||
|
||||
def test_b_invalid_bytes_incorrect_padding(self):
|
||||
self._test('=?us-ascii?b?dm\x01k?=',
|
||||
'vi',
|
||||
defects = [
|
||||
errors.InvalidBase64CharactersDefect,
|
||||
errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_b_padding_defect(self):
|
||||
self._test('=?us-ascii?b?dmk?=',
|
||||
'vi',
|
||||
defects = [errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_nonnull_lang(self):
|
||||
self._test('=?us-ascii*jive?q?test?=', 'test', lang='jive')
|
||||
|
||||
def test_unknown_8bit_charset(self):
|
||||
self._test('=?unknown-8bit?q?foo=ACbar?=',
|
||||
b'foo\xacbar'.decode('ascii', 'surrogateescape'),
|
||||
charset = 'unknown-8bit',
|
||||
defects = [])
|
||||
|
||||
def test_unknown_charset(self):
|
||||
self._test('=?foobar?q?foo=ACbar?=',
|
||||
b'foo\xacbar'.decode('ascii', 'surrogateescape'),
|
||||
charset = 'foobar',
|
||||
# XXX Should this be a new Defect instead?
|
||||
defects = [errors.CharsetError])
|
||||
|
||||
def test_q_nonascii(self):
|
||||
self._test('=?utf-8?q?=C3=89ric?=',
|
||||
'Éric',
|
||||
charset='utf-8')
|
||||
|
||||
|
||||
class TestEncodeQ(TestEmailBase):
|
||||
|
||||
def _test(self, src, expected):
|
||||
self.assertEqual(_ew.encode_q(src), expected)
|
||||
|
||||
def test_all_safe(self):
|
||||
self._test(b'foobar', 'foobar')
|
||||
|
||||
def test_spaces(self):
|
||||
self._test(b'foo bar ', 'foo_bar_')
|
||||
|
||||
def test_run_of_encodables(self):
|
||||
self._test(b'foo ,,bar', 'foo__=2C=2Cbar')
|
||||
|
||||
|
||||
class TestEncodeB(TestEmailBase):
|
||||
|
||||
def test_simple(self):
|
||||
self.assertEqual(_ew.encode_b(b'foo'), 'Zm9v')
|
||||
|
||||
def test_padding(self):
|
||||
self.assertEqual(_ew.encode_b(b'vi'), 'dmk=')
|
||||
|
||||
|
||||
class TestEncode(TestEmailBase):
|
||||
|
||||
def test_q(self):
|
||||
self.assertEqual(_ew.encode('foo', 'utf-8', 'q'), '=?utf-8?q?foo?=')
|
||||
|
||||
def test_b(self):
|
||||
self.assertEqual(_ew.encode('foo', 'utf-8', 'b'), '=?utf-8?b?Zm9v?=')
|
||||
|
||||
def test_auto_q(self):
|
||||
self.assertEqual(_ew.encode('foo', 'utf-8'), '=?utf-8?q?foo?=')
|
||||
|
||||
def test_auto_q_if_short_mostly_safe(self):
|
||||
self.assertEqual(_ew.encode('vi.', 'utf-8'), '=?utf-8?q?vi=2E?=')
|
||||
|
||||
def test_auto_b_if_enough_unsafe(self):
|
||||
self.assertEqual(_ew.encode('.....', 'utf-8'), '=?utf-8?b?Li4uLi4=?=')
|
||||
|
||||
def test_auto_b_if_long_unsafe(self):
|
||||
self.assertEqual(_ew.encode('vi.vi.vi.vi.vi.', 'utf-8'),
|
||||
'=?utf-8?b?dmkudmkudmkudmkudmku?=')
|
||||
|
||||
def test_auto_q_if_long_mostly_safe(self):
|
||||
self.assertEqual(_ew.encode('vi vi vi.vi ', 'utf-8'),
|
||||
'=?utf-8?q?vi_vi_vi=2Evi_?=')
|
||||
|
||||
def test_utf8_default(self):
|
||||
self.assertEqual(_ew.encode('foo'), '=?utf-8?q?foo?=')
|
||||
|
||||
def test_lang(self):
|
||||
self.assertEqual(_ew.encode('foo', lang='jive'), '=?utf-8*jive?q?foo?=')
|
||||
|
||||
def test_unknown_8bit(self):
|
||||
self.assertEqual(_ew.encode('foo\uDCACbar', charset='unknown-8bit'),
|
||||
'=?unknown-8bit?q?foo=ACbar?=')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
2791
third_party/python/Lib/test/test_email/test__header_value_parser.py
vendored
Normal file
2791
third_party/python/Lib/test/test_email/test__header_value_parser.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
81
third_party/python/Lib/test/test_email/test_asian_codecs.py
vendored
Normal file
81
third_party/python/Lib/test/test_email/test_asian_codecs.py
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
# Copyright (C) 2002-2006 Python Software Foundation
|
||||
# Contact: email-sig@python.org
|
||||
# email package unit tests for (optional) Asian codecs
|
||||
|
||||
import unittest
|
||||
|
||||
from test.test_email import TestEmailBase
|
||||
from email.charset import Charset
|
||||
from email.header import Header, decode_header
|
||||
from email.message import Message
|
||||
|
||||
# We're compatible with Python 2.3, but it doesn't have the built-in Asian
|
||||
# codecs, so we have to skip all these tests.
|
||||
try:
|
||||
str(b'foo', 'euc-jp')
|
||||
except LookupError:
|
||||
raise unittest.SkipTest
|
||||
|
||||
|
||||
|
||||
class TestEmailAsianCodecs(TestEmailBase):
|
||||
def test_japanese_codecs(self):
|
||||
eq = self.ndiffAssertEqual
|
||||
jcode = "euc-jp"
|
||||
gcode = "iso-8859-1"
|
||||
j = Charset(jcode)
|
||||
g = Charset(gcode)
|
||||
h = Header("Hello World!")
|
||||
jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc'
|
||||
b'\xa5\xeb\xa5\xc9\xa1\xaa', jcode)
|
||||
ghello = str(b'Gr\xfc\xdf Gott!', gcode)
|
||||
h.append(jhello, j)
|
||||
h.append(ghello, g)
|
||||
# BAW: This used to -- and maybe should -- fold the two iso-8859-1
|
||||
# chunks into a single encoded word. However it doesn't violate the
|
||||
# standard to have them as two encoded chunks and maybe it's
|
||||
# reasonable <wink> for each .append() call to result in a separate
|
||||
# encoded word.
|
||||
eq(h.encode(), """\
|
||||
Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=
|
||||
=?iso-8859-1?q?Gr=FC=DF_Gott!?=""")
|
||||
eq(decode_header(h.encode()),
|
||||
[(b'Hello World! ', None),
|
||||
(b'\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'),
|
||||
(b'Gr\xfc\xdf Gott!', gcode)])
|
||||
subject_bytes = (b'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5'
|
||||
b'\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2'
|
||||
b'\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3'
|
||||
b'\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9')
|
||||
subject = str(subject_bytes, jcode)
|
||||
h = Header(subject, j, header_name="Subject")
|
||||
# test a very long header
|
||||
enc = h.encode()
|
||||
# TK: splitting point may differ by codec design and/or Header encoding
|
||||
eq(enc , """\
|
||||
=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=
|
||||
=?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""")
|
||||
# TK: full decode comparison
|
||||
eq(str(h).encode(jcode), subject_bytes)
|
||||
|
||||
def test_payload_encoding_utf8(self):
|
||||
jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc'
|
||||
b'\xa5\xeb\xa5\xc9\xa1\xaa', 'euc-jp')
|
||||
msg = Message()
|
||||
msg.set_payload(jhello, 'utf-8')
|
||||
ustr = msg.get_payload(decode=True).decode(msg.get_content_charset())
|
||||
self.assertEqual(jhello, ustr)
|
||||
|
||||
def test_payload_encoding(self):
|
||||
jcode = 'euc-jp'
|
||||
jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc'
|
||||
b'\xa5\xeb\xa5\xc9\xa1\xaa', jcode)
|
||||
msg = Message()
|
||||
msg.set_payload(jhello, jcode)
|
||||
ustr = msg.get_payload(decode=True).decode(msg.get_content_charset())
|
||||
self.assertEqual(jhello, ustr)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
796
third_party/python/Lib/test/test_email/test_contentmanager.py
vendored
Normal file
796
third_party/python/Lib/test/test_email/test_contentmanager.py
vendored
Normal file
|
@ -0,0 +1,796 @@
|
|||
import unittest
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
import textwrap
|
||||
from email import policy
|
||||
from email.message import EmailMessage
|
||||
from email.contentmanager import ContentManager, raw_data_manager
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestContentManager(TestEmailBase):
|
||||
|
||||
policy = policy.default
|
||||
message = EmailMessage
|
||||
|
||||
get_key_params = {
|
||||
'full_type': (1, 'text/plain',),
|
||||
'maintype_only': (2, 'text',),
|
||||
'null_key': (3, '',),
|
||||
}
|
||||
|
||||
def get_key_as_get_content_key(self, order, key):
|
||||
def foo_getter(msg, foo=None):
|
||||
bar = msg['X-Bar-Header']
|
||||
return foo, bar
|
||||
cm = ContentManager()
|
||||
cm.add_get_handler(key, foo_getter)
|
||||
m = self._make_message()
|
||||
m['Content-Type'] = 'text/plain'
|
||||
m['X-Bar-Header'] = 'foo'
|
||||
self.assertEqual(cm.get_content(m, foo='bar'), ('bar', 'foo'))
|
||||
|
||||
def get_key_as_get_content_key_order(self, order, key):
|
||||
def bar_getter(msg):
|
||||
return msg['X-Bar-Header']
|
||||
def foo_getter(msg):
|
||||
return msg['X-Foo-Header']
|
||||
cm = ContentManager()
|
||||
cm.add_get_handler(key, foo_getter)
|
||||
for precedence, key in self.get_key_params.values():
|
||||
if precedence > order:
|
||||
cm.add_get_handler(key, bar_getter)
|
||||
m = self._make_message()
|
||||
m['Content-Type'] = 'text/plain'
|
||||
m['X-Bar-Header'] = 'bar'
|
||||
m['X-Foo-Header'] = 'foo'
|
||||
self.assertEqual(cm.get_content(m), ('foo'))
|
||||
|
||||
def test_get_content_raises_if_unknown_mimetype_and_no_default(self):
|
||||
cm = ContentManager()
|
||||
m = self._make_message()
|
||||
m['Content-Type'] = 'text/plain'
|
||||
with self.assertRaisesRegex(KeyError, 'text/plain'):
|
||||
cm.get_content(m)
|
||||
|
||||
class BaseThing(str):
|
||||
pass
|
||||
baseobject_full_path = __name__ + '.' + 'TestContentManager.BaseThing'
|
||||
class Thing(BaseThing):
|
||||
pass
|
||||
testobject_full_path = __name__ + '.' + 'TestContentManager.Thing'
|
||||
|
||||
set_key_params = {
|
||||
'type': (0, Thing,),
|
||||
'full_path': (1, testobject_full_path,),
|
||||
'qualname': (2, 'TestContentManager.Thing',),
|
||||
'name': (3, 'Thing',),
|
||||
'base_type': (4, BaseThing,),
|
||||
'base_full_path': (5, baseobject_full_path,),
|
||||
'base_qualname': (6, 'TestContentManager.BaseThing',),
|
||||
'base_name': (7, 'BaseThing',),
|
||||
'str_type': (8, str,),
|
||||
'str_full_path': (9, 'builtins.str',),
|
||||
'str_name': (10, 'str',), # str name and qualname are the same
|
||||
'null_key': (11, None,),
|
||||
}
|
||||
|
||||
def set_key_as_set_content_key(self, order, key):
|
||||
def foo_setter(msg, obj, foo=None):
|
||||
msg['X-Foo-Header'] = foo
|
||||
msg.set_payload(obj)
|
||||
cm = ContentManager()
|
||||
cm.add_set_handler(key, foo_setter)
|
||||
m = self._make_message()
|
||||
msg_obj = self.Thing()
|
||||
cm.set_content(m, msg_obj, foo='bar')
|
||||
self.assertEqual(m['X-Foo-Header'], 'bar')
|
||||
self.assertEqual(m.get_payload(), msg_obj)
|
||||
|
||||
def set_key_as_set_content_key_order(self, order, key):
|
||||
def foo_setter(msg, obj):
|
||||
msg['X-FooBar-Header'] = 'foo'
|
||||
msg.set_payload(obj)
|
||||
def bar_setter(msg, obj):
|
||||
msg['X-FooBar-Header'] = 'bar'
|
||||
cm = ContentManager()
|
||||
cm.add_set_handler(key, foo_setter)
|
||||
for precedence, key in self.get_key_params.values():
|
||||
if precedence > order:
|
||||
cm.add_set_handler(key, bar_setter)
|
||||
m = self._make_message()
|
||||
msg_obj = self.Thing()
|
||||
cm.set_content(m, msg_obj)
|
||||
self.assertEqual(m['X-FooBar-Header'], 'foo')
|
||||
self.assertEqual(m.get_payload(), msg_obj)
|
||||
|
||||
def test_set_content_raises_if_unknown_type_and_no_default(self):
|
||||
cm = ContentManager()
|
||||
m = self._make_message()
|
||||
msg_obj = self.Thing()
|
||||
with self.assertRaisesRegex(KeyError, self.testobject_full_path):
|
||||
cm.set_content(m, msg_obj)
|
||||
|
||||
def test_set_content_raises_if_called_on_multipart(self):
|
||||
cm = ContentManager()
|
||||
m = self._make_message()
|
||||
m['Content-Type'] = 'multipart/foo'
|
||||
with self.assertRaises(TypeError):
|
||||
cm.set_content(m, 'test')
|
||||
|
||||
def test_set_content_calls_clear_content(self):
|
||||
m = self._make_message()
|
||||
m['Content-Foo'] = 'bar'
|
||||
m['Content-Type'] = 'text/html'
|
||||
m['To'] = 'test'
|
||||
m.set_payload('abc')
|
||||
cm = ContentManager()
|
||||
cm.add_set_handler(str, lambda *args, **kw: None)
|
||||
m.set_content('xyz', content_manager=cm)
|
||||
self.assertIsNone(m['Content-Foo'])
|
||||
self.assertIsNone(m['Content-Type'])
|
||||
self.assertEqual(m['To'], 'test')
|
||||
self.assertIsNone(m.get_payload())
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestRawDataManager(TestEmailBase):
|
||||
# Note: these tests are dependent on the order in which headers are added
|
||||
# to the message objects by the code. There's no defined ordering in
|
||||
# RFC5322/MIME, so this makes the tests more fragile than the standards
|
||||
# require. However, if the header order changes it is best to understand
|
||||
# *why*, and make sure it isn't a subtle bug in whatever change was
|
||||
# applied.
|
||||
|
||||
policy = policy.default.clone(max_line_length=60,
|
||||
content_manager=raw_data_manager)
|
||||
message = EmailMessage
|
||||
|
||||
def test_get_text_plain(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain
|
||||
|
||||
Basic text.
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m), "Basic text.\n")
|
||||
|
||||
def test_get_text_html(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/html
|
||||
|
||||
<p>Basic text.</p>
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m),
|
||||
"<p>Basic text.</p>\n")
|
||||
|
||||
def test_get_text_plain_latin1(self):
|
||||
m = self._bytes_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset=latin1
|
||||
|
||||
Basìc tëxt.
|
||||
""").encode('latin1'))
|
||||
self.assertEqual(raw_data_manager.get_content(m), "Basìc tëxt.\n")
|
||||
|
||||
def test_get_text_plain_latin1_quoted_printable(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="latin-1"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
Bas=ECc t=EBxt.
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m), "Basìc tëxt.\n")
|
||||
|
||||
def test_get_text_plain_utf8_base64(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
QmFzw6xjIHTDq3h0Lgo=
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m), "Basìc tëxt.\n")
|
||||
|
||||
def test_get_text_plain_bad_utf8_quoted_printable(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
Bas=c3=acc t=c3=abxt=fd.
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m), "Basìc tëxt<78>.\n")
|
||||
|
||||
def test_get_text_plain_bad_utf8_quoted_printable_ignore_errors(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
Bas=c3=acc t=c3=abxt=fd.
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m, errors='ignore'),
|
||||
"Basìc tëxt.\n")
|
||||
|
||||
def test_get_text_plain_utf8_base64_recoverable_bad_CTE_data(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
QmFzw6xjIHTDq3h0Lgo\xFF=
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m, errors='ignore'),
|
||||
"Basìc tëxt.\n")
|
||||
|
||||
def test_get_text_invalid_keyword(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: text/plain
|
||||
|
||||
Basic text.
|
||||
"""))
|
||||
with self.assertRaises(TypeError):
|
||||
raw_data_manager.get_content(m, foo='ignore')
|
||||
|
||||
def test_get_non_text(self):
|
||||
template = textwrap.dedent("""\
|
||||
Content-Type: {}
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
Ym9ndXMgZGF0YQ==
|
||||
""")
|
||||
for maintype in 'audio image video application'.split():
|
||||
with self.subTest(maintype=maintype):
|
||||
m = self._str_msg(template.format(maintype+'/foo'))
|
||||
self.assertEqual(raw_data_manager.get_content(m), b"bogus data")
|
||||
|
||||
def test_get_non_text_invalid_keyword(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: image/jpg
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
Ym9ndXMgZGF0YQ==
|
||||
"""))
|
||||
with self.assertRaises(TypeError):
|
||||
raw_data_manager.get_content(m, errors='ignore')
|
||||
|
||||
def test_get_raises_on_multipart(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
--===--
|
||||
"""))
|
||||
with self.assertRaises(KeyError):
|
||||
raw_data_manager.get_content(m)
|
||||
|
||||
def test_get_message_rfc822_and_external_body(self):
|
||||
template = textwrap.dedent("""\
|
||||
Content-Type: message/{}
|
||||
|
||||
To: foo@example.com
|
||||
From: bar@example.com
|
||||
Subject: example
|
||||
|
||||
an example message
|
||||
""")
|
||||
for subtype in 'rfc822 external-body'.split():
|
||||
with self.subTest(subtype=subtype):
|
||||
m = self._str_msg(template.format(subtype))
|
||||
sub_msg = raw_data_manager.get_content(m)
|
||||
self.assertIsInstance(sub_msg, self.message)
|
||||
self.assertEqual(raw_data_manager.get_content(sub_msg),
|
||||
"an example message\n")
|
||||
self.assertEqual(sub_msg['to'], 'foo@example.com')
|
||||
self.assertEqual(sub_msg['from'].addresses[0].username, 'bar')
|
||||
|
||||
def test_get_message_non_rfc822_or_external_body_yields_bytes(self):
|
||||
m = self._str_msg(textwrap.dedent("""\
|
||||
Content-Type: message/partial
|
||||
|
||||
To: foo@example.com
|
||||
From: bar@example.com
|
||||
Subject: example
|
||||
|
||||
The real body is in another message.
|
||||
"""))
|
||||
self.assertEqual(raw_data_manager.get_content(m)[:10], b'To: foo@ex')
|
||||
|
||||
def test_set_text_plain(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Simple message.
|
||||
"""))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_html(self):
|
||||
m = self._make_message()
|
||||
content = "<p>Simple message.</p>\n"
|
||||
raw_data_manager.set_content(m, content, subtype='html')
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: text/html; charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
<p>Simple message.</p>
|
||||
"""))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_charset_latin_1(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
raw_data_manager.set_content(m, content, charset='latin-1')
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Simple message.
|
||||
"""))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_short_line_minimal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = "et là il est monté sur moi et il commence à m'éto.\n"
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
et là il est monté sur moi et il commence à m'éto.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_long_line_minimal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = ("j'ai un problème de python. il est sorti de son"
|
||||
" vivarium. et là il est monté sur moi et il commence"
|
||||
" à m'éto.\n")
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
j'ai un probl=C3=A8me de python. il est sorti de son vivari=
|
||||
um. et l=C3=A0 il est mont=C3=A9 sur moi et il commence =
|
||||
=C3=A0 m'=C3=A9to.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_11_lines_long_line_minimal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = '\n'*10 + (
|
||||
"j'ai un problème de python. il est sorti de son"
|
||||
" vivarium. et là il est monté sur moi et il commence"
|
||||
" à m'éto.\n")
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
""" + '\n'*10 + """
|
||||
j'ai un probl=C3=A8me de python. il est sorti de son vivari=
|
||||
um. et l=C3=A0 il est mont=C3=A9 sur moi et il commence =
|
||||
=C3=A0 m'=C3=A9to.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_maximal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = "áàäéèęöő.\n"
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
áàäéèęöő.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_11_lines_maximal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = '\n'*10 + "áàäéèęöő.\n"
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
""" + '\n'*10 + """
|
||||
áàäéèęöő.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_long_line_maximal_non_ascii_heuristics(self):
|
||||
m = self._make_message()
|
||||
content = ("áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n")
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
w6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOoxJnD
|
||||
tsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TDqcOo
|
||||
xJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOgw6TD
|
||||
qcOoxJnDtsWRw6HDoMOkw6nDqMSZw7bFkcOhw6DDpMOpw6jEmcO2xZHDocOg
|
||||
w6TDqcOoxJnDtsWRLgo=
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_11_lines_long_line_maximal_non_ascii_heuristics(self):
|
||||
# Yes, it chooses "wrong" here. It's a heuristic. So this result
|
||||
# could change if we come up with a better heuristic.
|
||||
m = self._make_message()
|
||||
content = ('\n'*10 +
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n")
|
||||
raw_data_manager.set_content(m, "\n"*10 +
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő"
|
||||
"áàäéèęöőáàäéèęöőáàäéèęöőáàäéèęöő.\n")
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
""" + '\n'*10 + """
|
||||
=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=
|
||||
=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=
|
||||
=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=
|
||||
=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=
|
||||
=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=
|
||||
=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=
|
||||
=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=
|
||||
=A4=C3=A9=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=
|
||||
=C3=A8=C4=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=
|
||||
=99=C3=B6=C5=91=C3=A1=C3=A0=C3=A4=C3=A9=C3=A8=C4=99=C3=B6=
|
||||
=C5=91.
|
||||
""").encode('utf-8'))
|
||||
self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_text_non_ascii_with_cte_7bit_raises(self):
|
||||
m = self._make_message()
|
||||
with self.assertRaises(UnicodeError):
|
||||
raw_data_manager.set_content(m,"áàäéèęöő.\n", cte='7bit')
|
||||
|
||||
def test_set_text_non_ascii_with_charset_ascii_raises(self):
|
||||
m = self._make_message()
|
||||
with self.assertRaises(UnicodeError):
|
||||
raw_data_manager.set_content(m,"áàäéèęöő.\n", charset='ascii')
|
||||
|
||||
def test_set_text_non_ascii_with_cte_7bit_and_charset_ascii_raises(self):
|
||||
m = self._make_message()
|
||||
with self.assertRaises(UnicodeError):
|
||||
raw_data_manager.set_content(m,"áàäéèęöő.\n", cte='7bit', charset='ascii')
|
||||
|
||||
def test_set_message(self):
|
||||
m = self._make_message()
|
||||
m['Subject'] = "Forwarded message"
|
||||
content = self._make_message()
|
||||
content['To'] = 'python@vivarium.org'
|
||||
content['From'] = 'police@monty.org'
|
||||
content['Subject'] = "get back in your box"
|
||||
content.set_content("Or face the comfy chair.")
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Subject: Forwarded message
|
||||
Content-Type: message/rfc822
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
To: python@vivarium.org
|
||||
From: police@monty.org
|
||||
Subject: get back in your box
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
MIME-Version: 1.0
|
||||
|
||||
Or face the comfy chair.
|
||||
"""))
|
||||
payload = m.get_payload(0)
|
||||
self.assertIsInstance(payload, self.message)
|
||||
self.assertEqual(str(payload), str(content))
|
||||
self.assertIsInstance(m.get_content(), self.message)
|
||||
self.assertEqual(str(m.get_content()), str(content))
|
||||
|
||||
def test_set_message_with_non_ascii_and_coercion_to_7bit(self):
|
||||
m = self._make_message()
|
||||
m['Subject'] = "Escape report"
|
||||
content = self._make_message()
|
||||
content['To'] = 'police@monty.org'
|
||||
content['From'] = 'victim@monty.org'
|
||||
content['Subject'] = "Help"
|
||||
content.set_content("j'ai un problème de python. il est sorti de son"
|
||||
" vivarium.")
|
||||
raw_data_manager.set_content(m, content)
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Subject: Escape report
|
||||
Content-Type: message/rfc822
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
To: police@monty.org
|
||||
From: victim@monty.org
|
||||
Subject: Help
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
|
||||
j'ai un problème de python. il est sorti de son vivarium.
|
||||
""").encode('utf-8'))
|
||||
# The choice of base64 for the body encoding is because generator
|
||||
# doesn't bother with heuristics and uses it unconditionally for utf-8
|
||||
# text.
|
||||
# XXX: the first cte should be 7bit, too...that's a generator bug.
|
||||
# XXX: the line length in the body also looks like a generator bug.
|
||||
self.assertEqual(m.as_string(maxheaderlen=self.policy.max_line_length),
|
||||
textwrap.dedent("""\
|
||||
Subject: Escape report
|
||||
Content-Type: message/rfc822
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
To: police@monty.org
|
||||
From: victim@monty.org
|
||||
Subject: Help
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: base64
|
||||
MIME-Version: 1.0
|
||||
|
||||
aidhaSB1biBwcm9ibMOobWUgZGUgcHl0aG9uLiBpbCBlc3Qgc29ydGkgZGUgc29uIHZpdmFyaXVt
|
||||
Lgo=
|
||||
"""))
|
||||
self.assertIsInstance(m.get_content(), self.message)
|
||||
self.assertEqual(str(m.get_content()), str(content))
|
||||
|
||||
def test_set_message_invalid_cte_raises(self):
|
||||
m = self._make_message()
|
||||
content = self._make_message()
|
||||
for cte in 'quoted-printable base64'.split():
|
||||
for subtype in 'rfc822 external-body'.split():
|
||||
with self.subTest(cte=cte, subtype=subtype):
|
||||
with self.assertRaises(ValueError) as ar:
|
||||
m.set_content(content, subtype, cte=cte)
|
||||
exc = str(ar.exception)
|
||||
self.assertIn(cte, exc)
|
||||
self.assertIn(subtype, exc)
|
||||
subtype = 'external-body'
|
||||
for cte in '8bit binary'.split():
|
||||
with self.subTest(cte=cte, subtype=subtype):
|
||||
with self.assertRaises(ValueError) as ar:
|
||||
m.set_content(content, subtype, cte=cte)
|
||||
exc = str(ar.exception)
|
||||
self.assertIn(cte, exc)
|
||||
self.assertIn(subtype, exc)
|
||||
|
||||
def test_set_image_jpg(self):
|
||||
for content in (b"bogus content",
|
||||
bytearray(b"bogus content"),
|
||||
memoryview(b"bogus content")):
|
||||
with self.subTest(content=content):
|
||||
m = self._make_message()
|
||||
raw_data_manager.set_content(m, content, 'image', 'jpeg')
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: image/jpeg
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
Ym9ndXMgY29udGVudA==
|
||||
"""))
|
||||
self.assertEqual(m.get_payload(decode=True), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_audio_aif_with_quoted_printable_cte(self):
|
||||
# Why you would use qp, I don't know, but it is technically supported.
|
||||
# XXX: the incorrect line length is because binascii.b2a_qp doesn't
|
||||
# support a line length parameter, but we must use it to get newline
|
||||
# encoding.
|
||||
# XXX: what about that lack of tailing newline? Do we actually handle
|
||||
# that correctly in all cases? That is, if the *source* has an
|
||||
# unencoded newline, do we add an extra newline to the returned payload
|
||||
# or not? And can that actually be disambiguated based on the RFC?
|
||||
m = self._make_message()
|
||||
content = b'b\xFFgus\tcon\nt\rent ' + b'z'*100
|
||||
m.set_content(content, 'audio', 'aif', cte='quoted-printable')
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: audio/aif
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
MIME-Version: 1.0
|
||||
|
||||
b=FFgus=09con=0At=0Dent=20zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
|
||||
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz""").encode('latin-1'))
|
||||
self.assertEqual(m.get_payload(decode=True), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_video_mpeg_with_binary_cte(self):
|
||||
m = self._make_message()
|
||||
content = b'b\xFFgus\tcon\nt\rent ' + b'z'*100
|
||||
m.set_content(content, 'video', 'mpeg', cte='binary')
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: video/mpeg
|
||||
Content-Transfer-Encoding: binary
|
||||
MIME-Version: 1.0
|
||||
|
||||
""").encode('ascii') +
|
||||
# XXX: the second \n ought to be a \r, but generator gets it wrong.
|
||||
# THIS MEANS WE DON'T ACTUALLY SUPPORT THE 'binary' CTE.
|
||||
b'b\xFFgus\tcon\nt\nent zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' +
|
||||
b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz')
|
||||
self.assertEqual(m.get_payload(decode=True), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_application_octet_stream_with_8bit_cte(self):
|
||||
# In 8bit mode, universal line end logic applies. It is up to the
|
||||
# application to make sure the lines are short enough; we don't check.
|
||||
m = self._make_message()
|
||||
content = b'b\xFFgus\tcon\nt\rent\n' + b'z'*60 + b'\n'
|
||||
m.set_content(content, 'application', 'octet-stream', cte='8bit')
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: application/octet-stream
|
||||
Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
|
||||
""").encode('ascii') +
|
||||
b'b\xFFgus\tcon\nt\nent\n' +
|
||||
b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\n')
|
||||
self.assertEqual(m.get_payload(decode=True), content)
|
||||
self.assertEqual(m.get_content(), content)
|
||||
|
||||
def test_set_headers_from_header_objects(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
header_factory = self.policy.header_factory
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
header_factory("To", "foo@example.com"),
|
||||
header_factory("From", "foo@example.com"),
|
||||
header_factory("Subject", "I'm talking to myself.")))
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
To: foo@example.com
|
||||
From: foo@example.com
|
||||
Subject: I'm talking to myself.
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Simple message.
|
||||
"""))
|
||||
|
||||
def test_set_headers_from_strings(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
"X-Foo-Header: foo",
|
||||
"X-Bar-Header: bar",))
|
||||
self.assertEqual(str(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
X-Foo-Header: foo
|
||||
X-Bar-Header: bar
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Simple message.
|
||||
"""))
|
||||
|
||||
def test_set_headers_with_invalid_duplicate_string_header_raises(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
with self.assertRaisesRegex(ValueError, 'Content-Type'):
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
"Content-Type: foo/bar",)
|
||||
)
|
||||
|
||||
def test_set_headers_with_invalid_duplicate_header_header_raises(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
header_factory = self.policy.header_factory
|
||||
with self.assertRaisesRegex(ValueError, 'Content-Type'):
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
header_factory("Content-Type", " foo/bar"),)
|
||||
)
|
||||
|
||||
def test_set_headers_with_defective_string_header_raises(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
with self.assertRaisesRegex(ValueError, 'a@fairly@@invalid@address'):
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
'To: a@fairly@@invalid@address',)
|
||||
)
|
||||
print(m['To'].defects)
|
||||
|
||||
def test_set_headers_with_defective_header_header_raises(self):
|
||||
m = self._make_message()
|
||||
content = "Simple message.\n"
|
||||
header_factory = self.policy.header_factory
|
||||
with self.assertRaisesRegex(ValueError, 'a@fairly@@invalid@address'):
|
||||
raw_data_manager.set_content(m, content, headers=(
|
||||
header_factory('To', 'a@fairly@@invalid@address'),)
|
||||
)
|
||||
print(m['To'].defects)
|
||||
|
||||
def test_set_disposition_inline(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', disposition='inline')
|
||||
self.assertEqual(m['Content-Disposition'], 'inline')
|
||||
|
||||
def test_set_disposition_attachment(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', disposition='attachment')
|
||||
self.assertEqual(m['Content-Disposition'], 'attachment')
|
||||
|
||||
def test_set_disposition_foo(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', disposition='foo')
|
||||
self.assertEqual(m['Content-Disposition'], 'foo')
|
||||
|
||||
# XXX: we should have a 'strict' policy mode (beyond raise_on_defect) that
|
||||
# would cause 'foo' above to raise.
|
||||
|
||||
def test_set_filename(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', filename='bar.txt')
|
||||
self.assertEqual(m['Content-Disposition'],
|
||||
'attachment; filename="bar.txt"')
|
||||
|
||||
def test_set_filename_and_disposition_inline(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', disposition='inline', filename='bar.txt')
|
||||
self.assertEqual(m['Content-Disposition'], 'inline; filename="bar.txt"')
|
||||
|
||||
def test_set_non_ascii_filename(self):
|
||||
m = self._make_message()
|
||||
m.set_content('foo', filename='ábárî.txt')
|
||||
self.assertEqual(bytes(m), textwrap.dedent("""\
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: attachment;
|
||||
filename*=utf-8''%C3%A1b%C3%A1r%C3%AE.txt
|
||||
MIME-Version: 1.0
|
||||
|
||||
foo
|
||||
""").encode('ascii'))
|
||||
|
||||
content_object_params = {
|
||||
'text_plain': ('content', ()),
|
||||
'text_html': ('content', ('html',)),
|
||||
'application_octet_stream': (b'content',
|
||||
('application', 'octet_stream')),
|
||||
'image_jpeg': (b'content', ('image', 'jpeg')),
|
||||
'message_rfc822': (message(), ()),
|
||||
'message_external_body': (message(), ('external-body',)),
|
||||
}
|
||||
|
||||
def content_object_as_header_receiver(self, obj, mimetype):
|
||||
m = self._make_message()
|
||||
m.set_content(obj, *mimetype, headers=(
|
||||
'To: foo@example.com',
|
||||
'From: bar@simple.net'))
|
||||
self.assertEqual(m['to'], 'foo@example.com')
|
||||
self.assertEqual(m['from'], 'bar@simple.net')
|
||||
|
||||
def content_object_as_disposition_inline_receiver(self, obj, mimetype):
|
||||
m = self._make_message()
|
||||
m.set_content(obj, *mimetype, disposition='inline')
|
||||
self.assertEqual(m['Content-Disposition'], 'inline')
|
||||
|
||||
def content_object_as_non_ascii_filename_receiver(self, obj, mimetype):
|
||||
m = self._make_message()
|
||||
m.set_content(obj, *mimetype, disposition='inline', filename='bár.txt')
|
||||
self.assertEqual(m['Content-Disposition'], 'inline; filename="bár.txt"')
|
||||
self.assertEqual(m.get_filename(), "bár.txt")
|
||||
self.assertEqual(m['Content-Disposition'].params['filename'], "bár.txt")
|
||||
|
||||
def content_object_as_cid_receiver(self, obj, mimetype):
|
||||
m = self._make_message()
|
||||
m.set_content(obj, *mimetype, cid='some_random_stuff')
|
||||
self.assertEqual(m['Content-ID'], 'some_random_stuff')
|
||||
|
||||
def content_object_as_params_receiver(self, obj, mimetype):
|
||||
m = self._make_message()
|
||||
params = {'foo': 'bár', 'abc': 'xyz'}
|
||||
m.set_content(obj, *mimetype, params=params)
|
||||
if isinstance(obj, str):
|
||||
params['charset'] = 'utf-8'
|
||||
self.assertEqual(m['Content-Type'].params, params)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
337
third_party/python/Lib/test/test_email/test_defect_handling.py
vendored
Normal file
337
third_party/python/Lib/test/test_email/test_defect_handling.py
vendored
Normal file
|
@ -0,0 +1,337 @@
|
|||
import textwrap
|
||||
import unittest
|
||||
import contextlib
|
||||
from email import policy
|
||||
from email import errors
|
||||
from test.test_email import TestEmailBase
|
||||
|
||||
|
||||
class TestDefectsBase:
|
||||
|
||||
policy = policy.default
|
||||
raise_expected = False
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _raise_point(self, defect):
|
||||
yield
|
||||
|
||||
def test_same_boundary_inner_outer(self):
|
||||
source = textwrap.dedent("""\
|
||||
Subject: XX
|
||||
From: xx@xx.dk
|
||||
To: XX
|
||||
Mime-version: 1.0
|
||||
Content-type: multipart/mixed;
|
||||
boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: multipart/alternative;
|
||||
boundary="MS_Mac_OE_3071477847_720252_MIME_Part"
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: text/plain; charset="ISO-8859-1"
|
||||
Content-transfer-encoding: quoted-printable
|
||||
|
||||
text
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: text/html; charset="ISO-8859-1"
|
||||
Content-transfer-encoding: quoted-printable
|
||||
|
||||
<HTML></HTML>
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part--
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part
|
||||
Content-type: image/gif; name="xx.gif";
|
||||
Content-disposition: attachment
|
||||
Content-transfer-encoding: base64
|
||||
|
||||
Some removed base64 encoded chars.
|
||||
|
||||
--MS_Mac_OE_3071477847_720252_MIME_Part--
|
||||
|
||||
""")
|
||||
# XXX better would be to actually detect the duplicate.
|
||||
with self._raise_point(errors.StartBoundaryNotFoundDefect):
|
||||
msg = self._str_msg(source)
|
||||
if self.raise_expected: return
|
||||
inner = msg.get_payload(0)
|
||||
self.assertTrue(hasattr(inner, 'defects'))
|
||||
self.assertEqual(len(self.get_defects(inner)), 1)
|
||||
self.assertIsInstance(self.get_defects(inner)[0],
|
||||
errors.StartBoundaryNotFoundDefect)
|
||||
|
||||
def test_multipart_no_boundary(self):
|
||||
source = textwrap.dedent("""\
|
||||
Date: Fri, 6 Apr 2001 09:23:06 -0800 (GMT-0800)
|
||||
From: foobar
|
||||
Subject: broken mail
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/report; report-type=delivery-status;
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com
|
||||
|
||||
One part
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com
|
||||
Content-Type: message/delivery-status
|
||||
|
||||
Header: Another part
|
||||
|
||||
--JAB03225.986577786/zinfandel.lacita.com--
|
||||
""")
|
||||
with self._raise_point(errors.NoBoundaryInMultipartDefect):
|
||||
msg = self._str_msg(source)
|
||||
if self.raise_expected: return
|
||||
self.assertIsInstance(msg.get_payload(), str)
|
||||
self.assertEqual(len(self.get_defects(msg)), 2)
|
||||
self.assertIsInstance(self.get_defects(msg)[0],
|
||||
errors.NoBoundaryInMultipartDefect)
|
||||
self.assertIsInstance(self.get_defects(msg)[1],
|
||||
errors.MultipartInvariantViolationDefect)
|
||||
|
||||
multipart_msg = textwrap.dedent("""\
|
||||
Date: Wed, 14 Nov 2007 12:56:23 GMT
|
||||
From: foo@bar.invalid
|
||||
To: foo@bar.invalid
|
||||
Subject: Content-Transfer-Encoding: base64 and multipart
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="===============3344438784458119861=="{}
|
||||
|
||||
--===============3344438784458119861==
|
||||
Content-Type: text/plain
|
||||
|
||||
Test message
|
||||
|
||||
--===============3344438784458119861==
|
||||
Content-Type: application/octet-stream
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
YWJj
|
||||
|
||||
--===============3344438784458119861==--
|
||||
""")
|
||||
|
||||
def test_multipart_invalid_cte(self):
|
||||
with self._raise_point(
|
||||
errors.InvalidMultipartContentTransferEncodingDefect):
|
||||
msg = self._str_msg(
|
||||
self.multipart_msg.format(
|
||||
"\nContent-Transfer-Encoding: base64"))
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(len(self.get_defects(msg)), 1)
|
||||
self.assertIsInstance(self.get_defects(msg)[0],
|
||||
errors.InvalidMultipartContentTransferEncodingDefect)
|
||||
|
||||
def test_multipart_no_cte_no_defect(self):
|
||||
if self.raise_expected: return
|
||||
msg = self._str_msg(self.multipart_msg.format(''))
|
||||
self.assertEqual(len(self.get_defects(msg)), 0)
|
||||
|
||||
def test_multipart_valid_cte_no_defect(self):
|
||||
if self.raise_expected: return
|
||||
for cte in ('7bit', '8bit', 'BINary'):
|
||||
msg = self._str_msg(
|
||||
self.multipart_msg.format("\nContent-Transfer-Encoding: "+cte))
|
||||
self.assertEqual(len(self.get_defects(msg)), 0, "cte="+cte)
|
||||
|
||||
def test_lying_multipart(self):
|
||||
source = textwrap.dedent("""\
|
||||
From: "Allison Dunlap" <xxx@example.com>
|
||||
To: yyy@example.com
|
||||
Subject: 64423
|
||||
Date: Sun, 11 Jul 2004 16:09:27 -0300
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
|
||||
Blah blah blah
|
||||
""")
|
||||
with self._raise_point(errors.NoBoundaryInMultipartDefect):
|
||||
msg = self._str_msg(source)
|
||||
if self.raise_expected: return
|
||||
self.assertTrue(hasattr(msg, 'defects'))
|
||||
self.assertEqual(len(self.get_defects(msg)), 2)
|
||||
self.assertIsInstance(self.get_defects(msg)[0],
|
||||
errors.NoBoundaryInMultipartDefect)
|
||||
self.assertIsInstance(self.get_defects(msg)[1],
|
||||
errors.MultipartInvariantViolationDefect)
|
||||
|
||||
def test_missing_start_boundary(self):
|
||||
source = textwrap.dedent("""\
|
||||
Content-Type: multipart/mixed; boundary="AAA"
|
||||
From: Mail Delivery Subsystem <xxx@example.com>
|
||||
To: yyy@example.com
|
||||
|
||||
--AAA
|
||||
|
||||
Stuff
|
||||
|
||||
--AAA
|
||||
Content-Type: message/rfc822
|
||||
|
||||
From: webmaster@python.org
|
||||
To: zzz@example.com
|
||||
Content-Type: multipart/mixed; boundary="BBB"
|
||||
|
||||
--BBB--
|
||||
|
||||
--AAA--
|
||||
|
||||
""")
|
||||
# The message structure is:
|
||||
#
|
||||
# multipart/mixed
|
||||
# text/plain
|
||||
# message/rfc822
|
||||
# multipart/mixed [*]
|
||||
#
|
||||
# [*] This message is missing its start boundary
|
||||
with self._raise_point(errors.StartBoundaryNotFoundDefect):
|
||||
outer = self._str_msg(source)
|
||||
if self.raise_expected: return
|
||||
bad = outer.get_payload(1).get_payload(0)
|
||||
self.assertEqual(len(self.get_defects(bad)), 1)
|
||||
self.assertIsInstance(self.get_defects(bad)[0],
|
||||
errors.StartBoundaryNotFoundDefect)
|
||||
|
||||
def test_first_line_is_continuation_header(self):
|
||||
with self._raise_point(errors.FirstHeaderLineIsContinuationDefect):
|
||||
msg = self._str_msg(' Line 1\nSubject: test\n\nbody')
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(msg.keys(), ['Subject'])
|
||||
self.assertEqual(msg.get_payload(), 'body')
|
||||
self.assertEqual(len(self.get_defects(msg)), 1)
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.FirstHeaderLineIsContinuationDefect])
|
||||
self.assertEqual(self.get_defects(msg)[0].line, ' Line 1\n')
|
||||
|
||||
def test_missing_header_body_separator(self):
|
||||
# Our heuristic if we see a line that doesn't look like a header (no
|
||||
# leading whitespace but no ':') is to assume that the blank line that
|
||||
# separates the header from the body is missing, and to stop parsing
|
||||
# headers and start parsing the body.
|
||||
with self._raise_point(errors.MissingHeaderBodySeparatorDefect):
|
||||
msg = self._str_msg('Subject: test\nnot a header\nTo: abc\n\nb\n')
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(msg.keys(), ['Subject'])
|
||||
self.assertEqual(msg.get_payload(), 'not a header\nTo: abc\n\nb\n')
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.MissingHeaderBodySeparatorDefect])
|
||||
|
||||
def test_bad_padding_in_base64_payload(self):
|
||||
source = textwrap.dedent("""\
|
||||
Subject: test
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
dmk
|
||||
""")
|
||||
msg = self._str_msg(source)
|
||||
with self._raise_point(errors.InvalidBase64PaddingDefect):
|
||||
payload = msg.get_payload(decode=True)
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(payload, b'vi')
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.InvalidBase64PaddingDefect])
|
||||
|
||||
def test_invalid_chars_in_base64_payload(self):
|
||||
source = textwrap.dedent("""\
|
||||
Subject: test
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
dm\x01k===
|
||||
""")
|
||||
msg = self._str_msg(source)
|
||||
with self._raise_point(errors.InvalidBase64CharactersDefect):
|
||||
payload = msg.get_payload(decode=True)
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(payload, b'vi')
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.InvalidBase64CharactersDefect])
|
||||
|
||||
def test_invalid_length_of_base64_payload(self):
|
||||
source = textwrap.dedent("""\
|
||||
Subject: test
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
abcde
|
||||
""")
|
||||
msg = self._str_msg(source)
|
||||
with self._raise_point(errors.InvalidBase64LengthDefect):
|
||||
payload = msg.get_payload(decode=True)
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(payload, b'abcde')
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.InvalidBase64LengthDefect])
|
||||
|
||||
def test_missing_ending_boundary(self):
|
||||
source = textwrap.dedent("""\
|
||||
To: 1@harrydomain4.com
|
||||
Subject: Fwd: 1
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="------------000101020201080900040301"
|
||||
|
||||
--------------000101020201080900040301
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Alternative 1
|
||||
|
||||
--------------000101020201080900040301
|
||||
Content-Type: text/html; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Alternative 2
|
||||
|
||||
""")
|
||||
with self._raise_point(errors.CloseBoundaryNotFoundDefect):
|
||||
msg = self._str_msg(source)
|
||||
if self.raise_expected: return
|
||||
self.assertEqual(len(msg.get_payload()), 2)
|
||||
self.assertEqual(msg.get_payload(1).get_payload(), 'Alternative 2\n')
|
||||
self.assertDefectsEqual(self.get_defects(msg),
|
||||
[errors.CloseBoundaryNotFoundDefect])
|
||||
|
||||
|
||||
class TestDefectDetection(TestDefectsBase, TestEmailBase):
|
||||
|
||||
def get_defects(self, obj):
|
||||
return obj.defects
|
||||
|
||||
|
||||
class TestDefectCapture(TestDefectsBase, TestEmailBase):
|
||||
|
||||
class CapturePolicy(policy.EmailPolicy):
|
||||
captured = None
|
||||
def register_defect(self, obj, defect):
|
||||
self.captured.append(defect)
|
||||
|
||||
def setUp(self):
|
||||
self.policy = self.CapturePolicy(captured=list())
|
||||
|
||||
def get_defects(self, obj):
|
||||
return self.policy.captured
|
||||
|
||||
|
||||
class TestDefectRaising(TestDefectsBase, TestEmailBase):
|
||||
|
||||
policy = TestDefectsBase.policy
|
||||
policy = policy.clone(raise_on_defect=True)
|
||||
raise_expected = True
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _raise_point(self, defect):
|
||||
with self.assertRaises(defect):
|
||||
yield
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
5416
third_party/python/Lib/test/test_email/test_email.py
vendored
Normal file
5416
third_party/python/Lib/test/test_email/test_email.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
296
third_party/python/Lib/test/test_email/test_generator.py
vendored
Normal file
296
third_party/python/Lib/test/test_email/test_generator.py
vendored
Normal file
|
@ -0,0 +1,296 @@
|
|||
import io
|
||||
import textwrap
|
||||
import unittest
|
||||
from email import message_from_string, message_from_bytes
|
||||
from email.message import EmailMessage
|
||||
from email.generator import Generator, BytesGenerator
|
||||
from email import policy
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestGeneratorBase:
|
||||
|
||||
policy = policy.default
|
||||
|
||||
def msgmaker(self, msg, policy=None):
|
||||
policy = self.policy if policy is None else policy
|
||||
return self.msgfunc(msg, policy=policy)
|
||||
|
||||
refold_long_expected = {
|
||||
0: textwrap.dedent("""\
|
||||
To: whom_it_may_concern@example.com
|
||||
From: nobody_you_want_to_know@example.com
|
||||
Subject: We the willing led by the unknowing are doing the
|
||||
impossible for the ungrateful. We have done so much for so long with so little
|
||||
we are now qualified to do anything with nothing.
|
||||
|
||||
None
|
||||
"""),
|
||||
40: textwrap.dedent("""\
|
||||
To: whom_it_may_concern@example.com
|
||||
From:
|
||||
nobody_you_want_to_know@example.com
|
||||
Subject: We the willing led by the
|
||||
unknowing are doing the impossible for
|
||||
the ungrateful. We have done so much
|
||||
for so long with so little we are now
|
||||
qualified to do anything with nothing.
|
||||
|
||||
None
|
||||
"""),
|
||||
20: textwrap.dedent("""\
|
||||
To:
|
||||
whom_it_may_concern@example.com
|
||||
From:
|
||||
nobody_you_want_to_know@example.com
|
||||
Subject: We the
|
||||
willing led by the
|
||||
unknowing are doing
|
||||
the impossible for
|
||||
the ungrateful. We
|
||||
have done so much
|
||||
for so long with so
|
||||
little we are now
|
||||
qualified to do
|
||||
anything with
|
||||
nothing.
|
||||
|
||||
None
|
||||
"""),
|
||||
}
|
||||
refold_long_expected[100] = refold_long_expected[0]
|
||||
|
||||
refold_all_expected = refold_long_expected.copy()
|
||||
refold_all_expected[0] = (
|
||||
"To: whom_it_may_concern@example.com\n"
|
||||
"From: nobody_you_want_to_know@example.com\n"
|
||||
"Subject: We the willing led by the unknowing are doing the "
|
||||
"impossible for the ungrateful. We have done so much for "
|
||||
"so long with so little we are now qualified to do anything "
|
||||
"with nothing.\n"
|
||||
"\n"
|
||||
"None\n")
|
||||
refold_all_expected[100] = (
|
||||
"To: whom_it_may_concern@example.com\n"
|
||||
"From: nobody_you_want_to_know@example.com\n"
|
||||
"Subject: We the willing led by the unknowing are doing the "
|
||||
"impossible for the ungrateful. We have\n"
|
||||
" done so much for so long with so little we are now qualified "
|
||||
"to do anything with nothing.\n"
|
||||
"\n"
|
||||
"None\n")
|
||||
|
||||
length_params = [n for n in refold_long_expected]
|
||||
|
||||
def length_as_maxheaderlen_parameter(self, n):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, maxheaderlen=n, policy=self.policy)
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
|
||||
|
||||
def length_as_max_line_length_policy(self, n):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=self.policy.clone(max_line_length=n))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
|
||||
|
||||
def length_as_maxheaderlen_parm_overrides_policy(self, n):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, maxheaderlen=n,
|
||||
policy=self.policy.clone(max_line_length=10))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
|
||||
|
||||
def length_as_max_line_length_with_refold_none_does_not_fold(self, n):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=self.policy.clone(refold_source='none',
|
||||
max_line_length=n))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[0]))
|
||||
|
||||
def length_as_max_line_length_with_refold_all_folds(self, n):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=self.policy.clone(refold_source='all',
|
||||
max_line_length=n))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_all_expected[n]))
|
||||
|
||||
def test_crlf_control_via_policy(self):
|
||||
source = "Subject: test\r\n\r\ntest body\r\n"
|
||||
expected = source
|
||||
msg = self.msgmaker(self.typ(source))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=policy.SMTP)
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
def test_flatten_linesep_overrides_policy(self):
|
||||
source = "Subject: test\n\ntest body\n"
|
||||
expected = source
|
||||
msg = self.msgmaker(self.typ(source))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=policy.SMTP)
|
||||
g.flatten(msg, linesep='\n')
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
def test_set_mangle_from_via_policy(self):
|
||||
source = textwrap.dedent("""\
|
||||
Subject: test that
|
||||
from is mangled in the body!
|
||||
|
||||
From time to time I write a rhyme.
|
||||
""")
|
||||
variants = (
|
||||
(None, True),
|
||||
(policy.compat32, True),
|
||||
(policy.default, False),
|
||||
(policy.default.clone(mangle_from_=True), True),
|
||||
)
|
||||
for p, mangle in variants:
|
||||
expected = source.replace('From ', '>From ') if mangle else source
|
||||
with self.subTest(policy=p, mangle_from_=mangle):
|
||||
msg = self.msgmaker(self.typ(source))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=p)
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
def test_compat32_max_line_length_does_not_fold_when_none(self):
|
||||
msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=policy.compat32.clone(max_line_length=None))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[0]))
|
||||
|
||||
def test_rfc2231_wrapping(self):
|
||||
# This is pretty much just to make sure we don't have an infinite
|
||||
# loop; I don't expect anyone to hit this in the field.
|
||||
msg = self.msgmaker(self.typ(textwrap.dedent("""\
|
||||
To: nobody
|
||||
Content-Disposition: attachment;
|
||||
filename="afilenamelongenoghtowraphere"
|
||||
|
||||
None
|
||||
""")))
|
||||
expected = textwrap.dedent("""\
|
||||
To: nobody
|
||||
Content-Disposition: attachment;
|
||||
filename*0*=us-ascii''afilename;
|
||||
filename*1*=longenoghtowraphere
|
||||
|
||||
None
|
||||
""")
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=self.policy.clone(max_line_length=33))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
def test_rfc2231_wrapping_switches_to_default_len_if_too_narrow(self):
|
||||
# This is just to make sure we don't have an infinite loop; I don't
|
||||
# expect anyone to hit this in the field, so I'm not bothering to make
|
||||
# the result optimal (the encoding isn't needed).
|
||||
msg = self.msgmaker(self.typ(textwrap.dedent("""\
|
||||
To: nobody
|
||||
Content-Disposition: attachment;
|
||||
filename="afilenamelongenoghtowraphere"
|
||||
|
||||
None
|
||||
""")))
|
||||
expected = textwrap.dedent("""\
|
||||
To: nobody
|
||||
Content-Disposition:
|
||||
attachment;
|
||||
filename*0*=us-ascii''afilenamelongenoghtowraphere
|
||||
|
||||
None
|
||||
""")
|
||||
s = self.ioclass()
|
||||
g = self.genclass(s, policy=self.policy.clone(max_line_length=20))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
|
||||
class TestGenerator(TestGeneratorBase, TestEmailBase):
|
||||
|
||||
msgfunc = staticmethod(message_from_string)
|
||||
genclass = Generator
|
||||
ioclass = io.StringIO
|
||||
typ = str
|
||||
|
||||
|
||||
class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
|
||||
|
||||
msgfunc = staticmethod(message_from_bytes)
|
||||
genclass = BytesGenerator
|
||||
ioclass = io.BytesIO
|
||||
typ = lambda self, x: x.encode('ascii')
|
||||
|
||||
def test_cte_type_7bit_handles_unknown_8bit(self):
|
||||
source = ("Subject: Maintenant je vous présente mon "
|
||||
"collègue\n\n").encode('utf-8')
|
||||
expected = ('Subject: Maintenant je vous =?unknown-8bit?q?'
|
||||
'pr=C3=A9sente_mon_coll=C3=A8gue?=\n\n').encode('ascii')
|
||||
msg = message_from_bytes(source)
|
||||
s = io.BytesIO()
|
||||
g = BytesGenerator(s, policy=self.policy.clone(cte_type='7bit'))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), expected)
|
||||
|
||||
def test_cte_type_7bit_transforms_8bit_cte(self):
|
||||
source = textwrap.dedent("""\
|
||||
From: foo@bar.com
|
||||
To: Dinsdale
|
||||
Subject: Nudge nudge, wink, wink
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset="latin-1"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
oh là là, know what I mean, know what I mean?
|
||||
""").encode('latin1')
|
||||
msg = message_from_bytes(source)
|
||||
expected = textwrap.dedent("""\
|
||||
From: foo@bar.com
|
||||
To: Dinsdale
|
||||
Subject: Nudge nudge, wink, wink
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
oh l=E0 l=E0, know what I mean, know what I mean?
|
||||
""").encode('ascii')
|
||||
s = io.BytesIO()
|
||||
g = BytesGenerator(s, policy=self.policy.clone(cte_type='7bit',
|
||||
linesep='\n'))
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), expected)
|
||||
|
||||
def test_smtputf8_policy(self):
|
||||
msg = EmailMessage()
|
||||
msg['From'] = "Páolo <főo@bar.com>"
|
||||
msg['To'] = 'Dinsdale'
|
||||
msg['Subject'] = 'Nudge nudge, wink, wink \u1F609'
|
||||
msg.set_content("oh là là, know what I mean, know what I mean?")
|
||||
expected = textwrap.dedent("""\
|
||||
From: Páolo <főo@bar.com>
|
||||
To: Dinsdale
|
||||
Subject: Nudge nudge, wink, wink \u1F609
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
|
||||
oh là là, know what I mean, know what I mean?
|
||||
""").encode('utf-8').replace(b'\n', b'\r\n')
|
||||
s = io.BytesIO()
|
||||
g = BytesGenerator(s, policy=policy.SMTPUTF8)
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
1672
third_party/python/Lib/test/test_email/test_headerregistry.py
vendored
Normal file
1672
third_party/python/Lib/test/test_email/test_headerregistry.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
70
third_party/python/Lib/test/test_email/test_inversion.py
vendored
Normal file
70
third_party/python/Lib/test/test_email/test_inversion.py
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
"""Test the parser and generator are inverses.
|
||||
|
||||
Note that this is only strictly true if we are parsing RFC valid messages and
|
||||
producing RFC valid messages.
|
||||
"""
|
||||
|
||||
import io
|
||||
import unittest
|
||||
from email import policy, message_from_bytes
|
||||
from email.message import EmailMessage
|
||||
from email.generator import BytesGenerator
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
|
||||
# This is like textwrap.dedent for bytes, except that it uses \r\n for the line
|
||||
# separators on the rebuilt string.
|
||||
def dedent(bstr):
|
||||
lines = bstr.splitlines()
|
||||
if not lines[0].strip():
|
||||
raise ValueError("First line must contain text")
|
||||
stripamt = len(lines[0]) - len(lines[0].lstrip())
|
||||
return b'\r\n'.join(
|
||||
[x[stripamt:] if len(x)>=stripamt else b''
|
||||
for x in lines])
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestInversion(TestEmailBase):
|
||||
|
||||
policy = policy.default
|
||||
message = EmailMessage
|
||||
|
||||
def msg_as_input(self, msg):
|
||||
m = message_from_bytes(msg, policy=policy.SMTP)
|
||||
b = io.BytesIO()
|
||||
g = BytesGenerator(b)
|
||||
g.flatten(m)
|
||||
self.assertEqual(b.getvalue(), msg)
|
||||
|
||||
# XXX: spaces are not preserved correctly here yet in the general case.
|
||||
msg_params = {
|
||||
'header_with_one_space_body': (dedent(b"""\
|
||||
From: abc@xyz.com
|
||||
X-Status:\x20
|
||||
Subject: test
|
||||
|
||||
foo
|
||||
"""),),
|
||||
|
||||
}
|
||||
|
||||
payload_params = {
|
||||
'plain_text': dict(payload='This is a test\n'*20),
|
||||
'base64_text': dict(payload=(('xy a'*40+'\n')*5), cte='base64'),
|
||||
'qp_text': dict(payload=(('xy a'*40+'\n')*5), cte='quoted-printable'),
|
||||
}
|
||||
|
||||
def payload_as_body(self, payload, **kw):
|
||||
msg = self._make_message()
|
||||
msg['From'] = 'foo'
|
||||
msg['To'] = 'bar'
|
||||
msg['Subject'] = 'payload round trip test'
|
||||
msg.set_content(payload, **kw)
|
||||
b = bytes(msg)
|
||||
msg2 = message_from_bytes(b, policy=self.policy)
|
||||
self.assertEqual(bytes(msg2), b)
|
||||
self.assertEqual(msg2.get_content(), payload)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
803
third_party/python/Lib/test/test_email/test_message.py
vendored
Normal file
803
third_party/python/Lib/test/test_email/test_message.py
vendored
Normal file
|
@ -0,0 +1,803 @@
|
|||
import unittest
|
||||
import textwrap
|
||||
from email import policy, message_from_string
|
||||
from email.message import EmailMessage, MIMEPart
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
|
||||
|
||||
# Helper.
|
||||
def first(iterable):
|
||||
return next(filter(lambda x: x is not None, iterable), None)
|
||||
|
||||
|
||||
class Test(TestEmailBase):
|
||||
|
||||
policy = policy.default
|
||||
|
||||
def test_error_on_setitem_if_max_count_exceeded(self):
|
||||
m = self._str_msg("")
|
||||
m['To'] = 'abc@xyz'
|
||||
with self.assertRaises(ValueError):
|
||||
m['To'] = 'xyz@abc'
|
||||
|
||||
def test_rfc2043_auto_decoded_and_emailmessage_used(self):
|
||||
m = message_from_string(textwrap.dedent("""\
|
||||
Subject: Ayons asperges pour le =?utf-8?q?d=C3=A9jeuner?=
|
||||
From: =?utf-8?q?Pep=C3=A9?= Le Pew <pepe@example.com>
|
||||
To: "Penelope Pussycat" <"penelope@example.com">
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
sample text
|
||||
"""), policy=policy.default)
|
||||
self.assertEqual(m['subject'], "Ayons asperges pour le déjeuner")
|
||||
self.assertEqual(m['from'], "Pepé Le Pew <pepe@example.com>")
|
||||
self.assertIsInstance(m, EmailMessage)
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestEmailMessageBase:
|
||||
|
||||
policy = policy.default
|
||||
|
||||
# The first argument is a triple (related, html, plain) of indices into the
|
||||
# list returned by 'walk' called on a Message constructed from the third.
|
||||
# The indices indicate which part should match the corresponding part-type
|
||||
# when passed to get_body (ie: the "first" part of that type in the
|
||||
# message). The second argument is a list of indices into the 'walk' list
|
||||
# of the attachments that should be returned by a call to
|
||||
# 'iter_attachments'. The third argument is a list of indices into 'walk'
|
||||
# that should be returned by a call to 'iter_parts'. Note that the first
|
||||
# item returned by 'walk' is the Message itself.
|
||||
|
||||
message_params = {
|
||||
|
||||
'empty_message': (
|
||||
(None, None, 0),
|
||||
(),
|
||||
(),
|
||||
""),
|
||||
|
||||
'non_mime_plain': (
|
||||
(None, None, 0),
|
||||
(),
|
||||
(),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
|
||||
simple text body
|
||||
""")),
|
||||
|
||||
'mime_non_text': (
|
||||
(None, None, None),
|
||||
(),
|
||||
(),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: image/jpg
|
||||
|
||||
bogus body.
|
||||
""")),
|
||||
|
||||
'plain_html_alternative': (
|
||||
(None, 2, 1),
|
||||
(),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="==="
|
||||
|
||||
preamble
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
--===--
|
||||
""")),
|
||||
|
||||
'plain_html_mixed': (
|
||||
(None, 2, 1),
|
||||
(),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
preamble
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
'plain_html_attachment_mixed': (
|
||||
(None, None, 1),
|
||||
(2,),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
Content-Disposition: attachment
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
'html_text_attachment_mixed': (
|
||||
(None, 2, None),
|
||||
(1,),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
Content-Disposition: AtTaChment
|
||||
|
||||
simple body
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
'html_text_attachment_inline_mixed': (
|
||||
(None, 2, 1),
|
||||
(),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
Content-Disposition: InLine
|
||||
|
||||
simple body
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
Content-Disposition: inline
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
# RFC 2387
|
||||
'related': (
|
||||
(0, 1, None),
|
||||
(2,),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/related; boundary="==="; type=text/html
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-ID: <image1>
|
||||
|
||||
bogus data
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
# This message structure will probably never be seen in the wild, but
|
||||
# it proves we distinguish between text parts based on 'start'. The
|
||||
# content would not, of course, actually work :)
|
||||
'related_with_start': (
|
||||
(0, 2, None),
|
||||
(1,),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/related; boundary="==="; type=text/html;
|
||||
start="<body>"
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
Content-ID: <include>
|
||||
|
||||
useless text
|
||||
|
||||
--===
|
||||
Content-Type: text/html
|
||||
Content-ID: <body>
|
||||
|
||||
<p>simple body</p>
|
||||
<!--#include file="<include>"-->
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
|
||||
'mixed_alternative_plain_related': (
|
||||
(3, 4, 2),
|
||||
(6, 7),
|
||||
(1, 6, 7),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: multipart/alternative; boundary="+++"
|
||||
|
||||
--+++
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--+++
|
||||
Content-Type: multipart/related; boundary="___"
|
||||
|
||||
--___
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--___
|
||||
Content-Type: image/jpg
|
||||
Content-ID: <image1@cid>
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--___--
|
||||
|
||||
--+++--
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: attachment
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: AttacHmenT
|
||||
|
||||
another bogus jpg body
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
# This structure suggested by Stephen J. Turnbull...may not exist/be
|
||||
# supported in the wild, but we want to support it.
|
||||
'mixed_related_alternative_plain_html': (
|
||||
(1, 4, 3),
|
||||
(6, 7),
|
||||
(1, 6, 7),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: multipart/related; boundary="+++"
|
||||
|
||||
--+++
|
||||
Content-Type: multipart/alternative; boundary="___"
|
||||
|
||||
--___
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--___
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--___--
|
||||
|
||||
--+++
|
||||
Content-Type: image/jpg
|
||||
Content-ID: <image1@cid>
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--+++--
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: attachment
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: attachment
|
||||
|
||||
another bogus jpg body
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
# Same thing, but proving we only look at the root part, which is the
|
||||
# first one if there isn't any start parameter. That is, this is a
|
||||
# broken related.
|
||||
'mixed_related_alternative_plain_html_wrong_order': (
|
||||
(1, None, None),
|
||||
(6, 7),
|
||||
(1, 6, 7),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: multipart/related; boundary="+++"
|
||||
|
||||
--+++
|
||||
Content-Type: image/jpg
|
||||
Content-ID: <image1@cid>
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--+++
|
||||
Content-Type: multipart/alternative; boundary="___"
|
||||
|
||||
--___
|
||||
Content-Type: text/plain
|
||||
|
||||
simple body
|
||||
|
||||
--___
|
||||
Content-Type: text/html
|
||||
|
||||
<p>simple body</p>
|
||||
|
||||
--___--
|
||||
|
||||
--+++--
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: attachment
|
||||
|
||||
bogus jpg body
|
||||
|
||||
--===
|
||||
Content-Type: image/jpg
|
||||
Content-Disposition: attachment
|
||||
|
||||
another bogus jpg body
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
'message_rfc822': (
|
||||
(None, None, None),
|
||||
(),
|
||||
(),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: message/rfc822
|
||||
|
||||
To: bar@example.com
|
||||
From: robot@examp.com
|
||||
|
||||
this is a message body.
|
||||
""")),
|
||||
|
||||
'mixed_text_message_rfc822': (
|
||||
(None, None, 1),
|
||||
(2,),
|
||||
(1, 2),
|
||||
textwrap.dedent("""\
|
||||
To: foo@example.com
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary="==="
|
||||
|
||||
--===
|
||||
Content-Type: text/plain
|
||||
|
||||
Your message has bounced, ser.
|
||||
|
||||
--===
|
||||
Content-Type: message/rfc822
|
||||
|
||||
To: bar@example.com
|
||||
From: robot@examp.com
|
||||
|
||||
this is a message body.
|
||||
|
||||
--===--
|
||||
""")),
|
||||
|
||||
}
|
||||
|
||||
def message_as_get_body(self, body_parts, attachments, parts, msg):
|
||||
m = self._str_msg(msg)
|
||||
allparts = list(m.walk())
|
||||
expected = [None if n is None else allparts[n] for n in body_parts]
|
||||
related = 0; html = 1; plain = 2
|
||||
self.assertEqual(m.get_body(), first(expected))
|
||||
self.assertEqual(m.get_body(preferencelist=(
|
||||
'related', 'html', 'plain')),
|
||||
first(expected))
|
||||
self.assertEqual(m.get_body(preferencelist=('related', 'html')),
|
||||
first(expected[related:html+1]))
|
||||
self.assertEqual(m.get_body(preferencelist=('related', 'plain')),
|
||||
first([expected[related], expected[plain]]))
|
||||
self.assertEqual(m.get_body(preferencelist=('html', 'plain')),
|
||||
first(expected[html:plain+1]))
|
||||
self.assertEqual(m.get_body(preferencelist=['related']),
|
||||
expected[related])
|
||||
self.assertEqual(m.get_body(preferencelist=['html']), expected[html])
|
||||
self.assertEqual(m.get_body(preferencelist=['plain']), expected[plain])
|
||||
self.assertEqual(m.get_body(preferencelist=('plain', 'html')),
|
||||
first(expected[plain:html-1:-1]))
|
||||
self.assertEqual(m.get_body(preferencelist=('plain', 'related')),
|
||||
first([expected[plain], expected[related]]))
|
||||
self.assertEqual(m.get_body(preferencelist=('html', 'related')),
|
||||
first(expected[html::-1]))
|
||||
self.assertEqual(m.get_body(preferencelist=('plain', 'html', 'related')),
|
||||
first(expected[::-1]))
|
||||
self.assertEqual(m.get_body(preferencelist=('html', 'plain', 'related')),
|
||||
first([expected[html],
|
||||
expected[plain],
|
||||
expected[related]]))
|
||||
|
||||
def message_as_iter_attachment(self, body_parts, attachments, parts, msg):
|
||||
m = self._str_msg(msg)
|
||||
allparts = list(m.walk())
|
||||
attachments = [allparts[n] for n in attachments]
|
||||
self.assertEqual(list(m.iter_attachments()), attachments)
|
||||
|
||||
def message_as_iter_parts(self, body_parts, attachments, parts, msg):
|
||||
m = self._str_msg(msg)
|
||||
allparts = list(m.walk())
|
||||
parts = [allparts[n] for n in parts]
|
||||
self.assertEqual(list(m.iter_parts()), parts)
|
||||
|
||||
class _TestContentManager:
|
||||
def get_content(self, msg, *args, **kw):
|
||||
return msg, args, kw
|
||||
def set_content(self, msg, *args, **kw):
|
||||
self.msg = msg
|
||||
self.args = args
|
||||
self.kw = kw
|
||||
|
||||
def test_get_content_with_cm(self):
|
||||
m = self._str_msg('')
|
||||
cm = self._TestContentManager()
|
||||
self.assertEqual(m.get_content(content_manager=cm), (m, (), {}))
|
||||
msg, args, kw = m.get_content('foo', content_manager=cm, bar=1, k=2)
|
||||
self.assertEqual(msg, m)
|
||||
self.assertEqual(args, ('foo',))
|
||||
self.assertEqual(kw, dict(bar=1, k=2))
|
||||
|
||||
def test_get_content_default_cm_comes_from_policy(self):
|
||||
p = policy.default.clone(content_manager=self._TestContentManager())
|
||||
m = self._str_msg('', policy=p)
|
||||
self.assertEqual(m.get_content(), (m, (), {}))
|
||||
msg, args, kw = m.get_content('foo', bar=1, k=2)
|
||||
self.assertEqual(msg, m)
|
||||
self.assertEqual(args, ('foo',))
|
||||
self.assertEqual(kw, dict(bar=1, k=2))
|
||||
|
||||
def test_set_content_with_cm(self):
|
||||
m = self._str_msg('')
|
||||
cm = self._TestContentManager()
|
||||
m.set_content(content_manager=cm)
|
||||
self.assertEqual(cm.msg, m)
|
||||
self.assertEqual(cm.args, ())
|
||||
self.assertEqual(cm.kw, {})
|
||||
m.set_content('foo', content_manager=cm, bar=1, k=2)
|
||||
self.assertEqual(cm.msg, m)
|
||||
self.assertEqual(cm.args, ('foo',))
|
||||
self.assertEqual(cm.kw, dict(bar=1, k=2))
|
||||
|
||||
def test_set_content_default_cm_comes_from_policy(self):
|
||||
cm = self._TestContentManager()
|
||||
p = policy.default.clone(content_manager=cm)
|
||||
m = self._str_msg('', policy=p)
|
||||
m.set_content()
|
||||
self.assertEqual(cm.msg, m)
|
||||
self.assertEqual(cm.args, ())
|
||||
self.assertEqual(cm.kw, {})
|
||||
m.set_content('foo', bar=1, k=2)
|
||||
self.assertEqual(cm.msg, m)
|
||||
self.assertEqual(cm.args, ('foo',))
|
||||
self.assertEqual(cm.kw, dict(bar=1, k=2))
|
||||
|
||||
# outcome is whether xxx_method should raise ValueError error when called
|
||||
# on multipart/subtype. Blank outcome means it depends on xxx (add
|
||||
# succeeds, make raises). Note: 'none' means there are content-type
|
||||
# headers but payload is None...this happening in practice would be very
|
||||
# unusual, so treating it as if there were content seems reasonable.
|
||||
# method subtype outcome
|
||||
subtype_params = (
|
||||
('related', 'no_content', 'succeeds'),
|
||||
('related', 'none', 'succeeds'),
|
||||
('related', 'plain', 'succeeds'),
|
||||
('related', 'related', ''),
|
||||
('related', 'alternative', 'raises'),
|
||||
('related', 'mixed', 'raises'),
|
||||
('alternative', 'no_content', 'succeeds'),
|
||||
('alternative', 'none', 'succeeds'),
|
||||
('alternative', 'plain', 'succeeds'),
|
||||
('alternative', 'related', 'succeeds'),
|
||||
('alternative', 'alternative', ''),
|
||||
('alternative', 'mixed', 'raises'),
|
||||
('mixed', 'no_content', 'succeeds'),
|
||||
('mixed', 'none', 'succeeds'),
|
||||
('mixed', 'plain', 'succeeds'),
|
||||
('mixed', 'related', 'succeeds'),
|
||||
('mixed', 'alternative', 'succeeds'),
|
||||
('mixed', 'mixed', ''),
|
||||
)
|
||||
|
||||
def _make_subtype_test_message(self, subtype):
|
||||
m = self.message()
|
||||
payload = None
|
||||
msg_headers = [
|
||||
('To', 'foo@bar.com'),
|
||||
('From', 'bar@foo.com'),
|
||||
]
|
||||
if subtype != 'no_content':
|
||||
('content-shadow', 'Logrus'),
|
||||
msg_headers.append(('X-Random-Header', 'Corwin'))
|
||||
if subtype == 'text':
|
||||
payload = ''
|
||||
msg_headers.append(('Content-Type', 'text/plain'))
|
||||
m.set_payload('')
|
||||
elif subtype != 'no_content':
|
||||
payload = []
|
||||
msg_headers.append(('Content-Type', 'multipart/' + subtype))
|
||||
msg_headers.append(('X-Trump', 'Random'))
|
||||
m.set_payload(payload)
|
||||
for name, value in msg_headers:
|
||||
m[name] = value
|
||||
return m, msg_headers, payload
|
||||
|
||||
def _check_disallowed_subtype_raises(self, m, method_name, subtype, method):
|
||||
with self.assertRaises(ValueError) as ar:
|
||||
getattr(m, method)()
|
||||
exc_text = str(ar.exception)
|
||||
self.assertIn(subtype, exc_text)
|
||||
self.assertIn(method_name, exc_text)
|
||||
|
||||
def _check_make_multipart(self, m, msg_headers, payload):
|
||||
count = 0
|
||||
for name, value in msg_headers:
|
||||
if not name.lower().startswith('content-'):
|
||||
self.assertEqual(m[name], value)
|
||||
count += 1
|
||||
self.assertEqual(len(m), count+1) # +1 for new Content-Type
|
||||
part = next(m.iter_parts())
|
||||
count = 0
|
||||
for name, value in msg_headers:
|
||||
if name.lower().startswith('content-'):
|
||||
self.assertEqual(part[name], value)
|
||||
count += 1
|
||||
self.assertEqual(len(part), count)
|
||||
self.assertEqual(part.get_payload(), payload)
|
||||
|
||||
def subtype_as_make(self, method, subtype, outcome):
|
||||
m, msg_headers, payload = self._make_subtype_test_message(subtype)
|
||||
make_method = 'make_' + method
|
||||
if outcome in ('', 'raises'):
|
||||
self._check_disallowed_subtype_raises(m, method, subtype, make_method)
|
||||
return
|
||||
getattr(m, make_method)()
|
||||
self.assertEqual(m.get_content_maintype(), 'multipart')
|
||||
self.assertEqual(m.get_content_subtype(), method)
|
||||
if subtype == 'no_content':
|
||||
self.assertEqual(len(m.get_payload()), 0)
|
||||
self.assertEqual(m.items(),
|
||||
msg_headers + [('Content-Type',
|
||||
'multipart/'+method)])
|
||||
else:
|
||||
self.assertEqual(len(m.get_payload()), 1)
|
||||
self._check_make_multipart(m, msg_headers, payload)
|
||||
|
||||
def subtype_as_make_with_boundary(self, method, subtype, outcome):
|
||||
# Doing all variation is a bit of overkill...
|
||||
m = self.message()
|
||||
if outcome in ('', 'raises'):
|
||||
m['Content-Type'] = 'multipart/' + subtype
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
getattr(m, 'make_' + method)()
|
||||
return
|
||||
if subtype == 'plain':
|
||||
m['Content-Type'] = 'text/plain'
|
||||
elif subtype != 'no_content':
|
||||
m['Content-Type'] = 'multipart/' + subtype
|
||||
getattr(m, 'make_' + method)(boundary="abc")
|
||||
self.assertTrue(m.is_multipart())
|
||||
self.assertEqual(m.get_boundary(), 'abc')
|
||||
|
||||
def test_policy_on_part_made_by_make_comes_from_message(self):
|
||||
for method in ('make_related', 'make_alternative', 'make_mixed'):
|
||||
m = self.message(policy=self.policy.clone(content_manager='foo'))
|
||||
m['Content-Type'] = 'text/plain'
|
||||
getattr(m, method)()
|
||||
self.assertEqual(m.get_payload(0).policy.content_manager, 'foo')
|
||||
|
||||
class _TestSetContentManager:
|
||||
def set_content(self, msg, content, *args, **kw):
|
||||
msg['Content-Type'] = 'text/plain'
|
||||
msg.set_payload(content)
|
||||
|
||||
def subtype_as_add(self, method, subtype, outcome):
|
||||
m, msg_headers, payload = self._make_subtype_test_message(subtype)
|
||||
cm = self._TestSetContentManager()
|
||||
add_method = 'add_attachment' if method=='mixed' else 'add_' + method
|
||||
if outcome == 'raises':
|
||||
self._check_disallowed_subtype_raises(m, method, subtype, add_method)
|
||||
return
|
||||
getattr(m, add_method)('test', content_manager=cm)
|
||||
self.assertEqual(m.get_content_maintype(), 'multipart')
|
||||
self.assertEqual(m.get_content_subtype(), method)
|
||||
if method == subtype or subtype == 'no_content':
|
||||
self.assertEqual(len(m.get_payload()), 1)
|
||||
for name, value in msg_headers:
|
||||
self.assertEqual(m[name], value)
|
||||
part = m.get_payload()[0]
|
||||
else:
|
||||
self.assertEqual(len(m.get_payload()), 2)
|
||||
self._check_make_multipart(m, msg_headers, payload)
|
||||
part = m.get_payload()[1]
|
||||
self.assertEqual(part.get_content_type(), 'text/plain')
|
||||
self.assertEqual(part.get_payload(), 'test')
|
||||
if method=='mixed':
|
||||
self.assertEqual(part['Content-Disposition'], 'attachment')
|
||||
elif method=='related':
|
||||
self.assertEqual(part['Content-Disposition'], 'inline')
|
||||
else:
|
||||
# Otherwise we don't guess.
|
||||
self.assertIsNone(part['Content-Disposition'])
|
||||
|
||||
class _TestSetRaisingContentManager:
|
||||
def set_content(self, msg, content, *args, **kw):
|
||||
raise Exception('test')
|
||||
|
||||
def test_default_content_manager_for_add_comes_from_policy(self):
|
||||
cm = self._TestSetRaisingContentManager()
|
||||
m = self.message(policy=self.policy.clone(content_manager=cm))
|
||||
for method in ('add_related', 'add_alternative', 'add_attachment'):
|
||||
with self.assertRaises(Exception) as ar:
|
||||
getattr(m, method)('')
|
||||
self.assertEqual(str(ar.exception), 'test')
|
||||
|
||||
def message_as_clear(self, body_parts, attachments, parts, msg):
|
||||
m = self._str_msg(msg)
|
||||
m.clear()
|
||||
self.assertEqual(len(m), 0)
|
||||
self.assertEqual(list(m.items()), [])
|
||||
self.assertIsNone(m.get_payload())
|
||||
self.assertEqual(list(m.iter_parts()), [])
|
||||
|
||||
def message_as_clear_content(self, body_parts, attachments, parts, msg):
|
||||
m = self._str_msg(msg)
|
||||
expected_headers = [h for h in m.keys()
|
||||
if not h.lower().startswith('content-')]
|
||||
m.clear_content()
|
||||
self.assertEqual(list(m.keys()), expected_headers)
|
||||
self.assertIsNone(m.get_payload())
|
||||
self.assertEqual(list(m.iter_parts()), [])
|
||||
|
||||
def test_is_attachment(self):
|
||||
m = self._make_message()
|
||||
self.assertFalse(m.is_attachment())
|
||||
m['Content-Disposition'] = 'inline'
|
||||
self.assertFalse(m.is_attachment())
|
||||
m.replace_header('Content-Disposition', 'attachment')
|
||||
self.assertTrue(m.is_attachment())
|
||||
m.replace_header('Content-Disposition', 'AtTachMent')
|
||||
self.assertTrue(m.is_attachment())
|
||||
m.set_param('filename', 'abc.png', 'Content-Disposition')
|
||||
self.assertTrue(m.is_attachment())
|
||||
|
||||
def test_iter_attachments_mutation(self):
|
||||
# We had a bug where iter_attachments was mutating the list.
|
||||
m = self._make_message()
|
||||
m.set_content('arbitrary text as main part')
|
||||
m.add_related('more text as a related part')
|
||||
m.add_related('yet more text as a second "attachment"')
|
||||
orig = m.get_payload().copy()
|
||||
self.assertEqual(len(list(m.iter_attachments())), 2)
|
||||
self.assertEqual(m.get_payload(), orig)
|
||||
|
||||
|
||||
class TestEmailMessage(TestEmailMessageBase, TestEmailBase):
|
||||
message = EmailMessage
|
||||
|
||||
def test_set_content_adds_MIME_Version(self):
|
||||
m = self._str_msg('')
|
||||
cm = self._TestContentManager()
|
||||
self.assertNotIn('MIME-Version', m)
|
||||
m.set_content(content_manager=cm)
|
||||
self.assertEqual(m['MIME-Version'], '1.0')
|
||||
|
||||
class _MIME_Version_adding_CM:
|
||||
def set_content(self, msg, *args, **kw):
|
||||
msg['MIME-Version'] = '1.0'
|
||||
|
||||
def test_set_content_does_not_duplicate_MIME_Version(self):
|
||||
m = self._str_msg('')
|
||||
cm = self._MIME_Version_adding_CM()
|
||||
self.assertNotIn('MIME-Version', m)
|
||||
m.set_content(content_manager=cm)
|
||||
self.assertEqual(m['MIME-Version'], '1.0')
|
||||
|
||||
def test_as_string_uses_max_header_length_by_default(self):
|
||||
m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n')
|
||||
self.assertEqual(len(m.as_string().strip().splitlines()), 3)
|
||||
|
||||
def test_as_string_allows_maxheaderlen(self):
|
||||
m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n')
|
||||
self.assertEqual(len(m.as_string(maxheaderlen=0).strip().splitlines()),
|
||||
1)
|
||||
self.assertEqual(len(m.as_string(maxheaderlen=34).strip().splitlines()),
|
||||
6)
|
||||
|
||||
def test_str_defaults_to_policy_max_line_length(self):
|
||||
m = self._str_msg('Subject: long line' + ' ab'*50 + '\n\n')
|
||||
self.assertEqual(len(str(m).strip().splitlines()), 3)
|
||||
|
||||
def test_str_defaults_to_utf8(self):
|
||||
m = EmailMessage()
|
||||
m['Subject'] = 'unicöde'
|
||||
self.assertEqual(str(m), 'Subject: unicöde\n\n')
|
||||
|
||||
|
||||
class TestMIMEPart(TestEmailMessageBase, TestEmailBase):
|
||||
# Doing the full test run here may seem a bit redundant, since the two
|
||||
# classes are almost identical. But what if they drift apart? So we do
|
||||
# the full tests so that any future drift doesn't introduce bugs.
|
||||
message = MIMEPart
|
||||
|
||||
def test_set_content_does_not_add_MIME_Version(self):
|
||||
m = self._str_msg('')
|
||||
cm = self._TestContentManager()
|
||||
self.assertNotIn('MIME-Version', m)
|
||||
m.set_content(content_manager=cm)
|
||||
self.assertNotIn('MIME-Version', m)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
110
third_party/python/Lib/test/test_email/test_parser.py
vendored
Normal file
110
third_party/python/Lib/test/test_email/test_parser.py
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
import io
|
||||
import email
|
||||
import unittest
|
||||
from email.message import Message, EmailMessage
|
||||
from email.policy import default
|
||||
from test.test_email import TestEmailBase
|
||||
|
||||
|
||||
class TestCustomMessage(TestEmailBase):
|
||||
|
||||
class MyMessage(Message):
|
||||
def __init__(self, policy):
|
||||
self.check_policy = policy
|
||||
super().__init__()
|
||||
|
||||
MyPolicy = TestEmailBase.policy.clone(linesep='boo')
|
||||
|
||||
def test_custom_message_gets_policy_if_possible_from_string(self):
|
||||
msg = email.message_from_string("Subject: bogus\n\nmsg\n",
|
||||
self.MyMessage,
|
||||
policy=self.MyPolicy)
|
||||
self.assertIsInstance(msg, self.MyMessage)
|
||||
self.assertIs(msg.check_policy, self.MyPolicy)
|
||||
|
||||
def test_custom_message_gets_policy_if_possible_from_file(self):
|
||||
source_file = io.StringIO("Subject: bogus\n\nmsg\n")
|
||||
msg = email.message_from_file(source_file,
|
||||
self.MyMessage,
|
||||
policy=self.MyPolicy)
|
||||
self.assertIsInstance(msg, self.MyMessage)
|
||||
self.assertIs(msg.check_policy, self.MyPolicy)
|
||||
|
||||
# XXX add tests for other functions that take Message arg.
|
||||
|
||||
|
||||
class TestParserBase:
|
||||
|
||||
def test_only_split_on_cr_lf(self):
|
||||
# The unicode line splitter splits on unicode linebreaks, which are
|
||||
# more numerous than allowed by the email RFCs; make sure we are only
|
||||
# splitting on those two.
|
||||
for parser in self.parsers:
|
||||
with self.subTest(parser=parser.__name__):
|
||||
msg = parser(
|
||||
"Next-Line: not\x85broken\r\n"
|
||||
"Null: not\x00broken\r\n"
|
||||
"Vertical-Tab: not\vbroken\r\n"
|
||||
"Form-Feed: not\fbroken\r\n"
|
||||
"File-Separator: not\x1Cbroken\r\n"
|
||||
"Group-Separator: not\x1Dbroken\r\n"
|
||||
"Record-Separator: not\x1Ebroken\r\n"
|
||||
"Line-Separator: not\u2028broken\r\n"
|
||||
"Paragraph-Separator: not\u2029broken\r\n"
|
||||
"\r\n",
|
||||
policy=default,
|
||||
)
|
||||
self.assertEqual(msg.items(), [
|
||||
("Next-Line", "not\x85broken"),
|
||||
("Null", "not\x00broken"),
|
||||
("Vertical-Tab", "not\vbroken"),
|
||||
("Form-Feed", "not\fbroken"),
|
||||
("File-Separator", "not\x1Cbroken"),
|
||||
("Group-Separator", "not\x1Dbroken"),
|
||||
("Record-Separator", "not\x1Ebroken"),
|
||||
("Line-Separator", "not\u2028broken"),
|
||||
("Paragraph-Separator", "not\u2029broken"),
|
||||
])
|
||||
self.assertEqual(msg.get_payload(), "")
|
||||
|
||||
class MyMessage(EmailMessage):
|
||||
pass
|
||||
|
||||
def test_custom_message_factory_on_policy(self):
|
||||
for parser in self.parsers:
|
||||
with self.subTest(parser=parser.__name__):
|
||||
MyPolicy = default.clone(message_factory=self.MyMessage)
|
||||
msg = parser("To: foo\n\ntest", policy=MyPolicy)
|
||||
self.assertIsInstance(msg, self.MyMessage)
|
||||
|
||||
def test_factory_arg_overrides_policy(self):
|
||||
for parser in self.parsers:
|
||||
with self.subTest(parser=parser.__name__):
|
||||
MyPolicy = default.clone(message_factory=self.MyMessage)
|
||||
msg = parser("To: foo\n\ntest", Message, policy=MyPolicy)
|
||||
self.assertNotIsInstance(msg, self.MyMessage)
|
||||
self.assertIsInstance(msg, Message)
|
||||
|
||||
# Play some games to get nice output in subTest. This code could be clearer
|
||||
# if staticmethod supported __name__.
|
||||
|
||||
def message_from_file(s, *args, **kw):
|
||||
f = io.StringIO(s)
|
||||
return email.message_from_file(f, *args, **kw)
|
||||
|
||||
class TestParser(TestParserBase, TestEmailBase):
|
||||
parsers = (email.message_from_string, message_from_file)
|
||||
|
||||
def message_from_bytes(s, *args, **kw):
|
||||
return email.message_from_bytes(s.encode(), *args, **kw)
|
||||
|
||||
def message_from_binary_file(s, *args, **kw):
|
||||
f = io.BytesIO(s.encode())
|
||||
return email.message_from_binary_file(f, *args, **kw)
|
||||
|
||||
class TestBytesParser(TestParserBase, TestEmailBase):
|
||||
parsers = (message_from_bytes, message_from_binary_file)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
76
third_party/python/Lib/test/test_email/test_pickleable.py
vendored
Normal file
76
third_party/python/Lib/test/test_email/test_pickleable.py
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
import unittest
|
||||
import textwrap
|
||||
import copy
|
||||
import pickle
|
||||
import email
|
||||
import email.message
|
||||
from email import policy
|
||||
from email.headerregistry import HeaderRegistry
|
||||
from test.test_email import TestEmailBase, parameterize
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestPickleCopyHeader(TestEmailBase):
|
||||
|
||||
header_factory = HeaderRegistry()
|
||||
|
||||
unstructured = header_factory('subject', 'this is a test')
|
||||
|
||||
header_params = {
|
||||
'subject': ('subject', 'this is a test'),
|
||||
'from': ('from', 'frodo@mordor.net'),
|
||||
'to': ('to', 'a: k@b.com, y@z.com;, j@f.com'),
|
||||
'date': ('date', 'Tue, 29 May 2012 09:24:26 +1000'),
|
||||
}
|
||||
|
||||
def header_as_deepcopy(self, name, value):
|
||||
header = self.header_factory(name, value)
|
||||
h = copy.deepcopy(header)
|
||||
self.assertEqual(str(h), str(header))
|
||||
|
||||
def header_as_pickle(self, name, value):
|
||||
header = self.header_factory(name, value)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
p = pickle.dumps(header, proto)
|
||||
h = pickle.loads(p)
|
||||
self.assertEqual(str(h), str(header))
|
||||
|
||||
|
||||
@parameterize
|
||||
class TestPickleCopyMessage(TestEmailBase):
|
||||
|
||||
# Message objects are a sequence, so we have to make them a one-tuple in
|
||||
# msg_params so they get passed to the parameterized test method as a
|
||||
# single argument instead of as a list of headers.
|
||||
msg_params = {}
|
||||
|
||||
# Note: there will be no custom header objects in the parsed message.
|
||||
msg_params['parsed'] = (email.message_from_string(textwrap.dedent("""\
|
||||
Date: Tue, 29 May 2012 09:24:26 +1000
|
||||
From: frodo@mordor.net
|
||||
To: bilbo@underhill.org
|
||||
Subject: help
|
||||
|
||||
I think I forgot the ring.
|
||||
"""), policy=policy.default),)
|
||||
|
||||
msg_params['created'] = (email.message.Message(policy=policy.default),)
|
||||
msg_params['created'][0]['Date'] = 'Tue, 29 May 2012 09:24:26 +1000'
|
||||
msg_params['created'][0]['From'] = 'frodo@mordor.net'
|
||||
msg_params['created'][0]['To'] = 'bilbo@underhill.org'
|
||||
msg_params['created'][0]['Subject'] = 'help'
|
||||
msg_params['created'][0].set_payload('I think I forgot the ring.')
|
||||
|
||||
def msg_as_deepcopy(self, msg):
|
||||
msg2 = copy.deepcopy(msg)
|
||||
self.assertEqual(msg2.as_string(), msg.as_string())
|
||||
|
||||
def msg_as_pickle(self, msg):
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
p = pickle.dumps(msg, proto)
|
||||
msg2 = pickle.loads(p)
|
||||
self.assertEqual(msg2.as_string(), msg.as_string())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
374
third_party/python/Lib/test/test_email/test_policy.py
vendored
Normal file
374
third_party/python/Lib/test/test_email/test_policy.py
vendored
Normal file
|
@ -0,0 +1,374 @@
|
|||
import io
|
||||
import types
|
||||
import textwrap
|
||||
import unittest
|
||||
import email.errors
|
||||
import email.policy
|
||||
import email.parser
|
||||
import email.generator
|
||||
import email.message
|
||||
from email import headerregistry
|
||||
|
||||
def make_defaults(base_defaults, differences):
|
||||
defaults = base_defaults.copy()
|
||||
defaults.update(differences)
|
||||
return defaults
|
||||
|
||||
class PolicyAPITests(unittest.TestCase):
|
||||
|
||||
longMessage = True
|
||||
|
||||
# Base default values.
|
||||
compat32_defaults = {
|
||||
'max_line_length': 78,
|
||||
'linesep': '\n',
|
||||
'cte_type': '8bit',
|
||||
'raise_on_defect': False,
|
||||
'mangle_from_': True,
|
||||
'message_factory': None,
|
||||
}
|
||||
# These default values are the ones set on email.policy.default.
|
||||
# If any of these defaults change, the docs must be updated.
|
||||
policy_defaults = compat32_defaults.copy()
|
||||
policy_defaults.update({
|
||||
'utf8': False,
|
||||
'raise_on_defect': False,
|
||||
'header_factory': email.policy.EmailPolicy.header_factory,
|
||||
'refold_source': 'long',
|
||||
'content_manager': email.policy.EmailPolicy.content_manager,
|
||||
'mangle_from_': False,
|
||||
'message_factory': email.message.EmailMessage,
|
||||
})
|
||||
|
||||
# For each policy under test, we give here what we expect the defaults to
|
||||
# be for that policy. The second argument to make defaults is the
|
||||
# difference between the base defaults and that for the particular policy.
|
||||
new_policy = email.policy.EmailPolicy()
|
||||
policies = {
|
||||
email.policy.compat32: make_defaults(compat32_defaults, {}),
|
||||
email.policy.default: make_defaults(policy_defaults, {}),
|
||||
email.policy.SMTP: make_defaults(policy_defaults,
|
||||
{'linesep': '\r\n'}),
|
||||
email.policy.SMTPUTF8: make_defaults(policy_defaults,
|
||||
{'linesep': '\r\n',
|
||||
'utf8': True}),
|
||||
email.policy.HTTP: make_defaults(policy_defaults,
|
||||
{'linesep': '\r\n',
|
||||
'max_line_length': None}),
|
||||
email.policy.strict: make_defaults(policy_defaults,
|
||||
{'raise_on_defect': True}),
|
||||
new_policy: make_defaults(policy_defaults, {}),
|
||||
}
|
||||
# Creating a new policy creates a new header factory. There is a test
|
||||
# later that proves this.
|
||||
policies[new_policy]['header_factory'] = new_policy.header_factory
|
||||
|
||||
def test_defaults(self):
|
||||
for policy, expected in self.policies.items():
|
||||
for attr, value in expected.items():
|
||||
with self.subTest(policy=policy, attr=attr):
|
||||
self.assertEqual(getattr(policy, attr), value,
|
||||
("change {} docs/docstrings if defaults have "
|
||||
"changed").format(policy))
|
||||
|
||||
def test_all_attributes_covered(self):
|
||||
for policy, expected in self.policies.items():
|
||||
for attr in dir(policy):
|
||||
with self.subTest(policy=policy, attr=attr):
|
||||
if (attr.startswith('_') or
|
||||
isinstance(getattr(email.policy.EmailPolicy, attr),
|
||||
types.FunctionType)):
|
||||
continue
|
||||
else:
|
||||
self.assertIn(attr, expected,
|
||||
"{} is not fully tested".format(attr))
|
||||
|
||||
def test_abc(self):
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
email.policy.Policy()
|
||||
msg = str(cm.exception)
|
||||
abstract_methods = ('fold',
|
||||
'fold_binary',
|
||||
'header_fetch_parse',
|
||||
'header_source_parse',
|
||||
'header_store_parse')
|
||||
for method in abstract_methods:
|
||||
self.assertIn(method, msg)
|
||||
|
||||
def test_policy_is_immutable(self):
|
||||
for policy, defaults in self.policies.items():
|
||||
for attr in defaults:
|
||||
with self.assertRaisesRegex(AttributeError, attr+".*read-only"):
|
||||
setattr(policy, attr, None)
|
||||
with self.assertRaisesRegex(AttributeError, 'no attribute.*foo'):
|
||||
policy.foo = None
|
||||
|
||||
def test_set_policy_attrs_when_cloned(self):
|
||||
# None of the attributes has a default value of None, so we set them
|
||||
# all to None in the clone call and check that it worked.
|
||||
for policyclass, defaults in self.policies.items():
|
||||
testattrdict = {attr: None for attr in defaults}
|
||||
policy = policyclass.clone(**testattrdict)
|
||||
for attr in defaults:
|
||||
self.assertIsNone(getattr(policy, attr))
|
||||
|
||||
def test_reject_non_policy_keyword_when_called(self):
|
||||
for policyclass in self.policies:
|
||||
with self.assertRaises(TypeError):
|
||||
policyclass(this_keyword_should_not_be_valid=None)
|
||||
with self.assertRaises(TypeError):
|
||||
policyclass(newtline=None)
|
||||
|
||||
def test_policy_addition(self):
|
||||
expected = self.policy_defaults.copy()
|
||||
p1 = email.policy.default.clone(max_line_length=100)
|
||||
p2 = email.policy.default.clone(max_line_length=50)
|
||||
added = p1 + p2
|
||||
expected.update(max_line_length=50)
|
||||
for attr, value in expected.items():
|
||||
self.assertEqual(getattr(added, attr), value)
|
||||
added = p2 + p1
|
||||
expected.update(max_line_length=100)
|
||||
for attr, value in expected.items():
|
||||
self.assertEqual(getattr(added, attr), value)
|
||||
added = added + email.policy.default
|
||||
for attr, value in expected.items():
|
||||
self.assertEqual(getattr(added, attr), value)
|
||||
|
||||
def test_register_defect(self):
|
||||
class Dummy:
|
||||
def __init__(self):
|
||||
self.defects = []
|
||||
obj = Dummy()
|
||||
defect = object()
|
||||
policy = email.policy.EmailPolicy()
|
||||
policy.register_defect(obj, defect)
|
||||
self.assertEqual(obj.defects, [defect])
|
||||
defect2 = object()
|
||||
policy.register_defect(obj, defect2)
|
||||
self.assertEqual(obj.defects, [defect, defect2])
|
||||
|
||||
class MyObj:
|
||||
def __init__(self):
|
||||
self.defects = []
|
||||
|
||||
class MyDefect(Exception):
|
||||
pass
|
||||
|
||||
def test_handle_defect_raises_on_strict(self):
|
||||
foo = self.MyObj()
|
||||
defect = self.MyDefect("the telly is broken")
|
||||
with self.assertRaisesRegex(self.MyDefect, "the telly is broken"):
|
||||
email.policy.strict.handle_defect(foo, defect)
|
||||
|
||||
def test_handle_defect_registers_defect(self):
|
||||
foo = self.MyObj()
|
||||
defect1 = self.MyDefect("one")
|
||||
email.policy.default.handle_defect(foo, defect1)
|
||||
self.assertEqual(foo.defects, [defect1])
|
||||
defect2 = self.MyDefect("two")
|
||||
email.policy.default.handle_defect(foo, defect2)
|
||||
self.assertEqual(foo.defects, [defect1, defect2])
|
||||
|
||||
class MyPolicy(email.policy.EmailPolicy):
|
||||
defects = None
|
||||
def __init__(self, *args, **kw):
|
||||
super().__init__(*args, defects=[], **kw)
|
||||
def register_defect(self, obj, defect):
|
||||
self.defects.append(defect)
|
||||
|
||||
def test_overridden_register_defect_still_raises(self):
|
||||
foo = self.MyObj()
|
||||
defect = self.MyDefect("the telly is broken")
|
||||
with self.assertRaisesRegex(self.MyDefect, "the telly is broken"):
|
||||
self.MyPolicy(raise_on_defect=True).handle_defect(foo, defect)
|
||||
|
||||
def test_overridden_register_defect_works(self):
|
||||
foo = self.MyObj()
|
||||
defect1 = self.MyDefect("one")
|
||||
my_policy = self.MyPolicy()
|
||||
my_policy.handle_defect(foo, defect1)
|
||||
self.assertEqual(my_policy.defects, [defect1])
|
||||
self.assertEqual(foo.defects, [])
|
||||
defect2 = self.MyDefect("two")
|
||||
my_policy.handle_defect(foo, defect2)
|
||||
self.assertEqual(my_policy.defects, [defect1, defect2])
|
||||
self.assertEqual(foo.defects, [])
|
||||
|
||||
def test_default_header_factory(self):
|
||||
h = email.policy.default.header_factory('Test', 'test')
|
||||
self.assertEqual(h.name, 'Test')
|
||||
self.assertIsInstance(h, headerregistry.UnstructuredHeader)
|
||||
self.assertIsInstance(h, headerregistry.BaseHeader)
|
||||
|
||||
class Foo:
|
||||
parse = headerregistry.UnstructuredHeader.parse
|
||||
|
||||
def test_each_Policy_gets_unique_factory(self):
|
||||
policy1 = email.policy.EmailPolicy()
|
||||
policy2 = email.policy.EmailPolicy()
|
||||
policy1.header_factory.map_to_type('foo', self.Foo)
|
||||
h = policy1.header_factory('foo', 'test')
|
||||
self.assertIsInstance(h, self.Foo)
|
||||
self.assertNotIsInstance(h, headerregistry.UnstructuredHeader)
|
||||
h = policy2.header_factory('foo', 'test')
|
||||
self.assertNotIsInstance(h, self.Foo)
|
||||
self.assertIsInstance(h, headerregistry.UnstructuredHeader)
|
||||
|
||||
def test_clone_copies_factory(self):
|
||||
policy1 = email.policy.EmailPolicy()
|
||||
policy2 = policy1.clone()
|
||||
policy1.header_factory.map_to_type('foo', self.Foo)
|
||||
h = policy1.header_factory('foo', 'test')
|
||||
self.assertIsInstance(h, self.Foo)
|
||||
h = policy2.header_factory('foo', 'test')
|
||||
self.assertIsInstance(h, self.Foo)
|
||||
|
||||
def test_new_factory_overrides_default(self):
|
||||
mypolicy = email.policy.EmailPolicy()
|
||||
myfactory = mypolicy.header_factory
|
||||
newpolicy = mypolicy + email.policy.strict
|
||||
self.assertEqual(newpolicy.header_factory, myfactory)
|
||||
newpolicy = email.policy.strict + mypolicy
|
||||
self.assertEqual(newpolicy.header_factory, myfactory)
|
||||
|
||||
def test_adding_default_policies_preserves_default_factory(self):
|
||||
newpolicy = email.policy.default + email.policy.strict
|
||||
self.assertEqual(newpolicy.header_factory,
|
||||
email.policy.EmailPolicy.header_factory)
|
||||
self.assertEqual(newpolicy.__dict__, {'raise_on_defect': True})
|
||||
|
||||
def test_non_ascii_chars_do_not_cause_inf_loop(self):
|
||||
policy = email.policy.default.clone(max_line_length=20)
|
||||
actual = policy.fold('Subject', 'ą' * 12)
|
||||
self.assertEqual(
|
||||
actual,
|
||||
'Subject: \n' +
|
||||
12 * ' =?utf-8?q?=C4=85?=\n')
|
||||
|
||||
def test_short_maxlen_error(self):
|
||||
# RFC 2047 chrome takes up 7 characters, plus the length of the charset
|
||||
# name, so folding should fail if maxlen is lower than the minimum
|
||||
# required length for a line.
|
||||
|
||||
# Note: This is only triggered when there is a single word longer than
|
||||
# max_line_length, hence the 1234567890 at the end of this whimsical
|
||||
# subject. This is because when we encounter a word longer than
|
||||
# max_line_length, it is broken down into encoded words to fit
|
||||
# max_line_length. If the max_line_length isn't large enough to even
|
||||
# contain the RFC 2047 chrome (`?=<charset>?q??=`), we fail.
|
||||
subject = "Melt away the pounds with this one simple trick! 1234567890"
|
||||
|
||||
for maxlen in [3, 7, 9]:
|
||||
with self.subTest(maxlen=maxlen):
|
||||
policy = email.policy.default.clone(max_line_length=maxlen)
|
||||
with self.assertRaises(email.errors.HeaderParseError):
|
||||
policy.fold("Subject", subject)
|
||||
|
||||
# XXX: Need subclassing tests.
|
||||
# For adding subclassed objects, make sure the usual rules apply (subclass
|
||||
# wins), but that the order still works (right overrides left).
|
||||
|
||||
|
||||
class TestException(Exception):
|
||||
pass
|
||||
|
||||
class TestPolicyPropagation(unittest.TestCase):
|
||||
|
||||
# The abstract methods are used by the parser but not by the wrapper
|
||||
# functions that call it, so if the exception gets raised we know that the
|
||||
# policy was actually propagated all the way to feedparser.
|
||||
class MyPolicy(email.policy.Policy):
|
||||
def badmethod(self, *args, **kw):
|
||||
raise TestException("test")
|
||||
fold = fold_binary = header_fetch_parser = badmethod
|
||||
header_source_parse = header_store_parse = badmethod
|
||||
|
||||
def test_message_from_string(self):
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
email.message_from_string("Subject: test\n\n",
|
||||
policy=self.MyPolicy)
|
||||
|
||||
def test_message_from_bytes(self):
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
email.message_from_bytes(b"Subject: test\n\n",
|
||||
policy=self.MyPolicy)
|
||||
|
||||
def test_message_from_file(self):
|
||||
f = io.StringIO('Subject: test\n\n')
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
email.message_from_file(f, policy=self.MyPolicy)
|
||||
|
||||
def test_message_from_binary_file(self):
|
||||
f = io.BytesIO(b'Subject: test\n\n')
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
email.message_from_binary_file(f, policy=self.MyPolicy)
|
||||
|
||||
# These are redundant, but we need them for black-box completeness.
|
||||
|
||||
def test_parser(self):
|
||||
p = email.parser.Parser(policy=self.MyPolicy)
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
p.parsestr('Subject: test\n\n')
|
||||
|
||||
def test_bytes_parser(self):
|
||||
p = email.parser.BytesParser(policy=self.MyPolicy)
|
||||
with self.assertRaisesRegex(TestException, "^test$"):
|
||||
p.parsebytes(b'Subject: test\n\n')
|
||||
|
||||
# Now that we've established that all the parse methods get the
|
||||
# policy in to feedparser, we can use message_from_string for
|
||||
# the rest of the propagation tests.
|
||||
|
||||
def _make_msg(self, source='Subject: test\n\n', policy=None):
|
||||
self.policy = email.policy.default.clone() if policy is None else policy
|
||||
return email.message_from_string(source, policy=self.policy)
|
||||
|
||||
def test_parser_propagates_policy_to_message(self):
|
||||
msg = self._make_msg()
|
||||
self.assertIs(msg.policy, self.policy)
|
||||
|
||||
def test_parser_propagates_policy_to_sub_messages(self):
|
||||
msg = self._make_msg(textwrap.dedent("""\
|
||||
Subject: mime test
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed, boundary="XXX"
|
||||
|
||||
--XXX
|
||||
Content-Type: text/plain
|
||||
|
||||
test
|
||||
--XXX
|
||||
Content-Type: text/plain
|
||||
|
||||
test2
|
||||
--XXX--
|
||||
"""))
|
||||
for part in msg.walk():
|
||||
self.assertIs(part.policy, self.policy)
|
||||
|
||||
def test_message_policy_propagates_to_generator(self):
|
||||
msg = self._make_msg("Subject: test\nTo: foo\n\n",
|
||||
policy=email.policy.default.clone(linesep='X'))
|
||||
s = io.StringIO()
|
||||
g = email.generator.Generator(s)
|
||||
g.flatten(msg)
|
||||
self.assertEqual(s.getvalue(), "Subject: testXTo: fooXX")
|
||||
|
||||
def test_message_policy_used_by_as_string(self):
|
||||
msg = self._make_msg("Subject: test\nTo: foo\n\n",
|
||||
policy=email.policy.default.clone(linesep='X'))
|
||||
self.assertEqual(msg.as_string(), "Subject: testXTo: fooXX")
|
||||
|
||||
|
||||
class TestConcretePolicies(unittest.TestCase):
|
||||
|
||||
def test_header_store_parse_rejects_newlines(self):
|
||||
instance = email.policy.EmailPolicy()
|
||||
self.assertRaises(ValueError,
|
||||
instance.header_store_parse,
|
||||
'From', 'spam\negg@foo.py')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
165
third_party/python/Lib/test/test_email/test_utils.py
vendored
Normal file
165
third_party/python/Lib/test/test_email/test_utils.py
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
import datetime
|
||||
from email import utils
|
||||
import test.support
|
||||
import time
|
||||
import unittest
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
class DateTimeTests(unittest.TestCase):
|
||||
|
||||
datestring = 'Sun, 23 Sep 2001 20:10:55'
|
||||
dateargs = (2001, 9, 23, 20, 10, 55)
|
||||
offsetstring = ' -0700'
|
||||
utcoffset = datetime.timedelta(hours=-7)
|
||||
tz = datetime.timezone(utcoffset)
|
||||
naive_dt = datetime.datetime(*dateargs)
|
||||
aware_dt = datetime.datetime(*dateargs, tzinfo=tz)
|
||||
|
||||
def test_naive_datetime(self):
|
||||
self.assertEqual(utils.format_datetime(self.naive_dt),
|
||||
self.datestring + ' -0000')
|
||||
|
||||
def test_aware_datetime(self):
|
||||
self.assertEqual(utils.format_datetime(self.aware_dt),
|
||||
self.datestring + self.offsetstring)
|
||||
|
||||
def test_usegmt(self):
|
||||
utc_dt = datetime.datetime(*self.dateargs,
|
||||
tzinfo=datetime.timezone.utc)
|
||||
self.assertEqual(utils.format_datetime(utc_dt, usegmt=True),
|
||||
self.datestring + ' GMT')
|
||||
|
||||
def test_usegmt_with_naive_datetime_raises(self):
|
||||
with self.assertRaises(ValueError):
|
||||
utils.format_datetime(self.naive_dt, usegmt=True)
|
||||
|
||||
def test_usegmt_with_non_utc_datetime_raises(self):
|
||||
with self.assertRaises(ValueError):
|
||||
utils.format_datetime(self.aware_dt, usegmt=True)
|
||||
|
||||
def test_parsedate_to_datetime(self):
|
||||
self.assertEqual(
|
||||
utils.parsedate_to_datetime(self.datestring + self.offsetstring),
|
||||
self.aware_dt)
|
||||
|
||||
def test_parsedate_to_datetime_naive(self):
|
||||
self.assertEqual(
|
||||
utils.parsedate_to_datetime(self.datestring + ' -0000'),
|
||||
self.naive_dt)
|
||||
|
||||
|
||||
class LocaltimeTests(unittest.TestCase):
|
||||
|
||||
def test_localtime_is_tz_aware_daylight_true(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t = utils.localtime()
|
||||
self.assertIsNotNone(t.tzinfo)
|
||||
|
||||
def test_localtime_is_tz_aware_daylight_false(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t = utils.localtime()
|
||||
self.assertIsNotNone(t.tzinfo)
|
||||
|
||||
def test_localtime_daylight_true_dst_false(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
t1 = utils.localtime(t0, isdst=-1)
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
def test_localtime_daylight_false_dst_false(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
t1 = utils.localtime(t0, isdst=-1)
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
@test.support.run_with_tz('Europe/Minsk')
|
||||
def test_localtime_daylight_true_dst_true(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
t1 = utils.localtime(t0, isdst=1)
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
@test.support.run_with_tz('Europe/Minsk')
|
||||
def test_localtime_daylight_false_dst_true(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t0 = datetime.datetime(2012, 3, 12, 1, 1)
|
||||
t1 = utils.localtime(t0, isdst=1)
|
||||
t2 = utils.localtime(t1)
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
@test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
|
||||
def test_localtime_epoch_utc_daylight_true(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc)
|
||||
t1 = utils.localtime(t0)
|
||||
t2 = t0 - datetime.timedelta(hours=5)
|
||||
t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5)))
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
@test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
|
||||
def test_localtime_epoch_utc_daylight_false(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc)
|
||||
t1 = utils.localtime(t0)
|
||||
t2 = t0 - datetime.timedelta(hours=5)
|
||||
t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5)))
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
def test_localtime_epoch_notz_daylight_true(self):
|
||||
test.support.patch(self, time, 'daylight', True)
|
||||
t0 = datetime.datetime(1990, 1, 1)
|
||||
t1 = utils.localtime(t0)
|
||||
t2 = utils.localtime(t0.replace(tzinfo=None))
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
def test_localtime_epoch_notz_daylight_false(self):
|
||||
test.support.patch(self, time, 'daylight', False)
|
||||
t0 = datetime.datetime(1990, 1, 1)
|
||||
t1 = utils.localtime(t0)
|
||||
t2 = utils.localtime(t0.replace(tzinfo=None))
|
||||
self.assertEqual(t1, t2)
|
||||
|
||||
# XXX: Need a more robust test for Olson's tzdata
|
||||
@unittest.skipIf(sys.platform.startswith('win'),
|
||||
"Windows does not use Olson's TZ database")
|
||||
@unittest.skipUnless(os.path.exists('/usr/share/zoneinfo') or
|
||||
os.path.exists('/usr/lib/zoneinfo'),
|
||||
"Can't find the Olson's TZ database")
|
||||
@test.support.run_with_tz('Europe/Kiev')
|
||||
def test_variable_tzname(self):
|
||||
t0 = datetime.datetime(1984, 1, 1, tzinfo=datetime.timezone.utc)
|
||||
t1 = utils.localtime(t0)
|
||||
self.assertEqual(t1.tzname(), 'MSK')
|
||||
t0 = datetime.datetime(1994, 1, 1, tzinfo=datetime.timezone.utc)
|
||||
t1 = utils.localtime(t0)
|
||||
self.assertEqual(t1.tzname(), 'EET')
|
||||
|
||||
# Issue #24836: The timezone files are out of date (pre 2011k)
|
||||
# on Mac OS X Snow Leopard.
|
||||
@test.support.requires_mac_ver(10, 7)
|
||||
class FormatDateTests(unittest.TestCase):
|
||||
|
||||
@test.support.run_with_tz('Europe/Minsk')
|
||||
def test_formatdate(self):
|
||||
timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0))
|
||||
string = utils.formatdate(timeval, localtime=False, usegmt=False)
|
||||
self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 -0000')
|
||||
string = utils.formatdate(timeval, localtime=False, usegmt=True)
|
||||
self.assertEqual(string, 'Thu, 01 Dec 2011 15:00:00 GMT')
|
||||
|
||||
@test.support.run_with_tz('Europe/Minsk')
|
||||
def test_formatdate_with_localtime(self):
|
||||
timeval = time.mktime((2011, 1, 1, 18, 0, 0, 6, 1, 0))
|
||||
string = utils.formatdate(timeval, localtime=True)
|
||||
self.assertEqual(string, 'Sat, 01 Jan 2011 18:00:00 +0200')
|
||||
# Minsk moved from +0200 (with DST) to +0300 (without DST) in 2011
|
||||
timeval = time.mktime((2011, 12, 1, 18, 0, 0, 4, 335, 0))
|
||||
string = utils.formatdate(timeval, localtime=True)
|
||||
self.assertEqual(string, 'Thu, 01 Dec 2011 18:00:00 +0300')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
133
third_party/python/Lib/test/test_email/torture_test.py
vendored
Normal file
133
third_party/python/Lib/test/test_email/torture_test.py
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
# Copyright (C) 2002-2004 Python Software Foundation
|
||||
#
|
||||
# A torture test of the email package. This should not be run as part of the
|
||||
# standard Python test suite since it requires several meg of email messages
|
||||
# collected in the wild. These source messages are not checked into the
|
||||
# Python distro, but are available as part of the standalone email package at
|
||||
# http://sf.net/projects/mimelib
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from io import StringIO
|
||||
|
||||
from test.test_email import TestEmailBase
|
||||
from test.support import run_unittest
|
||||
|
||||
import email
|
||||
from email import __file__ as testfile
|
||||
from email.iterators import _structure
|
||||
|
||||
def openfile(filename):
|
||||
from os.path import join, dirname, abspath
|
||||
path = abspath(join(dirname(testfile), os.pardir, 'moredata', filename))
|
||||
return open(path, 'r')
|
||||
|
||||
# Prevent this test from running in the Python distro
|
||||
try:
|
||||
openfile('crispin-torture.txt')
|
||||
except OSError:
|
||||
raise unittest.SkipTest
|
||||
|
||||
|
||||
|
||||
class TortureBase(TestEmailBase):
|
||||
def _msgobj(self, filename):
|
||||
fp = openfile(filename)
|
||||
try:
|
||||
msg = email.message_from_file(fp)
|
||||
finally:
|
||||
fp.close()
|
||||
return msg
|
||||
|
||||
|
||||
|
||||
class TestCrispinTorture(TortureBase):
|
||||
# Mark Crispin's torture test from the SquirrelMail project
|
||||
def test_mondo_message(self):
|
||||
eq = self.assertEqual
|
||||
neq = self.ndiffAssertEqual
|
||||
msg = self._msgobj('crispin-torture.txt')
|
||||
payload = msg.get_payload()
|
||||
eq(type(payload), list)
|
||||
eq(len(payload), 12)
|
||||
eq(msg.preamble, None)
|
||||
eq(msg.epilogue, '\n')
|
||||
# Probably the best way to verify the message is parsed correctly is to
|
||||
# dump its structure and compare it against the known structure.
|
||||
fp = StringIO()
|
||||
_structure(msg, fp=fp)
|
||||
neq(fp.getvalue(), """\
|
||||
multipart/mixed
|
||||
text/plain
|
||||
message/rfc822
|
||||
multipart/alternative
|
||||
text/plain
|
||||
multipart/mixed
|
||||
text/richtext
|
||||
application/andrew-inset
|
||||
message/rfc822
|
||||
audio/basic
|
||||
audio/basic
|
||||
image/pbm
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
multipart/mixed
|
||||
text/plain
|
||||
audio/x-sun
|
||||
multipart/mixed
|
||||
image/gif
|
||||
image/gif
|
||||
application/x-be2
|
||||
application/atomicmail
|
||||
audio/x-sun
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
text/plain
|
||||
image/pgm
|
||||
text/plain
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
text/plain
|
||||
image/pbm
|
||||
message/rfc822
|
||||
application/postscript
|
||||
image/gif
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
audio/basic
|
||||
audio/basic
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
application/postscript
|
||||
text/plain
|
||||
message/rfc822
|
||||
multipart/mixed
|
||||
text/plain
|
||||
multipart/parallel
|
||||
image/gif
|
||||
audio/basic
|
||||
application/atomicmail
|
||||
message/rfc822
|
||||
audio/x-sun
|
||||
""")
|
||||
|
||||
def _testclasses():
|
||||
mod = sys.modules[__name__]
|
||||
return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]
|
||||
|
||||
|
||||
def suite():
|
||||
suite = unittest.TestSuite()
|
||||
for testclass in _testclasses():
|
||||
suite.addTest(unittest.makeSuite(testclass))
|
||||
return suite
|
||||
|
||||
|
||||
def test_main():
|
||||
for testclass in _testclasses():
|
||||
run_unittest(testclass)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='suite')
|
Loading…
Add table
Add a link
Reference in a new issue