C# 转换EML';s至MSG';s

C# 转换EML';s至MSG';s,c#,outlook,msg,eml,C#,Outlook,Msg,Eml,我们有一个Web应用程序,允许用户在表中查看电子邮件,并双击它们在outlook中打开它们 为此,我们使用(简化的)代码段: var email = Session.OpenSharedItem(filename) as MailItem; 这适用于.msg消息,但表中也列出了.eml文件。OpenSharedItem方法无法打开.eml文件() 因此,我们希望将这些.eml文件转换为.msg文件 到目前为止,我们只在付费的第三方图书馆中找到了答案,而这是我们无法做到的。还有其他解决方案吗

我们有一个Web应用程序,允许用户在表中查看电子邮件,并双击它们在outlook中打开它们

为此,我们使用(简化的)代码段:

 var email = Session.OpenSharedItem(filename) as MailItem;
这适用于.msg消息,但表中也列出了.eml文件。OpenSharedItem方法无法打开.eml文件()

因此,我们希望将这些.eml文件转换为.msg文件

到目前为止,我们只在付费的第三方图书馆中找到了答案,而这是我们无法做到的。还有其他解决方案吗

编辑:更明确地说,我们不能使用付费第三方库。

当然,可以使用对象(原生Outlook MIME转换器),但它只能在C++或Delphi中访问。 您还可以创建自己的转换器,并一次创建一个MIME头的EML文件

使用(可以在服务中运行,与Outlook对象模型不同),转换非常简单

  set Session = CreateObject("Redemption.RDOSession")
  set Msg = Session.GetMessageFromMsgFile("c:\temp\test.msg")
  Msg.SaveAs "c:\temp\test.eml", 1031

如果您能够向外剥离,outlook.exe就可以运行emls,而无需像这样进行转换

outlook.exe /eml "path\to\file.eml"
如果电子邮件是可编辑的(
X-Unsent=1
),这甚至可以工作。
甚至可能有一种方法可以做一个相当不错的事情

或者,你可以通过编程来实现,但需要转换;事实上,如果您希望任何可编辑的电子邮件自动插入用户的签名(因为这将是一个oft,而不是msg/eml),您必须这样做。
下面我有一个powershell脚本,它接受eml并有条件地保存msg或oft,然后打开它

您可以使其仅转换而不打开,或仅打开而不转换(但您仍然需要制作临时文件:OOM不接受从内存制作
MailItem
s);我只是在为子孙后代做准备。
我使用它的目的是在客户机上,他们双击一个eml文件,它会在outlook中打开

即使是powershell,C#也是可以互换的;我的意思是,我写这篇文章时只阅读C#的示例和文档(可能是旧CDO的一些vbs)。
我不知道C#,我觉得把这篇文章放在这里会比不写任何东西对看到这篇文章的人有更大的帮助(因为我必须搜索互联网,从头开始写)。
我很乐意接受任何编辑,如果有人移植它

$location=$PSScriptRoot
开始转录本“$location\LOG.txt”-追加
#ADODB仅在MIME位于顶部时工作
. {
'MIME版本:1.0'
获取内容$args[0]
}$args[0]|设置内容“$location\tmp”
#解析eml
$eml=新对象-ComObject ADODB.Stream
$eml.Open()
$eml.LoadFromFile(“$location\tmp”)
$eml.Flush()
$email=新对象-ComObject“CDO.Message”
$email.DataSource.OpenObject($eml,“\u流”)
$email.DataSource.Save()
$eml.Close()
#!将此移到底部以演示无shellingout和msg转换
#如果电子邮件不可编辑,只需正常打开即可
#if($email.Fields('urn:schemas:mailheader:X-Unsent')。值-ne“1”){
#&“${env:ProgramFiles}\Microsoft Office\root\Office16\OUTLOOK.EXE”/eml$args[0]
#出口
#}
#构建模板
$outlook=新对象-ComObject outlook.Application
$output=$outlook.CreateItem(0)
$output.Sender=$email.From
$output.To=$email.To
$output.CC=$email.CC
$output.BCC=$email.BCC
$output.Subject=$email.Subject
如果($email.ReplyTo){
$output.ReplyRecipients.Add($email.ReplyTo)| Out Null
}
$output.BodyFormat=2
$output.HTMLBody=$email.HTMLBody
#对于每个附件
. {for($part=$email.HTMLBodyPart;$part=$part.Parent){
$part.BodyParts |对象所在位置{
$\字段('urn:schemas:httpmail:content-disposition-type')。值-匹配“^(内联附件)$”
}
}} | %{
#得到名字
$name=($\.FileName-替换“^.*[/\\]”,'').trim('.'))
#如果没有,就做一个
如果(!$name){
$name=(
“未平铺附件”+
($\字段('urn:schemas:httpmail:content-media-type')。值`
-替换“[/\\]”,“.”`
-替换“^\.+\.+$”,“`
-替换“^(.)”、“$1”
)
)
}
#将附件保存到文件
$_.
GetDecodedContentStream()。
SaveToFile(“$location\$name”,2)
#TODO unicode、双端unicode、utf8、utf7、utf32、ascii、默认值、oem
if($\字符集-imatch“UTF-8”){
获取内容“$location\$name”|输出文件“tmp”-编码utf8
移动项目“tmp”$location\$name”-强制
}
#把它放到邮件里
$attachment=$output.Attachments.Add(“$location\$name”).PropertyAccessor
删除项目“$location\$name”
#设置其属性
if($\字段('urn:schemas:mailheader:content-id').Value){
$attachment.SetProperty(
'http://schemas.microsoft.com/mapi/proptag/0x3712001F',
$\.Fields('urn:schemas:mailheader:content-id')。Value.trim(“”)
)
}
if($\字段('urn:schemas:httpmail:content-media-type').Value){
$attachment.SetProperty(
'http://schemas.microsoft.com/mapi/proptag/0x370E001F',
$\字段('urn:schemas:httpmail:content-media-type')。值
)
}
}
#保存并打开电子邮件
if($email.Fields('urn:schemas:mailheader:X-Unsent')。值-eq“1”){
$output.SaveAs(“email.oft”,2)
$output.Close(1)
$outlook.CreateItemFromTemplate(“email.oft”).Display()
}
否则{
$output.SaveAs(“email.msg”,3)
$output.Close(1)
$outlook.Session.OpenSharedItem(“email.msg”).Display()
}
#!如上所述#!;我通常不会在这里做x-unset测试
#!并且只保存模板,但简单地称之为“tmp”,因此不会生成剩余文件
删除项目“$location\tmp”
我想我已经涵盖了一切。这适用于附件、嵌入图像和css,但假设HTML电子邮件和utf8用于文本附件。
这正是我所需要的,虽然添加对其他东西的支持并不困难,但如果您是私人用户,或者可以使用付费第三方,Dmitry似乎做了一个fa