【问题标题】:TidMessage exception handling not working for EConvertErrorTidMessage 异常处理不适用于 EConvertError
【发布时间】:2018-03-13 01:35:00
【问题描述】:

我正在尝试阅读和处理由 Thunderebird 创建的电子邮件文件。我正在使用TIdMessage。它适用于绝大多数电子邮件,但有日期问题的邮件除外。

这是我的代码:

procedure TForm1.ButtonTestClick(Sender: TObject);
const
  CRLF = #13#10;
var
  IndyStringList: TStringList;
  IndyStream: TMemoryStream;
  IdMessage1: TIdMessage;
begin                      
  IdMessage1 := TIdMessage.Create(nil);
  s1 := 'C:\Temp\MboxTest4.txt'; //  shortened problem file

  IndyStringList := TStringList.Create;
  IndyStream := TMemoryStream.Create;
  IndyStringList.LoadFromFile(s1);
  IndyStringList.Add(CRLF + '.' + CRLF);
  IndyStringList.SaveToStream(IndyStream);
  IndyStream.Position := 0;
  try
    IdMessage1.LoadFromStream(IndyStream);
  except
    on E: EConvertError do
      ShowMessage(E.ClassName + '  ' + E.Message);
    on E : Exception do
      ShowMessage(E.ClassName+' error raised, with message : ' + E.Message);
  end;
end;

当我使用包含错误 Date 的文件运行此程序时,EConvertErrorException 处理程序不会执行,并且程序会继续运行,就好像没有错误一样。

这是电子邮件:

从 - 1965 年 1 月 1 日星期一 00:00:00 X-Persona: 收到:来自 yass.news.co.uk [194.129.35.178] 由 londondatabases.com (SMTPD32-6.06) id A3FA150060; 2002 年 8 月 29 日星期四 10:47:22 -0400 来自:星期日泰晤士报企业网 至:support@londondatabases.com 日期:2002 年 8 月 29 日星期四 15:40:46 +0100 (BST) 主题:星期日泰晤士报企业网 哑剧版:1.0 内容类型:文本/html;字符集=windows-1252 内容处置:内联 用户代理:YASS 消息 ID: X-RCPT-TO: X-UIDL:313625295 状态:U X-Mozilla-状态:8000 X-Mozilla-Status2: 00000000 内容传输编码:8bit

【问题讨论】:

  • 您能解释一下为什么您希望引发异常吗?让我们从库按设计运行的假设开始。
  • 如果它的设计假设所有电子邮件的格式都无可挑剔,那么我们就不需要错误处理。我想知道是不是这样?如果 TidMessage 设计为在数据不完美时失败,有什么建议可以替代 TidMessage?
  • 这类问题属于推荐问题,不在此列。我认为您需要研究您正在使用的 Indy 库的代码,以确定它是如何工作的。我认为您不能期望这会被记录在案。
  • 谢谢你。我不是一个好的程序员,你的建议超出了我的能力。这就是我在这里的原因。 :-)
  • @DavidHeffernan 仅供参考,AtoZed 为 CrossTalk、IntraWeb 和 Indy 创建了一个新的网络论坛:atozed.com/forums

标签: delphi indy


【解决方案1】:

您不应该使用TStringList 来按您的方式加载电子邮件文件(而且您也不应该将CRLFTStringList.Add() 一起使用)。没有理由手动将CRLF+'.'+CRLF 序列注入到电子邮件数据中(除非您使用的是内部尚未处理的非常旧的 Indy 版本)。您应该改用TIdMessage.LoadFromFile() 方法:

procedure TForm1.ButtonTestClick(Sender: TObject);
var
  IdMessage1: TIdMessage;
begin                      
  try
    IdMessage1 := TIdMessage.Create(nil);
    try
      IdMessage1.LoadFromFile('C:\Temp\MboxTest4.txt');
    finally
      IdMessage1.Free;
    end;
  except
    on E : Exception do
      ShowMessage(E.ClassName + ' error raised, with message : ' + E.Message);
  end;
end;

或者,TIdMessageHelper.LoadFromFile() 方法,如果电子邮件的行没有以点透明格式转义(有关详细信息,请参阅 New TIdMessage helper):

uses
  ..., IdMessageHelper;

procedure TForm1.ButtonTestClick(Sender: TObject);
var
  IdMessage1: TIdMessage;
begin                      
  try
    IdMessage1 := TIdMessage.Create(nil);
    try
      // if using D2006+
      IdMessage1.LoadFromFile('C:\Temp\MboxTest4.txt', False, False);

      // if using pre-D2006
      TIdMessageHelper_LoadFromFile(IdMessage1, 'C:\Temp\MboxTest4.txt', False, False);
    finally
      IdMessage1.Free;
    end;
  except
    on E : Exception do
      ShowMessage(E.ClassName + ' error raised, with message : ' + E.Message);
  end;
end;

无论哪种方式,您的代码没有捕获日期转换错误的原因是 Indy 在内部捕获了异常并将TIdMessage.Date 属性设置为0.0。异常不会引发到您的代码中,因此只有在 IDE 的调试器中运行代码时才能看到它。

电子邮件的Date 标头无法解析的原因是因为它的格式不符合RFC 822 Section 5 的规则。 August 应该是 Aug,然后它会正确解析:

Date: Thu, 29 Aug 2002 15:40:46 +0100 (BST)

但是,Indy 确实考虑了 RFC 822 不允许的几种替代语言拼写,但它没有处理完整的月份名称。所以我刚刚更新了 Indy 以支持解析额外的拼写,现在你原来的“格式错误”Date 将解析没有错误。

【讨论】:

  • 非常感谢。我明天会试一试,因为这里已经很晚了。 :-)
  • 我确认它按描述工作。再次感谢您。如果您可以发布允许处理完整月份名称的补丁,我将不胜感激。
  • @user1355041 你可以从Indy's SVN server 生成你自己的补丁,或者只是downloadinstall 最新的夜间快照。
  • 谢谢。我会努力做到的。
猜你喜欢
  • 2017-07-15
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 2014-03-21
  • 2018-06-26
相关资源
最近更新 更多