none
Opening an MSG in Outlook, adding attachment, then saving back to original MSG file RRS feed

  • Question

  • I am having a problem with adding attachments to existing MSG files.

    Users can open MSG files in Outlook and edit the body text and then save back to the original MSG file no problem.

    When users open the MSG files in Outlook and then add an attachment, the item in the inspector is no longer linked to the original MSG file, but becomes a new email message in the user's default mail folder (the inbox). So, once an attachment is added the users are no longer able to save their changes to the original MSG file. I also have no way of determining the location of the original MSG file to perform a save behind the scenes.

    Any ideas how I can allow users to add attachments to their email and save back to the original file without creating a new message in the inbox?

    Monday, November 19, 2012 1:48 PM

Answers

  • Since it is your code that creates the mesage, you can keep the entry id of each message create by your code in an internal list. Whne the message is saved, you can match the etnry id  and figure out where to save it.

    You do not have to implement a separate button to save - when MailItem.Write event fires, you can call MailItem.SveAs(..., olMsg) to update the MSG file as well.


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

    Tuesday, November 20, 2012 1:43 PM
  • Then you need to acccomplish 2 things:

    1. Trap the MailItem.Write event when the user saves the message and write the MSG file

    2. For #1, you need tio know that the item in an inspector actually came from you. Which means you are the one who needs to create and display it. Unless there is some other marker stored in the message that will let you identify the message as one of your messages.


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

    Tuesday, November 20, 2012 4:28 PM

All replies

  • you could do this without involving outlook at all, just using OpenIMsgOnIStg and family ( http://msdn.microsoft.com/en-us/library/office/cc815715.aspx) to achieve this. does it have to be from inside outlook?
    Monday, November 19, 2012 2:11 PM
  • Users want to be able to pass the MSG file around in a document management system and open it in Outlook to edit it and save back to the MSG file.

    The link you pasted does involve Outlook doesn't it as its Outlook interop...? I am developing an WPF application in C#, with an add in for Outlook to provide additional functionality.

    I was hoping I could get the file path of the MSG from my add in code and then force a save back to the MSG file instead of to a new message in the inbox, but the Outlook object model has no way of getting the path to the MSG file that the message originated from, so I can't tell if the message came from an MSG file or where that file would be...

    
    Monday, November 19, 2012 2:18 PM
  • functions that i pointed you towards have nothing to do with outlook, you control everything yourself, so you know path on disk where this file came from. From what i know about outlook (but i know very little) OOM does not expose such information to you, even more, accessing for example EntryId from OOM will generate one for you, fooling you into thinking that this message belongs to outlook store (msg saved on disk does not have entryid property at all). Maybe Ken or Dmitry know of a way to get this info from inside OOM.

    As for now, i would do it so:

    1. expose inside your app a way to choose msg file (maybe an entry from grid or something like this)

    2. if user wants to see contents of that msg file, either fire up outlook (directly or through shell/Process.Start) OR read PR_BODY*/RTF/HTML and display it inside your app

    3. depending on choice from point above either provide your button in outlook's ribbon to save back to msg file or button inside your app to add attachment and save msg

    Overall first point is the most importnant one - operation of choosing msg file must be started from your app, if you let outlook do it he will hide importnant information from you.

    Monday, November 19, 2012 7:37 PM
  • There's no way I'm aware of to find out where a MSG file originated, not from the Outlook object model. Dmitry might know of a way from Extended MAPI, but the object model's no help for that. Using Windows Search on the MSG file name to try to find the file system location is about all that occurs to me.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "DamianD" <=?utf-8?B?RGFtaWFuRA==?=> wrote in message news:604278d5-b5f9-4417-8532-3d87300aade4...

    functions that i pointed you towards have nothing to do with outlook, you control everything yourself, so you know path on disk where this file came from. From what i know about outlook (but i know very little) OOM does not expose such information to you, even more, accessing for example EntryId from OOM will generate one for you, fooling you into thinking that this message belongs to outlook store (msg saved on disk does not have entryid property at all). Maybe Ken or Dmitry know of a way to get this info from inside OOM.

    As for now, i would do it so:

    1. expose inside your app a way to choose msg file (maybe an entry from grid or something like this)

    2. if user wants to see contents of that msg file, either fire up outlook (directly or through shell/Process.Start) OR read PR_BODY*/RTF/HTML and display it inside your app

    3. depending on choice from point above either provide your button in outlook's ribbon to save back to msg file or button inside your app to add attachment and save msg

    Overall first point is the most importnant one - operation of choosing msg file must be started from your app, if you let outlook do it he will hide importnant information from you.


    Ken Slovak MVP - Outlook
    Monday, November 19, 2012 7:46 PM
    Moderator
  • I can only think of explicilty creating a message in one of Outlook's folders first and importing the contents of an MSG file (that is what Outlook does behind the scenes anyway). You can then display the message programmatically. When the inspector is closed, you can then export the message as an MSG file overwriting the original.


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

    Monday, November 19, 2012 8:11 PM
  • Thankyou for your responses. They are very helpful. I am going to have to give this some thought.

    I am not sure if your suggestions help with the Outlook behaviour of switching the save location from MSG file to Outlook message after adding an attachment. I suspect that if I displayed an MSG programatically in Outlook and the user then added an attachment, Outlook might no longer save back to the same MSG instance. I'll have to try this out and see what happens.

    Tuesday, November 20, 2012 9:32 AM
  • I am thinking of adding a custom MAPI property that identifies the MSG before it is opened in Outlook. This would alllow my add in to identify the message and know where to put it on save.
    Tuesday, November 20, 2012 9:35 AM
  • custom property is not needed, you just have to be the one that initiates operation with msg file and provide your own custom button in outlook ribbon to save mail back to msg. Of course your proposition should also work.
    Tuesday, November 20, 2012 9:56 AM
  • What I don't understand is how my Outlook button would know where to save to. I can't save to the exact same file name for every MSG as a user could be editing multiple MSGs simultaneously. Each MSG has its own unique file name and Outlook has no way to identify where the MSG came from. So how does my button know the correct file path? The application that initiates the operation is unable to pass this information to the Outlook button.

    Also, users are used to using the built in Outlook save feature. It would be too much to expect them to start using a new save button. I would need to try and override the built in save function.

    Tuesday, November 20, 2012 10:02 AM
  • if going that way is not an option for you, then no need to explain to pass that info :-)

    I would be careful though with overriding default behaviour, for example i would expect that if i open msg file from disk and modify it, then saving it will save it to draft folder - this is what i know and expect. I would never expect that installing some add-in would change this and for example override my msg template.

    Tuesday, November 20, 2012 10:14 AM
  • I would only want to override the default save behaviour in cases where I can be sure that the message is from an MSG file and an attachment has been added.
    Tuesday, November 20, 2012 10:17 AM
  • Since it is your code that creates the mesage, you can keep the entry id of each message create by your code in an internal list. Whne the message is saved, you can match the etnry id  and figure out where to save it.

    You do not have to implement a separate button to save - when MailItem.Write event fires, you can call MailItem.SveAs(..., olMsg) to update the MSG file as well.


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

    Tuesday, November 20, 2012 1:43 PM
  • Then you need to acccomplish 2 things:

    1. Trap the MailItem.Write event when the user saves the message and write the MSG file

    2. For #1, you need tio know that the item in an inspector actually came from you. Which means you are the one who needs to create and display it. Unless there is some other marker stored in the message that will let you identify the message as one of your messages.


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

    Tuesday, November 20, 2012 4:28 PM
  • Thanks Dmitry.

    I am now very close to solving this. I am creating a MailItem object in my application based on the existing MSG file and forcing a save, which works great.

    The only issue I have now is how to load the MSG into a MailItem and display it for the user to edit without the user's default mail signature being added.

    I am using CreateItemFromTemplate to load the MSG into MailItem and then calling Display(true). I think it is the inspector created in Display(true) that is adding the signature.

    I have created a method to delete the signature Bookmark from the WordEditor, but can't get it to work. If this method is called on MailItem.Open then the Inspector.WordEditor property is null. I can't call the method after Display because I am using the modal Display method.

    Any ideas how to load an MSG without adding the signature?

    Thursday, November 22, 2012 11:56 AM
  • to remove signature you have to wait for inspector to Activate (this is event), mail.Open event is too soon. There will be bookmark (_AutoSig or something like that, i do not remember) that you can use to find that signature. But i also think this can be done easier, 2 options:

    1. to open existing msg file, use OpenShareditem, not CreateItemFromtemplate

    2. after saving your info into msg file, you can simply pass to windows shell opening of that file by using Process.Start and passing path to that file.

    Thursday, November 22, 2012 2:47 PM
  • I can't seem to reference the Activate event. There only appears to be an Activate method. I am referencing Outlook Interop v11 for compatibility with Outlook 2003. Was the Activate event introduced in 2007?

    I can't use NameSpace.OpenSharedItem because its only in 2007 onwards.

    I cant use the Windows shell to open the MSG because then I wouldn't be able to handle the write events for my forced Save.


    • Edited by GlenThomas Thursday, November 22, 2012 2:54 PM
    Thursday, November 22, 2012 2:53 PM
  • I think I may have solved getting the Activate event by:

    Microsoft.Office.Interop.Outlook.

    Inspector inspector = _mailItem.GetInspector;

                    ((Microsoft.Office.Interop.Outlook.

    InspectorEvents_Event)inspector).Activate += new Microsoft.Office.Interop.Outlook.InspectorEvents_ActivateEventHandler(OutlookEmail_Activate);

    I still need to test this.

    Thursday, November 22, 2012 3:54 PM
  • The signature is also added when you call MailItem.GetInspector; you don't have to wait for the Activate event.

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

    Thursday, November 22, 2012 4:04 PM
  • The reason I need to wait for Activate is that the Inspector.WordEditor has not been initialised until Activate, so I am unable to delete the signature Bookmark before then.
    Thursday, November 22, 2012 4:15 PM