功能和特性

功能和特性

本页涵盖了 Aspose.Email FOSS for .NET 的所有主要功能,并提供可运行的 C# 示例。


读取 MSG 文件

从路径或流加载 MSG 文件并访问其所有属性:

using System.IO;
using Aspose.Email.Foss.Msg;

using var stream = File.OpenRead("message.msg");
var message = MapiMessage.FromStream(stream);

Console.WriteLine(message.Subject);
Console.WriteLine(message.Body);
Console.WriteLine(message.HtmlBody);
Console.WriteLine(message.SenderName);
Console.WriteLine(message.SenderEmailAddress);
Console.WriteLine(message.MessageDeliveryTime);
Console.WriteLine(message.InternetMessageId);

使用 strict: false 对非标准 MSG 文件进行宽松解析:

var message = MapiMessage.FromFile("message.msg", strict: false);

检查 ValidationIssues 以查看任何格式警告而不抛出:

foreach (var issue in message.ValidationIssues)
    Console.WriteLine($"Warning: {issue}");

创建 MSG 文件

使用 MapiMessage.Create() 构建完整的电子邮件,并使用 Save() 序列化:

using System.IO;
using Aspose.Email.Foss.Msg;

var message = MapiMessage.Create("Hello", "Body");
message.SenderName = "Alice";
message.SenderEmailAddress = "alice@example.com";
message.HtmlBody = "<p>Body</p>";
message.InternetMessageId = "<hello@example.com>";
message.MessageDeliveryTime = new DateTime(2024, 1, 2, 3, 4, 5, DateTimeKind.Utc);

message.AddRecipient("bob@example.com", "Bob");

using var output = File.Create("hello.msg");
message.Save(output);

Save() 在没有参数的情况下返回一个 byte[]Save(path) 直接写入文件路径。


收件人

添加 ToCcBcc 收件人,使用 AddRecipient()

message.AddRecipient("alice@example.com", "Alice");
message.AddRecipient("bob@example.com", "Bob", MapiMessage.RecipientTypeCc);
message.AddRecipient("carol@example.com", "Carol", MapiMessage.RecipientTypeBcc);

遍历已加载消息的收件人:

foreach (var recipient in message.Recipients)
    Console.WriteLine($"{recipient.DisplayName} <{recipient.EmailAddress}>");

附件

添加带有元数据的文件或流附件:

// From byte array
message.AddAttachment("report.pdf", pdfBytes, "application/pdf");

// From stream
using var attachStream = File.OpenRead("photo.png");
message.AddAttachment("photo.png", attachStream, "image/png");

// Inline image with Content-ID
message.AddAttachment("logo.png", logoBytes, "image/png", contentId: "logo@cid");

读取已加载消息的附件:

foreach (var attachment in message.Attachments)
{
    Console.WriteLine($"Filename: {attachment.Filename}");
    Console.WriteLine($"MIME type: {attachment.MimeType}");
    Console.WriteLine($"Size: {attachment.Data.Length} bytes");
    File.WriteAllBytes(attachment.Filename!, attachment.Data);
}

嵌入式消息附件

在另一个内部附加一个 MapiMessage — 在转发的电子邮件链中很常见:

using Aspose.Email.Foss.Msg;

var parent = MapiMessage.Create("Outer", "Parent body");
var child = MapiMessage.Create("Inner", "Child body");
child.SenderEmailAddress = "inner@example.com";
parent.AddEmbeddedMessageAttachment(child, "inner.msg");

parent.Save("outer.msg");

读取嵌入的消息附件:

var loaded = MapiMessage.FromFile("outer.msg");
foreach (var attachment in loaded.Attachments)
{
    if (attachment.IsEmbeddedMessage)
    {
        Console.WriteLine($"Embedded: {attachment.EmbeddedMessage!.Subject}");
    }
}

EML 和 MIME 转换

将 RFC 5322 .eml 文件加载到 MapiMessage 中,以实现 Outlook 兼容的存储:

using System.IO;
using Aspose.Email.Foss.Msg;

using var input = File.OpenRead("message.eml");
var message = MapiMessage.LoadFromEml(input);

using var msgOutput = File.Create("message.msg");
message.Save(msgOutput);

将 MSG 文件转换回 EML:

var message = MapiMessage.FromFile("message.msg");
using var emlOutput = File.Create("roundtrip.eml");
message.SaveToEml(emlOutput);

LoadFromEml() 也接受 string 路径或 byte[]SaveToEml() 在没有参数的情况下返回一个 byte[]。主题、正文、HTML 正文、发件人、收件人以及所有附件(包括带有 Content-ID 的内联图像)在完整的 EML ↔ MSG 往返过程中均得以保留。


MAPI 属性访问

MapiPropertyCollection 通过 SetProperty()
GetPropertyValue() 提供对 MAPI 属性的类型化访问。使用 CommonMessagePropertyId 枚举值来获取标准属性:

using Aspose.Email.Foss.Msg;

var message = MapiMessage.FromFile("sample.msg");

// Named convenience properties
Console.WriteLine(message.Subject);
Console.WriteLine(message.SenderName);
Console.WriteLine(message.MessageDeliveryTime);

// Iterate all MAPI property keys
foreach (var key in message.IterPropertyKeys())
    Console.WriteLine($"0x{(ushort)key.PropertyId:X4} / {key.PropertyType}");

CFB 容器访问

Outlook MSG 文件基于复合文件二进制(CFB)格式构建。CfbReader 提供完整的目录树以供检查和数据提取:

using System.Text;
using Aspose.Email.Foss.Cfb;

using var reader = CfbReader.FromFile("message.msg");

// Iterate all top-level children
foreach (var entry in reader.IterChildren(CfbConstants.RootStreamId))
    Console.WriteLine($"{(entry.IsStorage() ? "Storage" : "Stream")}: {entry.Name}");

// Navigate to a specific stream by path
var entry2 = reader.ResolvePath(["__substg1.0_0037001E"]);
if (entry2 is not null)
{
    var data = reader.GetStreamData(entry2.StreamId);
    Console.WriteLine(Encoding.Unicode.GetString(data));
}

从头构建并序列化 CFB 文档,使用 CfbWriter

using System.Text;
using Aspose.Email.Foss.Cfb;

var document = new CfbDocument();
document.Root.AddStream(new CfbStream("Notes", Encoding.UTF8.GetBytes("hello")));
var storage = document.Root.AddStorage(new CfbStorage("DataStore"));
storage.AddStream(new CfbStream("Payload", Encoding.UTF8.GetBytes("content")));

byte[] bytes = CfbWriter.ToBytes(document);
File.WriteAllBytes("output.cfb", bytes);

技巧与最佳实践

  • 使用 usingDispose()MapiMessageCfbReader 上释放文件句柄
  • 加载后检查 message.ValidationIssues 以检测非标准 MSG 格式
  • FromFile() / FromStream() 中的 strict 参数控制错误容忍度 — 使用 strict: false 对第三方系统的文件进行宽松解析
  • MapiMessage.Create() 默认生成 Unicode 字符串消息;设置 unicodeStrings: false 以兼容传统 ANSI
  • SaveToEml() 在没有参数的情况下返回 byte[] — 对于内存中工作流非常方便

常见问题

IssueCauseFix
加载时的 CfbException不是有效的 CFB/MSG 文件确认文件是 Outlook MSG
加载后 Body 为空正文仅以 HTML 形式存储改为检查 message.HtmlBody
未找到收件人类型常量不是独立类型使用 MapiMessage.RecipientTypeToMapiMessage.RecipientTypeCcMapiMessage.RecipientTypeBcc
LoadFromEml 后附件为 0EML 没有 Content-Disposition: attachment 部分内联部分(仅 Content-ID)也出现在 Attachments

API 参考摘要

ClassDescription
MapiMessage高级 MSG 消息表示
MapiAttachmentMapiMessage 上的附件或嵌入式消息
MapiRecipientMapiMessage 上的收件人
MapiProperty单个 MAPI 属性条目
MapiPropertyCollection类型化 MAPI 属性包
CommonMessagePropertyId标准 MAPI 属性标识符的枚举
MsgReader低级 MSG 结构读取器
MsgWriter低级 MSG 结构写入器
CfbReaderCFB 二进制容器读取器
CfbWriterCFB 二进制容器写入器
CfbDocument用于构建的内存中 CFB 文档
CfbStorageCFB 文档中的存储节点
CfbStreamCFB 文档中的流节点
 中文