création d'un modèle de courrier électronique MIME avec des images à envoyer avec python / django

StackOverflow https://stackoverflow.com/questions/1633109

  •  06-07-2019
  •  | 
  •  

Question

Dans mon application Web, j'envoie de temps en temps des courriels à l'aide d'une application de courrier réutilisable comme celle-ci:

user - self.user
subject = ("My subject")
from = "me@mydomain.com"
message = render_to_string("welcomeEmail/welcome.eml", { 
                "user" : user,
                })
send_mail(subject, message, from, [email], priority="high" )

Je souhaite envoyer un courrier électronique avec des images incorporées. J'ai donc essayé de créer le courrier dans un client de messagerie, d'afficher le code source et de l'insérer dans mon modèle (welcome.eml), mais je n'ai pas pu obtenir rendre correctement dans les clients de messagerie quand il est envoyé.

Est-ce que quelqu'un connaît un moyen simple pour moi de créer des modèles de courrier codés Mime avec des images intégrées qui seront correctement restitués lorsque je les enverrai?

Était-ce utile?

La solution

Mettre à jour

Merci beaucoup à Saqib Ali d'avoir ressuscité cette vieille question près de 5 ans après ma réponse.

Les instructions que j'ai données à l'époque ne fonctionnent plus. Je soupçonne que Django a connu des améliorations dans les années écoulées, ce qui signifie que send_mail () applique le texte brut. Peu importe ce que vous mettez dans le contenu, il sera toujours livré en texte brut.

La documentation Django la plus récente explique que send_mail () n’est vraiment qu’une commodité pour créer une instance de la classe django.core.mail.EmailMessage , puis appeler send () sur celui-ci. exemple. EmailMessage contient cette note pour le paramètre body, qui explique les résultats affichés en 2014:

  

body: le corps du texte. Cela devrait être un message en texte brut.

     

... un peu plus tard dans la documentation ...

     

Par défaut, le type de message MIME du paramètre body dans un EmailMessage est "text / plain". C'est une bonne pratique de laisser cela seul.

Très bien (j'avoue que je n'ai pas pris le temps de rechercher pourquoi les instructions de 2009 fonctionnaient - je les ai testées en 2009 - ou quand elles ont changé). Django fournit un document , un django.core.mail.EmailMultiAlternatives pour faciliter l'envoi d'un texte brut et d'une représentation HTML du même message.

Le cas de cette question est légèrement différent. Nous ne cherchons pas à ajouter une alternative en tant que telle, mais à ajouter des parties liées à l'une des alternatives. Dans la version HTML (et peu importe si vous avez ou non la version en texte brut), nous voulons incorporer une partie de données d'image. Ce n'est pas une vue alternative du contenu, mais un contenu lié ?? référencé dans le corps HTML.

L'envoi d'une image intégrée est toujours possible, mais je ne vois pas de moyen simple de le faire à l'aide de send_mail . Il est temps de se passer de la fonction de confort et d'instancier directement un EmailMessage .

Voici une mise à jour de l'exemple précédent:

from django.core.mail import EmailMessage
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Load the image you want to send as bytes
img_data = open('logo.jpg', 'rb').read()

# Create a "related" message container that will hold the HTML 
# message and the image. These are "related" (not "alternative")
# because they are different, unique parts of the HTML message,
# not alternative (html vs. plain text) views of the same content.
html_part = MIMEMultipart(_subtype='related')

# Create the body with HTML. Note that the image, since it is inline, is 
# referenced with the URL cid:myimage... you should take care to make
# "myimage" unique
body = MIMEText('<p>Hello <img src="cid:myimage" /></p>', _subtype='html')
html_part.attach(body)

# Now create the MIME container for the image
img = MIMEImage(img_data, 'jpeg')
img.add_header('Content-Id', '<myimage>')  # angle brackets are important
img.add_header("Content-Disposition", "inline", filename="myimage") # David Hess recommended this edit
html_part.attach(img)

# Configure and send an EmailMessage
# Note we are passing None for the body (the 2nd parameter). You could pass plain text
# to create an alternative part for this message
msg = EmailMessage('Subject Line', None, 'foo@bar.com', ['bar@foo.com'])
msg.attach(html_part) # Attach the raw MIMEBase descendant. This is a public method on EmailMessage
msg.send()

Réponse originale de 2009:

Pour envoyer un courrier électronique avec des images incorporées, utilisez le module de messagerie intégré de python pour créer les composants MIME.

Ce qui suit devrait le faire:

from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Load the image you want to send at bytes
img_data = open('logo.jpg', 'rb').read()

# Create a "related" message container that will hold the HTML 
# message and the image
msg = MIMEMultipart(_subtype='related')

# Create the body with HTML. Note that the image, since it is inline, is 
# referenced with the URL cid:myimage... you should take care to make
# "myimage" unique
body = MIMEText('<p>Hello <img src="cid:myimage" /></p>', _subtype='html')
msg.attach(body)

# Now create the MIME container for the image
img = MIMEImage(img_data, 'jpeg')
img.add_header('Content-Id', '<myimage>')  # angle brackets are important
msg.attach(img)

send_mail(subject, msg.as_string(), from, [to], priority="high")

En réalité, vous voudrez probablement envoyer le code HTML avec une alternative en texte brut. Dans ce cas, utilisez MIMEMultipart pour créer le fichier "connexe". conteneur de type MIME en tant que racine. Créez ensuite un autre MIMEMultipart avec le sous-type "alternative", et attachez un MIMEText (sous-type html) et un MIMEText (sous-type brut) à la pièce alternative. Ensuite, attachez l'image à la racine associée.

Autres conseils

J'avais des problèmes avec la recette de Jarret sur Django 1.10 - je rencontrais des erreurs MIME et des erreurs d'encodage pour les différentes manières de joindre des données MIME.

Voici un modèle transactionnel en plusieurs parties simple pour un courrier électronique avec un objet fichier coupon_image incorporé qui fonctionne sur django 1.10:

from django.core.mail import EmailMultiAlternatives
from email.mime.image import MIMEImage

def send_mail(coupon_image):
    params = {'foo':'bar'} # create a template context
    text_body = render_to_string('coupon_email.txt', params)
    html_body = render_to_string('coupon_email.html', params)
    img_data = coupon_image.read() #should be a file object, or ImageField
    img = MIMEImage(img_data)
    img.add_header('Content-ID', '<coupon_image>')
    img.add_header('Content-Disposition', 'inline', filename="coupon_image")

    email = EmailMultiAlternatives(
        subject="Here's your coupon!",
        body=text_body,
        from_email='noreply@example.com',
        to=['someone@example.com',]
    )

    email.attach_alternative(html_body, "text/html")
    email.mixed_subtype = 'related'
    email.attach(img)

    email.send(fail_silently=False)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top