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.