Caves Travel Diving Graphics Mizar Texts Cuisine Lemkov Contact Map RSS Polski
Trybiks' Dive Texts TIdMessage's CharSet YAC Software
  Back

List

Intraweb and MaxConnections

A Case for FreeAndNIL

Intraweb as an Apache DSO module

"Device not supported" in Intraweb

Automated GUI Testing

Fix for Highslide HTML Slides

Random()'s Determinism

Rounding and precision on the 8087 FPU

Clicking on links in JavaScript

PHP's mail()

File | Save Atavism

SessionTimeout in Intraweb

Using TChart with Intraweb

Unknown driver: MySQL

Automated GUI Testing in VMs

TIdMessage's CharSet

Product Peer Reviews - Introduction

Software Guarantees

Automated Testing of Window Forms

TChart - Missing Labels in Axes

Calculating Positions of HTML Elements

Memory Leaks and Connection Explosions in DBExpress

CSS for Scrollbars on Pages and in Frames

Controlling Conditional Defines and Compilation Switches

Turning Browser Caching off when Displaying Images Using PHP

Detecting Memory Leaks with DUnit

last_insert_id() and DBExpress

YAC Data Language

Registering Extensions

DBExpress and Thread Safety

Forms as Frames

Checking Dangling Pointers vs. the New Memory Manager

</form> ... <form>

Accessing Protected Members

TIdMessage's CharSet
Recently I had to send some e-mails automatically using Delphi (no SPAM, mind you). Obviously, I turned to the Indy components distributed by default with RAD Studio.

The problem was that I needed to encode those e-mails using ISO-8859-2. I thought that setting the CharSet property would be enough, just run the application and everything should work nicely...

Well, no, not entirely... Actually, not at all. This is how the message source looks like - in this message the subject and body include all Polish diacritic characters (the question marks at the bottom constitute the e-mail's body):
  From: ...
  Subject:
  =?ISO-8859-1?Q?=B1=E6=EA=B3=F1=F3=B6=BC=BF=A1=C6=CA=A3=D1=D3=A6=AC=AF?=
  To: ...
  Date: ...
  Message-Id: ...
  
  ????????????
So, here's one solution: forget about the CharSet property, just set ContentType appropriately, for instance:
  LMessage := TIdMessage.Create(NIL);
  LMessage.ContentType := 'text/plain; charset=ISO-8859-2';
If you don't set ContentType, the message body may appear fine in Outlook, but will still be garbled when viewing it under Thunderbird.

Another approach is to set two properties: Encoding and CharSet.
  LMessage := TIdMessage.Create(NIL);
  LMessage.CharSet := 'ISO-8859-2';
  LMessage.Encoding := meMIME;
When the encoding is set to MIME, then the character set set in CharSet is added to the header (but only with that encoding; doesn't work with mePlainText, for instance).

Both approaches above work, except that... the subject line is not encoded using the specified character set:
  From: ...
  Subject:
  =?ISO-8859-1?Q?=B1=E6=EA=B3=F1=F3=B6=BC=BF=A1=C6=CA=A3=D1=D3=A6=AC=AF?=
  To: ...
  Content-Type: text/plain; charset=ISO-8859-2
  Date: ...
  Message-Id: ...
  
  acelnoszzACELNOSZZ
This is, unfortunately, a bit more complicated.

TIdMessage has an additional procedural property: OnInitializeISO. You need to set this property to something like the code below. This procedure must be an "of object" kind - that is, it must be defined inside a class. One way is to subclass TIdMessage and define the procedure there. Another way is to assign a procedure defined in another class (such as defining the handler as a method of a form when the TIdMessage component is placed on that form - see the comment below). The way you assign this handler is not that relevant here - the code inside the handler is:
  TMyMessage = class(TIdMessage)
  private
    procedure InitializeISO88592(
      var VTransferHeader: TTransfer; var VHeaderEncoding: char; var VCharSet: string);
  end;
  
  procedure TMyMessage.InitializeISO88592(
    var VTransferHeader: TTransfer; var VHeaderEncoding: char; var VCharSet: string);
  begin
    VCharSet := 'ISO-8859-2';
  end;
And then:
  LMessage := TMyMessage.Create(NIL);
  LMessage.ContentType := 'text/plain; charset=ISO-8859-2';
  LMessage.OnInitializeISO := LMessage.InitializeISO88592;
Wow, finally the message's subject and body are both encoded using the correct character set:
  From: ...
  Subject:
  =?ISO-8859-2?Q?=B1=E6=EA=B3=F1=F3=B6=BC=BF=A1=C6=CA=A3=D1=D3=A6=AC=AF?=
  To: ...
  Content-Type: text/plain; charset=ISO-8859-2
  Date: ...
  Message-Id: ...
  
  acelnoszzACELNOSZZ
HTH

Top

Comments
#1
Dalis wrote on 2009-12-16 09:41:45
Thank you very much. This code help me with my problem.
#2
1 wrote on 2010-03-15 08:47:57
Component IdMessage -> Events -> OnInitializeISO

procedure TMainFrm.IdMessageInitializeISO(var VHeaderEncoding: Char;
var VCharSet: String);
begin
VCharSet := \'ISO-8859-2\';
end;

Top

Add a comment (fields with an asterisk are required)
Name / nick *
Mail (will remain hidden) *
Your website
Comment (no tags) *
Enter the text displayed below *
 

Top