-4

I'm on Delphi 2007, Indy version 10.6.1.5188.

When I send messages using my regular SMTP server and TIdSMTP, everything works fine.

But when I send using Amazon Simple Email Service SMTP (SES), all special chars in msg body, like á, ç, é are replaced for strange symbols like ¿½ and .

What should I do to fix this issue, and why is it happening only when I use SES?

Here is my current code :

  idsmtp1.Host := 'email-smtp.us-west-2.amazonaws.com';
  idsmtp1.username := 'myusername';
  idsmtp1.password := 'mypassword';
  idsmtp1.Port := 587;
  idsmtp1.IOHandler := IdServerIOHandlerSSLOpenSSL1;
  idsmtp1.usetls := utUseExplicitTLS;
  idsmtp1.UseEhlo := true;
  idmessage1.body.text := 'This is a test é á ó ç';
  with IdServerIOHandlerSSLOpenSSL1 do
      begin
      SSLOptions.Method := sslvTLSv1;
      SSLOptions.VerifyMode := [];
      SSLOptions.VerifyDepth := 0;
      end;
  idsmtp1.Connect;
  idsmtp1.Send(idmessage1);

And here is TIDMessage.savetofile contents :

From: "My Company" <myemail@mydomain.com>
Subject: Your subject
To: xxxx@hotmail.com.br
Bcc: myotheremail@mydomain.com
Content-Type: text/plain; charset=us-ascii
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Sender: My Company <myemail@mydomain.com>
Organization: My Organization
Date: Mon, 18 Nov 2019 09:19:05 -0300

VGhpcyBpcyBhIHRlc3Qgw6kgw6Egw7Mgw6cNCg==
.
delphirules
  • 6,443
  • 17
  • 59
  • 108
  • Kind of hard to tell without any information related to sending the email. You're missing a [mcve] that demonstrates the issue. You're not new here; you should know this before you posted. – Ken White Nov 14 '19 at 01:02
  • 1
    Delphi 2007 is a pre-Unicode version of Delphi. It uses 8bit strings. You need to manually encode your data, such as to UTF-8, and then set the email's `CharSet` to match. Are you doing that? Please show your actual code. – Remy Lebeau Nov 14 '19 at 02:25
  • @RemyLebeau Nothing fancy in the code, is the same of my previous question, but i edited the question now with the code. Could you please tell me how do i set the charset and encode my message body ? – delphirules Nov 14 '19 at 11:20
  • 1
    @delphirules see the answer I just posted – Remy Lebeau Nov 14 '19 at 16:04

1 Answers1

3

Delphi 2007 is a pre-Unicode version of Delphi, where all of the strings used in Indy are AnsiString. As such, you need to manually encode your email text to an 8-bit encoding, such as UTF-8, and then set the email's ContentType and CharSet properties to match, as well as the ContentTransferEncoding property so the UTF-8 bytes can pass through 7-bit email systems without losing data. For example:

IdSMTP1.Host := 'email-smtp.us-west-2.amazonaws.com';
IdSMTP1.Username := 'myusername';
IdSMTP1.Password := 'mypassword';
IdSMTP1.Port := 587;
IdSMTP1.IOHandler := IdServerIOHandlerSSLOpenSSL1;
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSMTP1.UseEhlo := True;

IdMessage1.Body.Text := UTF8Encode('This is a test é á ó ç');

IdMessage1.ContentType := 'text/plain';
IdMessage1.CharSet := 'utf-8';
//alternatively
// IdMessage1.ContentType := 'text/plain; charset=utf-8';

IdMessage1.ContentTransferEncoding := 'base64';

with IdServerIOHandlerSSLOpenSSL1 do
begin
  SSLOptions.Method := sslvTLSv1;
  SSLOptions.VerifyMode := [];
  SSLOptions.VerifyDepth := 0;
end;

IdSMTP1.Connect;
IdSMTP1.Send(IdMessage1);

If you don't do this, then the email ends up being interpretted in other random charsets, such as US-ASCII, Windows-1252, etc which will not give you the results you want.

If you ever upgrade your code to Delphi 2009 or later, where all of the strings used in Indy are UnicodeString, you still need the CharSet assignment, but you can drop the manual UTF8Encode() call:

IdSMTP1.Host := 'email-smtp.us-west-2.amazonaws.com';
IdSMTP1.Username := 'myusername';
IdSMTP1.Password := 'mypassword';
IdSMTP1.Port := 587;
IdSMTP1.IOHandler := IdServerIOHandlerSSLOpenSSL1;
IdSMTP1.UseTLS := utUseExplicitTLS;
IdSMTP1.UseEhlo := True;

IdMessage1.Body.Text := 'This is a test é á ó ç';

IdMessage1.ContentType := 'text/plain';
IdMessage1.CharSet := 'utf-8';
//alternatively
// IdMessage1.ContentType := 'text/plain; charset=utf-8';

IdMessage1.ContentTransferEncoding := 'base64';

with IdServerIOHandlerSSLOpenSSL1 do
begin
  SSLOptions.Method := sslvTLSv1;
  SSLOptions.VerifyMode := [];
  SSLOptions.VerifyDepth := 0;
end;

IdSMTP1.Connect;
IdSMTP1.Send(IdMessage1);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks, i did it, but now the strange chars were replaced by another ones : where should be "ó" is showing "ó", and where should be 'ã', is showing 'ã'... Any hints ? Do i need to do something on idmessageInitializeISO ? – delphirules Nov 14 '19 at 18:16
  • 1
    `ó` in UTF-8 is bytes `C3 B3`, when those bytes are misinterpreted as ISO-8859-1, Windows-1252, etc, the result is `ó`. Likewise, `ã` in UTF-8 is bytes `C3 A3`, which is `ã` when misinterpreted. So you are sending the correct bytes, they are just not being interpreted correctly by the reader. One thing I notice is that you are not setting a `ContentType` for the email. I have updated my answer to add that. As for the `OnInitializeISO` event, that is used only when encoding email *headers*, not when encoding *body text*. – Remy Lebeau Nov 15 '19 at 01:27
  • Tried this, still have the problem... now on gmail accounts, all special chars are replaced by a ? mark. The strange thing is the subject line is reading ok, with the correct special chars... – delphirules Nov 17 '19 at 16:28
  • 1
    @delphirules email headers and body text are encoded differently. You might try setting the `ContentTransferEncoding` property on addition to the `CharSet`. I have updated my answer. – Remy Lebeau Nov 17 '19 at 17:32
  • Thank you, tried this, but still, no luck :( The subject goes ok, but inside the body, 'á' becames 'á'. Anything else i could try ? Does it make difference to set idmessage1.charSet := 'utf-8' or 'UTF-8' ? – delphirules Nov 18 '19 at 00:38
  • I've noticed a weird thing : after i call 'IdMessage1.Body.Text := UTF8Encode('This is a test é á ó ç');', in debug time this is what i see on Delphi's watch for the body's text : 'This is a test é á ó ç' . Is this normal ? – delphirules Nov 18 '19 at 00:41
  • 1
    @delphirules yes, that is normal, because the debugger in D2007 doesn't know anything about UTF-8, only ANSI. And that is what UTF-8 looks like when displayed as ANSI. And no, there is no difference between using `'utf-8'` vs `'UTF-8'` for the `CharSet`. Everything you describe suggests the email IS being encoded in UTF-8, so the problem has to be in the receiving end. Can you call one of the `TIdMessage.SaveTo...()` methods and then edit your question to show the content it produces? – Remy Lebeau Nov 18 '19 at 02:34
  • Note it's say 'charset=us-ascii', but i've set IdMessage.charset to 'utf-8'... is that normal ? – delphirules Nov 18 '19 at 12:50
  • 1
    @delphirules Are you setting the `ContentType` at all, like I showed? If so, are you setting it before or after setting the `CharSet`? In older versions, the `ContentType` has to be set first, otherwise it overwrites the `CharSet`. That was fixed recently. 10.6.1 is a bit old. Otherwise, you can set the charset on the `ContentType` itself, see the update to my answer. – Remy Lebeau Nov 18 '19 at 18:23
  • This did the trick, indeed i was setting Contenttype after Charset ! Thank you very much ! Maybe i should update to the latest version, can i do it in D2007 without having problems with DataSnap ? – delphirules Nov 18 '19 at 18:35
  • Remy, i really would like to thank you for your invaluable help during all these years (more than a decade actually). Everytime i had an issue with Indy components you always was very helpful and kind. I'd like to send some beers (or coffees if you wish) to your paypal account, can i ? :-D – delphirules Nov 18 '19 at 18:42