Atozed Forums

Full Version: How I can decode TIdMessage from koi8-r to windows-1251?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I use Embarcadero C++Builder 10.2 Tokyo with Indy 10.
The task is to check emails via POP3. I can get emails, but I don't know how to decode their subjects, attachment file name, etc from koi8-r to windows-1251 or UTF-8.
Can anybody help me?


Code:
Return-path: <babichev@meccanosoft.com>
     Envelope-to: ear@meccanosoft.com
     Delivery-date: Thu, 12 Jul 2018 14:00:33 +0300
     Received: from [213.79.95.226] (helo=pccomerc)
     by server120.hosting.reg.ru with esmtpa (Exim 4.90_1)
     (envelope-from <babichev@meccanosoft.com>)
     id 1fdZKr-0002FS-1c
     for ear@meccanosoft.com; Thu, 12 Jul 2018 14:00:33 +0300
     From: =?KOI8-R?B?4sHCyd7F1yDzxdLHxco=?= <babichev@meccanosoft.com>
     To: ear@meccanosoft.com
     Subject: test8
     Date: Thu, 12 Jul 2018 14:00:29 +0300
     Message-Id: <006901d419cf$8e2aeed0$aa80cc70$@meccanosoft.com>
     MIME-Version: 1.0
     Content-Type: multipart/mixed; boundary="UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g"
     X-Mailer: Microsoft Outlook 16.0
     Thread-Index: AdQZz4RBq8MEckA1Rq6W+ide2hSKlw==
     Content-Language: ru
     In-Reply-To: <006901d419cf$8e2aeed0$aa80cc70$@meccanosoft.com>

     This is a multipart message in MIME format.

     --UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g
     Content-Type: multipart/alternative;
     boundary="jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB"

     --jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB
     Content-Type: text/plain; charset="koi8-r"
     Content-Transfer-Encoding: 7bit
     Content-Disposition: inline

     TEST8


     --jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB
     Content-Type: text/html; charset="koi8-r"
     Content-Transfer-Encoding: quoted-printable
     Content-Disposition: inline

     <html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas=
     -microsoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:off=
     ice:word" xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml"=
     xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta http-equiv=3DCo=
     ntent-Type content=3D"text/html; charset=3Dkoi8-r"><meta name=3DGenera=
     tor content=3D"Microsoft Word 15 (filtered medium)"><style><!--
     /* Font Definitions */
     @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
     @font-face
      {font-family:Calibri;
      panose-1:2 15 5 2 2 2 4 3 2 4;}
    /* Style Definitions */
    p.MsoNormal, li.MsoNormal, div.MsoNormal
      {margin:0cm;
      margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
     a:link, span.MsoHyperlink
    {mso-style-priority:99;
    color:#0563C1;
    text-decoration:underline;}
    a:visited, span.MsoHyperlinkFollowed
    {mso-style-priority:99;
    color:#954F72;
    text-decoration:underline;}
    span.EmailStyle17
    {mso-style-type:personal-compose;
    font-family:"Calibri",sans-serif;
    color:windowtext;}
     =2EMsoChpDefault
      {mso-style-type:export-only;
      font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
    @page WordSection1
    {size:612.0pt 792.0pt;
    margin:2.0cm 42.5pt 2.0cm 3.0cm;}
    div.WordSection1
    {page:WordSection1;}
     --></style><!--[if gte mso 9]><xml>
    <o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
    </xml><![endif]--><!--[if gte mso 9]><xml>
    <o:shapelayout v:ext=3D"edit">
    <o:idmap v:ext=3D"edit" data=3D"1" />
    </o:shapelayout></xml><![endif]--></head><body lang=3DRU link=3D"#0563=
    C1" vlink=3D"#954F72"><div class=3DWordSection1><p class=3DMsoNormal><=
    span lang=3DEN-US>TEST8<o:p></o:p></span></p></div></body></html>

    --jEgWjeMCC35bF=_m8mr8EoHknZfRtWVKzB--

    --UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g
    Content-Type: text/plain;
    name="=?KOI8-R?B?0M/e1MExLnR4dA==?="
    Content-Transfer-Encoding: quoted-printable
    Content-Disposition: attachment;
    filename="=?KOI8-R?B?0M/e1MExLnR4dA==?="
    ................................................
    --UMwhv1yjwbAJnDKFK8wyCH0CYSe2=_553g--
`
The problem is solved!
Maybe it will be useful for somebody.
Need to add
#include <IdHeaderCoderPlain.hpp>

to the form header.
Excuse me, but this is not solved completely. #include <IdHeaderCoderPlain.hpp> works fine in test. But in main project it no action.

The problem was found by debugger trace into Indy sources.  In IdHeaderCoderList.pas:

Code:
function TIdHeaderCoderList.ByCharSet(const ACharSet: string): TIdHeaderCoderClass;
var
  I: Integer;
  LCoder: TIdHeaderCoderClass;
begin
  Result := nil;
  // loop backwards so that user-defined coders can override native coders
  for I := Count-1 downto 0 do begin
    LCoder := TIdHeaderCoderClass(Items[I]);
    if LCoder.CanHandle(ACharSet) then begin
      Result := LCoder;
      Exit;
    end;
  end;
end;

Indy selects a coder that will decode a header's string.

In my test application coders are loaded in order:

TIdHeaderCoderPlain
TIdHeaderCoderIndy
TIdHeaderCoder2022JP

The letter's headers encoded in KOI-8R.

So, when TIdHeaderCoderList.ByCharSet is called, first from end is TIdHeaderCoder2022JP.  Its CanHandle returns "false" and next is TIdHeaderCoderIndy. Its CanHandle returns "true" and message decodes by TIdHeaderCoderIndy fine.

When I use this in my main project order of coders is other:

TIdHeaderCoderIndy
TIdHeaderCoder2022JP
TIdHeaderCoderPlain

First from end is TIdHeaderCoderPlain. It returns "true" and message is not decoded and unreadable. TIdHeaderCoderIndy not used.

What can I do?

Indy 10.2.6
(08-30-2018, 12:44 PM)SergJP Wrote: [ -> ]In my test application coders are loaded in order:

TIdHeaderCoderPlain
TIdHeaderCoderIndy
TIdHeaderCoder2022JP

...

When I use this in my main project order of coders is other:

TIdHeaderCoderIndy
TIdHeaderCoder2022JP
TIdHeaderCoderPlain

Known issue for C++.

If you use only #include <IdAllHeaderCoders.hpp>, rather than #include'ing individual IdHeaderCoderXXX.hpp files, Indy registers the coder classes in this order:

TIdHeaderCoderPlain
TIdHeaderCoder2022JP
TIdHeaderCoderIndy

(08-30-2018, 12:44 PM)SergJP Wrote: [ -> ]What can I do?

Make sure #include <IdHeaderCoderIndy.hpp> is the last header seen by the compiler.  Or use only #include <IdAllHeaderCoders.hpp> instead.  Or manually unregister and re-register the coder classes in the desired order at runtime using the UnregisterHeaderCoder() and RegisterHeaderCoder() functions declared in IdHeaderCoderBase.hpp.

Also, do note that the entire header coder system is slated to be removed in a future version of Indy (it is already removed in my dev copy), so this won't be an issue for much longer:

#44 Remove IdHeaderCoder sub-system
Remy, thanks for advice.

Quote:Make sure #include <IdHeaderCoderIndy.hpp> is the last header seen by the compiler.

In main project it is impossible, includes are a lot.

Quote:Or use only #include <IdAllHeaderCoders.hpp> instead.

No effect both test and main project.

Quote:Or manually unregister and re-register the coder classes in the desired order at runtime using the UnregisterHeaderCoder() and RegisterHeaderCoder() functions declared in IdHeaderCoderBase.hpp.

Seems it's the best idea.
Couldn't you give an example how to call them from C++ builder?

Regars,  Sergey
(08-31-2018, 11:00 AM)SergJP Wrote: [ -> ]Couldn't you give an example how to call them from C++ builder?

Like this:

Code:
#include <IdHeaderCoderBase.hpp>
#include <IdHeaderCoderIndy.hpp>

__fastcall TMainForm::TMainForm(TComponent *Owner)
    : TForm(Owner)
{
    // make sure TIdHeaderCoderIndy is at the end of the list...
    UnregisterHeaderCoder(__classid(TIdHeaderCoderIndy));
    RegisterHeaderCoder(__classid(TIdHeaderCoderIndy));
}
Remy, thanks a lot!
All works fine.