Not able to send UTF-8 email using delphi indy

ETL Man picture ETL Man · Mar 23, 2012 · Viewed 9.4k times · Source

Here is my code

Email body has got some unicode characters

  LSMTP := TIdSMTP.Create(nil);
  try
    LMsg := TIdMessage.Create(LSMTP);
    try
      with LMsg do
      begin
        Subject := Subj;
        Recipients.EMailAddresses := Email;    
        WriteToLog(cInformation,'To: '+Recipients.EMailAddresses);    
        From.Address := ReplaceVariables(From_Address);    
        From.Name    := ReplaceVariables(From_Name);    
        Body.Text    := EmailMessage;    
        ContentTransferEncoding := '8bit';    
        CharSet := 'UTF-8';    
        ContentType := 'text/plain';    
     end;

And this is what I get

Content-Type: text/plain; charset=us-ascii <<<<< WRONG
Content-Transfer-Encoding: 8bit
Date: Fri, 23 Mar 2012 17:53:19 +0000

Using delphi 2009

Answer

Remy Lebeau picture Remy Lebeau · Mar 23, 2012

That is by design. When the ContentType property is being set, the property setter may update the CharSet property with a default value if the input does not explicitally specify a charset. Certain content types, especially in the text/ realm, have specific charset defaults dictated in various RFCs. Indy tries to follow those rules as best it can. As such, you need to set the CharSet property to your intended value after you have set the ContentType property, as you already discovered:

//LMsg.CharSet := 'UTF-8';
LMsg.ContentType := 'text/plain';
LMsg.CharSet := 'UTF-8';

You can also do this instead:

LMsg.ContentType := 'text/plain; charset=UTF-8';

UPDATE: as of July 23 2019, ContentType property setters now preserve the corresponding CharSet property value if it is already set and a charset is not specified in the new ContentType value. So, the order in which paired ContentType+CharSet properties are set is no longer an issue.