Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Dekodieren eines Mail-Betreffs (https://www.delphipraxis.net/207365-dekodieren-eines-mail-betreffs.html)

Bbommel 17. Mär 2021 13:36

Dekodieren eines Mail-Betreffs
 
Hallo alle,

im Rahmen eines Projekts möchte ich Mails von einem Server abrufen und automatisch auswerten. Erste Versuche klappen soweit mit den Indys und konkret mit TidIMAP4 auch problemlos. Ich stolpere gerade nur über einen Klassiker, nämlich den kodierten Betreff einer Mail, sobald Umlaute oder andere Nicht-Ascii-Zeichen vorkommen. Also etwa:

'=?utf-8?Q?Re:_Frage_zur_Kapazit=C3=A4tsplanung?='

Der Betreff ist hier eigentlich "Re: Frage zur Kapazitätsplanung".

Nun habe ich verstanden, was ich im Wesentlichen tun muss, um das selbst auswerten zu können. Aber mich wundert, dass es da "nix fertiges" gibt, weil es ja doch ein Standardproblem ist, dass schon seit Jahrzehnten immer wieder auftaucht (wie gerade meine Google-Suche ergeben hat).

Ist da bei Delphi oder den Indys tatsächlich nichts fertiges dabei oder habe ich es nur übersehen?

Andere Komponenten/Bibliotheken würde ich extra dafür nicht installieren wollen, dann lieber selbermachen...

Bbommel 17. Mär 2021 16:54

AW: Dekodieren eines Mail-Betreffs
 
Hach, Manno, alle machen nur noch das moderne Zeugs mit REST-APIs und was weiß ich und niemand kümmert sich mehr um die leicht in die Jahre gekommenen Mails. ;-)

Hab das also mal kurz gebastelt. Code tut für mich soweit wunderbar in Tests mit ein paar hundert Mails. Vorab aber die Einschränkung: der Code sollte gut mit Betreffs umgehen können, die entweder UTF-8 oder ISO-8859-1 kodiert sind. Der (für uns hier) "Sonderfall" einer anderen Kodierunf wie ISO-8859-4 oder was weiß ich, habe ich jetzt nicht beachtet. Falls man so etwas mit einem modernen Delphi auch in einem Ein- bis Dreizeiler hinbekommt, bin ich da noch für Anregungen dankbar, war mir aber jetzt erstmal zu unwichtig, um noch selbst danach zu suchen.

Hier also der Code:

Delphi-Quellcode:

uses
  System.NetEncoding, IdCoderQuotedPrintable, [...] ;

function DecodeMailHeader (aInStr: string): string;

(* Wir wollen ein Header-Feld - normalerweise ein Betreff oder Absender - einer Mail decodieren.
   Schema der Codierung, die auch mitten im Text mehrfach vorkommen kann:
   =?<Zeichensatz>?Codierung?Text?=
   Also etwa:
   =?utf-8?Q?Re:_Frage_zur_Kapazit=C3=A4tsplanung?=
   ergibt
   Re: Frage zur Kapazitätsplanung
   und war im Zeichensatz UTF-8 und quoted-printable codiert.
*)

var
  offsetIdx: integer;
  startIdx: integer;
  endIdx: integer;
  foundEncoding: boolean;
  encodedStr: string;
  encodedArray: TArray<string>;
  decodedStr: string;

begin
  offsetIdx:=0;
  repeat
    foundEncoding:=false;
    startIdx:=aInStr.IndexOf('=?',offsetIdx);
    if startIdx>=0 then begin
      endIdx:=aInStr.IndexOf('?=',offsetIdx);
      if endIdx>=0 then begin
        encodedStr:=aInStr.Substring(startIdx+2,endIdx-startIdx-2);
        encodedArray:=encodedStr.Split(['?']);
        if length(encodedArray)=3 then begin
          encodedArray[1]:=encodedArray[1].ToLower;
          if (encodedArray[1]='q') or (encodedArray[1]='b') then begin
            foundEncoding:=true;
            if encodedArray[1]='q' then begin
              // quoted-printable - dort zunächst die "_" entfernen, dann von den Indys umwandeln lassen
              decodedStr:=encodedArray[2].Replace('_',' ');
              decodedStr:=TIdDecoderQuotedPrintable.DecodeString(decodedStr);
              if encodedArray[0].ToLower='utf-8' then
                decodedStr:=UTF8ToString(rawbyteString(decodedStr));
            end else
              // Base64-Encoding kann Delphi selbst...
              decodedStr:=TNetEncoding.Base64.Decode(encodedArray[2]);

            // austauschen des bisherigen Text gegen den decodierten
            // sollte ein Encoding mitten im Text enden, muss danach ein Leerzeichen kommen,
            // das wir mit entfernen müssen.
            if (endIdx<=aInStr.Length-3) and (aInStr.Chars[endIdx+2]=' ') then
              inc(endIdx);
            aInStr:=aInStr.Remove(startIdx,endIdx-startIdx+2).Insert(startIdx,decodedStr);
            offsetIdx:=startIdx+decodedStr.Length;
          end;
        end;
      end;
      if not foundEncoding then
        offsetIdx:=startIdx+2;
    end;
  until startIdx=-1;
  Result:=aInStr;
end;
Viel Spaß damit, falls jemand auf der Suche in einiger Zeit darüber stolpert.

Sinspin 17. Mär 2021 17:04

AW: Dekodieren eines Mail-Betreffs
 
Hey, wenn du Geld dafür ausgeben kannst, besorg dir /N Software IPWorks. Ich verwende das seit Jahren um Emails einzulesen und zu dekodieren. In dem Fall ist es die MIME Komponente.
Und das ganze moderne Zeug ist da auch alles mit dabei 8-)

TurboMagic 17. Mär 2021 17:25

AW: Dekodieren eines Mail-Betreffs
 
Hallo,

irgendwo in TNetEncoding oder so gibt's evtl. auch was in Delphi selber.
Da gibt's gewisse Convertierungsroutinen für manche Formate.

Grüße
TurboMagic

juergen 17. Mär 2021 22:13

AW: Dekodieren eines Mail-Betreffs
 
Zitat:

Zitat von TurboMagic (Beitrag 1485386)
Hallo,

irgendwo in TNetEncoding oder so gibt's evtl. auch was in Delphi selber.
Da gibt's gewisse Convertierungsroutinen für manche Formate.

Ich glaube, TurboMagic meinte etwas in dieser Art
Delphi-Quellcode:
TURI.URLEncode(...) { uses System.Net.URLClient }

TurboMagic 18. Mär 2021 08:21

AW: Dekodieren eines Mail-Betreffs
 
Genau sowas meinte ich...

Bbommel 18. Mär 2021 08:24

AW: Dekodieren eines Mail-Betreffs
 
Nein, System.NetEncoding enthält leider auch nichts, zumindest nichts was einen MIME-Header einer Mail komplett verarbeitet. NetEncoding kann URL, Base64 und HTML kodieren. Da URLs hier erwähnt wurden: das ist was anderes als die MIME-Kodierung eines Mail-Headers. :-)

Die in NetEncoding vorhandene Base64-Klasse nutze ich in meiner obigen Lösung ja auch, insofern ist die Unit durchaus hilfreich, hat aber auch nichts komplett fertiges. Bin aber mit meiner obigen Lösung soweit auch zufrieden.

Bbommel 18. Mär 2021 08:40

AW: Dekodieren eines Mail-Betreffs
 
Grummel. Wäre die sch...öne Indy-Dokumentation auch online erreichbar hätte ich es wahrscheinlich schneller gefunden. Denn natürlich gibt es was fertiges - hatte mich doch sehr gewundert, dass Indy (und Delphi selbst) alles dekodieren kann, nur die Header einer Mail nicht. ;-)

Es gibt bei den Indys die Unit IdCoderHeader. Dort gibt es dann die Funktion "DecodeHaeder". Macht genau das, was sie soll. :-)

internet11 1. Apr 2021 13:00

AW: Dekodieren eines Mail-Betreffs
 
Hallo zusammen,
ich würde Sinspin zustimmen. Nutze das auch und finde es sehr praktisch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:53 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz