You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#读取带MAPI .pst的POP3 Outlook账户完整邮件正文

问题:POP3邮件正文无法完整读取(Mac环境)

背景

  • 连接配置了MAPI个人存储文件夹(.pst)的Outlook POP3账户,因MAPI未同步文件夹,所有邮件集中显示,通过IF语句筛选特定发件人(no-reply@property24.com)的邮件,已成功读取邮件头、发件人、主题,但非目标邮件不处理。
  • 尝试用Console.WriteLine(message.FindFirstPlainTextVersion().GetBodyAsText());读取正文时,仅能获取第一段,无法读取完整内容。
  • 运行环境为Mac系统,无法使用Microsoft.Office.Interop.Outlook命名空间。

当前代码

using System;
using OpenPop.Pop3;
using OpenPop.Pop3.Exceptions;
using OpenPop.Mime.Header;
using OpenPop.Mime;
using Org.BouncyCastle.Asn1.X509;
using MimeKit;

namespace Ada_Buyers
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create an instance of the Pop3Client class
            Pop3Client client = new Pop3Client();

            // Specify host, username, password, Port and SecurityOptions for your client
            client.Connect("hostnumber", port, true);
    
            // Authenticate with the server using username and password
            client.Authenticate("name@email.com", "password");
    
            // Print message after connection
            Console.WriteLine(Environment.NewLine + "Connected to POP3 server.");
    
    
            // Get the number of messages in the inbox folder
            int messageCount = client.GetMessageCount();
            Console.WriteLine($"Number of messages in inbox folder: {messageCount}");
    
            // Print message before looping through messages
            Console.WriteLine("Looping through messages...");
    
            int PrivatePropertyCount = 0;
            int PropertyTwentyFour = 0;
            int notapplicable = 0;
    
            for (int i = 1; i <= messageCount; i++)
            {
                try
                {
                    // Get the message headers for the current message
                    MessageHeader headers = client.GetMessageHeaders(i);
    
                    // Check if the message is from the desired sender(s)
                    if (headers.From != null && (headers.From.Address.Equals("no-reply@property24.com", StringComparison.OrdinalIgnoreCase)))                     
                    {
                    
                    // Get the message using the message number
                    var message = client.GetMessage(i);
                    PropertyTwentyFour++;
    
                        // Print the entire email
                        Console.WriteLine("From: " + message.Headers.From.Address);
                        Console.WriteLine("To: " + message.Headers.To[0].Address);
                        Console.WriteLine("Subject: " + message.Headers.Subject);
                        Console.WriteLine("Email Body:");
                        // 此处原本调用FindFirstPlainTextVersion().GetBodyAsText()仅能读取第一段
                    }
    
                    else if (headers.From != null && (headers.From.Address.Equals("no-reply@property24.com", StringComparison.OrdinalIgnoreCase)))
                    {
                        // Get the message using the message number
                        Message message = client.GetMessage(i);
                        PropertyTwentyFour++;
    
                        // Print the entire email
                        Console.WriteLine("From: " + message.Headers.From.Address);
                        Console.WriteLine("To: " + message.Headers.To[0].Address);
                        Console.WriteLine("Subject: " + message.Headers.Subject);
                        Console.WriteLine("Email Body:");
    
                    }
                    else
                    {
                        notapplicable++;
                        Console.WriteLine("Email number: " + i + " was not in private property or property 24 folder.");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error processing message {i}: {ex.Message}");
                }
        }
        // Print the number of emails that contain the header no-reply@gumtree-protool.com
        Console.WriteLine($"Number of emails containing the header private Property: {PrivatePropertyCount}"); Console.WriteLine($"Number of emails containing the header Property 24 Alert: {PropertyTwentyFour}"); 
        Console.WriteLine($"Number of emails not send from private property of property 24 is: {notapplicable}");
        }
    }
}

注:出于安全考虑,主机名、端口号、邮箱地址和密码已修改。

解决方案

问题原因

FindFirstPlainTextVersion()仅返回邮件中第一个找到的纯文本部分,若邮件是多部分结构(比如正文分段存储、或包含附件+正文),则无法获取完整内容。

修复方法

替换原有的正文读取代码,改为以下两种方式之一:

方法1:直接获取完整纯文本正文

使用Message.GetBodyAsText()方法可直接提取邮件的完整纯文本内容,无需手动查找文本部分:

Console.WriteLine("Email Body:");
// 获取完整纯文本正文
string fullBody = message.GetBodyAsText();
Console.WriteLine(fullBody);

方法2:遍历所有文本部分(适用于复杂多部分邮件)

如果GetBodyAsText()仍有异常,可手动遍历邮件的所有MIME部分,提取所有纯文本内容:

Console.WriteLine("Email Body:");
// 遍历所有文本类型的MIME部分
foreach (var part in message.FindAllTextParts())
{
    if (part.ContentType.MediaType.Equals("text/plain", StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine(part.GetBodyAsText());
    }
}

额外代码优化

原代码中存在重复的IF判断逻辑(两个条件完全一致),可合并为一个分支,减少冗余:

// 合并重复的判断逻辑
if (headers.From != null && headers.From.Address.Equals("no-reply@property24.com", StringComparison.OrdinalIgnoreCase))
{
    var message = client.GetMessage(i);
    PropertyTwentyFour++;

    Console.WriteLine("From: " + message.Headers.From.Address);
    Console.WriteLine("To: " + message.Headers.To[0].Address);
    Console.WriteLine("Subject: " + message.Headers.Subject);
    Console.WriteLine("Email Body:");
    string fullBody = message.GetBodyAsText();
    Console.WriteLine(fullBody);
}
else
{
    notapplicable++;
    Console.WriteLine("Email number: " + i + " was not in private property or property 24 folder.");
}

内容的提问来源于stack exchange,提问作者Joruhan de Wit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:27:58