0
votes

i've written an outlook add-in (2010/2007) that gets the current selected (opened) mailitem and creates a new mail item based on the current mailitem's subject, body and attachments. My problem is that if the signiture is an image attachment, i can't position it in the original position of the current mailitem. the image of the signiture is placed on the top of the mail window (the attachment field). i've tried messing around with the attachment position, trying to place it at the end of the body but no luck, plus i think it's not the right way of doing it as i can't be sure what position each image placed within an email thread with multipile replaies for example. what i'm trying to go for here, is making a button like a Reply or Forward button but without the extra text that goes in the body (like: time the message was sent, sender etc..).

this is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using ForwardAsNewMail;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace ForwardAsNewMail
{
    public partial class ForwardAsNewMail
    {


        private void ForwardAsNewMail_Load(object sender, RibbonUIEventArgs e)
        {

        }

        private void btnNewMail_Click(object sender, RibbonControlEventArgs e)
        {
            Outlook.MailItem oldMailItem = GetMailItem(e);
            Outlook.Application outlookApp = new Outlook.Application();
            Outlook.MailItem newMailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
            newMailItem.HTMLBody = oldMailItem.HTMLBody;
            newMailItem.Subject = oldMailItem.Subject;

            #region Attahment
            // Get the count of Attachments

            int attachCount = oldMailItem.Attachments.Count;
            if (attachCount > 0)
            {
                // loop through each attachment 

                for (int idx = 1; idx <= attachCount; idx++)
                {
                    string sysPath = System.IO.Path.GetTempPath();
                    if (!System.IO.Directory.Exists(sysPath + "~test"))
                    {
                        System.IO.Directory.CreateDirectory(sysPath + "~test");
                    }
                    // get attached file and save in temp folder

                    string strSourceFileName = sysPath + "~test\\" +
                                   oldMailItem.Attachments[idx].FileName;
                    oldMailItem.Attachments[idx].SaveAsFile(strSourceFileName);
                    string strDisplayName = "Attachment";
                    int intPosition = 1;
                    int intAttachType = (int)Outlook.OlAttachmentType.olEmbeddeditem;
                    // Add the current attachment
                    newMailItem.Attachments.Add(strSourceFileName,
                                   intAttachType, intPosition, strDisplayName);
                }
            }
            #endregion

            newMailItem.Display();

        }

        ///
        /// Gets the mail item selected in the explorer view if one is selected or instance if that is the view active.
        ///
        /// The instance containing the event data.
        /// A Outlook.MailItem for the mail being viewed.
        private Microsoft.Office.Interop.Outlook.MailItem GetMailItem(RibbonControlEventArgs e)
        {
            // Check to see if a item is select in explorer or we are in inspector.
            if (e.Control.Context is Microsoft.Office.Interop.Outlook.Inspector)
            {
                Microsoft.Office.Interop.Outlook.Inspector inspector = (Microsoft.Office.Interop.Outlook.Inspector)e.Control.Context;

                if (inspector.CurrentItem is Microsoft.Office.Interop.Outlook.MailItem)
                {
                    return inspector.CurrentItem as Microsoft.Office.Interop.Outlook.MailItem;
                }
            }

            if (e.Control.Context is Microsoft.Office.Interop.Outlook.Explorer)
            {
                Microsoft.Office.Interop.Outlook.Explorer explorer = (Microsoft.Office.Interop.Outlook.Explorer)e.Control.Context;

                Microsoft.Office.Interop.Outlook.Selection selectedItems = explorer.Selection;
                if (selectedItems.Count != 1)
                {
                    return null;
                }

                if (selectedItems[1] is Microsoft.Office.Interop.Outlook.MailItem)
                {
                    return selectedItems[1] as Microsoft.Office.Interop.Outlook.MailItem;
                }
            }

            return null;
        }




    }
}

thanks in advance! :)

** EDIT With Solution** Well, after Dmitry pointed me out to the right direction I managed to find out how to save all attachment and embed the ones who were embedded. I also added an IF statement that checks if the attachment is embedded. so here is the code if any one interested:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Tools.Ribbon;
using ForwardAsNewMail;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Reflection;

namespace ForwardAsNewMail
{
    public partial class ForwardAsNewMail
    {

        private void ForwardAsNewMail_Load(object sender, RibbonUIEventArgs e)
        {

        }

        private void btnNewMail_Click(object sender, RibbonControlEventArgs e)
        {
            Outlook.MailItem oldMailItem = GetMailItem(e);
            Outlook.Application outlookApp = new Outlook.Application();
            Outlook.MailItem newMailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
            newMailItem.HTMLBody = oldMailItem.HTMLBody;
            newMailItem.Subject = oldMailItem.Subject;

            #region Attahment
            // Get the count of Attachments

            int attachCount = oldMailItem.Attachments.Count;
            if (attachCount > 0)
            {
                // loop through each attachment 

                for (int idx = 1; idx <= attachCount; idx++)
                {
                    string sysPath = System.IO.Path.GetTempPath();
                    if (!System.IO.Directory.Exists(sysPath + "~test"))
                    {
                        System.IO.Directory.CreateDirectory(sysPath + "~test");
                    }
                    // determain if the attachment is embeded or not (in-line or not)
                    string atchPropValue = oldMailItem.Attachments[idx].PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E");
                    if (atchPropValue == null || atchPropValue == string.Empty)
                    {
                        // get attached file and save in temp folder

                        string strSourceFileName = sysPath + "~test\\" + oldMailItem.Attachments[idx].FileName;

                        oldMailItem.Attachments[idx].SaveAsFile(strSourceFileName); // x

                        string strDisplayName = "Attachment";
                        int intPosition = oldMailItem.Attachments[idx].Index;
                        int intAttachType = (int)Outlook.OlAttachmentType.olEmbeddeditem;
                        // Add the current attachment
                        newMailItem.Attachments.Add(strSourceFileName, intAttachType, intPosition, strDisplayName);

                    }

                    else
                    {
                        Outlook.Attachment oldAttach = oldMailItem.Attachments[idx];
                        string strSourceFileName = sysPath + "~test\\" + oldAttach.FileName;
                        oldAttach.SaveAsFile(strSourceFileName);
                        // Add the current attachment
                        Outlook.Attachment newAttach = newMailItem.Attachments.Add(strSourceFileName,Missing.Value, Missing.Value, Missing.Value); // z
                        try
                        {
                            newAttach.PropertyAccessor.SetProperty(
                                @"http://schemas.microsoft.com/mapi/proptag/0x3712001F",
                                oldAttach.PropertyAccessor.GetProperty(
                                    @"http://schemas.microsoft.com/mapi/proptag/0x3712001F"));
                        }
                        catch
                        {

                        }
                    }  
                }
            }
            #endregion

            newMailItem.Display();

        }

        ///
        /// Gets the mail item selected in the explorer view if one is selected or instance if that is the view active.
        ///
        /// The instance containing the event data.
        /// A Outlook.MailItem for the mail being viewed.
        private Microsoft.Office.Interop.Outlook.MailItem GetMailItem(RibbonControlEventArgs e)
        {
            // Check to see if a item is select in explorer or we are in inspector.
            if (e.Control.Context is Microsoft.Office.Interop.Outlook.Inspector)
            {
                Microsoft.Office.Interop.Outlook.Inspector inspector = (Microsoft.Office.Interop.Outlook.Inspector)e.Control.Context;

                if (inspector.CurrentItem is Microsoft.Office.Interop.Outlook.MailItem)
                {
                    return inspector.CurrentItem as Microsoft.Office.Interop.Outlook.MailItem;
                }
            }

            if (e.Control.Context is Microsoft.Office.Interop.Outlook.Explorer)
            {
                Microsoft.Office.Interop.Outlook.Explorer explorer = (Microsoft.Office.Interop.Outlook.Explorer)e.Control.Context;

                Microsoft.Office.Interop.Outlook.Selection selectedItems = explorer.Selection;
                if (selectedItems.Count != 1)
                {
                    return null;
                }

                if (selectedItems[1] is Microsoft.Office.Interop.Outlook.MailItem)
                {
                    return selectedItems[1] as Microsoft.Office.Interop.Outlook.MailItem;
                }
            }

            return null;
        }
    }
}
1

1 Answers

1
votes

HTML body refers to the images through the src/cid attribute (e.g. <img src="cid:xyz">) - after you add the attachment, you need to make sure the PR_ATACH_CONTENT_ID property (DASL name http://schemas.microsoft.com/mapi/proptag/0x3712001F) is properly set using Attachment.PropertyAccessor.SetProperty. Take a look at an existing message with an embedded HTML image with OutlookSpy (click IMessage button).

You might want to get rid of the multiple dot notation when accessing attachments.

                Attachment oldAttach = oldMailItem.Attachments[idx]
                string strSourceFileName = sysPath + "~test\\" + oldAttach.FileName;
                oldAttach.SaveAsFile(strSourceFileName);
                // Add the current attachment
                Attachment newAttach = newMailItem.Attachments.Add(strSourceFileName,
                               Missing.Value, Missing.Value, Missing.Value);
                try
                {
                   newAttach.PropertyAccessor.SetProperty(
                       @"http://schemas.microsoft.com/mapi/proptag/0x3712001F",
                       oldAttach.PropertyAccessor.GetProperty(
                          @"http://schemas.microsoft.com/mapi/proptag/0x3712001F")
                }
                catch()
                {
                    //exception is raised if the property does not exist
                }