Add the default outlook signature in the email generated

前端 未结 11 455
甜味超标
甜味超标 2020-12-08 07:11

I am using the Microsoft.Office.Interop.Outlook.Application to generate an email and display it on the screen before the user can send it. The application is a

相关标签:
11条回答
  • 2020-12-08 07:48

    also I have dealt with this topic for several hours. Finally I stumbled across a very interesting Microsoft support case.

    https://support.microsoft.com/de-de/help/4020759/text-formatting-may-be-lost-when-editing-the-htmlbody-property-of-an

    The real problem is buried somewhere else: Microsoft Outlook uses Microsoft Word as the editor. Loss of formatting may occur if the HTML source is verified by the Word HTML module when the item is sent.

    To fix the problem, simply load Word.Interopt and use Word as the editor.

    Translated with www.DeepL.com/Translator

        public static void SendMail(string subject, string message, List<string> attachments, string recipients)
        {
            try
            {
                Outlook.Application application = new Outlook.Application();
    
                Outlook.MailItem mailItem = (Outlook.MailItem)application.CreateItem(Outlook.OlItemType.olMailItem);
                Word.Document  worDocument = mailItem.GetInspector.WordEditor as Word.Document;
                Word.Range wordRange = worDocument.Range(0, 0);
                wordRange.Text = message;
    
                foreach (string attachment in attachments ?? Enumerable.Empty<string>())
                {
                    string displayName = GetFileName(attachment);
                    int position = (int)mailItem.Body.Length + 1;
                    int attachType = (int)Outlook.OlAttachmentType.olByValue;
                    Outlook.Attachment attachmentItem = mailItem.Attachments.Add
                        (attachment, attachType, position, displayName);
                }
    
                mailItem.Subject = subject;
    
                Outlook.Recipients recipientsItems = (Outlook.Recipients)mailItem.Recipients;
                Outlook.Recipient recipientsItem = (Outlook.Recipient)recipientsItems.Add(recipients);
                recipientsItem.Resolve();
                mailItem.Display();
    
                recipientsItem = null;
                recipientsItems = null;
                mailItem = null;
                application = null;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
    
        private static string GetFileName(string fullpath)
        {
            string fileName = Path.GetFileNameWithoutExtension(fullpath);
            return fileName;
        }
    

    Have fun with it. Thomas

    0 讨论(0)
  • 2020-12-08 07:49

    I have had the exact same problem, but was able to solve it with Interop only, and thus get the default signature.

    The trick is to call GetInspector, which will magically set the HTMLBody property to the signature. Just reading the GetInspector property is enough. I tested this with Windows 7 / Outlook 2007.

    Credits to this blog post for the solution.

    0 讨论(0)
  • 2020-12-08 07:53

    Using GetInspector causes an exception when implementing an Interceptor using the Inspectors_NewInspector event. You will also find that the Signature has yet to be added to the MailItem when the Inspectors_NewInspector event is raised.

    If you trigger the Item.Send() with your own code (e.g. your own button) you will have an Anchor tag <a> for both the "Signature" and "Content End". Note these tags are removed from the HTMLBody (in the translation from Word HTML to HTML) if you handle the Outlook ribbon [Send] button click event yourself (as is common for Add-ins).

    My solution this is to handle the Item.Open event so that when the Interceptor/Inspectors_NewInspector is created/raised I can then add an Id attribute to the containing <p> tag to later use when sending. This attribute stays in the HTML even after sending.

    This ensures that whenever the Send is called I can detect in my code the "Signature" or the "Content End" paragraphs.

    0 讨论(0)
  • 2020-12-08 07:57

    I have a variant solution to this issue which is worth sharing and is complete for the purpose of sending an email from ANY Outlook Account with the email text merged with ANY signature which you can select.

    Assumptions:

    You have added a reference to the HtmlAgilityPack which is used to format the HTML content.

    As I could find no way (except via the registry) to get the email account signature, this is passed as a text value and can be set as a parameter in the program or by looking in the registry settings for the Outlook Account.

    The from account is a valid email account on the system The signature file was created by Outlook using the html format.

    I am sure there are numerous possible improvements to this.

        /// <summary>
        /// Sends an email from the specified account merging the signature with the text array
        /// </summary>
        /// <param name="to">email to address</param>
        /// <param name="subject">subect line</param>
        /// <param name="body">email details</param>
        /// <returns>false if account does not exist or there is another exception</returns>
        public static Boolean SendEmailFromAccount(string from, string to, string subject, List<string> text, string SignatureName)
        {
            // Retrieve the account that has the specific SMTP address. 
            Outlook.Application application = new Outlook.Application();
            Outlook.Account account = GetAccountForEmailAddress(application, from);
            // check account
            if (account == null)
            {
                return false;
            }
            // Create a new MailItem and set the To, Subject, and Body properties. 
            Outlook.MailItem newMail = (Outlook.MailItem)application.CreateItem(Outlook.OlItemType.olMailItem);
            // Use this account to send the e-mail. 
            newMail.SendUsingAccount = account;            
            newMail.To = to;
            newMail.Subject = subject;
            string Signature = ReadSignature(SignatureName);
            newMail.HTMLBody = CreateHTMLBody(Signature, text); 
            ((Outlook._MailItem)newMail).Send();
            return true;
        }
        private static Outlook.Account GetAccountForEmailAddress(Outlook.Application application, string smtpAddress)
        {
    
            // Loop over the Accounts collection of the current Outlook session. 
            Outlook.Accounts accounts = application.Session.Accounts;
            foreach (Outlook.Account account in accounts)
            {
                // When the e-mail address matches, return the account. 
                if (account.SmtpAddress == smtpAddress)
                {
                    return account;
                }
            }
            throw new System.Exception(string.Format("No Account with SmtpAddress: {0} exists!", smtpAddress));
        }
        /// <summary>
        /// Return an email signature based on the template name i.e. signature.htm
        /// </summary>
        /// <param name="SignatureName">Name of the file to return without the path</param>
        /// <returns>an HTML formatted email signature or a blank string</returns>
        public static string ReadSignature(string SignatureName)
        {
            string appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Signatures";
            string signature = string.Empty;
            DirectoryInfo diInfo = new DirectoryInfo(appDataDir);
            if
            (diInfo.Exists)
            {
                FileInfo[] fiSignature = diInfo.GetFiles("*.htm");
                foreach (FileInfo fi in fiSignature)
                {
                    if (fi.Name.ToUpper() == SignatureName.ToUpper()) 
                    {
                        StreamReader sr = new StreamReader(fi.FullName, Encoding.Default);
                        signature = sr.ReadToEnd();
                        if (!string.IsNullOrEmpty(signature))
                        {
                            // this merges the information in the signature files together as one string 
                            // with the correct relative paths
                            string fileName = fi.Name.Replace(fi.Extension, string.Empty);
                            signature = signature.Replace(fileName + "_files/", appDataDir + "/" + fileName + "_files/");
                        }
                        return signature; 
                    }
                }
            }
            return signature;
        }
        /// <summary>
        /// Merges an email signature with an array of plain text
        /// </summary>
        /// <param name="signature">string with the HTML email signature</param>
        /// <param name="text">array of text items as the content of the email</param>
        /// <returns>an HTML email body</returns>
        public static string CreateHTMLBody(string signature, List<string> text)
        {
            try
            {
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                HtmlAgilityPack.HtmlNode node;
                HtmlAgilityPack.HtmlNode txtnode;
    
                // if the signature is empty then create a new string with the text
                if (signature.Length == 0)
                {
                    node = HtmlAgilityPack.HtmlNode.CreateNode("<html><head></head><body></body></html>");
                    doc.DocumentNode.AppendChild(node);
                    // select the <body>
                    node = doc.DocumentNode.SelectSingleNode("/html/body");
                    // loop through the text lines and insert them
                    for (int i = 0; i < text.Count; i++)
                    {
                        node.AppendChild(HtmlAgilityPack.HtmlNode.CreateNode("<p>" + text[i] + "</p>"));
                    }
                    // return the full document
                    signature = doc.DocumentNode.OuterHtml;
                    return signature;
                }
    
                // load the signature string as HTML doc
                doc.LoadHtml(signature);
                // get the root node and insert the text paragraphs before the signature in the document
                node = doc.DocumentNode;
                node = node.FirstChild;
                foreach (HtmlAgilityPack.HtmlNode cn in node.ChildNodes)
                {
                    if (cn.Name == "body")
                    {
                        foreach (HtmlAgilityPack.HtmlNode cn2 in cn.ChildNodes)
                        {
                            if (cn2.Name == "div")
                            {
                                // loop through the text lines backwards as we are inserting them at the top
                                for (int i = text.Count -1; i >= 0; i--)
                                {
                                    if (text[i].Length == 0)
                                    {
                                        txtnode = HtmlAgilityPack.HtmlNode.CreateNode("<p class=\"MsoNormal\"><o:p>&nbsp;</o:p></p>");
                                    }
                                    else
                                    {
                                        txtnode = HtmlAgilityPack.HtmlNode.CreateNode("<p class=\"MsoNormal\">" + text[i] + "<o:p></o:p></p>");
                                    }
                                    cn2.InsertBefore(txtnode, cn2.FirstChild);                                   
                                }
                                // return the full document
                                signature = doc.DocumentNode.OuterHtml;
                            }
                        }
                    }
                }
                return signature;
            }
            catch (Exception)
            {
                return "";
            }
        }
    
    0 讨论(0)
  • 2020-12-08 07:58

    I've found a very easy way to attach the default outlook signature (including images). The trick is to retrieve the body message after calling the GetInspector and concat your message to that.

    Imports Microsoft.Office.Interop
    
    Dim fdMail As Outlook.MAPIFolder
    Dim oMsg As Outlook._MailItem
    oMsg = fdMail.Items.Add(Outlook.OlItemType.olMailItem)
    Dim olAccounts As Outlook.Accounts
    oMsg.SendUsingAccount = olAccounts.Item(1)
    oMsg.Subject = "XXX"
    oMsg.To = "xxx@xxx.com"
    Dim myInspector As Outlook.Inspector = oMsg.GetInspector
    Dim text As String
    text = "mail text" & oMsg.HTMLBody
    oMsg.HTMLBody = text
    oMsg.Send()
    
    0 讨论(0)
  • 2020-12-08 08:05

    I have got around the problem by mainly being 'sneaky'. If, when you make a new email in Outlook by Ctrl+N, it inserts the default signature, I store that blank email (with signature) in a temporary string then append that string to another string that has the content in it.

    Here is some code to demonstrate it:

    string s = "";
    Outlook.Application olApp = new Outlook.Application();
    Outlook.MailItem mail = olApp.CreateItem(Outlook.OlItemType.olMailItem);
    
    mail.To = "Hi@World.com";
    mail.Subject = "Example email";
    
    s = mainContentAsHTMLString + mail.HTMLBody;
    
    mail.Display();
    mail.HTMLBody = s;
    
    0 讨论(0)
提交回复
热议问题