1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

mail_body zerlegen

Dieses Thema im Forum "PHP" wurde erstellt von rernanded, 8. Mai 2012.

  1. rernanded

    rernanded Erfahrenes Mitglied

    Hi,
    wie kann ich die Ausgabe von Text/Plain aus dem mail_body filtern?
    Und wie kann ich das für den Text/HTML machen?
    Vllt gehts mit imap_fetchstructure() und / oder imap_fetchbody()? Nur wie?

    Moni

    PHP:
    1.  
    2. <?php
    3.  
    4. $mailbox=imap_open("{MAILSERVER}INBOX","USER","PASSWORD");
    5.  
    6.  
    7. if ($mailbox)
    8. {
    9.  
    10. $check=imap_check($mailbox);
    11.  
    12. $count_msg=$check->Nmsgs;
    13.  
    14. $count_new_msg=$check->Recent;
    15.  
    16. for ($i=1; $i<=imap_num_msg($mailbox);
    17. $i++)
    18.  
    19. {
    20.  
    21. $mail_body = imap_body($mailbox,$i);
    22.  
    23. echo '<b>Nachricht: </b><br>';
    24. echo $mail_body."<br><br>";
    25.  
    26. imap_delete($mailbox, $i);
    27.  
    28. }
    29. imap_expunge($mailbox);
    30. imap_close($mailbox);
    31. }
    32. ?>
    33.  
    Zuletzt bearbeitet: 8. Mai 2012
  2. saftmeister

    saftmeister Nutze den Saft! Premium-User

  3. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    Ich habe vor langer Zeit mal ein Skript dafür geschrieben, was den Quelltext von E-Mails parsed und zerlegt. Dabei gehe ich da auch auf den Wechsel von Zeichensätzen ein und auf Base-64-Blöcke.
    Code (PHP):
    1. class MailInterpreter
    2. {
    3.   private static $charset  = '';
    4.   private static $encoding = '';
    5.   private static $boundary = array();
    6.   private static $lines    = array();
    7.   private static $blocks   = array();
    8.  
    9.   #
    10.  # Interpretiert eine E-Mail
    11.  #
    12.  public static function interpret ($value)
    13.   {
    14.     # Nachricht in Zeilen teilen
    15.    self::$lines = explode("\n", str_replace("\r", '', $value));
    16.     # erster Datenblock besteht per Definition aus Kopfzeilen
    17.    self::header();
    18.    
    19.     # Ausnahmebehandlung: "This is a multi-part message in MIME format."
    20.    if ((trim(current(self::$lines)) === 'This is a multi-part message in MIME format.') && (self::$boundary !== array()))
    21.     {
    22.       next(self::$lines);
    23.     }
    24.    
    25.     # verarbeitet die Zeilen
    26.    while (list(, $line) = each(self::$lines))
    27.     {
    28.       # Grenze => Kopfzeilen
    29.      if ($line === '--' . end(self::$boundary))
    30.       {
    31.         self::header();
    32.         continue;
    33.       }
    34.       # Grenze (Ende) => entfernen
    35.      elseif(trim($line) === '--' . end(self::$boundary) . '--')
    36.       {
    37.         array_pop(self::$boundary);
    38.        
    39.         if(end(self::$boundary) === false)
    40.         {
    41.           break;
    42.         }
    43.         continue;
    44.       }
    45.      
    46.       # Klartext => Text
    47.      self::body();
    48.     }
    49.    
    50.     $blocks = self::$blocks;
    51.    
    52.     # alle klasseninternen Variablen zurücksetzen
    53.    self::$charset  = '';
    54.     self::$encoding = '';
    55.     self::$boundary = array();
    56.     self::$lines    = array();
    57.    
    58.     # Interpretierte Datenblöcke ausgeben
    59.    return $blocks;
    60.   }
    61.  
    62.   #
    63.  # Verarbeitet Zeilen als Kopfzeilen
    64.  #
    65.  private static function header ()
    66.   {
    67.     # Zeilen als Kopfzeilen verarbeiten
    68.    while (list(, $line) = each(self::$lines))
    69.     {
    70.       # Leerzeile => Ende der Kopfzeilen
    71.      if (trim($line) === '')
    72.       {
    73.         if ($content !== null)
    74.         {
    75.           $specification[] = self::encoding_and_charset($content);
    76.         }
    77.         self::$blocks[] = array(1, $specification);
    78.         return;
    79.       }
    80.      
    81.       # gehört zur vorherigen Angabe
    82.      if (($line[0] === ' ') || ($line[0] === "\t"))
    83.       {
    84.         $content .= ' ' . trim($line);
    85.         continue;
    86.       }
    87.      
    88.       # neue Angabe
    89.      # -- aktuelle Angabe speichern
    90.      # -- neue Angabe beginnen
    91.      if ($content !== null)
    92.       {
    93.         $specification[] = self::encoding_and_charset($content);
    94.       }
    95.      
    96.       $content = trim($line);
    97.     }
    98.   }
    99.  
    100.   #
    101.  # Verarbeitet Zeilen als Text
    102.  #
    103.  private static function body ()
    104.   {
    105.     # internen Zeiger um einen Eintrag zuruecksetzen
    106.    prev(self::$lines);
    107.    
    108.     # Zeilen als Text verarbeiten
    109.    while (list(, $line) = each(self::$lines))
    110.     {
    111.       # wenn die Zeile eine Grenze darstellt, wird der Datenblock gespeichert
    112.      if ((trim($line) === '--' . end(self::$boundary)) || (trim($line) === '--' . end(self::$boundary) . '--'))
    113.       {
    114.         # Datenblock speichern
    115.        if (trim($content) !== '')
    116.         {
    117.           self::$blocks[] = array(2, self::charset(self::encoding($content)));
    118.         }
    119.        
    120.         # internen Zeiger um einen Eintrag zurücksetzen
    121.        prev(self::$lines);
    122.         return;
    123.       }
    124.      
    125.       # neuen Datenblock beginnen oder an bestehenden anhaengen
    126.      if($content === null)
    127.       {
    128.         $content = $line;
    129.       }
    130.       else
    131.       {
    132.         $content .= "\n" . $line;
    133.       }
    134.     }
    135.    
    136.     # alle Zeilen wurden verarbeitet
    137.    if (trim($content) !== '')
    138.     {
    139.       self::$blocks[] = array(2, self::charset(self::encoding($content)));
    140.     }
    141.   }
    142.  
    143.   #
    144.  # Kodiert einen Text in Klartext
    145.  #
    146.  private static function encoding ($value)
    147.   {
    148.     if (self::$encoding === 'quoted-printable')
    149.     {
    150.       $value = quoted_printable_decode($value);
    151.     }
    152.    
    153.     return $value;
    154.   }
    155.  
    156.   #
    157.  # Wandelt den Zeichensatz in UTF-8 um
    158.  #
    159.  private static function charset ($value)
    160.   {
    161.     return iconv(self::$charset, 'utf-8', $value);
    162.   }
    163.  
    164.   #
    165.  # Ermittelt die Kodierung und den Zeichensatz aus einer Kopfzeile
    166.  #
    167.  private static function encoding_and_charset ($value)
    168.   {
    169.     # Zeichensatz und Kodierung ermitteln
    170.    if (substr($value, 0, 14) === 'Content-Type: ')
    171.     {
    172.       # Grenze ermitteln
    173.      if (preg_match('/boundary=("(.*)"|.*)/', $value, $match) === 1)
    174.       {
    175.         if (isset($match[2]) === true)
    176.         {
    177.           self::$boundary[] = $match[2];
    178.         }
    179.         else
    180.         {
    181.           self::$boundary[] = $match[1];
    182.         }
    183.       }
    184.      
    185.       # Zeichensatz ermitteln
    186.      if (preg_match('/charset=("(.*)"|.*)/', $value, $match) === 1)
    187.       {
    188.         if (isset($match[2]) === true)
    189.         {
    190.           self::$charset = $match[2];
    191.         }
    192.         else
    193.         {
    194.           self::$charset = $match[1];
    195.         }
    196.       }
    197.     }
    198.     # Zeile mit der Kodierungsangabe suchen
    199.    elseif (substr($value, 0, 27) === 'Content-Transfer-Encoding: ')
    200.     {
    201.       self::$encoding = substr($value, 27);
    202.     }
    203.    
    204.     return $value;
    205.   }
    206. }
  4. rernanded

    rernanded Erfahrenes Mitglied

    Danke an einfach nur crack.
    Moni
  5. JesusFreak777

    JesusFreak777 Erfahrenes Mitglied

    Hallo,

    ich bin auch auf der suche eine Email richtig zu interpretieren,...

    Da ich leider noch nicht so gut mir Klassen umgehen kann, verstehe ich nicht ganz wie ich die Klasse einbinden kann!

    klar
    PHP:
    1. include('MailInterpreter.class.php');
    aber mit welchen Befehl wende ich diese dann wo an?

    Vielen Dank für die Tipps!

    Gruß Baer
    Zuletzt bearbeitet: 11. Mai 2012
  6. Yaslaw

    Yaslaw n/a Moderator

    Diese Klasse von crack hat alles statische Funktionen. Ergo einen einfachen Statischen Aufruf
    Code (PHP):
    1. //Hab aber keine Ahnung was bei dieser Klasse $value ist und was genau als $result zurückkommt.
    2. //Die Dokumentaierung ist in dieser Hinsicht mangelnd.
    3. $result = MailInterpreter::interpret($value);
  7. JesusFreak777

    JesusFreak777 Erfahrenes Mitglied

    Vielen Dank,

    leider macht die Klasse nicht das, was ich mir erhofft habe,... bzw. ich kann damit nicht umgehen!

    zu meinem Problem:
    ich mache einen IMAP abruf und erhalte über diesen befehl
    PHP:
    1. $body = imap_body($mbox,$overview->msgno);
    2. echo "<pre>".$body."</pre>";
    3.  
    folgendes:
    Code (Text):
    1.  
    2. --_000_70DA0C594B96434684762CC7B68465410C1D9815BAERSERVERedvba_
    3. Content-Type: text/plain; charset="iso-8859-1"
    4. Content-Transfer-Encoding: quoted-printable
    5.  
    6. Dieses mal mit etwas l=E4ngeren text um zu testen ob die zeile wieder abgeb=
    7. rochen wird! Ca. 69 zeichen muss ich in eine zeile bringen um zu wissen ob =
    8. es funktioniert! Jetzt sollte ich auf jeden fall etwas mehr zeichen haben, =
    9. ich teste jetzt noch ein paar html funktionen wie fettschrift und zentriert=
    10. !
    11.  
    12.  
    13. Test fett
    14.  
    15. Test center
    16.  
    17. --_000_70DA0C594B96434684762CC7B68465410C1D9815BAERSERVERedvba_
    18. Content-Type: text/html; charset="iso-8859-1"
    19. Content-Transfer-Encoding: quoted-printable
    20.  
    21.  
    22.  
    23.  
    24.  
    25.  
    26.  
    27.  
    28.  
    29. Dieses mal mit etwas l=E4ngeren text um zu testen ob= die zeile wieder abgebrochen wird! Ca. 69 zeichen muss ich in eine zeile b= ringen um zu wissen ob es funktioniert! Jetzt sollte ich auf jeden fall etw= as mehr zeichen haben, ich teste jetzt noch ein paar html funktionen wie fettschrift und zentriert!
    30.  
    31.  
    32.  
    33.  
    34.  
    35. Test fett
    36.  
    37.  
    38.  
    39. Test ce= nter
    40.  
    41.  
    42.  
    43.  
    44. --_000_70DA0C594B96434684762CC7B68465410C1D9815BAERSERVERedvba_--
    45.  
    46.  
    oder
    Code (Text):
    1.  
    2. --_000_70DA0C594B96434684762CC7B68465410C1D87FDBAERSERVERedvba_
    3. Content-Type: text/plain; charset="iso-8859-1"
    4. Content-Transfer-Encoding: quoted-printable
    5.  
    6. hallo
    7.  
    8. --_000_70DA0C594B96434684762CC7B68465410C1D87FDBAERSERVERedvba_
    9. Content-Type: text/html; charset="iso-8859-1"
    10. Content-Transfer-Encoding: quoted-printable
    11.  
    12.  
    13.  
    14.  
    15.  
    16.  
    17.  
    18.  
    19.  
    20. hallo
    21.  
    22.  
    23.  
    24.  
    25. --_000_70DA0C594B96434684762CC7B68465410C1D87FDBAERSERVERedvba_--
    26.  
    27.  
    auch
    Code (Text):
    1.  
    2. kann mir bitte jemand die internet-adresse schicken? =3D) Ich w=C3=BCrde mi=
    3. ch sehr freuen... Schaf
    4.  
    5.  
    6. Um diese Email anzeigen zu k=C3=B6nnen, ben=C3=B6tigen Sie einen HTML f=C3=
    7. =A4higen Email=20
    8. Client!
    9.  
    Leider habe ich keinen Plan wie ich damit umgehen soll damit das richtig Formatiert ist,... mit etwas filterarbeit habe ich zwar schon einiges herausfiltern können,... aber bei einer anderen Email (von einem Anderen Client) kommt wieder etwas ganz anderes an!

    diese Funktionen habe ich schon einzeln und in Kombination getestet,... leider ohne vernünftigen erfolg!
    PHP:
    1.  
    2.     $body = htmlentities($body);
    3.     $body = htmlspecialchars ($body);
    4.     $body = nl2br($body);
    5.     $body = imap_utf8($body);
    6.     $body = imap_qprint($body);
    7.     $body = str_replace("\n", "<br>", $body);
    8.     $body = mb_convert_encoding($body, 'iso-8859-1');
    9.  
    damit bin ich etwas weiter gekommen,...
    http://www.tutorials.de/php/237298-imap_body-formatiert-und-mit-umlauten-ausgeben.html

    aber eine schöne Formatierte ausgabe in HTML oder nur TEXT,... wie es in der Email (wie bei den Maildiensten ja auch funktioniert) habe ich noch nicht hinbekommen :/

    Danke für die Hilfe schon im vorraus!

    Gruß
    Baer
    Zuletzt bearbeitet: 11. Mai 2012
  8. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    @Yaslaw: Wenn du dir einmal den Quelltext ansiehst, der einer jeden E-Mail zugrunde liegt, also das, was eigentlich übermittelt wird, dann hast du genau das, was meine Methode als Argument haben will.

    @JesusFreak: Wenn du mal das, was du als Mail-Quelltext beigetragen hast, nimmst, und es meiner Methode übergibst, dann wirst du sehen, dass meine Klasse die Kodierung zu UTF-8 automatisch vor nimmt. Allerdings musste ich gerade feststellen, dass meine Klasse auf etwas nicht eingeht: und zwar, dass als erste Zeile bereits eine Boundary kommt, was eigentlich sein dürfte. Daher werde ich gleich einmal probieren dafür eine Änderung einzufügen.
    Zuletzt bearbeitet: 11. Mai 2012
  9. Yaslaw

    Yaslaw n/a Moderator

    Naja, da ich noch nie mit PHP und mails gearbeitet habe, weiss ich nicht was $value ist und was der Rückwert ist (ich meine ohne den Code zu lesen - nur anhand des Kommentars).
    Darum macht es Sinn in der Beschreibung der MEthode @param und @return ganz kurz zu erläutern
    zB:
    Code (PHP):
    1.     /**
    2.      * $_FILE auswerten
    3.      * @param <Integer>        id bei einem Multiupload-Feld
    4.      * @return <Array>         Alle ausgelesenen Werte als Array
    5.      */
    6.     protected function getFileProperties($id = 0){
    7. ...
    Somit war meine posting nur eine Anleitung wie man eine statische Klasse verwendet.....
  10. JesusFreak777

    JesusFreak777 Erfahrenes Mitglied

    @crack wie genau binde ich die klasse ein?

    PHP:
    1.  
    2. include('MailInterpreter.class.php');  
    3.  
    4. ... imap empfang
    5.  
    6. $body = imap_body($mbox,$overview->msgno);
    7.  
    8. $result = MailInterpreter::interpret($body);  
    9.  
    10. echo $result;
    11.  
    Code (Text):
    1.  
    2. Notice: Undefined variable: content in /var/www/web1053/html/msg/MailInterpreter.class.php on line 93
    3. 93:       if ($content !== null)
    4.  
    5. Notice: Undefined variable: content in /var/www/web1053/html/msg/MailInterpreter.class.php on line 128
    6. 128:       if($content === null)
    7.  
    8.  
    irgendwas mach ich falsch!?

    Danke für eure Hilfe

    Gruß Baer

    Nachtrag:
    natürlich nicht echo sondern print_r,... ändert aber nichts an den fehlern!
    Zuletzt bearbeitet: 11. Mai 2012
  11. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    Okay, füge dazu einfach in der Methode "body" und der Methode "header" am Anfang folgendes ein:
    Code (PHP):
    1. $content = '';
  12. JesusFreak777

    JesusFreak777 Erfahrenes Mitglied

    hm,...

    Code (Text):
    1.  
    2. Notice: iconv() [function.iconv]: Detected an illegal character in input string in /var/www/web1053/html/msg/MailInterpreter.class.php on line 165
    3. 165:    return iconv(self::$charset, 'utf-8', $value);
    4.  
    Und was kann ich dann mit diesm array anstellen?
    Leider hab ich noch nie vorher was mit imap und diesen codierungen gemacht! Ich bekomme ein array zurück, das mir noch komplexer erscheint als der vorherige Wert!
  13. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    Kurz zum Aufbau von E-Mails: E-Mails bestehen aus zwei Dingen: aus Kopfzeilen und aus dem Körper. Beide sind voneinander durch eine Leerzeile getrennt. Wenn du jetzt jedoch einen Anhang verschicken willst, dann musst dieser in druckbaren Zeichen verschickt werden. Dazu wird der Dateiinhalt mit Base64 kodiert und Eigenschaften wie Dateigröße, Format und Name werden als Kopfzeilen verwendet. Solche Bereiche (also Paare aus Kopfzeile und Körper), die separat zum eigentlichen Inhalt einer E-Mail versendet werden, werden zwischen zwei Boundaries (Begrenzungen) als Körper des eigentlichen Inhalts der E-Mail verschickt. Somit kann der Client, der die E-Mail erhält, nun die E-Mail wieder so zusammen bauen, wie sie ursprünglich aussah.

    Was mein Skript macht: mein Skript sucht man Boundaries und Leerzeilen und teilt somit die E-Mail in Bereiche ein. Dabei teilt es Kopfzeilen vom eigentlichen Körper eines Bereiches und formatiert Inhalt, wenn es ein solcher ist, entsprechend der angegebenen Kodierung in UTF-8.

    [table="width: 500, class: grid, align: left"]

    E-Mail-Quelltext
    Beschreibung

    --_000_70DA0C594B96434684762CC7B68465410C1D9815BAERSERVERedvba_
    Boundary (Beginn eines Bereiches)

    Content-Type: text/plain; charset="iso-8859-1"
    Content-Transfer-Encoding: quoted-printable
    Kopfzeilen


    Leerzeile

    Dieses mal mit etwas l=E4ngeren text um zu testen ob die zeile wieder abgeb=
    rochen wird! Ca. 69 zeichen muss ich in eine zeile bringen um zu wissen ob =
    es funktioniert! Jetzt sollte ich auf jeden fall etwas mehr zeichen haben, =
    ich teste jetzt noch ein paar html funktionen wie fettschrift und zentriert=
    !


    Test fett

    Test center

    Körper

    --_000_70DA0C594B96434684762CC7B68465410C1D9815BAERSERVERedvba_
    Boundary (Ende des Bereiches)

    Content-Type: text/html; charset="iso-8859-1"
    Content-Transfer-Encoding: quoted-printable
    Kopfzeilen


    Leerzeile









    Dieses mal mit etwas l=E4ngeren text um zu testen ob= die zeile wieder abgebrochen wird! Ca. 69 zeichen muss ich in eine zeile b= ringen um zu wissen ob es funktioniert! Jetzt sollte ich auf jeden fall etw= as mehr zeichen haben, ich teste jetzt noch ein paar html funktionen wie fettschrift und zentriert!





    Test fett



    Test ce= nter
    Körper
    [/table]
  14. JesusFreak777

    JesusFreak777 Erfahrenes Mitglied

    WOW, vielen Dank für die gute erklärung,...

    again what learned :)

    ok,... soweit hab ich das jetzt,... wie kann ich jetzt weiter verfahren,...

    einerseits hab ich noch solche zeichen ('=E4', '= ') und anderer seits, hab ich noch solche emails:
    Code (Text):
    1.  
    2. Array
    3. (
    4.     [0] => Array
    5.         (
    6.             [0] => 1
    7.             [1] => Array
    8.                 (
    9.                     [0] =>
    10.                     [1] => This is a MIME-encapsulated message.
    11.                 )
    12.  
    13.         )
    14.  
    15.     [1] => Array
    16.         (
    17.             [0] => 2
    18.             [1] =>
    19. --A1745A05E2.1335374365/webbox111.irgendein-server.tld
    20. Content-Description: Notification
    21. Content-Type: text/plain; charset=us-ascii
    22.  
    23. This is the mail system at host webbox111.irgendein-server.tld.
    24.  
    25. I'm sorry to have to inform you that your message could not
    26. be delivered to one or more recipients. It's attached below.
    27.  
    28. For further assistance, please send mail to postmaster.
    29.  
    30. If you do so, please include this problem report. You can
    31. delete your own text from the attached returned message.
    32.  
    33.                    The mail system
    34.  
    35. : host mx-ha02.web.de[213.365.27.10] said: 552-Requested
    36.     mail action aborted: exceeded storage allocation 552-Quota exceeded. 552
    37.     For explanation visit http://postmaster.web.de/error-messages (in reply to
    38.     RCPT TO command)
    39.  
    40. --A1745A05E2.1335374365/webbox111.irgendein-server.tld
    41. Content-Description: Delivery report
    42. Content-Type: message/delivery-status
    43.  
    44. Reporting-MTA: dns; webbox111.irgendein-server.tld
    45. X-Postfix-Queue-ID: A1745A05E2
    46. X-Postfix-Sender: rfc822; mail@irgendeine-domain.de
    47. Arrival-Date: Wed, 25 Apr 2012 19:19:24 +0200 (CEST)
    48.  
    49. Final-Recipient: rfc822; name.nachname@web.de
    50. Original-Recipient: rfc822;name.nachname@web.de
    51. Action: failed
    52. Status: 5.0.0
    53. Remote-MTA: dns; mx-ha02.web.de
    54. Diagnostic-Code: smtp; 552-Requested mail action aborted: exceeded storage
    55.     allocation 552-Quota exceeded. 552 For explanation visit
    56.     http://postmaster.web.de/error-messages
    57.  
    58. --A1745A05E2.1335374365/webbox111.irgendein-server.tld
    59. Content-Description: Undelivered Message
    60. Content-Type: message/rfc822
    61. Content-Transfer-Encoding: 8bit
    62.  
    63. Return-Path:
    64. Received: from smtp.domain.tld (unknown [83.220.144.77])
    65.     by webbox111.irgendein-server.tld (Postfix) with ESMTPA id A1745A05E2
    66.     for ; Wed, 25 Apr 2012 19:19:24 +0200 (CEST)
    67. Date: Wed, 25 Apr 2012 19:19:24 +0200
    68. To: Julius Gracz
    69. From: "MAIL - domain.de"
    70. Reply-to: "MAIL - domain.de"
    71. Subject: Neuer Blogeintrag von baer
    72. Message-ID: <29187703a4b88ba094539ed751f8365a@smtp.domain.tld>
    73. X-Priority: 3
    74. X-Mailer: PHPMailer 5.1 (phpmailer.sourceforge.net)
    75. MIME-Version: 1.0
    76. Content-Type: multipart/alternative;
    77.     boundary="b1_29187703a4b88ba094539ed751f8365a"
    78.  
    79.  
    80. --b1_29187703a4b88ba094539ed751f8365a
    81. Content-Type: text/plain; charset = "UTF-8"
    82. Content-Transfer-Encoding: 8bit
    83.  
    84. Um diese Email anzeigen zu k
    85.         )
    86.  
    87. )
    88.  
    89.  

    -> ursprünglich habe ich gehofft, das es fertige klassen dafür gibt! aber egal, was ich bisher versucht habe ich habe es nicht hinbekommen, emails die von web, outlook oder googlemail,... kommen in ner vernünftigen formatierung hinzubekommen,...

    was jetzt noch nicht wichtig ist, aber auch noch auf mich zukommt sind dann die anhänge! bilder die mit in die email eingebunden ist,...

    ?

    was ist mein nächster schritt?

    und der Fehler steht auch noch aus:

    Code (Text):
    1.  
    2. Notice: iconv() [function.iconv]: Detected an illegal character in input string in /var/www/web1053/html/msg/MailInterpreter.class.php on line 165
    3. 165:    return iconv(self::$charset, 'utf-8', $value);
    4.  
  15. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    Ich arbeite daran. Das Problem besteht aus zwei Teilen: laut Spezifikation darf die erste Zeile keine Leerzeile sein, ist sie bei dir aber. Außerdem ist dein erster Block ein Boundary-Block, was eigentlich auch nicht erlaubt ist.
  16. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    So. Ich habe jetzt mein Skript komplett überarbeitet, also eher komplett neu geschrieben, und damit alle möglichen Fehler beseitigt, die ich mir erdenken konnte, und es parset deinen Quelltext jetzt auch fehlerfrei.. wenn er vollständig ist. Denn das, was du uns hier als Schippsel gezeigt hast, kann nur ein Ausschnitt des ganzen Quelltextes sein. Ansonsten solltest du mal bei deinem E-Mail-Anbieter fragen, ob dessen Server kaputt ist.
    Code (PHP):
    1. class MailSourceParser
    2. {
    3.   public static function parse ($source)
    4.   {
    5.     # split source into lines
    6.    $lines = explode("\n", str_replace("\r", '', $source));
    7.    
    8.     # remove empty lines
    9.    foreach ($lines as $i => $line)
    10.     {
    11.       # break at first non-empty line
    12.      if (trim($line) !== '')
    13.       {
    14.         break;
    15.       }
    16.       # remove empty line
    17.      else
    18.       {
    19.         unset($lines[$i]);
    20.       }
    21.     }
    22.    
    23.     # give new indices to the array values, starting at 0
    24.    $lines = array_values($lines);
    25.    
    26.     # exceptional handling for this line of code
    27.    if (($_ = strtolower($lines[0])) === 'this is a' && strpos($_, 'mime') !== false && strpos($_, 'message') !== false)
    28.     {
    29.       # remove this line of code and ...
    30.      unset($lines[0]);
    31.       # give new indices to the array values, starting at 0
    32.      $lines = array_values($lines);
    33.     }
    34.    
    35.     $current    = array();
    36.     $blocks     = array();
    37.     $boundary   = null;
    38.     $boundaries = array();
    39.     $mode       = 1;
    40.    
    41.     # collect data
    42.    foreach ($lines as $i => $line)
    43.     {
    44.       $line = str_replace("\r", '', $line);
    45.      
    46.       # seems to be a boundary
    47.      if (substr($line, 0, 2) === '--' && sscanf($line, '--%s', $boundary) === 1)
    48.       {
    49.         # start boundary
    50.        if (substr($line, -2, 2) !== '--')
    51.         {
    52.           # this line is the first of all, the line before was empty or a boundary
    53.          if ($i === 0 || trim($lines[$i - 1]) === '' || sscanf($lines[$i - 1], '--%s', $_) === 1)
    54.           {
    55.             # real boundary (is defined in header)
    56.            if (in_array($boundary, $boundaries))
    57.             {
    58.               # no reason for adding an empty entry to the list
    59.              if ($current !== array())
    60.               {
    61.                 $blocks[]   = $current;
    62.               }
    63.              
    64.               # reset all for a new block
    65.              $current    = array();
    66.               $current[0] = $boundary;
    67.               $mode       = 1;
    68.               continue;
    69.             }
    70.           }
    71.         }
    72.         # end boundary
    73.        else
    74.         {
    75.           # real boundary (is defined in header)
    76.          if (in_array(substr($boundary, 0, strlen($boundary) - 2), $boundaries))
    77.           {
    78.             continue;
    79.           }
    80.         }
    81.       }
    82.      
    83.       switch ($mode)
    84.       {
    85.         # header
    86.        case 1:
    87.         {
    88.           if (trim($line) === '')
    89.           {
    90.             $mode = 2;
    91.           }
    92.           else
    93.           {
    94.             $current[1][] = $line;
    95.            
    96.             if (strtolower(substr($line, 0, 14)) === 'content-type: ')
    97.             {
    98.               if (preg_match('/boundary=([^; ]+)/', $line, $match) === 1)
    99.               {
    100.                 $boundaries[] = $match[1];
    101.               }
    102.             }
    103.           }
    104.         }
    105.         break;
    106.        
    107.         # body
    108.        case 2:
    109.         {
    110.           $current[2][] = $line;
    111.         }
    112.         break;
    113.       }
    114.     }
    115.    
    116.     if ($current !== array())
    117.     {
    118.       $blocks[] = $current;
    119.     }
    120.    
    121.     $result = array();
    122.    
    123.     # format data and decode the content
    124.    foreach ($blocks as $i => $block)
    125.     {
    126.       $last    = 0;
    127.       $current = array();
    128.      
    129.       # boundary name
    130.      if (isset($block[0]) && trim($block[0]) !== '')
    131.       {
    132.         $current[0] = $block[0];
    133.       }
    134.       else
    135.       {
    136.         $current[0] = null;
    137.       }
    138.      
    139.       # header
    140.      foreach ($block[1] as $i => $line)
    141.       {
    142.         # add current line to last entry
    143.        if (trim(substr($line, 0, 1)) === '')
    144.         {
    145.           $current[1][$last] .= ' ' . trim($line);
    146.         }
    147.         # add current line as new entry
    148.        else
    149.         {
    150.           $current[1][$i] = $line;
    151.           $last = $i;
    152.         }
    153.       }
    154.      
    155.       # give new indices to the array values, starting at 0
    156.      $current[1] = array_values($current[1]);
    157.      
    158.       foreach ($current[1] as $i => $line)
    159.       {
    160.         # split headers into a key and a value
    161.        $temp = explode(':', $line, 2);
    162.         $current[1][$i] = array(
    163.           trim($temp[0]),
    164.           trim($temp[1])
    165.         );
    166.       }
    167.      
    168.       # content
    169.      if (isset($block[2]))
    170.       {
    171.         $content_type     = null;
    172.         $content_encoding = null;
    173.        
    174.         foreach ($current[1] as $entry)
    175.         {
    176.           # get charset
    177.          if (strtolower($entry[0]) === 'content-type')
    178.           {
    179.             if (preg_match('/charset=("([^ ;]*)"|[^ ;]*)/', $entry[1], $match) === 1)
    180.             {
    181.               $content_type = isset($match[2]) ? $match[2] : $match[1];
    182.             }
    183.           }
    184.           # get transfer encoding
    185.          elseif (strtolower($entry[0]) === 'content-transfer-encoding')
    186.           {
    187.             $content_encoding = trim($entry[1]);
    188.           }
    189.         }
    190.        
    191.         # remove last line (is always empty)
    192.        array_pop($block[2]);
    193.         # put all lines together
    194.        $current[2] = implode("\r\n", $block[2]);
    195.        
    196.         # decode content
    197.        if ($content_encoding !== null)
    198.         {
    199.           if ($content_encoding === 'quoted-printable')
    200.           {
    201.             $current[2] = quoted_printable_decode($current[2]);
    202.           }
    203.         }
    204.        
    205.         # encode content to utf-8
    206.        if ($content_type !== null)
    207.         {
    208.           $current[2] = iconv($content_type, 'utf-8', $current[2]);
    209.         }
    210.       }
    211.      
    212.       # add entry to the result array
    213.      $result[] = $current;
    214.     }
    215.    
    216.     return $result;
    217.   }
    218. }
    Wie man sieht, haben sich drei Dinge grundsätzlich geändert: erstens heißt die Klasse jetzt anders, zweitens heißt die aufzurufende Methode anders und drittens gibt es nur noch eine Methode. Ansonsten sieht auch das ausgegebene Array jetzt anders aus:
    Code (Text):
    1. [
    2.   0 : [
    3.     0 : 'boundary name',
    4.     1 : [ 'liste mit kopfzeilen, wobei jede kopfzeile wiederum
    5.            eine liste ist, wobei der erste eintrag der name
    6.            und der zweite eintrag der wert ist' ],
    7.     2 : 'inhalt des blocks',
    8.   ],
    9.   1 : [ ... ],
    10.   2 : [ ... ],
    11.   ...
    12. ]
    Zuletzt bearbeitet: 11. Mai 2012
  17. einfach nur crack

    einfach nur crack mag Cookies & Kekse

    Während ich JesusFreak half mein Skript für seine Zwecke in seine Webseite einzupflegen, habe ich noch einige kleine Änderungen, sowie zwei zusätzliche Klassen getätigt. Zu diesen will ich natürlich auch allen anderen Zugang gewähren:

    Klasse: MailSourceParser (neu: kleine Bugfixes sowie die statische Methode get, welche ein MailMessage-Objekt zurückgibt)
    Code (PHP):
    1. class MailSourceParser
    2. {
    3.   public static function get ($source)
    4.   {
    5.     return new MailMessage(self::parse($source));
    6.   }
    7.  
    8.   public static function parse ($source)
    9.   {
    10.     # split source into lines
    11.    $lines = explode("\n", str_replace("\r", '', $source));
    12.  
    13.     # remove empty lines
    14.    foreach ($lines as $i => $line)
    15.     {
    16.       # break at first non-empty line
    17.      if (trim($line) !== '')
    18.       {
    19.         break;
    20.       }
    21.       # remove empty line
    22.      else
    23.       {
    24.         unset($lines[$i]);
    25.       }
    26.     }
    27.  
    28.     # give new indices to the array values, starting at 0
    29.    $lines = array_values($lines);
    30.  
    31.     # exceptional handling for this line of code
    32.    if (($_ = strtolower($lines[0])) === 'this is a' && strpos($_, 'mime') !== false && strpos($_, 'message') !== false)
    33.     {
    34.       # remove this line of code and ...
    35.      unset($lines[0]);
    36.       # give new indices to the array values, starting at 0
    37.      $lines = array_values($lines);
    38.     }
    39.  
    40.     $current    = array();
    41.     $blocks     = array();
    42.     $boundary   = null;
    43.     $boundaries = array();
    44.     $mode       = 1;
    45.  
    46.     # collect data
    47.    while (list($i, $line) = each($lines))
    48.     {
    49.       $line = str_replace("\r", '', $line);
    50.    
    51.       # seems to be a boundary
    52.      if (substr($line, 0, 2) === '--' && sscanf($line, '--%s', $boundary) === 1)
    53.       {
    54.         # start boundary
    55.        if (substr($line, -2, 2) !== '--')
    56.         {
    57.           # maybe the whole mail is in a boundary, so add it
    58.          if ($i === 0)
    59.           {
    60.             $boundaries[] = $boundary;
    61.           }
    62.        
    63.           # real boundary (is defined in header)
    64.          if (in_array($boundary, $boundaries))
    65.           {
    66.             # no reason for adding an empty entry to the list
    67.            if ($current !== array())
    68.             {
    69.               $blocks[]   = $current;
    70.             }
    71.          
    72.             # reset all for a new block
    73.            $current    = array();
    74.             $current[0] = $boundary;
    75.             $mode       = 1;
    76.             continue;
    77.           }
    78.         }
    79.         # end boundary
    80.        else
    81.         {
    82.           # real boundary (is defined in header)
    83.          if (in_array(substr($boundary, 0, strlen($boundary) - 2), $boundaries))
    84.           {
    85.             continue;
    86.           }
    87.         }
    88.       }
    89.    
    90.       switch ($mode)
    91.       {
    92.         # header
    93.        case 1:
    94.         {
    95.           if (trim($line) === '')
    96.           {
    97.             $mode = 2;
    98.           }
    99.           else
    100.           {
    101.             # add associating lines together (must begin with a tabulator or space)
    102.            while (isset($lines[$i + 1]) && (($_ = ord(substr($lines[$i + 1], 0, 1))) === 9 || $_ === 32))
    103.             {
    104.               $line .= ' ' . trim($lines[++$i]);
    105.               next($lines);
    106.             }
    107.          
    108.             $current[1][] = $line;
    109.          
    110.             if (strtolower(substr($line, 0, 14)) === 'content-type: ')
    111.             {
    112.               if (preg_match('/boundary=(([^"; ]+)|"([^"; ]+)")/', $line, $match) === 1)
    113.               {
    114.                 # boundary with quotation marks
    115.                if (isset($match[3]))
    116.                 {
    117.                   $boundaries[] = $match[3];
    118.                 }
    119.                 # boundary without quotation marks
    120.                else
    121.                 {
    122.                   $boundaries[] = $match[2];
    123.                 }
    124.               }
    125.             }
    126.           }
    127.         }
    128.         break;
    129.      
    130.         # body
    131.        case 2:
    132.         {
    133.           $current[2][] = $line;
    134.         }
    135.         break;
    136.       }
    137.     }
    138.  
    139.     if ($current !== array())
    140.     {
    141.       $blocks[] = $current;
    142.     }
    143.  
    144.     $result = array();
    145.  
    146.     # format data and decode the content
    147.    foreach ($blocks as $i => $block)
    148.     {
    149.       $last    = 0;
    150.       $current = array();
    151.    
    152.       # boundary name
    153.      if (isset($block[0]) && trim($block[0]) !== '')
    154.       {
    155.         $current[0] = $block[0];
    156.       }
    157.       else
    158.       {
    159.         $current[0] = null;
    160.       }
    161.    
    162.       foreach ($block[1] as $i => $line)
    163.       {
    164.         # split headers into a key and a value
    165.        $temp    = explode(':', $line, 2);
    166.         # trim parts
    167.        $temp[0] = trim($temp[0]);
    168.         $temp[1] = trim($temp[1]);
    169.      
    170.         # decode if there is an charset mark
    171.        if (preg_match('/=\?([^\?]+)\?(Q|q)\?([^\?]+)\?=/', $temp[1], $match))
    172.         {
    173.           # replace encoded string with the decoded one and convert dashes to spaces (and encode it to utf-8)
    174.          $temp[1] = str_replace($match[0], str_replace('_', ' ', iconv($match[1], 'utf-8', quoted_printable_decode($match[3]))), $temp[1]);
    175.         }
    176.      
    177.         # save parts
    178.        $current[1][$i] = $temp;
    179.       }
    180.    
    181.       # content
    182.      if (isset($block[2]))
    183.       {
    184.         $content_type     = null;
    185.         $content_encoding = null;
    186.         $is_attachment    = false;
    187.      
    188.         foreach ($current[1] as $entry)
    189.         {
    190.           # get charset
    191.          if (strtolower($entry[0]) === 'content-type')
    192.           {
    193.             if (preg_match('/charset=("([^ ;]*)"|[^ ;]*)/', $entry[1], $match) === 1)
    194.             {
    195.               $content_type = isset($match[2]) ? $match[2] : $match[1];
    196.             }
    197.           }
    198.           # get transfer encoding
    199.          elseif (strtolower($entry[0]) === 'content-transfer-encoding')
    200.           {
    201.             $content_encoding = trim($entry[1]);
    202.           }
    203.           elseif (strtolower($entry[0]) === 'content-disposition' && strpos($entry[1], 'attachment') !== false)
    204.           {
    205.             $is_attachment = true;
    206.           }
    207.         }
    208.      
    209.         # put all lines together
    210.        $current[2] = implode("\r\n", $block[2]);
    211.      
    212.         # decode content
    213.        if ($content_encoding !== null)
    214.         {
    215.           if ($content_encoding === 'quoted-printable')
    216.           {
    217.             $current[2] = quoted_printable_decode($current[2]);
    218.           }
    219.           elseif ($content_encoding === 'base64' && !$is_attachment)
    220.           {
    221.             $current[2] = base64_decode($current[2]);
    222.           }
    223.         }
    224.      
    225.         # encode content to utf-8
    226.        if ($content_type !== null)
    227.         {
    228.           $current[2] = iconv($content_type, 'utf-8', $current[2]);
    229.         }
    230.       }
    231.    
    232.       # add entry to the result array
    233.      $result[] = $current;
    234.     }
    235.  
    236.     return $result;
    237.   }
    238. }
    Klasse: MailMessage (stellt eine E-Mail-Nachricht dar, so dass man bequem auf deren Inhalte sowie Anhänge und Kopfzeilen zugreifen kann)
    Code (PHP):
    1. class MailMessage
    2. {
    3.   private $data        = array();
    4.   private $attachments = array();
    5.   private $contents    = array();
    6.   private $headers     = array();
    7.  
    8.   public function __construct (array $data)
    9.   {
    10.     $this->data = $data;
    11.    
    12.     foreach ($data as $block)
    13.     {
    14.       foreach ($block[1] as $header)
    15.       {
    16.         if (strtolower($header[0]) === 'content-disposition' && strpos($header[1], 'attachment') !== false)
    17.         {
    18.           if (preg_match('/(file)name=("([^"]+)"|([^;]+))/', $header[1], $match))
    19.           {
    20.             if (isset($match[4]))
    21.             {
    22.               $name = $match[4];
    23.             }
    24.             else
    25.             {
    26.               $name = $match[3];
    27.             }
    28.           }
    29.           else
    30.           {
    31.             $name = null;
    32.           }
    33.          
    34.           $this->attachments[] = new FileObject(base64_decode($block[2]), $name);
    35.           continue 2;
    36.         }
    37.       }
    38.      
    39.       if (isset($block[2]))
    40.       {
    41.         $this->contents[] = $block;
    42.       }
    43.       elseif ($block[0] === null)
    44.       {
    45.         foreach ($block[1] as $header)
    46.         {
    47.           $this->headers[] = $header;
    48.         }
    49.       }
    50.     }
    51.   }
    52.  
    53.   public function headers ()
    54.   {
    55.     return $this->headers;
    56.   }
    57.  
    58.   public function contents ()
    59.   {
    60.     return $this->contents;
    61.   }
    62.  
    63.   public function attachments ($return_as_zip = false)
    64.   {
    65.     if ($this->attachments === array())
    66.     {
    67.       return null;
    68.     }
    69.    
    70.     if ($return_as_zip !== false)
    71.     {
    72.       if (is_string($return_as_zip))
    73.       {
    74.         $name = $return_as_zip;
    75.       }
    76.       else
    77.       {
    78.         $name = 'attachments.zip';
    79.       }
    80.      
    81.       $zip = new ZipArchive;
    82.       $zip->open($name, ZIPARCHIVE::CREATE);
    83.      
    84.       foreach ($this->attachments as $attachment)
    85.       {
    86.         $zip->addFromString($attachment->name(), $attachment->data());
    87.       }
    88.      
    89.       $zip->close();
    90.       return true;
    91.     }
    92.     else
    93.     {
    94.       return $this->attachments;
    95.     }
    96.   }
    97. }
    Klasse: FileObject (stellt eine Datei dar)
    Code (PHP):
    1. class FileObject
    2. {
    3.   private $data = '';
    4.   private $name = '';
    5.  
    6.   public static function load ($name)
    7.   {
    8.     $instance = new self(file_get_contents($name));
    9.     $instance->name = $name;
    10.     return $instance;
    11.   }
    12.  
    13.   public function __construct ($data = null, $name = null)
    14.   {
    15.     if ($data !== null)
    16.     {
    17.       $this->data = $data;
    18.     }
    19.    
    20.     if ($name !== null)
    21.     {
    22.       $this->name = $name;
    23.     }
    24.   }
    25.  
    26.   public function save ($name = null)
    27.   {
    28.     if ($name === null)
    29.     {
    30.       if ($this->name === '')
    31.       {
    32.         throw new RuntimeException('invalid file name');
    33.       }
    34.      
    35.       $name = $this->name;
    36.     }
    37.    
    38.     if (($bytes = file_put_contents($name, $this->data)) === false)
    39.     {
    40.       throw new RuntimeException('could not save file as "' . $name . '"');
    41.     }
    42.     else
    43.     {
    44.       return $bytes;
    45.     }
    46.   }
    47.  
    48.   public function name ()
    49.   {
    50.     return $this->name;
    51.   }
    52.  
    53.   public function data ()
    54.   {
    55.     return $this->data;
    56.   }
    57. }
    Verwendung:
    Code (PHP):
    1. $source = ''; # Quelltext einer E-Mail
    2. $message = MailSourceParser::get($source);
    3.  
    4. # gibt ein Array mit allen Anhängen zurück oder null, wenn keine vorhanden
    5. $attachments = $message->attachments();
    6. # wähle den ersten Anhang aus
    7. $file = $attachments[0];
    8. # gib den Namen der Datei aus
    9. $file->name();
    10. # gib die Daten der Datei aus
    11. $file->data();
    12. # speichert die Datei unter dem Original-Dateinamen
    13. $file->save();
    14. # speichert die Datei unter neuem Namen
    15. $file->save('neuer_dateiname.png');
    16.  
    17. # erzeugt eine ZIP-Datei, die alle Anhänge enthält, und speichert diese
    18. # im gleichen Verzeichnis wie das Skript
    19. $message->attachments(true);
    20. # erzeugt eine ZIP-Datei, die alle Anhänge enthält, und speichert sie
    21. # unter dem angegebenen Namen
    22. $message->attachments('../attachments/anhang.zip');
    23.  
    24. # gibt alle Kopfzeilen der E-Mail zurück (nur die Kopfzeilen,
    25. # die außerhalb eines Boundary-Blocks liegen)
    26. $message->headers();
    27.  
    28. # gibt alle Blöcke zurück, die keinen Anhang darstellen
    29. $message->contents();
    Zuletzt bearbeitet: 14. Mai 2012

Diese Seite empfehlen