3
votes

following code is what i modified(to work with 10.5.8) form the sample in order to send email independently using the smtp client described in Indy Mail server

following is from INDY smtpserver sample

procedure TForm1.btnServerOnClick(Sender: TObject);
 begin

 IdSMTPServer1.active := true;
end;

procedure TForm1.btnServerOffClick(Sender: TObject);
begin

 IdSMTPServer1.active := false;
end;

procedure TForm1.IdSMTPServer1MailFrom(ASender: TIdSMTPServerContext;
  const AAddress: string; AParams: TStrings; var VAction: TIdMailFromReply);
begin
// Here we are testing the MAIL FROM line sent to the server.
 // MAIL FROM address comes in via AAddress. VAction sets the return action to the server.

 // The following actions can be returned to the server:
 { mAccept, mReject }

 // For now, we will just always allow the mail from address.
 VAction := mAccept;
end;

procedure TForm1.IdSMTPServer1MsgReceive(ASender: TIdSMTPServerContext;
  AMsg: TStream; var LAction: TIdDataReply);
var
 LMsg : TIdMessage;
 LStream : TFileStream;
begin
// When a message is received by the server, this event fires.
// The message data is made available in the AMsg : TStream.
// In this example, we will save it to a temporary file, and the load it using
// IdMessage and parse some header elements.

LStream := TFileStream.Create(ExtractFilePath(Application.exename) + 'test.eml', fmCreate);
Try
 LStream.CopyFrom(AMsg, 0);
Finally
 FreeAndNil(LStream);
End;

LMsg := TIdMessage.Create;
Try
 LMsg.LoadFromFile(ExtractFilePath(Application.exename) + 'test.eml', False);
 ToLabel.Caption := LMsg.Recipients.EMailAddresses;
 FromLabel.Caption := LMsg.From.Text;
 SubjectLabel.Caption := LMsg.Subject;
 Memo1.Lines := LMsg.Body;
Finally
 FreeAndNil(LMsg);
End;

end;


procedure TForm1.IdSMTPServer1UserLogin(ASender: TIdSMTPServerContext;
  const AUsername, APassword: String; var VAuthenticated: Boolean);
begin
 // This event is fired if a user attempts to login to the server
 // Normally used to grant relay access to specific users etc.
 VAuthenticated := True;
end;



procedure TForm1.IdSMTPServer1RcptTo(ASender: TIdSMTPServerContext;
  const AAddress: string; AParams: TStrings; var VAction: TIdRCPToReply;
  var VForward: string);
begin
   VAction := rAddressOk;    
end;

procedure TForm1.IdSMTPServer1Received(ASender: TIdSMTPServerContext;
  var AReceived: string);
begin
//
end;

what do i have to add to this project to work as email sending server.

I haven't done many changes to the original sample(only for compatibility) as i can't understand most of the concepts behind how email is sent and received. please explain me how to make this code to send email to the destination(eg: [email protected]) given in this question Indy Mail server (smtpclient),

1
I do not understand what you are asking for exactly. Please clearify your question.Remy Lebeau
thanks i have updated please see the last paragraph ; you said "If that delivery is not working, then you are not storing/forwarding the data correctly, so please show the code that stored and retreives the data" in the privious post , That is itVibeeshanRC

1 Answers

5
votes

To pass the email on to another system (Gmail in this case), use the TIdSMTPRelay component, eg:

procedure TForm1.IdSMTPServer1RcptTo(ASender: TIdSMTPServerContext;                
  const AAddress: string; AParams: TStrings; var VAction: TIdRCPToReply;                
  var VForward: string);                
begin                
  if (AAddress represents a user in your network) then
    VAction := rAddressOk
  else if (AAddress is outside of your network) then
    VAction := rWillForward;                    
end;

procedure TForm1.IdSMTPServer1MsgReceive(ASender: TIdSMTPServerContext; AMsg: TStream; var LAction: TIdDataReply); 
var 
  LMsg : TIdMessage; 
  LMsgClient: TIdMessageClient;
  LStream : TFileStream; 
  LRelayRecipients: TIdEMailAddressList;
  LRelay: TIdSMTPRelay;
  I: Integer;
begin 
  // When a message is received by the server, this event fires. 
  // The message data is made available in the AMsg : TStream. 
  // In this example, we will save it to a temporary file, and load it using 
  // IdMessage to parse some header elements. 

  LStream := TFileStream.Create(ExtractFilePath(Application.exename) + 'test.eml', fmCreate); 
  Try 
    LStream.CopyFrom(AMsg, 0); 
  Finally 
    LStream.Free; 
  End; 
  AMsg.Position := 0;

  LMsg := TIdMessage.Create; 
  Try 
    //LMsg.LoadFromFile(ExtractFilePath(Application.exename) + 'test.eml', False); 

    // Do not use the TIdMessage.LoadFrom...() methods here! The email
    // data contained in the AMsg stream does not escape leading periods
    // on lines of text. That escaping is only used when the email was
    // transmitted over the socket, as a period character has special
    // meaning to the SMTP protocol.  TIdSMTPServer removes the escaping
    // from the data before firing this event. However, the LoadFrom...()
    // methods (which uses TIdMessageClient internally) require the
    // data to be escaped!  This is a known limitation in Indy's core
    // architecture and will be addressed in Indy 11.  Until then,
    // use TIdMessageClient manually so the necessary escaping can be
    // re-introduced into the data while it is being parsed...

    LMsgClient := TIdMessageClient.Create(nil);
    try
      LMsgClient.IOHandler := TIdIOHandlerStreamMsg.Create(LMsgClient, AMsg);
      with TIdIOHandlerStreamMsg(LMsgClient.IOHandler) do
      begin
        FreeStreams := False;
        EscapeLines := True;
      end;
      LMsgClient.IOHandler.Open;
      LMsgClient.ProcessMessage(LMsg, False);
    finally
      LMsgClient.Free;
    end;

    // process LMsg as needed...

    // save the email for local users and forward it to other SMTP servers as needed...

    LRelayRecipients := nil;
    try
      for I := 0 to ASender.RCPTList.Count-1 do
      begin
        if (ASender.RCPTList[I] represents a user in your network) then
        begin
          // save AMsg in the user's mailbox somewhere on the local
          // machine/network where an POP3/IMAP4 client can retreive
          // it from later...
        end else
        begin
          if not Assigned(LRelayRecipients) then LRelayRecipients := TIdEMailAddressList.Create(nil);
          LRelayRecipients.Add.Assign(ASender.RCPTList[I]);
        end;
      end;

      if Assigned(LRelayRecipients) then
      begin
        LRelay := TIdSMTPRelay.Create(nil);
        try
          // you must supply the IP/Host of a DNS server that
          // will be used for determining the SMTP server of
          // each recipient domain...
          LRelay.DNSServer := ...;

          LRelay.Send(LMsg, LRelayRecipients);
        finally
          LRelay.Free;
        end;
      end;
    finally
      LRelayRecipients.Free;
    end;

  Finally 
    LMsg.Free; 
  End; 
end;