Slow emailing with Indy

86 Views Asked by At

After upgrade from Delphi 10.4 to 11.3 I got a strange problem with attachments in emails. Send email from file directly from server where exe-file is running is fast Send two attachments of 300 KB takes about 10 minutes where the files is located on a networkshare. My first thought was slow network. It was measured about 20 MB per second. Not so fast but 300 KB should take seconds not minutes to send.

My application is not responding during this time as it happen in main thread. So this is a huge problem. Taskmanager show only low CPU usage so obviously it is waiting on something.

Here is the method that send email. Please review and comment for any suspicious code. Note that CreateBoldHelper is an internal method that use an interface (vHelp) to release memory for the parameters. The idea is that I don't need the traditional try/finally for this. What about TIdMessageBuilderHtml ? Html is not used only plain text. Is there any better ways to send plan text with attachments with Indy ?

class function TATMail.SendMail(const aReceiver, aSender, aReplyTo, aCc,
    aSubject, aBody, aAttachments: string; out aOutMessage: string): Boolean;
var
  smtp: TIdSMTP;                 
  msg: TidMessage;               
  builder: TIdMessageBuilderHtml;
  i: Integer;
  vStrList: TStringList;
  vUserName, vPassword: String;
  vHelp: IBoldHelper;
begin
  Result := False;
  vHelp := CreateBoldHelper(vStrList, smtp, msg, builder);
  vStrList := TStringList.Create;
  msg := TIdMessage.Create(nil);

  builder := TIdMessageBuilderHtml.Create;
  builder.PlainText.Text := aBody;
  builder.PlainTextCharSet := cnUTF8;

  if aAttachments <> '' then
  begin
    vStrList.CommaText := aAttachments;

    for i := 0 to vStrList.Count - 1 do
      if FileExists(vStrList[i]) then
        builder.Attachments.Add(vStrList[i]);
  end;
  builder.FillMessage(msg);

  msg.From.Name := aSender;
  msg.From.Address := aReplyTo;
  msg.Subject := aSubject;
  msg.Recipients.EMailAddresses := aReceiver;
  if Pos('@', aCc) > 0 then
    msg.CCList.EMailAddresses := aCc;

  smtp := TIdSMTP.Create(nil);
  try
    smtp.Host := GetSystemConfig.SMTPHost;
    // smtp.UseTLS := utNoTLSSupport;
    smtp.Port := GetSystemConfig.Port;
    vUserName := GetSystemConfig.UserName;
    vPassword := GetSystemConfig.PassWord;
    if (vUserName <> '') and (vPassword <> '') then
    begin
      smtp.Username := vUserName;
      smtp.Password := vPassword;
      smtp.AuthType := satDefault;
    end
    else
      smtp.AuthType := satNone;

    smtp.Connect;
    try
      smtp.Send(msg);
      aOutMessage := 'Mail sent to ' + aReceiver +'.';
      Result := true;
    finally
      smtp.Disconnect;
    end;
  except
    on E: Exception do  // Do not raise exception again. Only show errormessage for user
      aOutMessage := Format('%s. Mail couldn''t be sent to %s.', [E.Message, aReceiver]);
  end;
end;
1

There are 1 best solutions below

0
Roland Bengtsson On

Just want to say that copy attachements to a fast folder like local one before send email was much faster