Einzelnen Beitrag anzeigen

Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
648 Beiträge
 
Delphi 12 Athens
 
#2

AW: Dekodieren eines Mail-Betreffs

  Alt 17. Mär 2021, 16:54
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]='qthen 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-8then
                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.
  Mit Zitat antworten Zitat