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;

关于此代码,我有 2 个问题:

a) 这是在任意邮件消息中找到 Tlines 部分的正确方法吗?(考虑INDY 10 EMAIL MSG PARTS中显示的建议)

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

4

1 回答 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;
于 2013-02-03T12:21:17.730 回答