Search code examples
delphiindy

Delphi 2007/Indy10 SMTP client : sends ??????? not Greek characters


I use TidSMTP component with Delphi 2007 to send eMails in Greek language with the following code

with IdMsg do begin
    clear;
    contentType := 'multipart/mixed';
    Charset := 'GREEK_CHARSET';
    with TidText.Create(MessageParts) do begin
        ContentType := 'text/plain';
        Charset := 'GREEK_CHARSET';
        Body.Text := Memo1.Text; // memo1 has text in Greek language
    end;
    if Edit1.Text = '' then From.name := some text in Greek language
    else From.name := Edit1.Text;
    if Edit2.Text = '' then From.Address := 'myEmail@asdf.gr'
    else From.Address := Edit2.Text; // has text in Greek language
    Recipients.EMailAddresses := an eMail address;
    
    if edit10.Text = '' then subject := some text in Greek language
                        else Subject := edit10.Text;// has text in Greek language
    .....
    IdSMTP1.Connect;
    IdSMTP1.Send(IdMsg);
    .....

On the recipient side the name and subject text looks like "???????" but the body text is in Greek as expected. Why is this difference and how can I fix it?


Solution

  • GREEK_CHARSET is not a valid charset name. The standard charset for Greek is ISO-8859-7, and there is also the Windows-1253 codepage on Windows.

    The reason why Greek is not working in the email headers, but is working in the email body, is because you are specifying a Greek charset for the body but not for the headers. You are using a pre-Unicode 1 version of Delphi where string is AnsiString, and you have Greek-encoded AnsiStrings in the body which are being sent with a Greek charset specified in the TIdText.Charset property (the TIdMessage.Charset property doesn't apply for multipart emails). So everything matches up. That is not the case with the email headers.

    • 1: Delphi switched to full Unicode (ie string is UnicodeString) in Delphi 2009.

    To send non-ASCII characters in email headers, they must be encoded using the rules of RFC 2047. You can use the TIdMessage.OnInitializeISO event to specify a HeaderEncoding ('Q' for quoted-printable, 'B' for base64, or '8' for raw) and CharSet for Indy's RFC 2047 encoder to use. On a Greek machine using a pre-Unicode Delphi, TIdMessage will default to using 'Q' and 'ISO-8859-1', respectively 2. But, ISO-8859-1 can't handle Greek characters, hence the ? characters.

    • 2: on a Unicode-enabled Delphi, TIdMessage will default to 'B' and 'UTF-8', respectively, for most languages including Greek (for Chinese, Japanese, Korean, Russian, and Ukrainian, it will use other defaults).

    Try this:

    // TIdMessage.OnInitializeISO event handler
    procedure TMyForm.IdMsgInitializeISO(
      var VHeaderEncoding: Char; var VCharSet: string);
    begin
      VHeaderEncoding := 'Q';
      VCharSet := 'ISO-8859-7'; // or 'Windows-1253'
    end;
    
    ...
    
    with IdMsg do begin
      Clear;
      ContentType := 'multipart/mixed';
      with TIdText.Create(MessageParts) do begin
        ContentType := 'text/plain';
        Charset := 'ISO-8859-7'; // or 'Windows-1253'
        Body.Text := Memo1.Text;
      end;
      ...
    end;
    

    That begin said, I really suggest that you use UTF-8 instead of Greek, eg:

    procedure TMyForm.IdMsgInitializeISO(
      var VHeaderEncoding: Char; var VCharSet: string);
    begin
      VHeaderEncoding := 'B';
      VCharSet := 'UTF-8';
    end;
    
    ...
    
    with IdMsg do begin
      Clear;
      ContentType := 'multipart/mixed';
      with TIdText.Create(MessageParts) do begin
        ContentType := 'text/plain';
        Charset := 'UTF-8';
        Body.Text := UTF8Encode(Memo1.Text); // UTF8Encode() not needed in D2009+
      end;
      ...
    end;