none
Saving embedded images with attachment.SaveAsFile throws Exception: "Cannot save the attachment. Cannot add the attachment; no data source was provided" (VSTO 4.0, C#, Outlook 2007) RRS feed

  • Question

  • Hi,


    we are trying to save embedded images from html-mails to the disk.

    We first run through all attachments and if the attachment is embedded we try to save it with attachment.SaveAsFile()

    But unfortunately with embedded images the attachment.SaveAsFile() method is not working.

    It always throws an exception with the following message:

    "Cannot save the attachment. Cannot add the attachment; no data source was provided"

    Did we miss something? Is there another way to save embedded images to disk?

    Thank you



    Regards Mark

    Tuesday, December 10, 2013 4:13 PM

Answers

  • Hello Mark,

    I have just tested your code on my machine with Outlook 2013 installed. You are right, I get an exception when trying to save an attachment in the ItemSend event handler. But then I added a line of code which checks whether a mail item is saved and call the Save method if not:

    Outlook.MailItem mail = Item as Outlook.MailItem;
    
    if(string.IsNullOrEmpty(mail.EntryID))
       mail.Save();
    
    Outlook.Attachments atts = mail.Attachments;
    Outlook.Attachment att = atts[1];
    att.SaveAsFile(@"D:\temp\image.png");
    Now I can save the attachment even when the message is not saved by a user before sending.

    Saturday, December 28, 2013 8:55 AM

All replies

  • Hi Wompi,

    According to your description, you want to save the embedded images to the disk. What do you mean embedded images?

    If you set the format of mailbodyto RichText, you can use Attachment.SaveAsFileto save the embedded images to the disk.

     If the format of mailbodyis Html, there is no direct way we can get the embedded images. However we can get the images by saving the mailItemto html files. You can refer to code below to get the embedded images:
     private void SaveHtml_Click(object sender, RibbonControlEventArgs e)
            {
                MailItem mailItem = Globals.ThisAddIn.Application.ActiveInspector().CurrentItem;
                String path=@"C:\Users\UserName\Desktop\EmbeddedImages.Html";
                mailItem.SaveAs(path, OlSaveAsType.olHTML);
            }

    You can find all embedded images in the folder of EmbeddedImages_fileslike figure below:

    Best regards

    Fei


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, December 11, 2013 11:16 AM
    Moderator
  • Hi Fei,

    thank you very much for your answer.

    Sorry, I didn't know what was the right description for "embedded images" in Outlook but it is exactly what you have written. If I refer in the following text to "embedded images" I mean the images which are inline in the html body of the mailitem :)

    We already tried to save the mail in html but we encountered another problem with this approach so we tried to save the attachments directly.

    To explain the problem a little bit further.

    We want to save the embedded images to disk as files. Afterwards we process the mailitem and after this process has ended we want to reembed the images we have saved earlier.

    To save the images and to reintegrate them afterwards with PR_ATTACH_CONTENT_ID works well but when we save the images with SaveAs() in html format Outlook reenumerates the filenames so that these do not match the filenames in the cids in the html body of the mail.

    E.g. The html body contains the images Image001.png, Image002.png and Image005.jpg. If we save the mail as html then outlook saves the images as Image001.png, Image002.png and Image003.jpg. So, when we want to reembed the images the last image name does not match and the image is not embedded then.

    With Outlook 2007 it is worse. Outlook saves all embedded images in png and partly the same images also in jpg and enumerates all images. e.g. if there is one embedded image in the mail with the cid: image001.png@... then outlook saves the image as image001.png and image002.jpg.

    So if there are more images in the mail then there is no possiblity to exactly determine where we have to put which image. :(

    So we hoped to find a way to save the images by hand to enumerate them on our own.

    Is there probably another way to do this?

    Thank you very much


    Regards Mark



    • Edited by Wompi Wednesday, December 11, 2013 2:36 PM
    Wednesday, December 11, 2013 2:33 PM
  • Are you sure this is an HTML message, not RTF?

    What file name do you pass to SaveAsFile? Did you make sure it does not have invalid characters, such as "<" or ":"?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Wednesday, December 11, 2013 5:35 PM
  • Hi Dmitry,

    I created a small project to test the saveAsFile method. The mail is definitely a html mail. Within the mail there is one embedded image which I try to save to C:\temp\image.png. The temp folder already exists.

    During the SaveAsFile method it throws the mentioned exception.

    Here is the code from the test project:

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
            }
    
            void Application_ItemSend(object Item, ref bool Cancel)
            {
                var mail = Item as Outlook.MailItem;
                var attachment = mail.Attachments[1];
                attachment.SaveAsFile(@"C:\temp\image.png");
            }
    I tested it with Outlook 2007 and 2010.


    Regards Mark




    • Edited by Wompi Thursday, December 12, 2013 8:25 AM
    Thursday, December 12, 2013 8:22 AM
  • Can the whole message be saved as an MSG file (MailItem.SaveAs(..., olMsg))?

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Thursday, December 12, 2013 2:25 PM
  • Hi Dmitry,

    yes, saving the MailItem as MSG works.

    Is there any possibility to replace the mailItem with the saved one afterwards?

    Thank you.


    Regards Mark

    Thursday, December 12, 2013 2:56 PM
  • Hello Wompi,

    I have just tried to reproduce the issue on my machine with Outlook 2013 installed. The following code is used for testing the SaveAsFile method:

    Outlook.Inspector inspector = control.Context as Outlook.Inspector;
    Outlook.MailItem mail = inspector.CurrentItem as Outlook.MailItem;
    Outlook.Attachments atts = mail.Attachments;
    Outlook.Attachment att = atts[1];
    att.SaveAsFile(@"C:\temp\image.png");

    The code works like a charm, I couldn't reproduce the issue.

    Here is the value for PR_ATTACH_CONTENT_ID - image001.jpg@01CEF8EC.1DF7C330 .

    Do you have the latest updates and service packs installed for Outlook/Office?
    • Edited by Eugene Astafiev Saturday, December 14, 2013 1:58 PM question is added
    Saturday, December 14, 2013 1:57 PM
  • Hi Wompi,

    I created an mail message like fingure below:

    Then I ran the code successfully below:

      string path = @"C:\Users\Person1\Desktop\image.png";
                MailItem mailItem = Globals.ThisAddIn.Application.ActiveInspector().CurrentItem;
                mailItem.Attachments[1].SaveAsFile(path);

    Did I miss anything?

    Best regards

    Fei


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, December 16, 2013 10:04 AM
    Moderator
  • Hi


    thank you very much for your answers.

    @Eugene:

    Where did you save the your embedded image? I investigated further and if you save the embedded image from mails from your inbox then you are right and the code works.

    But unfortunately (and sorry, for not explicitely mentioning this point), like in my example code above we try to save the embedded image in the ItemSend method.

    There it throws the error.

    @Fei:

    I saw that you have saved the mailitem before saving the embedded image.

    If you don't save the mailitem, then the code will throw an exception.

    But thank you for pointing this out, that the code will work with an saved item (a quick test showed that this also works in the ItemSend method).

    If there isn't a better workaround this is maybe a (not perfect) solution, but I have to evaluate this because the next problem which then occurs is, that if the send routine is cancelled somehow then the saved mails stay in the drafts folder.


    Regards Mark






    • Edited by Wompi Monday, December 16, 2013 5:15 PM
    Monday, December 16, 2013 4:52 PM
  • Hi Wompi,

    >>I saw that you have saved the mailitem before saving the embedded image.

    If you don't save the mailitem, then the code will throw an exception.<<

    I tested the code in Outlook 2007 before saveing the mailItem. It did throw an exceprion what is Array index out of bounds rather than the exceprion cannot save the attachment. Could you please let me know how can we reproduce this issue?

    Best regards

    Fei


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, December 17, 2013 1:18 AM
    Moderator
  • Hi Fei,

    yes you are right, this is another exception.

    To reproduce the same issue we have, you have to handle the save of the embedded images in the ItemSend method.

    Please use the sample code I posted earlier in this thread (and attached below).

    So the steps are:

    - Create an addin with the sample code

    - Open Outlook and a new html mail

    - embed a screenshot or any other picture into the body

    - Send the mail

    => Outlook will jump into the ItemSend event. There the code will try to save the embedded image and receives the "source not found"-exception.

    Please also ensure, that you didn't save the email before sending.

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
            }
    
            void Application_ItemSend(object Item, ref bool Cancel)
            {
                var mail = Item as Outlook.MailItem;
                var attachment = mail.Attachments[1];
                attachment.SaveAsFile(@"C:\temp\image.png");
            }


    Regards Mark



    • Edited by Wompi Wednesday, December 18, 2013 8:05 AM
    Wednesday, December 18, 2013 8:04 AM
  • I have a vague recollection of this problem: it has to do with how Outlook stores the images in an HTML message being composed: before the message is saved, the images are stored in the temporary files instead of attachments. These files are finally converted to real attachments only when the message is saved.

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Saturday, December 21, 2013 9:13 PM
  • Hello Mark,

    I have just tested your code on my machine with Outlook 2013 installed. You are right, I get an exception when trying to save an attachment in the ItemSend event handler. But then I added a line of code which checks whether a mail item is saved and call the Save method if not:

    Outlook.MailItem mail = Item as Outlook.MailItem;
    
    if(string.IsNullOrEmpty(mail.EntryID))
       mail.Save();
    
    Outlook.Attachments atts = mail.Attachments;
    Outlook.Attachment att = atts[1];
    att.SaveAsFile(@"D:\temp\image.png");
    Now I can save the attachment even when the message is not saved by a user before sending.

    Saturday, December 28, 2013 8:55 AM