summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/email/mime/application.py5
-rw-r--r--Lib/email/mime/audio.py5
-rw-r--r--Lib/email/mime/base.py8
-rw-r--r--Lib/email/mime/image.py5
-rw-r--r--Lib/email/mime/message.py4
-rw-r--r--Lib/email/mime/multipart.py3
-rw-r--r--Lib/email/mime/text.py4
-rw-r--r--Lib/test/test_email/test_email.py41
8 files changed, 62 insertions, 13 deletions
diff --git a/Lib/email/mime/application.py b/Lib/email/mime/application.py
index f5c5905..6877e55 100644
--- a/Lib/email/mime/application.py
+++ b/Lib/email/mime/application.py
@@ -14,7 +14,7 @@ class MIMEApplication(MIMENonMultipart):
"""Class for generating application/* MIME documents."""
def __init__(self, _data, _subtype='octet-stream',
- _encoder=encoders.encode_base64, **_params):
+ _encoder=encoders.encode_base64, *, policy=None, **_params):
"""Create an application/* type MIME document.
_data is a string containing the raw application data.
@@ -31,6 +31,7 @@ class MIMEApplication(MIMENonMultipart):
"""
if _subtype is None:
raise TypeError('Invalid application MIME subtype')
- MIMENonMultipart.__init__(self, 'application', _subtype, **_params)
+ MIMENonMultipart.__init__(self, 'application', _subtype, policy=policy,
+ **_params)
self.set_payload(_data)
_encoder(self)
diff --git a/Lib/email/mime/audio.py b/Lib/email/mime/audio.py
index fbc1189..4bcd7b2 100644
--- a/Lib/email/mime/audio.py
+++ b/Lib/email/mime/audio.py
@@ -43,7 +43,7 @@ class MIMEAudio(MIMENonMultipart):
"""Class for generating audio/* MIME documents."""
def __init__(self, _audiodata, _subtype=None,
- _encoder=encoders.encode_base64, **_params):
+ _encoder=encoders.encode_base64, *, policy=None, **_params):
"""Create an audio/* type MIME document.
_audiodata is a string containing the raw audio data. If this data
@@ -68,6 +68,7 @@ class MIMEAudio(MIMENonMultipart):
_subtype = _whatsnd(_audiodata)
if _subtype is None:
raise TypeError('Could not find audio MIME subtype')
- MIMENonMultipart.__init__(self, 'audio', _subtype, **_params)
+ MIMENonMultipart.__init__(self, 'audio', _subtype, policy=policy,
+ **_params)
self.set_payload(_audiodata)
_encoder(self)
diff --git a/Lib/email/mime/base.py b/Lib/email/mime/base.py
index ac91925..1a3f9b5 100644
--- a/Lib/email/mime/base.py
+++ b/Lib/email/mime/base.py
@@ -6,6 +6,8 @@
__all__ = ['MIMEBase']
+import email.policy
+
from email import message
@@ -13,14 +15,16 @@ from email import message
class MIMEBase(message.Message):
"""Base class for MIME specializations."""
- def __init__(self, _maintype, _subtype, **_params):
+ def __init__(self, _maintype, _subtype, *, policy=None, **_params):
"""This constructor adds a Content-Type: and a MIME-Version: header.
The Content-Type: header is taken from the _maintype and _subtype
arguments. Additional parameters for this header are taken from the
keyword arguments.
"""
- message.Message.__init__(self)
+ if policy is None:
+ policy = email.policy.compat32
+ message.Message.__init__(self, policy=policy)
ctype = '%s/%s' % (_maintype, _subtype)
self.add_header('Content-Type', ctype, **_params)
self['MIME-Version'] = '1.0'
diff --git a/Lib/email/mime/image.py b/Lib/email/mime/image.py
index 5563823..9272464 100644
--- a/Lib/email/mime/image.py
+++ b/Lib/email/mime/image.py
@@ -17,7 +17,7 @@ class MIMEImage(MIMENonMultipart):
"""Class for generating image/* type MIME documents."""
def __init__(self, _imagedata, _subtype=None,
- _encoder=encoders.encode_base64, **_params):
+ _encoder=encoders.encode_base64, *, policy=None, **_params):
"""Create an image/* type MIME document.
_imagedata is a string containing the raw image data. If this data
@@ -41,6 +41,7 @@ class MIMEImage(MIMENonMultipart):
_subtype = imghdr.what(None, _imagedata)
if _subtype is None:
raise TypeError('Could not guess image MIME subtype')
- MIMENonMultipart.__init__(self, 'image', _subtype, **_params)
+ MIMENonMultipart.__init__(self, 'image', _subtype, policy=policy,
+ **_params)
self.set_payload(_imagedata)
_encoder(self)
diff --git a/Lib/email/mime/message.py b/Lib/email/mime/message.py
index 275dbfd..07e4f2d 100644
--- a/Lib/email/mime/message.py
+++ b/Lib/email/mime/message.py
@@ -14,7 +14,7 @@ from email.mime.nonmultipart import MIMENonMultipart
class MIMEMessage(MIMENonMultipart):
"""Class representing message/* MIME documents."""
- def __init__(self, _msg, _subtype='rfc822'):
+ def __init__(self, _msg, _subtype='rfc822', *, policy=None):
"""Create a message/* type MIME document.
_msg is a message object and must be an instance of Message, or a
@@ -24,7 +24,7 @@ class MIMEMessage(MIMENonMultipart):
default is "rfc822" (this is defined by the MIME standard, even though
the term "rfc822" is technically outdated by RFC 2822).
"""
- MIMENonMultipart.__init__(self, 'message', _subtype)
+ MIMENonMultipart.__init__(self, 'message', _subtype, policy=policy)
if not isinstance(_msg, message.Message):
raise TypeError('Argument is not an instance of Message')
# It's convenient to use this base class method. We need to do it
diff --git a/Lib/email/mime/multipart.py b/Lib/email/mime/multipart.py
index 9661865..2d3f288 100644
--- a/Lib/email/mime/multipart.py
+++ b/Lib/email/mime/multipart.py
@@ -14,6 +14,7 @@ class MIMEMultipart(MIMEBase):
"""Base class for MIME multipart/* type messages."""
def __init__(self, _subtype='mixed', boundary=None, _subparts=None,
+ *, policy=None,
**_params):
"""Creates a multipart/* type message.
@@ -33,7 +34,7 @@ class MIMEMultipart(MIMEBase):
Additional parameters for the Content-Type header are taken from the
keyword arguments (or passed into the _params argument).
"""
- MIMEBase.__init__(self, 'multipart', _subtype, **_params)
+ MIMEBase.__init__(self, 'multipart', _subtype, policy=policy, **_params)
# Initialise _payload to an empty list as the Message superclass's
# implementation of is_multipart assumes that _payload is a list for
diff --git a/Lib/email/mime/text.py b/Lib/email/mime/text.py
index 479928e..87de8d2 100644
--- a/Lib/email/mime/text.py
+++ b/Lib/email/mime/text.py
@@ -14,7 +14,7 @@ from email.mime.nonmultipart import MIMENonMultipart
class MIMEText(MIMENonMultipart):
"""Class for generating text/* type MIME documents."""
- def __init__(self, _text, _subtype='plain', _charset=None):
+ def __init__(self, _text, _subtype='plain', _charset=None, *, policy=None):
"""Create a text/* type MIME document.
_text is the string for this message object.
@@ -38,7 +38,7 @@ class MIMEText(MIMENonMultipart):
if isinstance(_charset, Charset):
_charset = str(_charset)
- MIMENonMultipart.__init__(self, 'text', _subtype,
+ MIMENonMultipart.__init__(self, 'text', _subtype, policy=policy,
**{'charset': _charset})
self.set_payload(_text, _charset)
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 8aaca01..85fccf9 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -31,6 +31,7 @@ from email.mime.image import MIMEImage
from email.mime.base import MIMEBase
from email.mime.message import MIMEMessage
from email.mime.multipart import MIMEMultipart
+from email.mime.nonmultipart import MIMENonMultipart
from email import utils
from email import errors
from email import encoders
@@ -2062,7 +2063,13 @@ YXNkZg==
--===============0012394164==--""")
self.assertEqual(m.get_payload(0).get_payload(), 'YXNkZg==')
+ def test_mimebase_default_policy(self):
+ m = MIMEBase('multipart', 'mixed')
+ self.assertIs(m.policy, email.policy.compat32)
+ def test_mimebase_custom_policy(self):
+ m = MIMEBase('multipart', 'mixed', policy=email.policy.default)
+ self.assertIs(m.policy, email.policy.default)
# Test some badly formatted messages
class TestNonConformant(TestEmailBase):
@@ -2664,6 +2671,19 @@ message 2
msg = MIMEMultipart()
self.assertTrue(msg.is_multipart())
+ def test_multipart_default_policy(self):
+ msg = MIMEMultipart()
+ msg['To'] = 'a@b.com'
+ msg['To'] = 'c@d.com'
+ self.assertEqual(msg.get_all('to'), ['a@b.com', 'c@d.com'])
+
+ def test_multipart_custom_policy(self):
+ msg = MIMEMultipart(policy=email.policy.default)
+ msg['To'] = 'a@b.com'
+ with self.assertRaises(ValueError) as cm:
+ msg['To'] = 'c@d.com'
+ self.assertEqual(str(cm.exception),
+ 'There may be at most 1 To headers in a message')
# A general test of parser->model->generator idempotency. IOW, read a message
# in, parse it into a message object tree, then without touching the tree,
@@ -3313,6 +3333,27 @@ multipart/report
g.flatten(msg, linesep='\r\n')
self.assertEqual(s.getvalue(), msgtxt)
+ def test_mime_classes_policy_argument(self):
+ with openfile('audiotest.au', 'rb') as fp:
+ audiodata = fp.read()
+ with openfile('PyBanner048.gif', 'rb') as fp:
+ bindata = fp.read()
+ classes = [
+ (MIMEApplication, ('',)),
+ (MIMEAudio, (audiodata,)),
+ (MIMEImage, (bindata,)),
+ (MIMEMessage, (Message(),)),
+ (MIMENonMultipart, ('multipart', 'mixed')),
+ (MIMEText, ('',)),
+ ]
+ for cls, constructor in classes:
+ with self.subTest(cls=cls.__name__, policy='compat32'):
+ m = cls(*constructor)
+ self.assertIs(m.policy, email.policy.compat32)
+ with self.subTest(cls=cls.__name__, policy='default'):
+ m = cls(*constructor, policy=email.policy.default)
+ self.assertIs(m.policy, email.policy.default)
+
# Test the iterator/generators
class TestIterators(TestEmailBase):