Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Doc/includes/email-mime.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Import smtplib for the actual sending function
import smtplib

# And imghdr to find the types of our images
import imghdr

# Here are the email package modules we'll need
from email.message import EmailMessage

Expand All @@ -22,7 +19,7 @@
with open(file, 'rb') as fp:
img_data = fp.read()
msg.add_attachment(img_data, maintype='image',
subtype=imghdr.what(None, img_data))
subtype="jpeg")
Comment thread
warsaw marked this conversation as resolved.
Resolved

# Send the email via our own SMTP server.
with smtplib.SMTP('localhost') as s:
Expand Down
14 changes: 9 additions & 5 deletions Doc/library/email.mime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,11 @@ Here are the classes:
A subclass of :class:`~email.mime.nonmultipart.MIMENonMultipart`, the
:class:`MIMEImage` class is used to create MIME message objects of major type
:mimetype:`image`. *_imagedata* is a string containing the raw image data. If
this data can be decoded by the standard Python module :mod:`imghdr`, then the
subtype will be automatically included in the :mailheader:`Content-Type` header.
Otherwise you can explicitly specify the image subtype via the *_subtype*
argument. If the minor type could not be guessed and *_subtype* was not given,
then :exc:`TypeError` is raised.
this data can be decoded by the standard Python module :mod:`imghdr`
(which is deprecated), then the subtype will be automatically included in the
Comment thread
brettcannon marked this conversation as resolved.
Resolved
:mailheader:`Content-Type` header. Otherwise you can explicitly specify the
image subtype via the *_subtype* argument. If the minor type could not be
guessed and *_subtype* was not given, then :exc:`TypeError` is raised.

Optional *_encoder* is a callable (i.e. function) which will perform the actual
encoding of the image data for transport. This callable takes one argument,
Expand All @@ -204,6 +204,10 @@ Here are the classes:
.. versionchanged:: 3.6
Added *policy* keyword-only parameter.

.. deprecated:: 3.11
The default argument for *_subtype* due :mod:`imghdr` being
Comment thread
brettcannon marked this conversation as resolved.
Resolved
deprecated.

.. currentmodule:: email.mime.message

.. class:: MIMEMessage(_msg, _subtype='rfc822', *, policy=compat32)
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -852,9 +852,14 @@ Deprecated
* :mod:`cgitb`
* :mod:`chunk`
* :mod:`crypt`
* :mod:`imghdr`

(Contributed by Brett Cannon in :issue:`47061`.)

* The default argument for *_subtype* for :class:`email.mime.MIMEImage`
has been deprecated due to the deprecation of :mod:`imghdr`. Please
explicitly provide a an image subtype.

Comment thread
brettcannon marked this conversation as resolved.
Resolved

Removed
=======
Expand Down
23 changes: 16 additions & 7 deletions Lib/email/mime/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

__all__ = ['MIMEImage']

import imghdr

from email import encoders
from email.mime.nonmultipart import MIMENonMultipart
import warnings

with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
import imghdr




class MIMEImage(MIMENonMultipart):
"""Class for generating image/* type MIME documents."""

Expand All @@ -21,10 +24,10 @@ def __init__(self, _imagedata, _subtype=None,
"""Create an image/* type MIME document.

_imagedata is a string containing the raw image data. If this data
can be decoded by the standard Python `imghdr' module, then the
subtype will be automatically included in the Content-Type header.
Otherwise, you can specify the specific image subtype via the _subtype
parameter.
can be decoded by the standard Python `imghdr' module
(which is deprecated), then the subtype will be automatically included
in the Content-Type header. Otherwise, you can specify the specific
image subtype via the _subtype parameter.

_encoder is a function which will perform the actual encoding for
transport of the image data. It takes one argument, which is this
Expand All @@ -38,6 +41,12 @@ def __init__(self, _imagedata, _subtype=None,
header.
"""
if _subtype is None:
fullname = f"{__name__}.{self.__class__.__qualname__}"
msg = ("The *_subtype* argument's default value for {name}"
"is deprecated due to the deprecation of imghdr (slated for "
"removal in Python {remove}); explicitly specify the image "
"subtype")
Comment thread
brettcannon marked this conversation as resolved.
Resolved
warnings._deprecated(fullname, msg, remove=(3, 13))
_subtype = imghdr.what(None, _imagedata)
if _subtype is None:
raise TypeError('Could not guess image MIME subtype')
Expand Down
5 changes: 5 additions & 0 deletions Lib/imghdr.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
"""Recognize image file formats based on their first few bytes."""

from os import PathLike
import warnings

__all__ = ["what"]


warnings._deprecated(__name__, remove=(3, 13))


#-------------------------#
# Recognize image headers #
#-------------------------#
Expand Down
15 changes: 11 additions & 4 deletions Lib/test/test_email/test_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import base64
import unittest
import textwrap
import warnings

from io import StringIO, BytesIO
from itertools import chain
Expand Down Expand Up @@ -799,7 +800,7 @@ class TestEncoders(unittest.TestCase):
def test_EncodersEncode_base64(self):
with openfile('PyBanner048.gif', 'rb') as fp:
bindata = fp.read()
mimed = email.mime.image.MIMEImage(bindata)
mimed = email.mime.image.MIMEImage(bindata, 'gif')
base64ed = mimed.get_payload()
# the transfer-encoded body lines should all be <=76 characters
lines = base64ed.split('\n')
Expand Down Expand Up @@ -1557,7 +1558,7 @@ class TestMIMEImage(unittest.TestCase):
def setUp(self):
with openfile('PyBanner048.gif', 'rb') as fp:
self._imgdata = fp.read()
self._im = MIMEImage(self._imgdata)
self._im = MIMEImage(self._imgdata, _subtype='gif')

def test_guess_minor_type(self):
self.assertEqual(self._im.get_content_type(), 'image/gif')
Expand Down Expand Up @@ -1590,6 +1591,12 @@ def test_add_header(self):
self.assertIs(self._im.get_param('attachment', missing,
header='foobar'), missing)

def test_subtype_default_deprecation(self):
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
with self.assertRaises(DeprecationWarning):
self._im = MIMEImage(self._imgdata)



# Test the basic MIMEApplication class
Expand Down Expand Up @@ -1750,7 +1757,7 @@ def setUp(self):
with openfile('PyBanner048.gif', 'rb') as fp:
data = fp.read()
container = MIMEBase('multipart', 'mixed', boundary='BOUNDARY')
image = MIMEImage(data, name='dingusfish.gif')
image = MIMEImage(data, name='dingusfish.gif', _subtype="gif")
image.add_header('content-disposition', 'attachment',
filename='dingusfish.gif')
intro = MIMEText('''\
Expand Down Expand Up @@ -3449,7 +3456,7 @@ def test_mime_classes_policy_argument(self):
classes = [
(MIMEApplication, ('',)),
(MIMEAudio, (audiodata,)),
(MIMEImage, (bindata,)),
(MIMEImage, (bindata, 'gif')),
(MIMEMessage, (Message(),)),
(MIMENonMultipart, ('multipart', 'mixed')),
(MIMEText, ('',)),
Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_imghdr.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import imghdr
import io
import os
import pathlib
import unittest
import warnings
from test.support import findfile
from test.support import findfile, warnings_helper
from test.support.os_helper import TESTFN, unlink

imghdr = warnings_helper.import_deprecated("imghdr")


TEST_FILES = (
('python.png', 'png'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Deprecate the imghdr module. Along the way, deprecate the default argument
for email.mime.MIMEImage's *_subtype* parameter.