1

I can only attach image files but embedded image files doesn't appears in the mail . It says The link image cannot be displayed file may be removed, deleted or renamed. verify link point to correct image file and location and also files attached are of same size. below is the code which I used

from requests_toolbelt import MultipartEncoder
import requests
import smtplib
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.mime.image import MIMEImage
from os.path import basename
from jinja2 import Template

def send_mail(send_from: str, subject: str, text: str,send_to: list, files= None):

    send_to= default_address if not send_to else send_to
    main = Template('''
    <html><body>
    {% for image in pictures %}<img src="cid:{{image}}">{% endfor %}
    </body></html>''')  
    msg = MIMEMultipart()
    html = main.render(pictures=files)
    part2 = MIMEText(html, 'html')
    msg.attach(part2)
    msg['From'] = send_from
    msg['To'] = ', '.join(send_to)
    msg['Subject'] = subject
    for f in files or []:
        with open(f, "rb") as fil:
            msgImage = MIMEImage(fil.read())
            ext = f.split('.')[-1:]
            attachedfile = MIMEApplication(fil.read(), _subtype = ext)
            fil.close()
            msgImage.add_header('Content-ID', '<{}>'.format(f))
            msgImage.add_header('content-Disposition','inline',filename=f)
            msg.attach(msgImage)
            attachedfile.add_header(
                'content-disposition', 'attachment', filename=basename(f) )
        msg.attach(msgImage)
        msg.attach(attachedfile)
    smtp = smtplib.SMTP(host="smtp-mail.outlook.com", port= 25)
    smtp.starttls()
    smtp.login(usr,pwd)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()
send_mail(send_from= frommail,
subject="Daily backup Testing",
text='files added: ',
send_to= tomail,
files= files_list)

I get mail as this screenshot. Image path files are correct. when I print I get this files ['check123\\Screenshot (161).png', 'check123\\Screenshot (163).png', 'check123\\Screenshot (164).png'] How can I solve this issue?

can I fix it
  • 73
  • 2
  • 10

1 Answers1

1

The file names are not particularly suitable as cid: identifiers. In particular, the backslashes and parentheses are not valid in cid: identifiers. See also What are the valid characters for a Mime Multipart message ContentId "CID:"?

Maybe just generate unique random identifiers from a constrained set of characters and map them to your file names instead.

Off the top of my head (untested),

import random # in addition to the other imports you have
import string

# cribbed from https://stackoverflow.com/a/2030081/874188
def random_cid ():
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(10))

def send_mail(send_from: str, subject: str, text: str,send_to: list, files= None):

    send_to= default_address if not send_to else send_to

    cid_map = { x: random_cid() for x in files }
    main = Template('''
    <html><body>
    {% for image in pictures %}<img src="cid:{{cid_map[image]}}">{% endfor %}
    </body></html>''')
    msg = MIMEMultipart()
    html = main.render(pictures=files, cid_map=cid_map)
    part2 = MIMEText(html, 'html')  
    # ...
    for f in files:
        with open(f, "rb") as fil:
            msgImage = MIMEImage(fil.read())
            ext = f.split('.')[-1:]
            attachedfile = MIMEApplication(fil.read(), _subtype = ext)
            fil.close()
            msgImage.add_header('Content-ID', '<{}>'.format(cid_map[f]))
            msgImage.add_header('content-Disposition','inline',filename=f)
            msg.attach(msgImage)
            attachedfile.add_header(
                'content-disposition', 'attachment', filename=basename(f) )
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • hey thanks for the answer , I tried based on your answer I'm getting UndefinedError: 'cid_map' is undefined, I have included changed code in question please have a look – can I fix it Apr 08 '19 at 08:51
  • @canIfixit Thanks for the feedback! I needed to pass in the `cid_map` to `main.render(...)` too -- see updated answer now. – tripleee Apr 08 '19 at 09:05
  • that fixed my image embedding problem thanks, but still attached file are of corrupt file of same size as shown in picture question. I'm not seeing any way to fix this problem. May be you should know the cause of the issue – can I fix it Apr 08 '19 at 10:15
  • The attempt to `read()` the file twice is certainly broken but I really don't see what you are trying to do here ... if the intent is to fix the image's type, shouldn't you be updating the actual `MIMEImage`'s type? Do you think you could share a Pastebin or similar of the generated MIME message? – tripleee Apr 08 '19 at 10:25
  • I'm trying to attach and embed image files to mail. MIMEImage for reading image file to embed image and MIMEApplication for reading image for attaching the image file. I'm not aware of pastebin or any other way of sharing – can I fix it Apr 08 '19 at 15:27
  • https://pastebin.com/ but perhaps post a new question with the code (perhaps without the `smtplib` parts which aren't pertinent for a [mcve]) and a sample of the generated message. Feel free to ping me here with @tripleee (you can only ping people where they have partipated so you can't do that from a new question). – tripleee Apr 08 '19 at 15:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/191489/discussion-between-can-i-fix-it-and-tripleee). – can I fix it Apr 09 '19 at 02:59
  • @caifixit sure, ping me when you can join back. – tripleee Apr 09 '19 at 04:46