Hi Guys,
I have a big problem.
I want to merge two oft/msg outlook templates.
when I try to open my oft/msg outlook template with:

Outlook.Application oApp = new Outlook.Application();
Outlook.MailItem newMail = (Outlook.MailItem)oApp.CreateItemFromTemplate(path);
newMail.Display();

It works - pictures are visible..

The problem is that I need to merge two templates into one email.
I tried to copy one HTMLBody to string and to add it to other HTMLBody
It works - but pictures dissapear :(
IS there any way to achieve that including the pictures??

HELP!

Dani AI

Generated

Brief summary: the symptom (images vanish after concatenating two template bodies) can be caused by two different things. As noted, externally hosted image URLs should be checked. For embedded images the root cause is that Outlook places those images as message attachments referenced by content‑IDs; simply joining two HTML strings does not bring those attachments along or guarantee their identifiers remain valid.

Practical, high‑level workflow (no code reproduced from replies): create a fresh message, append only the body fragments (avoid duplicating full <html>/<head> sections), and for each template copy any inline-image attachments into the new message. When copying inline attachments preserve the binary data and the identifier used by the HTML (the CID). If the same CID value appears in multiple templates, assign a new unique CID for the copied attachment and rewrite the corresponding src="cid:..." in the HTML fragment before appending. Use unique temporary filenames when saving attachments and delete them after adding.

Troubleshooting notes and pitfalls: make sure image sources are absolute URLs for externally hosted images; check for duplicate CSS or conflicting head content when merging complete HTML documents; some mobile or web mail clients do not honor cid: images the same way as desktop Outlook; programmatic Outlook access can trigger security prompts so test under the same security context that will run in production. If images still do not render, inspect the merged message in Outlook’s inspector to confirm the inline attachments exist and that their CIDs match the HTML references.

Alternatives and practical advice: if templates are relatively static, maintain a single combined template. For robust .msg/.oft manipulation, consider a library that understands MAPI properties (for example, commercial libraries and Redemption/MsgReader variants are commonly used) rather than fragile string concatenation. ’s helper in the thread is a solid starting point; augment it to extract body fragments, detect/resolve CID collisions, and to preserve MIME metadata when copying attachments.

Recommended Answers

All 6 Replies

Have you checked that the image URL is still relevant? I.e. the merged image code still makes sense inside the the second email?
If the images are the only thing wrong there the image SRC would be the main suspect to have a look at

Thx...Will check it out then...O hope it'll give me any clue..

the problem is that adding pure html wont solve the issue... :(
I need to find out the method to merge two msg files in one...
Anyone has experience with sth similar?
thx!

Have you considered just creating a third template that has the necessary info on it? Why do you feel you need to automate it?

The following seems to work with Outlook 2010:

Add reference to Outlook Object Library:

  • Project
  • Add Reference
  • COM
  • Microsoft Outlook xx.x Object Library

Add the following "using statements":

  • using System.Runtime.InteropServices;
  • using Outlook = Microsoft.Office.Interop.Outlook;

Declare the constants as seen below:

//Content-id - MIME
private const string PR_ATTACH_CONTENT_ID_A = "";
private const string PR_ATTACH_CONTENT_ID = "";

//binary attachment data
private const string PR_ATTACH_DATA_BIN = "";

//formatting info for attachment
private const string PR_ATTACH_MIME_TAG_A = "";
private const string PR_ATTACH_MIME_TAG = "";

//set to true for hidden attachments
//undefined otherwise and will throw an exception if queried
private const string PR_ATTACHMENT_HIDDEN = "";

mergeTemplates:

private void mergeTemplates(string templatePath1, string templatePath2)
{

    string tempDir = System.Environment.GetEnvironmentVariable("TEMP");

    Outlook.Application oApp = new Outlook.Application();

    if (!tempDir.EndsWith(@"\"))
    {
        tempDir += @"\";
    }//if

    //put first template into a MailItem
    Outlook.MailItem newMail1 = oApp.CreateItemFromTemplate(templatePath1);

    //put second template into a MailItem
    Outlook.MailItem newMail2 = oApp.CreateItemFromTemplate(templatePath2);

    //create a new MailItem for our merged template
    Outlook.MailItem mergedMailItem = oApp.CreateItem(Outlook.OlItemType.olMailItem);

    //merge HTMLBody from newMail1 and newMail2
    mergedMailItem.HTMLBody = newMail1.HTMLBody + System.Environment.NewLine + newMail2.HTMLBody;


    if (newMail1.Attachments.Count > 0)
    {
        for (int i = 1; i <= newMail1.Attachments.Count; i++)
        {
            string tempFn = tempDir + newMail1.Attachments[i].FileName;

            //save attachment from template to temp file
            newMail1.Attachments[i].SaveAsFile(tempFn);

            //add attachment
            Outlook.Attachment mergedMailItemAttachment = mergedMailItem.Attachments.Add(tempFn);

            //delete temp file
            System.IO.File.Delete(tempFn);

            //get content-id from template
            string imageCidA = newMail1.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID_A);
            string imageCid = newMail1.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID);

            //set content-id
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID_A, imageCidA);
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID, imageCid);

            //make attachment hidden
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACHMENT_HIDDEN, true);

            //set formatting info for attachment
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG_A, newMail1.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG_A));
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG, newMail1.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG));

            //set binary attachment data
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_DATA_BIN, newMail1.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN));

            //release
            Marshal.ReleaseComObject(mergedMailItemAttachment);

            //set value to null
            mergedMailItemAttachment = null;
        }//for
    }//if

    //release
    Marshal.ReleaseComObject(newMail1);
    newMail1 = null;

    if (newMail2.Attachments.Count > 0)
    {
        for (int i = 1; i <= newMail2.Attachments.Count; i++)
        {

            string tempFn = tempDir + newMail2.Attachments[i].FileName;
            newMail2.Attachments[i].SaveAsFile(tempFn);

            //add attachment
            Outlook.Attachment mergedMailItemAttachment = mergedMailItem.Attachments.Add(tempFn);

            //delete temp file
            System.IO.File.Delete(tempFn);

            //get content-id from template
            string imageCidA = newMail2.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID_A);
            string imageCid = newMail2.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID);

            //set content-id
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID_A, imageCidA);
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID, imageCid);

            //make attachment hidden
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACHMENT_HIDDEN, true);

            //set formatting info for attachment
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG_A, newMail2.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG_A));
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG, newMail2.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG));

            //set binary attachment data
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_DATA_BIN, newMail2.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN));

            //release
            Marshal.ReleaseComObject(mergedMailItemAttachment);

            //set value to null
            mergedMailItemAttachment = null;
        }//for
      }//if

      //release
      Marshal.ReleaseComObject(newMail2);
      newMail2 = null;

      //display in Outlook
      mergedMailItem.Display();

}//mergeTemplates

Resources:
Outlook Object Model Overview

Attachment Properties

Distinguish visible and invisible attachments with Outlook...

MailItem.SaveAs Method (Outlook)

Reading an Outlook MSG File in C#

Email template with an image

Referencing Properties by Namespace

Read MAPI properties not exposed in Outlook's Object Model

Embed an image in Outlook 2010 when send email with ASP.NET MVC C#

How To: Get a list of Outlook attachments

Embed images in a mail message using C#

PR_ATTACH_DATA_BIN

How to embed image in html body in c# into outlook mail

Attachments.Add Method (Outlook)

Note: Attached is the above code (OutlookTemplateHelper_v1) and a modified version of the above code (OutlookTemplateHelper_v2). Using the attached class (OutlookTemplateHelper_v2), you will be able to merge numerous templates (.oft files) into one.

I've modified version 1 (to eliminate redundant code). Here is the updated version.

Note: Version 2 (OutlookTemplateHelper_v2) remains unchanged.

Add reference to Outlook Object Library:

  • Project
  • Add Reference
  • COM
  • Microsoft Outlook xx.x Object Library

Add the following "using statements":

  • using System.Runtime.InteropServices;
  • using Outlook = Microsoft.Office.Interop.Outlook;

Declare the constants as seen below:

//Content-id - MIME
private const string PR_ATTACH_CONTENT_ID_A = "";
private const string PR_ATTACH_CONTENT_ID = "";

// binary attachment data
private const string PR_ATTACH_DATA_BIN = "";

//formatting info for attachment
private const string PR_ATTACH_MIME_TAG = "";
private const string PR_ATTACH_MIME_TAG_A = "";

//set to true for hidden attachments
// undefined otherwise and will throw an exception if queried
private const string PR_ATTACHMENT_HIDDEN = "";

//create instance of Outlook.Application
private static Outlook.Application oApp = new Outlook.Application();

//create a new instance of MailItem for merged template
private static Outlook.MailItem mergedMailItem = null;

mergeTemplate:

private static void mergeTemplate(ref Outlook.MailItem mergedMailItem, string templatePath)
{
    string tempDir = System.Environment.GetEnvironmentVariable("TEMP");

    if (!tempDir.EndsWith(@"\"))
    {
        tempDir += @"\";
    }//if

    //put first template into a MailItem
    Outlook.MailItem tempMailItem = oApp.CreateItemFromTemplate(templatePath);

    //merge HTMLBody from newMail1 and newMail2
    mergedMailItem.HTMLBody += tempMailItem.HTMLBody + System.Environment.NewLine;

    if (tempMailItem.Attachments.Count > 0)
    {
        for (int i = 1; i <= tempMailItem.Attachments.Count; i++)
        {
            string tempFn = tempDir + tempMailItem.Attachments[i].FileName;

            //save attachment from template to temp file
            tempMailItem.Attachments[i].SaveAsFile(tempFn);

            //add attachment
            Outlook.Attachment mergedMailItemAttachment = mergedMailItem.Attachments.Add(tempFn);

            //delete temp file
            System.IO.File.Delete(tempFn);

            //get content-id from template
            string imageCidA = tempMailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID_A);
            string imageCid = tempMailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_CONTENT_ID);

            //set content-id
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID_A, imageCidA);
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_CONTENT_ID, imageCid);

            //make attachment hidden
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACHMENT_HIDDEN, true);

            //set formatting info for attachment
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG_A, tempMailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG_A));
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_MIME_TAG, tempMailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_MIME_TAG));

            //set binary attachment data
            mergedMailItemAttachment.PropertyAccessor.SetProperty(PR_ATTACH_DATA_BIN, tempMailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN));

            //release
            Marshal.ReleaseComObject(mergedMailItemAttachment);

            //set value to null
            mergedMailItemAttachment = null;
        }//for
    }//if

    //release
    Marshal.ReleaseComObject(tempMailItem);
    tempMailItem = null;

}//mergeTemplate

mergeOutlookTemplates:

public static void mergeOutlookTemplates(string templatePath1, string templatePath2)
{
    //create a new MailItem for our merged template
    mergedMailItem = oApp.CreateItem(Outlook.OlItemType.olMailItem);

    //merge template 1
    mergeTemplate(ref mergedMailItem, templatePath1);

    //merge template 2
    mergeTemplate(ref mergedMailItem, templatePath2);

    //display in Outlook
    mergedMailItem.Display();

}//mergeOutlookTemplates

Usage:
OutlookTemplateHelper.mergeOutlookTemplates(path1, path2);

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.