TIdSMTP:如何发送在电子邮件正文中正确显示的特殊字符

TIdSMTP : How to send special chars showing correctly in email body

我在 Delphi 2007,Indy 版本 10.6.1.5188。

当我使用常规 SMTP 服务器和 TIdSMTP 发送邮件时,一切正常。

但是当我使用 Amazon Simple Email Service SMTP (SES) 发送时,消息正文中的所有特殊字符,如 áçé 都被替换为奇怪的符号,如¿½.

我应该怎么做才能解决这个问题,为什么只有在我使用 SES 时才会发生?

这是我当前的代码:

  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);

这是TIDMessage.savetofile内容:

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==
.

Delphi 2007 是 Delphi 的 pre-Unicode 版本,其中 Indy 中使用的所有字符串都是 AnsiString。因此,您需要手动将电子邮件文本编码为 8 位编码,例如 UTF-8,然后将电子邮件的 ContentTypeCharSet 属性设置为匹配,以及 ContentTransferEncoding 属性 因此 UTF-8 字节可以通过 7 位电子邮件系统而不会丢失数据。例如:

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);

如果您不这样做,那么电子邮件最终会被解释为其他随机字符集,例如 US-ASCII、Windows-1252 等,这不会给您想要的结果。

如果您将代码升级到 Delphi 2009 或更高版本,Indy 中使用的所有字符串都是 UnicodeString,您仍然需要 CharSet 分配,但您可以删除手册 UTF8Encode() 调用:

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);