![]() |
Plaintext aus .EML-Datei extrahieren?
Hallo und schönen Tag!
Ich möchte in Delphi 10 Seattle den Plaintext des body und die anderen Mailfelder aus einer .EML-Datei (von Thunderbird gespeichert, kann eine HTML-Mail oder eine Plaintext-Mail enthalten) auslesen. Das funktioniert mit dem folgenden Code nur zum Teil:
Delphi-Quellcode:
In der for-Schleife erhalte ich zwei Ergebnisse:
//uses IdText...
procedure TForm1.ExtractPlainTextFromEMLFileContainingHTMLMail; // Drop a TIdMessage component on the form and name it "IdMessage" var IndyStringList: TStringList; IndyStream: TMemoryStream; I: Integer; const CRLF = #13#10; begin IndyStringList := TStringList.Create; IndyStream := TMemoryStream.Create; try IndyStringList.LoadFromFile('C:\Ihre Bestellung.eml'); IndyStringList.Add(CRLF + '.' + CRLF); IndyStringList.SaveToStream(IndyStream); IndyStream.Position := 0; IdMessage.Clear; IdMessage.LoadFromStream(IndyStream); Memo1.Clear; Memo1.Lines.Assign(IdMessage.Headers); Memo2.Clear; Memo2.Lines.Add(IdMessage.From.Text); Memo2.Lines.Add(IdMessage.Recipients.EMailAddresses); Memo2.Lines.Add(IdMessage.Subject); Memo2.Lines.Add(DateTimeToStr(IdMessage.Date)); Memo2.Lines.Add(''); for I := 0 to IdMessage.MessageParts.Count - 1 do if IdMessage.MessageParts.Items[I] is IdText.TidText then begin Memo2.Lines.Add(IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text); // This is called TWICE. The first time it gets this text: // 'This is a multi-part message in MIME format.' // The second time it gets the HTML code of the message body // So how can I get the plain-text of the message body? end; finally IndyStringList.Free; IndyStream.Free; end; end; 1. Wie kann das Programm zur Laufzeit wissen, welches der beiden der Plaintext-body ist? 2. Wenn das Ergebnis ein HTML-Code ist: Wie kann aus diesem der Plaintext decodiert werden? |
AW: Plaintext aus .EML-Datei extrahieren?
Ob plain/text oder html/text sollte im Contenttyp stehen.
Sowas in der Art: Content-Type: text/plain; charset="utf-8" bzw. Content-Type: text/html; charset="utf-8" Wenn ich unbedingt aus HTML reinen Text machen muss, dann gehe ich so vor:
|
AW: Plaintext aus .EML-Datei extrahieren?
Zitat:
|
AW: Plaintext aus .EML-Datei extrahieren?
Jeder Part einer Mail sollte seinen eigenen Contenttyp haben.
Gibt es in 'ner Mail sowohl HTML als auch reinen Text, so sollte die Mail zwei MessageParts haben, einen mit Contenttyp html/text und einen mit plain/text. Für die Mail selbst gilt: 'This is a multi-part message in MIME format.' Das musst Du halt nachschauen und dann den gewünschten Teil verarbeiten. Beide Teile müssten vom Typ IdText.TidText sein. |
AW: Plaintext aus .EML-Datei extrahieren?
Vielen Dank, ContentType war der richtige Tipp. Dieser Code ergibt jetzt den body:
Delphi-Quellcode:
for I := 0 to IdMessage.MessageParts.Count - 1 do
begin if IdMessage.MessageParts.Items[I] is IdText.TidText then begin if IdText.TidText(IdMessage.MessageParts.Items[I]).ContentType = 'text/html' then Memo2.Lines.Add(IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text); end; end; |
AW: Plaintext aus .EML-Datei extrahieren?
Liste der Anhänge anzeigen (Anzahl: 1)
I habe mir jetzt selbst eine Email geschickt, die sowohl Reintext als auch HTML enthält, und die empfangene Email dann als .EML abgespeichert:
Anhang 45101 Wenn ich aber die IdMessage.MessageParts.Items dieser .EML-datei durchgehe, so ist keines darunter, das den ContentType plain/text hat! Wieso nicht? |
AW: Plaintext aus .EML-Datei extrahieren?
Grummel! Es muss nicht 'plain/text' heißen, sondern 'text/plain; format=flowed' - dann kriege ich den Plaintext-body!
Aber was bedeutet "format=flowed"? |
AW: Plaintext aus .EML-Datei extrahieren?
Ich habe jetzt diesen Code produziert:
Delphi-Quellcode:
Haltet ihr das für einigermaßen sicher?
for I := 0 to IdMessage.MessageParts.Count - 1 do
begin if IdMessage.MessageParts.Items[I] is IdText.TidText then begin if Pos('text/plain', IdText.TidText(IdMessage.MessageParts.Items[I]).ContentType) > 0 then begin PlaintextBody := IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text; BREAK; end else if IdText.TidText(IdMessage.MessageParts.Items[I]).ContentType = 'text/html' then HTMLBody := IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text; end; end; if PlaintextBody <> '' then Memo2.Lines.Add(PlaintextBody) else if HTMLBody <> '' then Memo2.Lines.Add(ExtractTextFrom(HTMLBody)); |
AW: Plaintext aus .EML-Datei extrahieren?
Liste der Anhänge anzeigen (Anzahl: 1)
Die Sache ist doch um einiges komplexer als ich dachte: "multi-part" oder "multipart", unterschiedliche Ebenen.
Delphi-Quellcode:
Ich stelle jetzt mal das ganze Projekt online (s. Anhang) mit der Bitte, das mit euren .EML-Dateien zu verifizieren. Ich habe es mit einer großen Menge von .EML-Dateien verwendet und bisher hat es mit allen funktioniert. Solltet ihr eine .EML-Datei finden, die nicht funktioniert, so bitte ich euch, diese zu anonymisieren und hier online zu stellen, damit ich den Code ggf. anpassen kann.
procedure TForm1.ExtractPlainTextFromEMLFile;
// Drop a TIdMessage component on the form and name it "IdMessage" var IndyStringList: TStringList; IndyStream: TMemoryStream; I: Integer; HTMLBody, PlaintextBody: string; const CRLF = #13#10; begin IndyStringList := TStringList.Create; IndyStream := TMemoryStream.Create; try IndyStringList.LoadFromFile(Trim(Edit1.Text)); IndyStringList.Add(CRLF + '.' + CRLF); IndyStringList.SaveToStream(IndyStream); IndyStream.Position := 0; IdMessage.Clear; IdMessage.LoadFromStream(IndyStream); Memo1.Clear; Memo1.Lines.Assign(IdMessage.Headers); Memo2.Clear; Memo2.Lines.Add(IdMessage.From.Text); Memo2.Lines.Add(IdMessage.Recipients.EMailAddresses); Memo2.Lines.Add(IdMessage.Subject); Memo2.Lines.Add(DateTimeToStr(IdMessage.Date)); Memo2.Lines.Add(''); if (Pos('multi-part', IdMessage.ContentType) > 0) or (Pos('multipart', IdMessage.ContentType) > 0) then begin for I := 0 to IdMessage.MessageParts.Count - 1 do begin if IdMessage.MessageParts.Items[I] is IdText.TidText then begin if Pos('text/plain', IdText.TidText(IdMessage.MessageParts.Items[I]).ContentType) > 0 then begin PlaintextBody := IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text; BREAK; end else if IdText.TidText(IdMessage.MessageParts.Items[I]).ContentType = 'text/html' then HTMLBody := IdText.TidText(IdMessage.MessageParts.Items[I]).Body.Text; end; end; if PlaintextBody <> '' then Memo2.Lines.Add(Trim(PlaintextBody)) else if HTMLBody <> '' then Memo2.Lines.Add(ExtractTextFrom(HTMLBody)) else Memo2.Lines.Add('The body could not be extracted from the .EML file. Please report this error and attach your .EML file'); end else begin Memo2.Lines.Add(Trim(IdMessage.Body.Text)); end; finally IndyStringList.Free; IndyStream.Free; end; end; |
AW: Plaintext aus .EML-Datei extrahieren?
Hallo,
hier findest Du eine Seite mit 'ner Liste von Mimetypen, das ist das, womit Du rechnen solltest/kannst/musst: ![]() Die Methode, den Text über den TWebBrowser zu holen, finde ich gut. Ansonsten sieht Dein Programm so aus, als sollte das funktionieren. Was mir auffiel: Nachdem Du den PlainTextBody gefunden hast, verlässt Du die Schleife mit break, beim HTMLBody nicht. Sollten in 'nem EML mehrere PlainTextBodys sein, so übernimmst Du damit den ersten, beim HTMLBody jedoch den letzten. Zugebenermaßen weiß ich nicht, ob es auch nur annähernd spezifikationskonform ist, wenn es in 'nem EML mehrere Plaintext-Bodys oder HTML-Bodys gibt / geben darf / geben kann. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz