Search code examples
delphiindyindy10

Why body and sender are empty?


I am using this code to read emails from the server and it work except that Sender.Address and Body.Text are empty why is that ?. Here is the code:

var
  MsgCount : Integer;
  i        : Integer;
  FMailMessage :  TIdMessage;
begin
  Memo1.Lines.Clear;
  //The IdPop31 is on the form so it is constructing when the
  //form is created and so is Memo1.
  IdPOP31.Host      := 'server.com'; //Setting the HostName;
  IdPOP31.Username  := '[email protected]';//Setting UserName;
  IdPOP31.Password  := 'xxxxxx';//Setting Password;
  IdPOP31.Port      := 110;//Setting Port;

  try
    IdPOP31.Connect();
    //Getting the number of the messages that server has.
    MsgCount := IdPOP31.CheckMessages;
    for i:= 1 to Pred(MsgCount) do
    begin
      try
        FMailMessage := TIdMessage.Create(nil);
        IdPOP31.Retrieve(i,FMailMessage);
        Memo1.Lines.Add('=================================================');
        Memo1.Lines.Add(FMailMessage.From.Address);
        Memo1.Lines.Add(FMailMessage.Recipients.EMailAddresses);
        Memo1.Lines.Add(FMailMessage.Subject);
        Memo1.Lines.Add(FMailMessage.Sender.Address);
        Memo1.Lines.Add(FMailMessage.Body.Text);
        Memo1.Lines.Add('=================================================');
      finally
        FMailMessage.Free;
      end;
    end;
  finally
    IdPOP31.Disconnect;
  end;
end;

Solution

  • The TIdMessage.Sender is populated only if the email has a top-level Sender header, which is rare. Typically the sender is in the From header instead.

    The body content will be stored in either the TIdMessage.Body or TIdMessage.MessageParts, depending on how the email is encoded. Typically, multi-piece emails, such as those encoded with MIME, especially if they contain attachments, will use TIdMessage.MessageParts, whereas simple emails, like plaintext-only emails, will use TIdMessage.Body. So, you need to check both as needed.

    For example:

    var
      MsgCount, I: Integer;
      FMailMessage: TIdMessage;
      Body: TStrings;
    
      function FindTextBody(AParent: Integer): TStrings;
      var
        J: integer;
        Part: TIdMessagePart;
      begin
        Result := nil;
        // MIME parts are ordered from least complex to most complex, and can be nested,
        // so loop backwards through the parts, recursing through nested levels as needed...
        for J := Pred(FMailMessage.MessageParts.Count) downto (AParent+1) do
        begin
          Part := FMailMessage.MessageParts[J];
          if Part.ParentPart = AParent then
          begin
            if IsHeaderMediaType(Part.ContentType, 'multipart') then
            begin
              Result := FindTextBody(Part.Index);
              if Result <> nil then Exit;
            end
            else if IsHeaderMediaType(Part.ContentType, 'text') then
            begin
              Result := (Part as TIdText).Body;
              Exit;
            end;
          end;
        end;
      end;
    
    begin
      Memo1.Lines.Clear;
      //The IdPop31 is on the form so it is constructing when the
      //form is created and so is Memo1.
      IdPOP31.Host      := 'server.com'; //Setting the HostName;
      IdPOP31.Username  := '[email protected]';//Setting UserName;
      IdPOP31.Password  := 'xxxxxx';//Setting Password;
      IdPOP31.Port      := 110;//Setting Port;
      try
        IdPOP31.Connect();
        //Getting the number of the messages that server has.
        MsgCount := IdPOP31.CheckMessages;
        for I := 1 to Pred(MsgCount) do
        begin
          FMailMessage := TIdMessage.Create(nil);
          try
            IdPOP31.Retrieve(I, FMailMessage);
            Memo1.Lines.Add('=================================================');
            Memo1.Lines.Add(FMailMessage.From.Address);
            Memo1.Lines.Add(FMailMessage.Recipients.EMailAddresses);
            Memo1.Lines.Add(FMailMessage.Subject);
            Memo1.Lines.Add(FMailMessage.Sender.Address);
            if FMailMessage.MessageParts.Count > 0 then
              Body := FindTextBody(-1)
            else
              Body := FMailMessage.Body;
            if Body <> nil then
              Memo1.Lines.Add(Body.Text);
            Memo1.Lines.Add('=================================================');
          finally
            FMailMessage.Free;
          end;
        end;
      finally
        IdPOP31.Disconnect;
      end;
    end;