1
votes

I have been fooling about with the SMTP client and server components in Indy 9 using demos with Delphi 7. Everything works fine. However, when I telnet into the server, the demo shows only the email subject and mail body, the From: and To: fields are not shown.

The code below shows that AMsg is lacking the relevant data.

procedure TForm1.IdSMTPServer1ReceiveMessageParsed(ASender: TIdCommand;
  var AMsg: TIdMessage; RCPT: TIdEMailAddressList;
  var CustomError: String);
begin
  // This is the main event if you have opted to have the idSMTPServer to do your parsing for you.

  // The AMessage contains the completed TIdMessage.

  // NOTE: Dont forget to add IdMessage to your USES clause!

  ToLabel.Caption := AMsg.Recipients.EMailAddresses;
  FromLabel.Caption := AMsg.From.Text;
  SubjectLabel.Caption := AMsg.Subject;
  Memo1.Lines := AMsg.Body;

  // Implement your file system here :)
end;

Can anybody suggest a reason? First of all, a thankyou to Remy for his response. Second, it seems I can't post images here, yet, but here is a link to images of server-telnet session https://postimg.org/image/f0n9j0kcx/. The telnet session shows the server responses. Thanks also for reminding me about Wireshark, and the suggestion of using a TIdLog component.

1
Welcome to StackOverflow. Please show the actual commands you are sending over Telnet, you are likely missing something.Remy Lebeau
How to I post an image of my Telnet session? Does it go here in a comment, or do I click "Answer your question"?grasshopper
It would be better if you copy/paste the actual commands from your terminal window, instead of post an image. But either way, please edit your question to include the new info, do not post it in an answer or comment.Remy Lebeau

1 Answers

1
votes

It is tricky to know for sure since you did not show the actual SMTP commands you are sending via Telnet, but you are likely missing required commands/data that TIdSMTP sends. To see the actual SMTP commands/responses that are being exchanged, you can use a packet sniffer like Wireshark, or attach one of Indy's TIdLog... components to the TIdSMTP and/or TIdSMTPServer socket connections.

Any email address that is received via a MAIL FROM command and accepted by the server (see the OnCommandMail event) is passed to the OnReceive... events in the TIdSMTPServerThread(ASender.Thread).From property. The server will not accept a RCPT TO command if an email address has not been accepted from MAIL FROM first. If you do not assign an OnCommandMail handler, the server will accept any email address it receives.

Any email addresses that are received via RCPT TO commands and accepted by the server (see the OnCommandRCPT event) are passed to the OnReceive... events in the RCPT parameter, and also in the TIdSMTPServerThread(ASender.Thread).RCPTList property. The server will not accept a DATA command if at least one email address was not accepted from RCPT TO first. If you do not assign an OnCommandRCPT handler, the server will accept every email address it receives.

In the OnReceiveMessage... events, the provided TIdMessage object is first populated from the raw email data that is sent in the DATA command only. In the case of the OnReceiveMessageParsed event only, any email addresses that were previously accepted via RCPT TO are then merged into the TIdMessage.Recipients property if they do not already exist. However, any email address received in the MAIL FROM command is not merged into the TIdMessage.From property.

So, depending on what email data you are actually sending in the DATA command, the AMsg.From property may or may not be empty. But the AMsg.Recipients property certainly should not be.

Also, something else to keep in mind - TIdSMTPServer is multi-threaded (as most Indy servers are). Its events are fired in the context of worker threads, not the main UI thread. Your code is directly accessing VCL UI controls from outside of the main UI thread, which is not safe and can cause all kinds of problems. You must synchronize with the main UI thread, using either the VCL's TThread.Synchronize() or TThread.Queue() methods, or Indy's TIdSync or TIdNotify classes, or any other thread-safe sync mechanism of your choosing, as long as the synced code runs in the context of the main UI thread only.