@@ -136,10 +136,17 @@ Normalized inbound message
136136.. class :: anymail.inbound.AnymailInboundMessage
137137
138138 The :attr: `~AnymailInboundEvent.message ` attribute of an :class: `AnymailInboundEvent `
139- is an AnymailInboundMessage---an extension of Python's standard :class: `email.message.Message `
139+ is an AnymailInboundMessage---an extension of Python's standard :class: `email.message.EmailMessage `
140140 with additional features to simplify inbound handling.
141141
142- In addition to the base :class: `~email.message.Message ` functionality, it includes these attributes:
142+ .. versionchanged :: 10.1
143+
144+ Earlier releases extended Python's legacy :class: `email.message.Message ` class.
145+ :class: `~email.message.EmailMessage ` is a superset that fixes bugs and improves
146+ compatibility with email standards.
147+
148+ In addition to the base :class: `~email.message.EmailMessage ` functionality,
149+ :class: `!AnymailInboundMessage ` includes these attributes:
143150
144151 .. attribute :: envelope_sender
145152
@@ -221,24 +228,47 @@ Normalized inbound message
221228 The message's plaintext message body as a `str `, or `None ` if the
222229 message doesn't include a plaintext body.
223230
231+ For certain messages that are sent as plaintext with inline images
232+ (such as those sometimes composed by the Apple Mail app), this will
233+ include only the text before the first inline image.
234+
224235 .. attribute :: html
225236
226237 The message's HTML message body as a `str `, or `None ` if the
227238 message doesn't include an HTML body.
228239
229240 .. attribute :: attachments
230241
231- A `list ` of all (non-inline) attachments to the message, or an empty list if there are
232- no attachments. See :ref: `inbound-attachments ` below for the contents of each list item.
242+ A `list ` of all attachments to the message, or an empty list if there are
243+ no attachments. See :ref: `inbound-attachments ` below a description of the values.
244+
245+ If the inbound message includes an attached message, :attr: `!attachments `
246+ will include the attached message and all of *its * attachments, recursively.
247+ Consider Python's :meth: `~email.message.EmailMessage.iter_attachments ` as an
248+ alternative that doesn't descend into attached messages.
249+
250+ .. attribute :: inlines
251+
252+ A `list ` of all inline content parts in the message, or an empty list if none.
253+ See :ref: `inbound-attachments ` below for a description of the values.
254+
255+ Like :attr: `attachments `, this will recursively descend into any attached messages.
233256
234- .. attribute :: inline_attachments
257+ .. versionadded :: 10.1
235258
236- A `dict ` mapping inline Content-ID references to attachment content. Each key is an
259+ .. attribute :: content_id_map
260+
261+ A `dict ` mapping inline Content-ID references to inline content. Each key is an
237262 "unquoted" cid without angle brackets. E.g., if the :attr: `html ` body contains
238263 ``<img src="cid:abc123..."> ``, you could get that inline image using
239- ``message.inline_attachments["abc123..."] ``.
264+ ``message.content_id_map["abc123..."] ``.
265+
266+ The value of each item is described in :ref: `inbound-attachments ` below.
267+
268+ .. versionadded :: 10.1
240269
241- The content of each attachment is described in :ref: `inbound-attachments ` below.
270+ This property was previously available as :attr: `!inline_attachments `.
271+ The old name still works, but is deprecated.
242272
243273 .. attribute :: spam_score
244274
@@ -267,38 +297,39 @@ Normalized inbound message
267297
268298 .. rubric :: Other headers, complex messages, etc.
269299
270- You can use all of Python's :class: `email.message.Message ` features with an
300+ You can use all of Python's :class: `email.message.EmailMessage ` features with an
271301 AnymailInboundMessage. For example, you can access message headers using
272- Message 's :meth: `mapping interface <email.message.Message .__getitem__> `:
302+ EmailMessage 's :meth: `mapping interface <email.message.EmailMessage .__getitem__> `:
273303
274304 .. code-block :: python
275305
276306 message[' reply-to' ] # the Reply-To header (header keys are case-insensitive)
277307 message.getall(' DKIM-Signature' ) # list of all DKIM-Signature headers
278308
279- And you can use Message methods like :meth: `~email.message.Message .walk ` and
280- :meth: `~email.message.Message .get_content_type ` to examine more-complex
309+ And you can use Message methods like :meth: `~email.message.EmailMessage .walk ` and
310+ :meth: `~email.message.EmailMessage .get_content_type ` to examine more-complex
281311 multipart MIME messages (digests, delivery reports, or whatever).
282312
283313
284314.. _inbound-attachments :
285315
286- Handling Inbound Attachments
287- ----------------------------
316+ Attached and inline content
317+ ---------------------------
288318
289- Anymail converts each inbound attachment to a specialized MIME object with
319+ Anymail converts each inbound attachment and inline content to a specialized MIME object with
290320additional methods for handling attachments and integrating with Django.
291321
292- The attachment objects in an AnymailInboundMessage's
293- :attr: `~AnymailInboundMessage.attachments ` list and
294- :attr: `~AnymailInboundMessage.inline_attachments ` dict
322+ The objects in an AnymailInboundMessage's
323+ :attr: `~anymail.inbound.AnymailInboundMessage.attachments `,
324+ :attr: `~anymail.inbound.AnymailInboundMessage.inlines `,
325+ and :attr: `~anymail.inbound.AnymailInboundMessage.content_id_map `
295326have these methods:
296327
297328.. class :: AnymailInboundMessage
298329
299330 .. method :: as_uploaded_file()
300331
301- Returns the attachment converted to a Django :class: `~django.core.files.uploadedfile.UploadedFile `
332+ Returns the content converted to a Django :class: `~django.core.files.uploadedfile.UploadedFile `
302333 object. This is suitable for assigning to a model's :class: `~django.db.models.FileField `
303334 or :class: `~django.db.models.ImageField `:
304335
@@ -322,9 +353,9 @@ have these methods:
322353 attachments are essentially user-uploaded content, so you should
323354 :ref: `never trust the sender <inbound-security >`.)
324355
325- See the Python docs for more info on :meth: `email.message.Message .get_content_type `,
326- :meth: `~email.message.Message .get_content_maintype `, and
327- :meth: `~email.message.Message .get_content_subtype `.
356+ See the Python docs for more info on :meth: `email.message.EmailMessage .get_content_type `,
357+ :meth: `~email.message.EmailMessage .get_content_maintype `, and
358+ :meth: `~email.message.EmailMessage .get_content_subtype `.
328359
329360 (Note that you *cannot * determine the attachment type using code like
330361 ``issubclass(attachment, email.mime.image.MIMEImage) ``. You should instead use something
@@ -341,13 +372,19 @@ have these methods:
341372
342373 .. method :: is_attachment()
343374
344- Returns `True ` for a (non-inline) attachment, `False ` otherwise.
375+ Returns `True ` for attachment content (with :mailheader: `Content-Disposition ` "attachment"),
376+ `False ` otherwise.
345377
346- .. method :: is_inline_attachment ()
378+ .. method :: is_inline ()
347379
348- Returns `True ` for an inline attachment (one with :mailheader: `Content-Disposition ` "inline"),
380+ Returns `True ` for inline content ( with :mailheader: `Content-Disposition ` "inline"),
349381 `False ` otherwise.
350382
383+ .. versionchanged :: 10.1
384+
385+ This method was previously named :meth: `!is_inline_attachment `;
386+ the old name still works, but is deprecated.
387+
351388 .. method :: get_content_disposition()
352389
353390 Returns the lowercased value (without parameters) of the attachment's
@@ -374,7 +411,7 @@ have these methods:
374411
375412 An Anymail inbound attachment is actually just an :class: `AnymailInboundMessage ` instance,
376413 following the Python email package's usual recursive representation of MIME messages.
377- All :class: `AnymailInboundMessage ` and :class: `email.message.Message ` functionality
414+ All :class: `AnymailInboundMessage ` and :class: `email.message.EmailMessage ` functionality
378415 is available on attachment objects (though of course not all features are meaningful in all contexts).
379416
380417 This can be helpful for, e.g., parsing email messages that are forwarded as attachments
0 commit comments