Microsoft.Office.Interop.Outlook.Application
を使用してメールを生成し、ユーザーが送信する前に画面に表示します。アプリケーションは、C#
内の.NET Framework 3.5 SP1
でコーディングされたwinform
アプリケーションであり、Microsoft 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
にアプリケーションを使用しているユーザーのデフォルトの署名を挿入/追加するにはどうすればよいですか?助けていただければ幸いです。
以下のリンクをご覧ください。署名がファイルシステムのどこにあるか、またそれらを適切に読み取る方法について説明します。
http://social.msdn.Microsoft.com/Forums/en/vsto/thread/86ce09e2-9526-4b53-b5bb-968c2b8ba6d6
スレッドには、Window XPおよびWindows Vista署名の場所のみが記載されています。Windows7の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または2010年のこのスレッドでの@japelの回答.
言及されていない本当に簡単な方法があります。以下の変更を参照してください。
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;
}
Mailitemを表示した後にHTMLBodyを編集することにより、Outlookがデフォルトの署名を追加し、基本的にコピー、編集、および追加の作業を行えるようにします。
私はまったく同じ問題を抱えていましたが、Interopでのみ解決できたため、デフォルトの署名を取得できました。
トリックは GetInspector を呼び出すことです。これにより、魔法のように HTMLBody プロパティが署名に設定されます。 GetInspectorプロパティを読むだけで十分です。これをWindows 7/Outlook 2007でテストしました。
ソリューションに対する このブログ投稿 への謝辞。
何らかの理由で、インストールされている言語に応じてライブラリが少し異なります。また、署名にはロゴ画像を保持できますが、その理由はわかりませんが、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;
弦の取り扱いはもっと賢くすることができますが、これはうまく機能し、私の罪深い神の幸運を与えてくれました。
私は主に「卑劣」であることで問題を回避しています。 Outlookで新しいメールを作成するときに Ctrl+N、デフォルトの署名を挿入し、その空のメール(署名付き)を一時的な文字列に保存してから、その文字列をコンテンツが含まれる別の文字列に追加します。
これを実証するためのコードを次に示します。
string s = "";
Outlook.Application olApp = new Outlook.Application();
Outlook.MailItem mail = olApp.CreateItem(Outlook.OlItemType.olMailItem);
mail.To = "[email protected]";
mail.Subject = "Example email";
s = mainContentAsHTMLString + mail.HTMLBody;
mail.Display();
mail.HTMLBody = s;
デフォルトのOutlook署名(画像を含む)を添付する非常に簡単な方法を見つけました。秘Theは、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 = "[email protected]"
Dim myInspector As Outlook.Inspector = oMsg.GetInspector
Dim text As String
text = "mail text" & oMsg.HTMLBody
oMsg.HTMLBody = text
oMsg.Send()
また、私はこのトピックを数時間にわたって扱ってきました。最後に、非常に興味深いマイクロソフトのサポートケースを見つけました。
本当の問題はどこかに埋もれています。MicrosoftOutlookは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;
}
それを楽しんでください。トーマス
私は共有する価値があり、選択可能な任意の署名とマージされた電子メールテキストで任意のOutlookアカウントから電子メールを送信する目的のために完全であるこの問題に対する別の解決策を持っています。
仮定:
HTMLコンテンツのフォーマットに使用されるHtmlAgilityPackへの参照を追加しました。
私は電子メールアカウントの署名を取得する方法を見つけることができなかったため(レジストリを介して)、これはテキスト値として渡され、プログラムのパラメーターとして、またはOutlookアカウントのレジストリ設定を調べることで設定できます。
Fromアカウントは、システム上の有効な電子メールアカウントです。署名ファイルは、html形式を使用してOutlookによって作成されました。
これには多くの改善が考えられます。
/// <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> </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 "";
}
}
すべてのそれらの年後に答えを探している人のために。
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();
ユーザーのデフォルト署名を取得/設定するには、Windowsレジストリを使用できます。 Outlook 2010の例:HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Common\MailSettings名前:NewSignatureデータ型:文字列値:(終了しない署名ファイルの名前)
GetInspectorを使用すると、Inspectors_NewInspectorイベントを使用してインターセプターを実装するときに例外が発生します。 Inspectors_NewInspectorイベントが発生したときに、まだMailItemに署名が追加されていないこともわかります。
独自のコード(たとえば、独自のボタン)でItem.Send()をトリガーすると、「Signature」と「Content End」の両方にアンカータグ<a>
が設定されます。 Outlookリボンの[送信]ボタンクリックイベントを自分で処理する場合(アドインで一般的)、これらのタグは(Word HTMLからHTMLへの翻訳で)HTMLBodyから削除されます。
私の解決策は、Interceptor/Inspectors_NewInspectorが作成/発生したときに、後で送信時に使用する<p>
タグにId属性を追加できるように、Item.Openイベントを処理することです。この属性は、送信後もHTMLに残ります。
これにより、Sendが呼び出されるたびに、コード内で「Signature」または「Content End」段落を検出できます。