[英]TIdSMTP : How to send special chars showing correctly in email body
我在 Delphi 2007,Indy 版本 10.6.1.5188。
當我使用我的常規 SMTP 服務器和TIdSMTP
發送消息時,一切正常。
但是,當我使用 Amazon Simple Email 服務 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
。 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 系統不會丟失數據。 例如:
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);
如果您不這樣做,那么 email 最終會被解釋為其他隨機字符集,例如 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);
我自己也遇到了這個問題,這是我用來確保 email 內容正確 UTF8 編碼的 function:
procedure SendEmailIndy(
const SMTPServer: string;
const SMTPPort: integer;
const SMTPUserName : string;
const SMTPPassword : string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma "," separated list of e-mail addresses
const CCAddresses: string; //comma "," separated list of e-mail addresses
const BCCAddresses: string; //comma "," separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean; //verses Plain Text
const Attachments: TStrings;
UseTLS : Boolean);
var
smtp: TIdSMTP; // IdSmtp.pas
TLSHandler : TIdSSLIOHandlerSocketOpenSSL; // TLS support
msg: TidMessage; // IdMessage.pas
builder: TIdCustomMessageBuilder; //IdMessageBuilder.pas
s: string;
emailAddress: string;
begin
{
Sample usage:
SendEmailIndy(
'smtp.stackoverflow.com', //the SMTP server address
'Spammy McSpamerson', 'spams@example.com', //From name, from e-mail address
'joe@foo.net, jane@bar.net', //To addresses - comma separated
'john@doe.net', //CC addresses - comma separated
'', //BCC addresses - comma separated
'Here is your sample spam e-mail', //Subject
'<!DOCTYPE html><html><body>Hello, world!</body></html>', //html body
True, //the body is HTML (as opposed to plaintext)
nil); //attachments
}
TLSHandler := nil;
msg := TidMessage.Create(nil);
try
if IsBodyHtml then
begin
builder := TIdMessageBuilderHtml.Create;
TIdMessageBuilderHtml(builder).Html.Text := DecodeTextTags(eMailBody,True);
end
else
begin
builder := TIdMessageBuilderPlain.Create;
end;
try
Try
if Attachments <> nil then for s in Attachments do builder.Attachments.Add(s);
builder.FillMessage(msg);
Except
on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry('eMail_'+debugFileExceptions,'Exception : '+E.Message+CRLF+CRLF+'To:'+ToAddresses+CRLF+CRLF+'Content:'+CRLF+eMailBody){$ENDIF};
End;
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
//If the message is plaintext then we must fill the body outside of the PlainText email builder.
//(the PlainTextBuilder is unable to build plaintext e-mail)
if not IsBodyHtml then msg.Body.Text := DecodeTextTags(eMailBody,True);
msg.ContentType := 'text/html';
msg.CharSet := 'UTF-8';
msg.ContentTransferEncoding := '8bit';
//msg.Encoding :=
for s in ToAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
begin
with msg.recipients.Add do
begin
//Name := '<Name of recipient>';
Address := emailAddress;
end;
end;
end;
for s in CCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then msg.CCList.Add.Address := emailAddress;
end;
for s in BCCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then msg.BccList.Add.Address := emailAddress;
end;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer;
smtp.Port := SMTPPort;
smtp.Username := SMTPUserName;
smtp.Password := SMTPPassword;
If UseTLS = True then
Begin
TLSHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
smtp.IOHandler := TLSHandler;
smtp.UseTLS := TIdUseTLS.utUseRequireTLS;
End;
Try
smtp.Connect;
try
try
smtp.Send(msg)
Except
on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry('eMail_'+debugFileExceptions,'SMTP Send Exception : '+E.Message+CRLF+CRLF+'To:'+ToAddresses){$ENDIF};
End;
finally
smtp.Disconnect;
end;
Except
on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry('eMail_'+debugFileExceptions,'SMTP Connect Exception : '+E.Message+CRLF+CRLF+'To:'+ToAddresses){$ENDIF};
End;
finally
smtp.Free;
If TLSHandler <> nil then TLSHandler.Free;
end;
finally
msg.Free;
end;
end;
完全歸功於這里的人和 delphi 實踐,這是 function 的基礎。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.