簡體   English   中英

TIdSMTP:如何發送在 email 正文中正確顯示的特殊字符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM