如何用C#的EAGetMail库通过POP3动态读取新邮件?
解决方案:用EAGetMail+POP3实现新邮件自动读取
完全可以通过EAGetMail结合POP3服务器实现新邮件动态读取,不需要重启应用或自行搭建服务器。你的代码问题出在没有定期重新拉取邮件列表,且循环逻辑有误,以下是具体修正方案:
问题分析
- 你仅在应用启动时调用了一次
GetMailInfos(),后续循环一直复用旧的邮件列表,自然无法获取新到达的邮件。 - 循环条件
oServer.SSLConnection是SSL连接的配置项(始终为true),会导致无限循环重复处理旧邮件,且没有请求间隔,会对服务器造成不必要的压力。 - 缺少已处理邮件的记录机制,会重复下载同一批邮件。
修正后的代码
using EAGetMail; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Threading; namespace PopServer { class Program { // 生成唯一的邮件保存文件名 static string _generateFileName(int sequence) { DateTime currentDateTime = DateTime.Now; return string.Format("{0}-{1:000}-{2:000}.eml", currentDateTime.ToString("yyyyMMddHHmmss", new CultureInfo("en-US")), currentDateTime.Millisecond, sequence); } static void Main(string[] args) { // 记录已处理过的邮件UIDL,避免重复处理 HashSet<string> processedUidl = new HashSet<string>(); // 邮件检查间隔(单位:毫秒,这里设为30秒) int checkInterval = 30000; MailClient oClient = null; try { string localInbox = Path.Combine(Directory.GetCurrentDirectory(), "inbox"); if (!Directory.Exists(localInbox)) { Directory.CreateDirectory(localInbox); } MailServer oServer = new MailServer("popserver.com", "username@mail.com", "password", ServerProtocol.Pop3); oServer.SSLConnection = true; oServer.Port = 995; oClient = new MailClient("TryIt"); oClient.Connect(oServer); Console.WriteLine("已连接到POP3服务器,开始监听新邮件..."); // 首次拉取邮件并标记为已处理 MailInfo[] initialInfos = oClient.GetMailInfos(); foreach (var info in initialInfos) { processedUidl.Add(info.UIDL); } Console.WriteLine($"初始化完成,已标记{initialInfos.Length}封历史邮件为已处理"); // 持续监听新邮件 while (true) { try { // 重新拉取最新的邮件列表 MailInfo[] infos = oClient.GetMailInfos(); int newMailCount = 0; foreach (MailInfo info in infos) { // 只处理未记录过的新邮件 if (!processedUidl.Contains(info.UIDL)) { newMailCount++; Console.WriteLine($"发现新邮件:Index: {info.Index}; UIDL: {info.UIDL}"); // 下载邮件 Mail oMail = oClient.GetMail(info); Console.WriteLine("发件人: {0}", oMail.From.ToString()); Console.WriteLine("主题: {0}\r\n", oMail.Subject); Console.WriteLine("正文: {0}\r\n", oMail.TextBody); // 保存邮件到本地 string fileName = _generateFileName(newMailCount); string fullPath = Path.Combine(localInbox, fileName); oMail.SaveAs(fullPath, true); // 标记该邮件为已处理 processedUidl.Add(info.UIDL); // 可选:删除服务器上的邮件 // oClient.Delete(info); } } if (newMailCount > 0) { Console.WriteLine($"已处理{newMailCount}封新邮件"); } else { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 未发现新邮件"); } // 等待指定间隔后再次检查 Thread.Sleep(checkInterval); } catch (Exception loopEx) { Console.WriteLine($"检查邮件时出错:{loopEx.Message}"); // 尝试重新连接 if (!oClient.IsConnected) { Console.WriteLine("尝试重新连接服务器..."); oClient.Connect(oServer); } // 等待一段时间后重试 Thread.Sleep(checkInterval); } } } catch (Exception ep) { Console.WriteLine($"初始化出错:{ep.Message}"); } finally { // 确保退出时断开连接 oClient?.Quit(); Console.WriteLine("已断开与服务器的连接"); } } } }
关键改进点
- 新增已处理邮件记录:用
HashSet<string>存储已处理的邮件UIDL(POP3协议中唯一标识邮件的字符串),避免重复下载。 - 定期拉取邮件列表:在循环内部每次重新调用
GetMailInfos(),获取最新的邮件状态。 - 添加检查间隔:用
Thread.Sleep()设置检查间隔(比如30秒),减少对服务器的请求频率。 - 异常处理增强:处理循环中的异常,连接断开时自动重试连接。
- 优化路径处理:用
Path.Combine()替代字符串拼接,避免路径分隔符问题。
内容的提问来源于stack exchange,提问作者Shawn_Medinsky
相关产品推荐
相关产品推荐

