Search code examples
c#outlookattachmentcom-automation

C# .NET 4.7.2: Embed an outlook object as an email's attachment


I created a code that builds a html string being the body of an email. However, I want this email to be an attachment of my general and base email that I created in first place. The code below actually works but at the end of it, when I open my general email, I have the secondary email as attachment but when I click on it, the email attached is a blanck email. This outcome despite I created the html body. the html string just vanish at the end of the last method "AddMessageAsAttachment". Any help would be much appreciated... Thank you

using Microsoft.Office.Interop.Outlook;

foreach (var positionlist in result)
{
    string salesEmailAddress = positionlist.Key;

    //Create the general email to the salesman
    Microsoft.Office.Interop.Outlook.Application application = new Microsoft.Office.Interop.Application();
    MailItem generalMail = application.CreateItem(Outlook.OlItemType.olMailItem) as MailItem;
    generalMail.Body = "Hello, Please find your quarterly reports";
    generalMail.Subject = $"Quarterly Report";
    generalMail.To = salesEmailAddress;

    foreach (DataRow row in positionlist)
    {
        MailItem mailToAdd = CreateSecondaryEmail(row, "EN", "P:/My_path/Report_EN.oft", @"P:\Another_path\SecondaryEmailAttachment.pdf");
        Globale.AddMessageAsAttachment(generalMail, mailToAdd);
    }

    private MailItem CreateSecondaryEmail(DataRow row, string lang, string template, string attachement)
    {
        string clientNumber = row["account_nbr"];
        string currency = row["Ccy"];

        html += $@"<html>
                    <div style='font-family: Haboro Contrast Ext Thin;font-size: 15,5'>
                        <p style=''></p><BR>
                        <span style=''>{clientNumber}</span><BR>
                        <span style=''> {currency}</span><BR>            
                    </div>";

        html += "</html>";
        MailItem mailPosition = Globale.CreateItemFromTemplate(html, email, template, factsheet);

        return mailPosition;
    }
}

"CreateItemFromTemplate" actually links from a template the body of the secondary email and a quick pdf report (parameter "attachement") that will be attached:

public static Outlook.MailItem CreateItemFromTemplate(string html, string emailaddress, string template, string attachement = null, string client_number = null)
    {

        Outlook.Application application = new Outlook.Application();
        Outlook.MailItem mail = application.CreateItemFromTemplate(template) as Outlook.MailItem;
        mail.HTMLBody = mail.HTMLBody.Replace("#BODY", html);
        DateTime dt = DateTime.Now;
        string date = $"Data as of  {dt.Day}.{dt.Month}.{dt.Year}";
        mail.HTMLBody = mail.HTMLBody.Replace("#DATE",date);
        mail.Subject = $"Quarterly Report of the client {client_number}";
        mail.To = emailaddress;
        if (attachement != null)
        {
            mail.Attachments.Add(attachement);
        }
        return mail;     
    }

Eventually, I created a "Globale" class with a method that will retrieve the secondary email (mailPosition) that is generated by the above "CreateItemFromTemplate" method and put it in the general email as an attachment.

public static void AddMessageAsAttachment(Outlook.MailItem mailContainer,Outlook.MailItem mailToAttach)
    {
        Outlook.Attachments attachments = null;
        Outlook.Attachment attachment = null;
        try
        {
            attachments = mailContainer.Attachments;
            attachment = attachments.Add(mailToAttach,
               Outlook.OlAttachmentType.olEmbeddeditem, 1, "The attached e-mail");
            mailContainer.Save();
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
        }
        finally
        {
            if (attachment != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(attachment);
            if (attachments != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(attachments);
        }
    }

Solution

  • Try to call the Save method after doing any modifications to any newly created items before attaching them.

    Also there is no need to create a new Outlook Application instance in the code. For example, I've noticed the following code in the beginning of your post:

    //Create the general email to the salesman
        Microsoft.Office.Interop.Outlook.Application application = new Microsoft.Office.Interop.Application();
        MailItem generalMail = application.CreateItem(Outlook.OlItemType.olMailItem) as MailItem;
        generalMail.Body = "Hello, Please find your quarterly reports";
    

    And in the CreateItemFromTemplate method I see:

    Outlook.Application application = new Outlook.Application();
    Outlook.MailItem mail = application.CreateItemFromTemplate(template) as Outlook.MailItem;
    mail.HTMLBody = mail.HTMLBody.Replace("#BODY", html);
    

    Finally, I'd suggest attaching web page instead of creating items and attaching them. The web page can be opened and viewed in Outlook.