anoved / OctoPrint-EmailNotifier

Receive email notifications when OctoPrint jobs are complete. Currently broken. Please fork and fix!
GNU Affero General Public License v3.0
16 stars 35 forks source link

Send image embedded instead of attachment #5

Closed EddyMI3d closed 7 years ago

EddyMI3d commented 9 years ago

Hello!

Is it possible to send the image declared as embedded instead of attached. Not every email client shows an attached image. Thanks in advance. Eddy

anoved commented 9 years ago

Thanks for the request. yagmail evidently supports marking image attachments as inline images, but at a glance I can't quite figure out how to do so. Any ideas?

doughoyt commented 7 years ago

I've done a little research on this topic and this is what I've found ...

  1. The webcam snapshot filename resulting from the urlretrieve method does not have a file extension, so yagmail cannot determine the MIME type properly. Therefore, when image is attached, it gets 'Content-Type: None/None; name="snapshot.jpg"' in the MIME part.
    • This makes the client heavily reliant on knowing what to do based on attached file extension
    • In my experience, both desktop and mobile clients need to download the attachment first, then try to open with mixed results
  2. If you rename the original image file (adding ".jpg"), yagmail is able to guess the correct MIME type and the email will contain: 'Content-Type: image/jpeg; name="snapshot.jpg"' (this is a little better)
    • Still appears as an attachment with the name "snapshot.jpg" if you append the content as a DICT
    • With the correct content-type, email clients know how to handle them better and may even automatically show image
    • Unfortunately however, on my android phone, the image was completely lost (no inline, no attachment) which I cannot explain
  3. If you rename the original file to ensure it has ",jpg" and use a yagmail.inline modifier, yagmail tries to show it as an embedded image.
    • Using inline, you cannot send the image as a DICT with a friendly name, so the image name has to be the original (however, since you need to rename it to add the extension, there is no reason you cannot rename it to something friendlier at that time--just need to gracefully handle an existing file)
    • Unfortunately, there appears to be a defect in yagmail where the image's MIME content "location" is in the wrong place in the nested MIME blocks. CID images should be inside the multipart/related block, but yagmail puts it outside this block.
    • This breaks in Thunderbird: displays a "broken image" icon inline, but also displays the attachment (since it does that automatically with image attachments)
    • Weirdly, my android client shows the image inline, just like we'd hope (it must silently cope with incorrect MIME formatting)

Since # 3 above gave the most useful behavior--usable in Thunderbird, if you ignore the broken image icon, and exactly how I want on mobile--I made the following modifications to the plugin in my local env to accomplish what I wanted (give explicit destination when GETing the snapshot image and use yagmail.inline with that file):

             if snapshot_url:
                      try:
                              import urllib
                              filename, headers = urllib.urlretrieve(snapshot_url,"/tmp/snapshot.jpg")
                      except Exception as e:
                              self._logger.exception("Snapshot error (sending email notification without image): %s" % (str(e)))
                      else:
                              content.append(yagmail.inline(filename))

NOTE! since I used an explicit destination with urlretrieve, my changes are now platform-dependent. There is probably a better way to generate an explicit filename in a valid temporary location that would work for all platforms.