mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Improve inline-image handling
* Add filename param to attach_inline_image * Add attach_inline_image_file function (parallels EmailMessage.attach and attach_file) * Use `Content-Disposition: inline` to decide whether an attachment should be handled inline (whether or not it's an image, and whether or not it has a Content-ID) * Stop conflating filename and Content-ID, for ESPs that allow both. (Solves problem where Google Inbox was displaying inline images as attachments when sent through SendGrid.)
This commit is contained in:
@@ -88,14 +88,14 @@ Changes to settings
|
||||
the values from :setting:`ANYMAIL_SEND_DEFAULTS`.
|
||||
|
||||
``MANDRILL_SUBACCOUNT``
|
||||
Use :attr:`esp_extra` in :setting:`ANYMAIL_MANDRILL_SEND_DEFAULTS`:
|
||||
Use :setting:`ANYMAIL_MANDRILL_SEND_DEFAULTS`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
ANYMAIL = {
|
||||
...
|
||||
"MANDRILL_SEND_DEFAULTS": {
|
||||
"esp_extra": {"subaccount": "<your subaccount>"}
|
||||
"subaccount": "<your subaccount>"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,3 +149,17 @@ Changes to EmailMessage attributes
|
||||
to your code. In the future, the Mandrill-only attributes
|
||||
will be moved into the
|
||||
:attr:`~anymail.message.AnymailMessage.esp_extra` dict.
|
||||
|
||||
**Inline images**
|
||||
Djrill (incorrectly) used the presence of a :mailheader:`Content-ID`
|
||||
header to decide whether to treat an image as inline. Anymail
|
||||
looks for :mailheader:`Content-Disposition: inline`.
|
||||
|
||||
If you were constructing MIMEImage inline image attachments
|
||||
for your Djrill messages, in addition to setting the Content-ID,
|
||||
you should also add::
|
||||
|
||||
image.add_header('Content-Disposition', 'inline')
|
||||
|
||||
Or better yet, use Anymail's new :ref:`inline-images`
|
||||
helper functions to attach your inline images.
|
||||
|
||||
@@ -182,7 +182,15 @@ ESP send options (AnymailMessage)
|
||||
:class:`AnymailMessageMixin` objects. Unlike the attributes above,
|
||||
they can't be used on an arbitrary :class:`~django.core.mail.EmailMessage`.)
|
||||
|
||||
.. method:: attach_inline_image(content, subtype=None, idstring="img", domain=None)
|
||||
.. method:: attach_inline_image_file(path, subtype=None, idstring="img", domain=None)
|
||||
|
||||
Attach an inline (embedded) image to the message and return its :mailheader:`Content-ID`.
|
||||
|
||||
This calls :func:`attach_inline_image_file` on the message. See :ref:`inline-images`
|
||||
for details and an example.
|
||||
|
||||
|
||||
.. method:: attach_inline_image(content, filename=None, subtype=None, idstring="img", domain=None)
|
||||
|
||||
Attach an inline (embedded) image to the message and return its :mailheader:`Content-ID`.
|
||||
|
||||
@@ -303,9 +311,17 @@ ESP send status
|
||||
Inline images
|
||||
-------------
|
||||
|
||||
Anymail includes a convenience function to simplify attaching inline images to email.
|
||||
Anymail includes convenience functions to simplify attaching inline images to email.
|
||||
|
||||
.. function:: attach_inline_image(message, content, subtype=None, idstring="img", domain=None)
|
||||
These functions work with *any* Django :class:`~django.core.mail.EmailMessage` --
|
||||
they're not specific to Anymail email backends. You can use them with messages sent
|
||||
through Django's SMTP backend or any other that properly supports MIME attachments.
|
||||
|
||||
(Both functions are also available as convenience methods on Anymail's
|
||||
:class:`~anymail.message.AnymailMessage` and :class:`~anymail.message.AnymailMessageMixin`
|
||||
classes.)
|
||||
|
||||
.. function:: attach_inline_image_file(message, path, subtype=None, idstring="img", domain=None)
|
||||
|
||||
Attach an inline (embedded) image to the message and return its :mailheader:`Content-ID`.
|
||||
|
||||
@@ -315,23 +331,20 @@ Anymail includes a convenience function to simplify attaching inline images to e
|
||||
.. code-block:: python
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from anymail.message import attach_inline_image
|
||||
|
||||
# read image content -- be sure to open the file in binary mode:
|
||||
with f = open("path/to/picture.jpg", "rb"):
|
||||
raw_image_data = f.read()
|
||||
from anymail.message import attach_inline_image_file
|
||||
|
||||
message = EmailMultiAlternatives( ... )
|
||||
cid = attach_inline_image(message, raw_image_data)
|
||||
cid = attach_inline_image_file(message, 'path/to/picture.jpg')
|
||||
html = '... <img alt="Picture" src="cid:%s"> ...' % cid
|
||||
message.attach_alternative(html, "text/html")
|
||||
message.attach_alternative(html, 'text/html')
|
||||
|
||||
message.send()
|
||||
|
||||
|
||||
`message` must be an :class:`~django.core.mail.EmailMessage` (or subclass) object.
|
||||
|
||||
`content` must be the binary image data (e.g., read from a file).
|
||||
`path` must be the pathname to an image file. (Its basename will also be used as the
|
||||
attachment's filename, which may be visible in some email clients.)
|
||||
|
||||
`subtype` is an optional MIME :mimetype:`image` subtype, e.g., `"png"` or `"jpg"`.
|
||||
By default, this is determined automatically from the content.
|
||||
@@ -342,14 +355,23 @@ Anymail includes a convenience function to simplify attaching inline images to e
|
||||
(But be aware the default `domain` can leak your server's local hostname
|
||||
in the resulting email.)
|
||||
|
||||
This function works with *any* Django :class:`~django.core.mail.EmailMessage` --
|
||||
it's not specific to Anymail email backends. You can use it with messages sent
|
||||
through Django's SMTP backend or any other that properly supports MIME attachments.
|
||||
|
||||
(This function is also available as the
|
||||
:meth:`~anymail.message.AnymailMessage.attach_inline_image` method
|
||||
on Anymail's :class:`~anymail.message.AnymailMessage` and
|
||||
:class:`~anymail.message.AnymailMessageMixin` classes.)
|
||||
.. function:: attach_inline_image(message, content, filename=None, subtype=None, idstring="img", domain=None)
|
||||
|
||||
This is a version of :func:`attach_inline_image_file` that accepts raw
|
||||
image data, rather than reading it from a file.
|
||||
|
||||
`message` must be an :class:`~django.core.mail.EmailMessage` (or subclass) object.
|
||||
|
||||
`content` must be the binary image data
|
||||
|
||||
`filename` is an optional `str` that will be used as as the attachment's
|
||||
filename -- e.g., `"picture.jpg"`. This may be visible in email clients that
|
||||
choose to display the image as an attachment as well as making it available
|
||||
for inline use (this is up to the email client). It should be a base filename,
|
||||
without any path info.
|
||||
|
||||
`subtype`, `idstring` and `domain` are as described in :func:`attach_inline_image_file`
|
||||
|
||||
|
||||
.. _send-defaults:
|
||||
|
||||
@@ -73,14 +73,20 @@ will send.
|
||||
|
||||
.. rubric:: Inline images
|
||||
|
||||
If your message has any image attachments with :mailheader:`Content-ID` headers,
|
||||
Anymail will tell your ESP to treat them as inline images rather than ordinary
|
||||
attached files.
|
||||
If your message has any attachments with :mailheader:`Content-Disposition: inline`
|
||||
headers, Anymail will tell your ESP to treat them as inline rather than ordinary
|
||||
attached files. If you want to reference an attachment from an `<img>` in your
|
||||
HTML source, the attachment also needs a :mailheader:`Content-ID` header.
|
||||
|
||||
You can construct an inline image attachment yourself with Python's
|
||||
:class:`python:email.mime.image.MIMEImage`, or you can use the convenience
|
||||
function :func:`~message.attach_inline_image` included with
|
||||
Anymail. See :ref:`inline-images` in the "Anymail additions" section.
|
||||
Anymail's comes with :func:`~message.attach_inline_image` and
|
||||
:func:`~message.attach_inline_image_file` convenience functions that
|
||||
do the right thing. See :ref:`inline-images` in the "Anymail additions" section.
|
||||
|
||||
(If you prefer to do the work yourself, Python's :class:`~email.mime.image.MIMEImage`
|
||||
and :meth:`~email.message.Message.add_header` should be helpful.)
|
||||
|
||||
Even if you mark an attachment as inline, some email clients may decide to also
|
||||
display it as an attachment. This is largely outside your control.
|
||||
|
||||
|
||||
.. _message-headers:
|
||||
|
||||
Reference in New Issue
Block a user