вторник, 21 августа 2012 г.

Delphi Indy 10 SSL and Encoding Issues


When sending mail through Indy components in Delphi 7 encountered periodically on different issues.
Variants of problems:


  • sending emails from machines that - there are Russian letters in the names
  • email using SSL
  • problems with encoding in the subject and body of the message


I didn't find common solution in internet - only scattered pieces.

All solutions brought here. May be it will be useful for someone (tested on russian charsets)

System configuration:

  • Delphi 7, 
  • Indy components version: 10.5.9.4797 (installed manually by article http://conferences.embarcadero.com/article/32160
    file: Indy10_4798.zip)
  • SSL Library: openssl-1.0.0d-i386-win32.zip
    from http://indy.fulgan.com/SSL/
    (files libeay32.dll and ssleay32.dll are copied to project output directory)

main procedure is - SendEmail
Main pieces of code are commented.

uses
...

IdCoderMIME , IdMessage, IdSMTP,
IdSSLOpenSSL , IdIOHandler, IdAttachmentFile, IdExplicitTLSClientServerBase, idCharSets, idText
...

type

  //-- helper stub-class for TidMessage.OnInitializeISO event  handling
  Tindystub = class(tobject)
  public
    procedure OnInitISO(var VHeaderEncoding: Char; var VCharSet: string);
  end;

procedure Tindystub.OnInitISO(var VHeaderEncoding: Char;
  var VCharSet: string);
begin
  VCharSet := IdCharsetNames[ idcs_UTF_8 ];
end;


procedure SendEmail(
    aSmtpServer: string;
    aSmtpPort: integer;
    aSmtpLogin: string;
    aSmtpPassword: string;
    aFromAddress: string;
    aFromName: string;
    aToAddress: string;
    aMessageSubject: string;
    aMessageText: string;
    aAttachmentFileFullName: string;
    aUseSSL: boolean = false
    );
var
  lMessage : TIDMessage;
  lSMTP    : TIdSMTP;
  attach   : TIdAttachmentFile;
  sslHandler: TIdSSLIOHandlerSocketOpenSSL;
  lindystub: Tindystub;
  idtTextPart: TIdText;
begin
  lMessage:= TIDMessage.Create(nil);
  lSmtp:= TIDSmtp.Create(nil);
  sslHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  lindystub:= Tindystub.Create();
  try
    lSMTP.AuthType:= satDefault;

    lSMTP.Host     := aSmtpServer;   //Хост
    lSMTP.Port     := aSmtpPort;     //Порт (25 - по умолчанию)

    lSMTP.Username := aSmtpLogin;
    lSMTP.Password := aSmtpPassword;

    //-- solving "non-english computer name" problem
    lSMTP.HeloName := 'tfo';

    //-- using SSL
    if (aUseSSL) then
    begin
      SSLHandler.Destination := aSmtpServer+':'+IntToStr(aSmtpPort);
      SSLHandler.Host := aSmtpServer;
      SSLHandler.Port := aSmtpPort;
      SSLHandler.DefaultPort := 0;
      SSLHandler.SSLOptions.Method := sslvSSLv23;
      SSLHandler.SSLOptions.Mode := sslmUnassigned;
      lSMTP.IOHandler := SSLHandler;
      lSMTP.UseTLS := utUseImplicitTLS;
    end;

    //-- subject encoding
    lMessage.OnInitializeISO := lindystub.OnInitISO;

    lMessage.Subject      := aMessageSubject;
    lMessage.From.Address := aFromAddress;
    lMessage.From.Name    := aFromName;
    lMessage.Recipients.EMailAddresses:= aToAddress;

    //-- message body encoding
    idtTextPart := TIdText.Create(lMessage.MessageParts, nil);
    idtTextPart.ContentType := 'text/plain';
    idtTextPart.CharSet := 'Windows-1251';

    idtTextPart.Body.Text:= aMessageText;

    //-- work with attached files
    if (aAttachmentFileFullName <> '') then
    begin
      attach:=TIdAttachmentFile.Create(lMessage.MessageParts, aAttachmentFileFullName); //Вложение
    end;

    //-- sending email
    lSMTP.Connect;
    try
      lSMTP.Send(lMessage);
    finally
      lSMTP.Disconnect;
    end;

  finally
    sslHandler.Free;
    lMessage.Free;
    lSmtp.Free;
    lindystub.Free;
  end;
end;

1 комментарий: