Probleme mit PHP-IMAP und Abfragen einer Mailbox

Mordor

Registered User
Hallo zusammen.
Ich habe ein Problem mit dem Aufbau einer IMAP-Verbindung über PHP
Diese benötige ich um eine Mail auszulesen in der bilder im anhang sind, die dann auf dem Server gespeichert werden sollen. Nur es scheitert schon bei der Abfrage der Mailbox. Die Verbindung funktioniert.

Hier das Testskript:
PHP:
$mbox = imap_open("{mail.meinserver.tld:143/imap/novalidate-cert} INBOX", 'fotoupload@meinedomain.tld', 'password');
if($mbox == FALSE)
{
    echo 'Verbindung fehlgeschlagen';
    $err = imap_errors();
    print_r($err);
}
else
{
    $head = imap_headers($mbox);
    print_r($head);
    $info = imap_check($mbox);
    var_dump($info);
}
imap_close($mbox);
Also, die Verbindung wird aufgebaut, und im Ordner new auf dem Server liegt auch eine neue Nachricht drin. Nur gibt mir die Funktion imap_headers zwar ein Array zurück, jedoch ist dieses leer. Die Funktion imap_check gibt mir auch ein Objekt zurück, jedoch ist unter $info->Nmsg der wert 0. PHP sagt also, dass keine Nachricht da ist. Gehe ich jedoch in das dementsprechende Verzeichnis, so kann ich sehen, dass hier eine neue Mail liegt.

Die PHP-Anwendung läuft auf einem Testserver bei mir zu Hause (Debian ETCH vps mit open-vz Host, PHP5.2 mit imap-Erweiterung). Der IMAP-Server läuft auf meinem Root(Debian ETCH mit Postfix und Courier-IMAP)

Die Frage ist jetzt, warum er die Nachricht, die schon auf dem Server liegt nicht auslesen kann und diese auch nicht sieht. Liegt es an Coruier, oder an PHP???

Danke schon mal

Gruß Mordor
 
So, ich habe jetzt nochmals einen imap_errors Befehl vor dem Imap_close eingefügt. Dieser gibt folgendes aus:
Code:
Mailbox does not exist, or must be subscribed to.
Nur wundert mich das, dass die Mailbox eben garnicht existieren soll. Denn in Outlook kann ich sie ja auch abrufen, und dann liegen meine Mails auch alle in INBOX.
 
Na super, so einfach kannst manchmal sein.

Aber könnte das mal jemand den Jungs von php.net sagen, denn hier in der Beschreibung zu imap_open steht das mit Leerschritt bei den Beispielen ;-)
PHP: imap_open - Manual

Danke für die Hilfe auf jeden Fall.
 
Und weiter gehen die Probleme:

Ich kann mittlerweile die Header sauber auslesen, und auch den Body. Ich kann also die ganze Mail auseinandernehmen. Nur ein Problem habe ich, was das ganze Projekt stopt.

Ich möchte gerne die Bilder, die als Anhang in den Mails drin sind, auf dei Platte des Servers schreiben. Nur funktioniert das leider nicht. Der Code sieht momentan so aus:
PHP:
$mbox = imap_open("{mail.meinserver.tld:143/novalidate-cert}INBOX", 'fotoupload@domain.tld', 'password');
if($mbox == FALSE)
{
    //Bei fehlgeschlagenem Verbindungsaufbau
    echo 'Verbindung fehlgeschlagen';
    $err = imap_errors();
    print_r($err);
}
else
{
    //Lese Anzahl Mails
    $info = imap_check($mbox);
    if($info->Nmsgs >= 1)
    {
        for($i=1;$i<=$info->Nmsgs;$i++)
        { 
            //Hole Anhang
            $actmail = imap_fetchstructure($mbox, $i);
            $headerinfo = imap_headerinfo($mbox, $i);
            $partsinmail = count($actmail->parts);
            if($partsinmail>=2)
            {
                for($p=1;$p<$partsinmail;$p++)
                {
                    //Lese einzelne Anhänge und kodiere
                    $inhalt = imap_fetchbody($mbox, $i, $p+1);
                    $inahlt1 = imap_base64($inhalt);
                    
                    //Schreibe Anhänge in Datei
                    $fp = fopen($i.$p.'.jpg', 'w+');
                    fwrite ($fp, $inhalt1) or die ("Schreibfehler!");
                    fclose($fp);
                }
            }
        }
    }
}
imap_close($mbox);

Das Problem ist, dass er zwar den Inhalt der Variable $inhalt1 in die Datei schreibt, rufe ich diese aber über den Browser auf, so bekomme ich nur den Namen und Pfad der Datei zu sehen.

EDIT:
So, insgesamt liegen 2 E-Mails mit Bildgrößen zwischen 400 und 800KB auf dem Server. In der ersten Mail sind 2 Bilder, in der zweiten Mail 5 Bilder. Das Lustige ist, dass er aus der zweiten Mail, das zweite Bild speichert, die anderen aber nicht. Die anderen Files sind alle nur 41 Bytes groß.
Die PHP-Memory-Einstellungen habe ich schon mal höher gesetzt, was aber nichts gebracht hat.
Gruß Mordor
 
Last edited by a moderator:
Und wieder einen Schritt weiter!

Das Problem ist anscheinend, dass wenn ich die bilder mit Entourage für Apple losschicke, das Mailprogramm die JPEGs so codiert, dass sie PHP nicht sauber mit base64 wandeln kann. Sobald ich sie mit einem anderen Mailprogramm losschicke, oder von einema anderen Rechner, funktioniert es. Auch wenn ich im Entourage die Codierung des anhangs auf Windows MIME-Type stelle funktioniert es.

Jetzt stellt sich mir die Frage, ob es eine Möglichkeit gibt, die bilder auch mit einer Applecodierung zu wandeln.
 
Als MIME-Type wird ein octet-stream angegeben.

Ich hab jetzt schon mal nach der Codierung nachgesehen, aber irgendwie finde ich da nichts, wie man diese MIME richtig decodiert.

Hier mal die Ausgabe eines imap_fetchstructure für einen Part der Mail, wo eben so eine JPEG drin ist:
Code:
stdClass Object ( 
  [type] => 1 
  [encoding] => 0 
  [ifsubtype] => 1 
  [subtype] => APPLEDOUBLE 
  [ifdescription] => 0 
  [ifid] => 0 
  [ifdisposition] => 0 
  [ifdparameters] => 0 
  [ifparameters] => 1 
  [parameters] => Array ( 
     [0] => stdClass Object ( 
          [attribute] => boundary 
          [value] => B_3314112411_20313546 ) ) 
  [parts] => Array ( 
     [0] => stdClass Object ( 
          [type] => 3 
          [encoding] => 3 
          [ifsubtype] => 1 
          [subtype] => APPLEFILE 
          [ifdescription] => 0 
          [ifid] => 0 
          [bytes] => 72018 
          [ifdisposition] => 1 
          [disposition] => attachment 
          [ifdparameters] => 1 
          [dparameters] => Array ( 
               [0] => stdClass Object ( 
                    [attribute] => filename 
                    [value] => IMG_0055.JPG ) ) 
          [ifparameters] => 1 
          [parameters] => Array ( 
               [0] => stdClass Object ( 
                    [attribute] => name 
                    [value] => IMG_0055.JPG ) ) ) 
     [1] => stdClass Object ( 
          [type] => 3 
          [encoding] => 3 
          [ifsubtype] => 1 
          [subtype] => OCTET-STREAM 
          [ifdescription] => 0 
          [ifid] => 0 
          [bytes] => 455162 
          [ifdisposition] => 1 
          [disposition] => attachment 
          [ifdparameters] => 1 
          [dparameters] => Array ( 
               [0] => stdClass Object ( 
                    [attribute] => filename 
                    [value] => IMG_0055.JPG ) ) 
          [ifparameters] => 1 
          [parameters] => Array ( 
               [0] => stdClass Object ( 
               [attribute] => name 
               [value] => IMG_0055.JPG ) ) ) ) )

Gruß Mordor
 
Sorry, ich habe mich falsch ausgedrückt. Ich meinte welche Content-Transfer-Encoding verwendet wird. Hier mal ein Ausschnitt aus einer Mail, wenn man sie als Quellcode anschaut.
Code:
--------------000306070501030305070507
Content-Type: image/jpeg;
 name="FroheWeihnachten.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
 filename="FroheWeihnachten.jpg"

/9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD//gATQ3JlYXRl
...
epONvskdoWg5uoqZcKuNOAeJehHJSulunLH2PsN8QijicMosj0eaeF0jzc3+q//Z
--------------000306070501030305070507--
Der Octet-Stream-Typ ist ja ein generischer Typ, der verwendet wird, wenn nichts genaues über den Datei-Typ bekannt ist... Zur Übertragung können allerdings einige Codierungsarten verwendet werden.
 
Also, wenn ich die Mail mit Pico auf dem Server öffne, finde ich dann das hier:
Code:
--B_3314112419_20306048
Content-type: multipart/appledouble;
        boundary="B_3314112411_20313546"

--B_3314112411_20313546
Content-type: application/applefile; name="IMG_0055.JPG"
Content-transfer-encoding: base64
Content-disposition: attachment;
        filename="IMG_0055.JPG"

AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAJAA
...
uf//AAAAAAAPMMQ=
--B_3314112411_20313546
Bei einer Mail, wo es mit den Fotos funktioniert, finde ich hingegen das hier:
Code:
Content-type: application/octet-stream; name="IMG_0057.JPG"
Content-disposition: attachment;
        filename="IMG_0057.JPG"
Content-transfer-encoding: base64

Kann es sein, dass das problem in der Zeile mit Content-type: application/applefile entsteht, weil hier eben was von applefile steht???
 
Das AppleDouble-Format ist in der Tat etwas eigen ;) Es kommt also darauf an, welchen Sub-Part Du dekodierst -- der sollte dann das normale JPEG enthalten, auch wenn man es nicht vorher am MIME-Type selber ablesen kann.
 
Okay, jetzt bin ich schon mal einiges weiter, hab mir einiges an Material durchgelesen, und bin zu der Auffassung gekommen, dass das ein komisches Zeug ist ( Applefiles, Applesingle und Appledouble)

Wenn ich das richtig verstehe, schreibt der Apfel also einen Datenstream mit mehreren Forks in welchen unterschiedliche Daten drin liegen. So können in einem Fork die Header Daten der Datei liegen, in einem anderen Finder-spezifische Daten, und wieder in einem anderen die eigentlichen Daten.

So, jetzt hab ich aber ein Problem:
Ich habe eine Datei in ASCI, also meine Mail, in welcher mehrere Bereiche sind. Mein Head und Mein Body. Der Body besteht wieder aus mehreren Bereichen. Zum einen habe ich hier meinen Mail Text, der in meinem Fall in Plaintext ist, zum anderen habe ich die Anhänge die ich base64-decodiere. Nur ist es ja anscheinend so, dass mir PHP nur einen Fork decodiert und nicht die komplette Datei.
Wie schaffe ich es jetzt die Datei so zu decodieren, dass ich die komplette JPEG zurück bekomme.
 
Ich habe Deinen Code jetzt nur überflogen und da ich bisher keine Lust hatte, PHP zu lernen, mag ich auch syntaktische Feinheiten übersehen haben, aber wenn ich die Anleitung (und die Beispiele) zu imap_fetchbody anschaue, denke ich dass Du gesondert auf die Sub-Parts zugreifen musst (also nicht auf Part 2 sondern Part 2.1, usw.). YMMV!
 
Vielen Dank!!!
Das war genau der Hinweis, den ich gebraucht habe.

In einem meiner Vorposts konnte man sehen, dass das File mehrere Unterparts hat, nämlich einen der den subtype Applefile hat, und einen anderen der den subtype octet-stream hat. Ich dachte dann nach den ersten Ausführungen von dir, wie ich denn da blos drauf zugreiffen soll. Aber es ist ganz einfach, denn die Funktion imap_fetchbody ermöglicht mir das ja.
Der Aufruf der Funktion sieht ja so aus:
Code:
imap_fetchbody([emailhandle], [emailnr], [parnummer])
Bei der Partnummer kann man eine ganze Zahl eingeben. Normalerweise ist part 1 der Textteil und alle weiteren Parts (2, 3, 4) die Anhänge. Jetzt habe ich aber auch die Möglichkeit, dass ich da mehrere Zahlen mit einem Punkt getrennt angeben kann, und so erhalte ich die Unterparts. In meinem Fall würde der Aufruf für die erste Mail und den ersten Anhang so aussehen:
Code:
imap_fetchbody($mbox, '1', '2.2')

Super, vielen Dank für die Hilfe.

Gruß Mordor
 
Back
Top