简体   繁体   English

在生成的电子邮件中添加默认的 Outlook 签名

[英]Add the default outlook signature in the email generated

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.我正在使用Microsoft.Office.Interop.Outlook.Application生成电子邮件并将其显示在屏幕上,然后用户才能发送它。 The application is a winform application coded in C# in the .NET Framework 3.5 SP1 and it is Microsoft Outlook 2003 .该应用程序是在.NET Framework 3.5 SP1 winform C#编码的winform应用程序,它是Microsoft Outlook 2003 I am using the following code:我正在使用以下代码:

public static void GenerateEmail(string emailTo, string ccTo, string subject, string body)
    {
        var objOutlook = new Application();
        var mailItem = (MailItem)(objOutlook.CreateItem(OlItemType.olMailItem));        
        mailItem.To = emailTo;          
        mailItem.CC = ccTo;
        mailItem.Subject = subject;
        mailItem.HTMLBody = body;
        mailItem.Display(mailItem);
    }

My question is:我的问题是:

How do i insert/add the default signature of the user who is using the application in the body of the email generated?如何在生成的电子邮件body中插入/添加使用该应用程序的用户的默认签名? Any help appreciated.任何帮助表示赞赏。

There is a really quick easy way that hasn't been mentioned.有一个非常快速简单的方法没有提到。 See modified below:见修改如下:

public static void GenerateEmail(string emailTo, string ccTo, string subject, string body)
{
    var objOutlook = new Application();
    var mailItem = (MailItem)(objOutlook.CreateItem(OlItemType.olMailItem));        
    mailItem.To = emailTo;          
    mailItem.CC = ccTo;
    mailItem.Subject = subject;
    mailItem.Display(mailItem);
    mailItem.HTMLBody = body + mailItem.HTMLBody;
}

By editing the HTMLBody after you display the mailitem you allow for Outlook to do the work of adding the default signature and then essentially copy, edit, and append.通过在显示邮件项后编辑 HTMLBody,您允许 Outlook 执行添加默认签名的工作,然后基本上进行复制、编辑和附加。

Take a look at the link below.看看下面的链接。 It explains where the signatures can be found in the file system as well as how to read them properly.它解释了可以在文件系统中的何处找到签名以及如何正确读取它们。

http://social.msdn.microsoft.com/Forums/en/vsto/thread/86ce09e2-9526-4b53-b5bb-968c2b8ba6d6 http://social.msdn.microsoft.com/Forums/en/vsto/thread/86ce09e2-9526-4b53-b5bb-968c2b8ba6d6

The thread only mentions Window XP and Windows Vista signature locations.该线程仅提及 Window XP 和 Windows Vista 签名位置。 I have confirmed that Outlooks signatures on Windows 7 live in the same place as Vista.我已确认 Windows 7 上的 Outlooks 签名与 Vista 位于同一位置。 I have also confirmed that the signature location is the same for Outlook 2003, 2007, and 2010.我还确认 Outlook 2003、2007 和 2010 的签名位置相同。

Here's a code sample if you choose to go this route.如果您选择走这条路线,这里有一个代码示例。 Taken from this site.取自本站。

private string ReadSignature()
{
    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");

        if (fiSignature.Length > 0)
        {
            StreamReader sr = new StreamReader(fiSignature[0].FullName, Encoding.Default);
            signature = sr.ReadToEnd();

            if (!string.IsNullOrEmpty(signature))
            {
                string fileName = fiSignature[0].Name.Replace(fiSignature[0].Extension, string.Empty);
                signature = signature.Replace(fileName + "_files/", appDataDir + "/" + fileName + "_files/");
            }
        }
    }
        return signature;
}

Edit: See here to find the name of the default signature for Outlook 2013 or @japel's answer in this thread for 2010.编辑: 请参阅此处以查找Outlook 2013 的默认签名名称或@japel 在此线程中的 2010 年答案。

I have had the exact same problem, but was able to solve it with Interop only, and thus get the default signature.我遇到了完全相同的问题,但只能使用 Interop 解决它,从而获得默认签名。

The trick is to call GetInspector , which will magically set the HTMLBody property to the signature.诀窍是调用GetInspector ,它会神奇地将HTMLBody属性设置为签名。 Just reading the GetInspector property is enough.只需阅读 GetInspector 属性就足够了。 I tested this with Windows 7 / Outlook 2007.我用 Windows 7/Outlook 2007 对此进行了测试。

Credits to this blog post for the solution.归功于此博客文章的解决方案。

I've found a very easy way to attach the default outlook signature (including images).我找到了一种非常简单的方法来附加默认的 Outlook 签名(包括图像)。 The trick is to retrieve the body message after calling the GetInspector and concat your message to that.诀窍是在调用 GetInspector 并将您的消息连接到该消息后检索正文消息。

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()

Edit 05/03/2021 Be aware that this method seems to fail whe using Office 365 from build 13530.20440 or higher. 2021 年 5 月 3 日编辑 请注意,使用内部版本 13530.20440 或更高版本的 Office 365 时,此方法似乎失败。 You will get a "Sorry, something went wrong. You may want to try again" message.您将收到“抱歉,出了点问题。您可能想再试一次”消息。 Still waiting for it to be fixed.还在等待修复。

For some reason libraries are made a bit different depending on language installed.出于某种原因,库会因安装的语言而有所不同。 Also a signature can hold a logo-image, wich I do not know why, but it is made in 2 files in 2 different sizes.签名也可以包含徽标图像,我不知道为什么,但它是由 2 个不同大小的 2 个文件组成的。

private string ReadSignature()
    {
        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");

            if (fiSignature.Length > 0)
            {
                StreamReader sr = new StreamReader(fiSignature[0].FullName, Encoding.Default);
                signature = sr.ReadToEnd();

                if (!string.IsNullOrEmpty(signature))
                {
                    string fileName = fiSignature[0].Name.Replace(fiSignature[0].Extension, string.Empty);
                    signature = signature.Replace(fileName + "_files/", appDataDir + "/" + fileName + "_files/");
                }
            }
        }
        else
        {
            appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Signaturer";
            signature = string.Empty;
            diInfo = new DirectoryInfo(appDataDir);

            if (diInfo.Exists)
            {
                FileInfo[] fiSignature = diInfo.GetFiles("*.htm");

                if (fiSignature.Length > 0)
                {
                    StreamReader sr = new StreamReader(fiSignature[0].FullName, Encoding.Default);
                    signature = sr.ReadToEnd();

                    if (!string.IsNullOrEmpty(signature))
                    {
                        string fileName = fiSignature[0].Name.Replace(fiSignature[0].Extension, string.Empty);
                        signature = signature.Replace(fileName + "_files/", appDataDir + "/" + fileName + "_files/");
                    }
                }
            }
        }
        if (signature.Contains("img"))
        {
            int position = signature.LastIndexOf("img");
            int position1 = signature.IndexOf("src", position);
            position1 = position1 + 5;
            position = signature.IndexOf("\"", position1);
            billede1 = appDataDir.ToString() + "\\" + signature.Substring(position1, position - position1);
            position = billede1.IndexOf("/");
            billede1 = billede1.Remove(position, 1);
            billede1 = billede1.Insert(position, "\\");

            billede1 = System.Web.HttpUtility.UrlDecode(billede1);

            position = signature.LastIndexOf("imagedata");
            position1 = signature.IndexOf("src", position);
            position1 = position1 + 5;
            position = signature.IndexOf("\"", position1);
            billede2 = appDataDir.ToString() + "\\" + signature.Substring(position1, position - position1);
            position = billede2.IndexOf("/");
            billede2 = billede2.Remove(position, 1);
            billede2 = billede2.Insert(position, "\\");

            billede2 = System.Web.HttpUtility.UrlDecode(billede2);
        }
        return signature;
    }

Getting and inserting the signature: Global variables:获取并插入签名:全局变量:

    string billede1 = string.Empty;    // holding image1
    string billede2 = string.Empty;    // holding image2

                        string signature = ReadSignature();
                        if (signature.Contains("img"))
                        {
                            int position = signature.LastIndexOf("img");
                            int position1 = signature.IndexOf("src", position);
                            position1 = position1 + 5;
                            position = signature.IndexOf("\"", position1);

                            //CONTENT-ID
                            const string SchemaPR_ATTACH_CONTENT_ID = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
                            string contentID = Guid.NewGuid().ToString();

                            //Attach image
                            mailItem.Attachments.Add(@billede1, Microsoft.Office.Interop.Outlook.OlAttachmentType.olByValue, mailItem.Body.Length, Type.Missing);
                            mailItem.Attachments[mailItem.Attachments.Count].PropertyAccessor.SetProperty(SchemaPR_ATTACH_CONTENT_ID, contentID);

                            //Create and add banner
                            string banner = string.Format(@"cid:{0}", contentID);
                            signature = signature.Remove(position1, position - position1);
                            signature = signature.Insert(position1, banner);

                            position = signature.LastIndexOf("imagedata");
                            position1 = signature.IndexOf("src", position);
                            position1 = position1 + 5;
                            position = signature.IndexOf("\"", position1);

                            //CONTENT-ID
                           // const string SchemaPR_ATTACH_CONTENT_ID = @"http://schemas.microsoft.com/mapi/proptag/0x3712001E";
                            contentID = Guid.NewGuid().ToString();

                            //Attach image
                            mailItem.Attachments.Add(@billede2, Microsoft.Office.Interop.Outlook.OlAttachmentType.olByValue, mailItem.Body.Length, Type.Missing);
                            mailItem.Attachments[mailItem.Attachments.Count].PropertyAccessor.SetProperty(SchemaPR_ATTACH_CONTENT_ID, contentID);

                            //Create and add banner
                            banner = string.Format(@"cid:{0}", contentID);
                            signature = signature.Remove(position1, position - position1);
                            signature = signature.Insert(position1, banner);
                        }
                        mailItem.HTMLBody = mailItem.Body + signature;

The stringhandling can be don smarter, but this Works and gave me my sinature God luck.字符串处理可以更聪明,但是这个作品并给了我我的sinature 上帝的运气。

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.如果,当您通过Ctrl + N在 Outlook 中创建新电子邮件时,它会插入默认签名,我将该空白电子邮件(带签名)存储在一个临时字符串中,然后将该字符串附加到另一个包含该内容的字符串中。

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;

For anyone looking for an answer after all those years.对于那些在这么多年后寻找答案的人。

In Outlook 2016 mailItem.HTMLBody already contains your default signature/footer.在 Outlook 2016 中, mailItem.HTMLBody已包含您的默认签名/页脚。

In my case I replied to someone.就我而言,我回复了某人。 If you want to add a message before just do as shown below.如果您想在之前添加消息,请执行以下操作。 Simple.简单的。

MailItem itemObj = item as MailItem; //itemObj is the email I am replying to
var itemReply = itemObj.Reply();
itemReply.HTMLBody = "Your message" + itemReply.HTMLBody; //here happens the magic, your footer is already there in HTMLBody by default, just don't you delete it :)
itemReply.Send();

also I have dealt with this topic for several hours.我也处理了这个话题几个小时。 Finally I stumbled across a very interesting Microsoft support case.最后,我偶然发现了一个非常有趣的 Microsoft 支持案例。

https://support.microsoft.com/de-de/help/4020759/text-formatting-may-be-lost-when-editing-the-htmlbody-property-of-an 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.真正的问题隐藏在别处:Microsoft Outlook 使用 Microsoft Word 作为编辑器。 Loss of formatting may occur if the HTML source is verified by the Word HTML module when the item is sent.如果在发送项目时 Word HTML 模块验证了 HTML 源,则可能会丢失格式。

To fix the problem, simply load Word.Interopt and use Word as the editor.要解决此问题,只需加载 Word.Interopt 并使用 Word 作为编辑器。

Translated with www.DeepL.com/Translator通过 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托马斯

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.我有一个解决这个问题的变体解决方案,值得分享并且是完整的,目的是从任何 Outlook 帐户发送电子邮件,其中电子邮件文本与您可以选择的任何签名合并。

Assumptions:假设:

You have added a reference to the HtmlAgilityPack which is used to format the HTML content.您已添加对用于格式化 HTML 内容的 HtmlAgilityPack 的引用。

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.由于我找不到获取电子邮件帐户签名的方法(除了通过注册表),因此它作为文本值传递,并且可以设置为程序中的参数或通过查看 Outlook 帐户的注册表设置。

The from account is a valid email account on the system The signature file was created by Outlook using the html format.发件人帐户是系统上的有效电子邮件帐户签名文件是由 Outlook 使用 html 格式创建的。

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 "";
        }
    }

To get/set the user's default signature you can use the windows registry.要获取/设置用户的默认签名,您可以使用 Windows 注册表。 Example for Outlook 2010: HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\14.0\\Common\\MailSettings Name: NewSignature Datatype: String Value: (name of signature file without ending) Outlook 2010 示例:HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\14.0\\Common\\MailSettings 名称:NewSignature 数据类型:字符串 值:(无结尾的签名文件名称)

Using GetInspector causes an exception when implementing an Interceptor using the Inspectors_NewInspector event.使用Inspectors_NewInspector事件实现拦截器时,使用GetInspector会导致异常。 You will also find that the Signature has yet to be added to the MailItem when the Inspectors_NewInspector event is raised.您还会发现,在引发Inspectors_NewInspector事件时,尚未将签名添加到 MailItem。

If you trigger the Item.Send() with your own code (eg your own button) you will have an Anchor tag <a> for both the "Signature" and "Content End".如果您使用自己的代码(例如您自己的按钮)触发Item.Send() ,您将拥有一个用于“签名”和“内容结束”的锚标记<a> 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).请注意,如果您自己处理 Outlook 功能区 [发送] 按钮单击事件(这在加载项中很常见),则会从 HTMLBody 中删除这些标记(在从 Word HTML 到 HTML 的转换中)。

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.我的解决方案是处理 Item.Open 事件,以便在创建/引发 Interceptor/Inspectors_NewInspector 时,我可以将 Id 属性添加到包含的<p>标记中,以便以后在发送时使用。 This attribute stays in the HTML even after sending.即使在发送后,此属性仍保留在 HTML 中。

This ensures that whenever the Send is called I can detect in my code the "Signature" or the "Content End" paragraphs.这确保每当调用 Send 时,我都可以在我的代码中检测到“签名”或“内容结束”段落。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM