Droomdre: TXT parsen

Hallo folks, meine Datei sieht folgendermassen aus:

----------------------------
To: ab@domain.tld
Subject: Der Betreff
From: xp@domain.tld
Reply-To: xp@domain.tld

Hier kommt meine Nachricht
To: gc@domain.tld
Subject: Der Betreff
From: xp@domain.tld
Reply-To: xp@domain.tld

Hier kommt eine andere Nachricht
--------------------------------

Ich möchte gern diese Datei in 2 Arrays speichern, um daraus die Emails zu verschicken. explode("To:",$txt_file); klappt nicht wegen Reply-To: An strpos habe ich auch gedacht aber ich brauche eine Funktion, die mir alle vorkommen eines Zeichens zurückgibt. Hat jdn eine Lösung?

vielen Dank.

  1. wenn du was fertiges suchst, guck mal bei Github nach "php mail parser". Kann aber sein, dass auch der bei so einem mülligen Format scheitert. Da kann man dann ggf. noch drüber Regexen und das "To:" am Zeilenanfang suchen.

  2. Ich zitiere die Datei in Tilden eingeschlossen, um die Zeilenumbrüche zu retten. Ich unterstelle mal, dass die Minuszeichen-Zeilen nicht zur Datei gehören.

    To: ab@domain.tld
    Subject: Der Betreff
    From: xp@domain.tld
    Reply-To: xp@domain.tld
    
    Hier kommt meine Nachricht
    To: gc@domain.tld
    Subject: Der Betreff
    From: xp@domain.tld
    Reply-To: xp@domain.tld
    
    Hier kommt eine andere Nachricht
    

    Erstmal eine Antwort im Rahmen deiner Grundannahmen:

    Ein explode("To:") ist meiner Meinung nach nicht nur wegen des Reply-To riskant, du kannst ja auch ein To: im Mail-Body oder im Subject haben. Meiner Meinung nach solltest Du als Minimallösung die Datei zeilenweise einlesen und an den Zeilenanfängen nach dem To: suchen. Dann weißt Du, in welchen Zeilen die Mails beginnen und kannst die Ausgabe danach gruppieren.

    Und jetzt mal weiter gedacht:

    Kennst Du die Mail-"Norm" RFC-822 bzw. ihre Nachfolger 2822 und 5322? Ich finde es riskant, den Anfang einer Mail (und damit das Ende einer vorigen Mail) durch eine To: Zeile festzulegen, das kann schief gehen. RFC-822 legt fest, dass eine Mail mit Headern beginnt (schlüsselwort doppelpunkt space headerwerte), darauf folgt eine Leerzeile und dann beginnt der Body. Für den Body gilt nur eine Einschränkung: Die Zeilen DÜRFEN nicht länger als 998 Zeichen sein und SOLLTEN die 78 Zeichen nicht überschreiten (plus CR LF als Zeilenschaltung). Eine Body-Zeile, die mit To: beginnt, ist absolut legal und würde Dich aus der Bahn werfen.

    Zum einen legt RFC-822 meines Wissens nicht fest, dass To: das erste Headerfeld sein muss. Wenn die Datei von Dir erzeugt wird, oder du irgendeine Form von Kontrolle über ihre Erzeugung hast, solltest Du eine andere Kennung für "Ab hier neue Mail" finden.

    Gruß Rolf

    1. wobei hier dann auch "mbox", RFC 4155, zum Einsatz kommen sollte, wenn man mehrere Mails in eine Datei packt, und vorallem: wenn man sich das Format aussuchen kann um von dem Kram oben wegzukommen.

      1. wobei hier dann auch "mbox", RFC 4155, zum Einsatz kommen sollte,

        Rolf b, chorn: Eure Aussagen sind goldrichtig. Hat man einen "technischen Text", der nach einer bekannten und nachvollziehbaren Vorschrift "zusammengebaut" ist, dann hat man automatisch auch die Vorschrift, wie dieser wieder zu zerlegen ist.

        Das gilt immer dann wenn man keine sehr guten Gründe hat, die "bekannte und nachvollziehbare Vorschrift" (hier RFC 4155) zu übergehen - z.B. weil sonst, auch im Rahmen einer von der Vorschrift gedeckten Modifizierung, geforderte Funktionen nicht realisierbar sind. Ein guter Grund, die RFC zu nutzen, ist schon das es Drittsoftware (Programme, Module, Bibliotheken) gibt, welche den Text erzeugen und, ich sag mal, "nutzen" können. Zudem ist die Eigenentwicklung einer Vorschrift für den Aufbau eines solchen Textes nicht wirklich trivial. Man muss also auch bei Erweiterungen oder erheblichen Änderungen am Gesamtprojekt voraussichtlich weniger selbst tun.

        Gründe, die Vorschrift aus RFC 4155 zu missachten, kann ich hier nicht erkennen.

  3. Hi,

    An strpos habe ich auch gedacht aber ich brauche eine Funktion, die mir alle vorkommen eines Zeichens zurückgibt.

    Wenn die Datei immer so aufgebaut ist, kannst du wie erwähnt Regex z.B. mit preg_split verwenden.

    $res = preg_split('/\R+(?=To:)/m', $txt_file, -1, PREG_SPLIT_NO_EMPTY);

    Split bei 1 oder mehr newlines, wenn substr To: folgt (check mittels lookahead assertion).

    \R+ matches any Unicode newline sequence; can be modified using verbs
    	Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
    (?=To:) Positive Lookahead - Assert that the regex below can be matched
    	To: matches the characters To: literally (case sensitive)
    m modifier: multi-line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)
    

    lG, Robert

    1. Weiß gar nicht, wer das runterbewertet hat. Wenn man von den grundsätzlichen Problemen mit To: als Trenner absieht, ist das eine nette Idee, die mit To: beginnenden Zeilen zu identifizieren.

      Rolf

      1. Weiß gar nicht, wer das runterbewertet hat...

        Hatte vergessen das multiline flag rauszunehmen. Wohl würde auch /\v+(?=To:)/ gereichen.

        \v = shorthand für vertical whitespace.

        Gutes Gelingen, Robert