使用Indy 10和DELPHI评估电子邮件

4
我使用以下代码来评估使用INDY 10组件接收的电子邮件消息的内容(正文/行)
function LinesFromMsg(aMsg: TIdMessage): TStrings; 
var
  i: Integer; 
begin
  for i := 0 to aMsg.MessageParts.AttachmentCount-1 do
  begin
    if (amsg.MessageParts.Items[i].ContentType ='HTML') then
    begin
      if (amsg.MessageParts.Items[i] is Tidtext) then
        Result := TidText(amsg.MessageParts.Items[i]).body;
    end;
  end; 
end;

关于这段代码,我有两个问题:

a)在任意邮件消息中查找Tlines部分的方法是否正确?(请考虑在INDY 10 EMAIL MSG PARTS中给出的建议)

b)在哪里可以找到所有不同Contenttype字符串值的教程?

1个回答

8
正确的ContentType值应该是text/html。使用Indy的IsHeaderMediaType()函数进行检查,因为ContentType值可能有与之关联的其他属性,您需要忽略这些属性进行比较。
您还需要考虑TIdMessage.ContentType,因为HTML电子邮件可能没有MIME编码,因此根本不使用TIdMessage.MessageParts集合。
最后,您的循环需要使用MessageParts.Count属性而不是MessageParts.AttachmentsCount属性。
尝试这个:
function HTMLFromMsg(aMsg: TIdMessage): TStrings; 
var
  i: Integer; 
  Part: TIdMessagePart;
begin
  Result := nil;
  if IsHeaderMediaType(aMsg.ContentType, 'text/html') then
  begin
    Result := aMsg.Body;
    Exit;
  end;
  for i := 0 to aMsg.MessageParts.Count-1 do
  begin
    Part := aMsg.MessageParts.Items[i];
    if (Part is TIdText) and IsHeaderMediaType(Part.ContentType, 'text/html') then
    begin
      Result := TIdText(Part).Body;
      Exit;
    end;
  end; 
end;

话虽如此,这并不是处理MIME的正确方式。官方规定,符合要求的阅读器应该从最简单的形式向下到最复杂的形式依次循环遍历MIME部分。因此,您需要考虑MIME的嵌套情况,倒序循环查找您支持的最复杂形式。以下是更接近官方要求的代码示例(未经测试):

procedure DisplayPlainText(Body: TStrings);
begin
  // display plain text as needed...
end;

procedure DisplayHTML(Body: TStrings);
begin
  // display html as needed...
end;

procedure DisplayMultiPartAlternative(aMsg: TIdMessage; aParentIndex, aLastIndex: Integer);
var
  Part: TIdMessagePart;
  i: Integer:
begin
  for i := aLastIndex-1 downto aParentIndex+1 do
  begin
    Part := aMsg.MessageParts.Items[i];
    if (Part.ParentPart = aParentIndex) and (Part is TIdText) then
    begin
      if IsHeaderMediaType(Part.ContentType, 'text/html') then
      begin
        DisplayHTML(TIdText(Part).Body);
        Exit;
      end;
      if IsHeaderMediaType(Part.ContentType, 'text/plain') then
      begin
        DisplayPlainText(TIdText(Part).Body);
        Exit;
      end;
    end;
  end;
  // nothing supported to display...
end;

procedure DisplayMultiPartMixed(aMsg: TIdMessage; aParentIndex, aLastIndex: Integer);
var
  Part: TIdMessagePart;
  i: Integer;
begin
  for i := aLastIndex-1 downto aParentIndex+1 do
  begin
    Part := aMsg.MessageParts.Items[i];
    if (Part.ParentPart = aParentIndex) and (Part is TIdText) then
    begin
      if IsHeaderMediaType(Part.ContentType, 'multipart/alternative') then
      begin
        DisplayMultiPartAlternative(aMsg, ParentPart.Index, aLastIndex);
        Exit;
      end;
      if IsHeaderMediaType(ParentPart.ContentType, 'text/html') then
      begin
        DisplayHTML(TIdText(Part).Body);
        Exit;
      end;
      if IsHeaderMediaType(Part.ContentType, 'text/plain') then
      begin
        DisplayPlainText(TIdText(Part).Body);
        Exit;
      end;
      aLastIndex := i;
    end;
  end;
  // nothing supported to display...
end;

procedure DisplayMsg(aMsg: TIdMessage); 
var
  ContentType: string;
begin
  ContentType := ExtractHeaderMediaType(aMsg.ContentType);
  case PosInStrArray(ContentType, ['multipart/mixed', 'multipart/alternative', 'text/html', 'text/plain'], False) of
    0: begin
      DisplayMultiPartAlternative(aMsg, -1, aMsg.MessageParts.Count);
      Exit;
    end;
    1: begin
      DisplayMultiPartMixed(aMsg, -1, aMsg.MessageParts.Count);
      Exit;
    end;
    2: begin
      DisplayHTML(aMsg.Body);
      Exit;
    end;
    3: begin
      DisplayPlainText(aMsg.Body);
      Exit;
    end;
  else
    // nothing supported to display...
  end;
end;

And IdMessageParts - Freddie Bell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接