我正在尝试在我的 .net 6.0 c# 应用程序中制作一种 outlook“发送到 onenote”插件(作为拖放)。据我所知,整个电子邮件正文(从读取 outlook 收件箱/发件箱的列表视图中拖出)作为新页面推送到 onenote(listviewArchive 包含带有 .one 文件的文件夹)。唯一的问题是我似乎无法弄清楚如何将附件(不是内联,而是文件作为 mailitem 中的附件)添加到 onennote 页面,就像 outlook“发送到 onennote”一样。 和我的。我用来将电子邮件推送到 onenote 的代码是
using Onenote = Microsoft.Office.Interop.OneNote;
private async void listViewArchive_DragDrop(object sender, DragEventArgs e)
{
Point clientPoint = listViewArchive.PointToClient(new Point(e.X, e.Y));
ListViewItem targetItem = listViewArchive.GetItemAt(clientPoint.X, clientPoint.Y);
Onenote.Application onenoteApp = new Onenote.Application();
if (targetItem != null && e.Data.GetDataPresent(typeof(ListView.SelectedListViewItemCollection)))
{
ViewReadOnly = false;
string targetPath = (string)targetItem.Tag;
string folderName = draggedFrom ? "in.one" : "out.one";
targetPath = Path.Combine(targetPath, folderName);
if (!File.Exists(targetPath))
{
MessageBox.Show("No section file found, Mailwill not be added as a page", "File not found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
Marshal.ReleaseComObject(onenoteApp);
onenoteApp= null;
return;
}
ListView.SelectedListViewItemCollection selectedItems = (ListView.SelectedListViewItemCollection)e.Data.GetData(typeof(ListView.SelectedListViewItemCollection));
foreach (ListViewItem item in selectedItems)
{
if (item.Tag is Outlook.MailItem mailItem)
{
string m_xmlNewOutlineContent =
"<one:Meta name=\"{2}\" content=\"{1}\"/>" +
"<one:OEChildren><one:HTMLBlock><one:Data><![CDATA[{0}]]></one:Data></one:HTMLBlock></one:OEChildren>";
string m_xmlNewOutline =
"<?xml version=\"1.0\"?>" +
"<one:Page xmlns:one=\"{2}\" ID=\"{1}\">" +
"<one:Outline>{0}</one:Outline></one:Page>";
string m_outlineIDMetaName = "Outlook Email To OneNote AddIn ID";
string m_xmlns = "http://schemas.microsoft.com/office/onenote/2013/onenote";
await Task.Run(() =>
{
string subject = mailItem.Subject;
string from = mailItem.SenderName;
string to = mailItem.To;
string cc = mailItem.CC;
DateTime sentTime = mailItem.SentOn;
string attachments = "";
List<string> attachmentPaths = new List<string>();
foreach (Outlook.Attachment attachment in mailItem.Attachments)
{
bool isInline = false;
try
{
isInline = (bool)attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7FFE000B");
}
catch (Exception)
{
// still to add....
}
if (!isInline)
{
string attachmentPath = Path.Combine(Path.GetTempPath(), attachment.FileName);
attachment.SaveAsFile(attachmentPath);
attachmentPaths.Add(attachmentPath);
attachments += attachment.FileName + ";";
}
}
string insertedFiles = string.Empty;
foreach (string attachmentPath in attachmentPaths)
{
//code to add the files to the table in string emailBody, no idea how....
}
string emailBody =
"<table border=\"1\" cellpadding=\"5\"><tr><th>Subject</th><th>From</th><th>To</th><th>CC</th><th>Sent Time</th><th>Attachments</th></tr>" +
$"<tr><td>{subject}</td><td>{from}</td><td>{to}</td><td>{cc}</td><td>{sentTime}</td><td>{insertedFiles}</td></tr></table>" +
mailItem.HTMLBody;
// Create new OneNote page and insert email content
string xmlHierarchy;
onenoteApp.GetHierarchy("", HierarchyScope.hsSections, out xmlHierarchy);
string targetID = string.Empty;
onenoteApp.OpenHierarchy(targetPath, string.Empty, out targetID);
onenoteApp.CreateNewPage(targetID, out string pageID, NewPageStyle.npsBlankPageWithTitle);
int outlineID = new Random().Next();
string outlineContent = string.Format(m_xmlNewOutlineContent, emailBody, outlineID, m_outlineIDMetaName);
string xml = string.Format(m_xmlNewOutline, outlineContent, pageID, m_xmlns);
// Get the title and set it to our page name
onenoteApp.GetPageContent(pageID, out xml, PageInfo.piAll);
XNamespace ns = null;
var doc = XDocument.Parse(xml);
ns = doc.Root.Name.Namespace;
var title = doc.Descendants(ns + "T").First();
title.Value = subject;
// Update the page to add pagetitle/pagename
onenoteApp.UpdatePageContent(doc.ToString());
// Update the page again to add the actual body of the mailitem
onenoteApp.UpdatePageContent(xml, DateTime.MinValue);
});
}
}
}
Marshal.ReleaseComObject(onenoteApp);
onenoteApp= null;
}
它处理内联图像并不总是正确的。我花了很多互联网搜索和复制/粘贴才能找到这个点但是...... 如果有人可以添加代码来处理附件并查看邮件正文中的内联图像,那就太好了!我没有足够的知识来弄清楚这个......
做了很多但没有保留这个。迷路了。在 stackoverflow 中搜索了很多但找不到任何关于这个的东西......
编辑/更新1:
problem 2) Attach files 尚未解决。有帮助吗?
问题 1“内联图像”看起来已解决。我在“await Task.Run(())”中移动了一些东西。现在内联图像被添加到 onenote 正文中。我将 foreach(mailItem.Attachments 中的 Outlook.Attachment 附件)移动到“string emailBody”下方并添加了其他if (isInline) 代码块。foreach 循环现在通过转换和替换以正确的方式使用内联图像更新“字符串 emailBody”。电子邮件的内联图像现在显示在 onenote 页面上
await Task.Run(() =>
{
string subject = mailItem.Subject;
string from = mailItem.SenderName;
string to = mailItem.To;
string cc = mailItem.CC;
DateTime sentTime = mailItem.SentOn;
string attachments = "";
string insertedFiles = string.Empty;
string emailBody =
"<table border=\"1\" cellpadding=\"5\"><tr><th>Subject</th><th>From</th><th>To</th><th>CC</th><th>Sent Time</th><th>Attachments</th></tr>" +
$"<tr><td>{subject}</td><td>{from}</td><td>{to}</td><td>{cc}</td><td>{sentTime}</td><td>{insertedFiles}</td></tr></table>" +
mailItem.HTMLBody;
List<string> attachmentPaths = new List<string>();
foreach (Outlook.Attachment attachment in mailItem.Attachments)
{
bool isInline = false;
try
{
isInline = (bool)attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7FFE000B");
}
catch (Exception)
{
}
if (!isInline)
//saving them mfirst on temp location is just to see if i am able to get the files
{
string attachmentPath = Path.Combine(Path.GetTempPath(), attachment.FileName);
attachment.SaveAsFile(attachmentPath);
attachmentPaths.Add(attachmentPath);
attachments += attachment.FileName + ";";
}
else if (isInline)
{
byte[] attachmentData = (byte[])attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x37010102");
// Convert the binary data to a base64 string
string base64String = Convert.ToBase64String(attachmentData);
// Replace the inline image tag with the base64 encoded string
string cid = attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E") as string;
emailBody = emailBody.Replace($"cid:{cid}", $"data:image/png;base64,{base64String}");
}
}
foreach (string attachmentPath in attachmentPaths)
{
//still needs solving. the save files need to be added to the onenote page as attached file
//but it seems redonned to first save the email attached file and the grapping them form temp location.
//so be able to get them form mail directly
}
// Create new OneNote page and insert email content
string xmlHierarchy;
onenoteApp.GetHierarchy("", HierarchyScope.hsSections, out xmlHierarchy);
string targetID = string.Empty;
onenoteApp.OpenHierarchy(targetPath, string.Empty, out targetID);
onenoteApp.CreateNewPage(targetID, out string pageID, NewPageStyle.npsBlankPageWithTitle);
int outlineID = new Random().Next();
string outlineContent = string.Format(m_xmlNewOutlineContent, emailBody, outlineID, m_outlineIDMetaName);
string xml = string.Format(m_xmlNewOutline, outlineContent, pageID, m_xmlns);
// Get the title and set it to our page name
onenoteApp.GetPageContent(pageID, out xml, PageInfo.piAll);
XNamespace ns = null;
var doc = XDocument.Parse(xml);
ns = doc.Root.Name.Namespace;
var title = doc.Descendants(ns + "T").First();
title.Value = subject;
// Update the page to add pagetitle/pagename
onenoteApp.UpdatePageContent(doc.ToString());
outlineContent = string.Format(m_xmlNewOutlineContent,emailBody, outlineID, m_outlineIDMetaName);
xml = string.Format(m_xmlNewOutline, outlineContent, pageID, m_xmlns);
// Update the page again to add the actual body of the mailitem
onenoteApp.UpdatePageContent(xml, DateTime.MinValue);
});
听起来您只需要为附加的文件附加图像,并在需要的地方(在表格单元格中)显示在消息正文中。以下代码显示了如何附加图像,然后在邮件正文中设置对它的引用:
Attachment attachment = newMail.Attachments.Add(@"E:\Pictures\image001.jpg", OlAttachmentType.olEmbeddeditem, null, "Some image display name");
string imageCid = "image@123";
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", imageCid);
newMail.HTMLBody = String.Format("<body><img src=\"cid:{0}\"></body>", imageCid);
您基本上需要在附件上设置
PR_ATTACH_CONTENT_ID
属性,然后在正文中引用它。此外,如果您想从视图中隐藏附件,您还可以考虑设置 PT_ATTACH_HIDDEN
属性(DASL 名称为 http://schemas.microsoft.com/mapi/proptag/0x7FFE000B
)。
Outlook不支持base64图片,需要处理附加项。所以下面这段代码没有任何意义:
emailBody = emailBody.Replace($"cid:{cid}", $"data:image/png;base64,{base64String}");
使用
<a>
元素在邮件正文中显示附加项目,其中src
属性设置为CID值(见上文)。
编辑/更新2:
我也解决了第二个问题,实际上并不是很复杂,见下文。这会将 outlook 文件附件作为文件附件添加到 onenote 页面。仍然需要重写整个 Dragdrop 方法才能......更好!
if (!isInline)
{
string attachmentPath = Path.Combine(Path.GetTempPath(), attachment.FileName);
attachment.SaveAsFile(attachmentPath);
//enclose the file in the correct onenote node
attachments += string.Format("<one:InsertedFile pathSource=\"{0}\" preferredName=\"{1}\" />", attachmentPath, attachment.FileName);
//update string incase this if statement is invoked
m_xmlNewOutline =
"<?xml version=\"1.0\"?>" +
"<one:Page xmlns:one=\"{2}\" ID=\"{1}\">" +
$"{attachments}"+
"<one:Outline>{0}" +
"</one:Outline></one:Page>";
//still need to look at handling multiple fileattachments...
}
但至少上面的代码可以将 outlook 文件附件附加到 onenote 页面。整个 DragDrop 方法还包括我制作的自定义进度条的实例,用于指示某些内容正在复制到/保存到 onenote,并且 mailitem 本身获得一个自定义属性,指示 mailitem 已存档到 onenote。这在 listviewInbox/Outbox 中启用了一个复选框,并使这些列表视图中的项目“变灰”...