32

我正在使用Microsoft.Office.Interop.Outlook.Application生成电子邮件并在用户发送之前将其显示在屏幕上。该应用程序是在中winform编码的应用程序,它是. 我正在使用以下代码:C#.NET Framework 3.5 SP1Microsoft Outlook 2003

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

我的问题是:

如何在body生成的电子邮件中插入/添加正在使用该应用程序的用户的默认签名? 任何帮助表示赞赏。

4

11 回答 11

54

有一种非常快速简单的方法尚未提及。请参阅下面的修改:

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

通过在显示邮件项后编辑 HTMLBody,您可以让 Outlook 完成添加默认签名的工作,然后基本上是复制、编辑和附加。

于 2013-06-26T00:26:37.590 回答
20

看看下面的链接。它解释了可以在文件系统中找到签名的位置以及如何正确读取它们。

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

该线程仅提及 Window XP 和 Windows Vista 签名位置。我已确认 Windows 7 上的 Outlook 签名与 Vista 位于同一位置。我还确认 Outlook 2003、2007 和 2010 的签名位置相同。

如果您选择走这条路,这里有一个代码示例。取自本站。

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

编辑:请参阅此处以查找 Outlook 2013 的默认签名的名称或 @japel 在此线程中 2010 年的答案。

于 2011-06-23T12:40:06.140 回答
15

我遇到了完全相同的问题,但只能使用 Interop 解决它,从而获得默认签名。

诀窍是调用GetInspector,它会神奇地将HTMLBody属性设置为签名。只需阅读 GetInspector 属性就足够了。我使用 Windows 7 / Outlook 2007 对此进行了测试。

归功于此博客文章的解决方案。

于 2011-11-02T17:24:14.750 回答
6

我找到了一种非常简单的方法来附加默认的 Outlook 签名(包括图像)。诀窍是在调用 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()

编辑 05/03/2021 请注意,使用 Office 365 build 13530.20440 或更高版本时,此方法似乎失败。您将收到“抱歉,出了点问题。您可能想再试一次”消息。还在等它修好。如果您在 oMsg.Send() 之前调用 oMsg.Display() 而不是 getInspector 方法,它会起作用,但用户会看到 Outlook 窗口闪烁。

于 2016-07-25T16:15:20.567 回答
4

出于某种原因,库会根据安装的语言而有所不同。签名也可以包含徽标图像,我不知道为什么,但它是由 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;
    }

获取和插入签名:全局变量:

    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;

字符串处理可以更聪明,但这很有效,给了我我的天性好运。

于 2013-07-29T21:05:33.323 回答
3

我主要通过“偷偷摸摸”解决了这个问题。如果,当您在 Outlook 中通过Ctrl+发送新电子邮件时N,它会插入默认签名,我会将该空白电子邮件(带签名)存储在一个临时字符串中,然后将该字符串附加到另一个包含该内容的字符串中。

下面是一些代码来演示它:

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;
于 2012-07-30T09:45:08.283 回答
2

对于那些在这么多年后寻找答案的人。

在 Outlook 2016中,mailItem.HTMLBody已经包含您的默认签名/页脚。

就我而言,我回复了某人。如果您想在之前添加一条消息,请执行以下操作。简单的。

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();
于 2019-04-01T10:55:41.057 回答
2

我也处理了这个话题几个小时。最后,我偶然发现了一个非常有趣的 Microsoft 支持案例。

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

真正的问题隐藏在其他地方:Microsoft Outlook 使用 Microsoft Word 作为编辑器。如果在发送项目时由 Word HTML 模块验证 HTML 源,则可能会丢失格式。

要解决此问题,只需加载 Word.Interopt 并使用 Word 作为编辑器。

通过 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;
    }

玩得开心。托马斯

于 2019-08-13T19:00:44.180 回答
1

对于这个问题,我有一个变体解决方案,值得分享,并且是完整的,用于从任何 Outlook 帐户发送电子邮件,电子邮件文本与您可以选择的任何签名合并。

假设:

您添加了对用于格式化 HTML 内容的 HtmlAgilityPack 的引用。

由于我找不到任何方法(除了通过注册表)来获取电子邮件帐户签名,因此这是作为文本值传递的,可以在程序中设置为参数或通过查看 Outlook 帐户的注册表设置。

发件人帐户是系统上的有效电子邮件帐户签名文件由 Outlook 使用 html 格式创建。

我相信对此有许多可能的改进。

    /// <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 "";
        }
    }
于 2014-03-18T11:21:02.737 回答
0

要获取/设置用户的默认签名,您可以使用 Windows 注册表。Outlook 2010 示例:HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Common\MailSettings 名称:NewSignature 数据类型:字符串 值:(签名文件的名称不带结尾)

于 2013-03-18T09:18:27.957 回答
0

在使用Inspectors_NewInspector事件实现拦截器时,使用GetInspector会导致异常。您还会发现,在引发Inspectors_NewInspector事件时,尚未将 Signature 添加到 MailItem。

如果您使用您自己的代码(例如您自己的按钮)触发Item.Send()<a> ,您将拥有一个用于“签名”和“内容结束”的 Anchor 标记。请注意,如果您自己处理 Outlook 功能区 [发送] 按钮单击事件(对于加载项来说很常见),这些标记将从 HTMLBody 中删除(在从 Word HTML 到 HTML 的翻译中)。

我的解决方案是处理 Item.Open 事件,以便在创建/引发 Interceptor/Inspectors_NewInspector 时,我可以将 Id 属性添加到包含<p>标签,以便稍后在发送时使用。此属性即使在发送后仍保留在 HTML 中。

这确保了每当调用 Send 时,我都可以在我的代码中检测到“签名”或“内容结束”段落。

于 2018-07-26T16:02:51.883 回答