Stefan Rohloff: Ist es möglich, eine Mail mit Anhang zu verschicken?

Hallo,

die Einträge meines Gästebuches werden in einer Datei gast.txt gespeichert. Ich würde mir gerne automatisch bei jedem neuen Eintrag die gesamte Datei gast.txt als eine Art Backup schicken lassen. Ist es in PHP möglich, eine Mail mit solch einer Datei als Anhang zu verschicken?

Liebe Grüße, Stefan

  1. hi,

    Ist es in PHP möglich, eine Mail mit solch einer Datei als Anhang zu verschicken?

    Sieht fast so aus.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
  2. Hallo Stefan,

    [...] Ist es in PHP möglich, eine Mail mit solch einer Datei als Anhang zu verschicken?

    selbstverständlich. Es interessiert die mail()-Funktion keinen Deut, was der Parameter 'message' alles enthält. Natürlich kannst du da auch beliebige Attachments einarbeiten, wenn das Grundgerüst drumherum stimmt.

    So long,
     Martin

    --
    Paradox ist, wenn jemand eingefleischter Vegetarier ist.
  3. Danke und sorry! :)

    Habe gesucht und versucht was zu lernen.
    Bin den den Anweisungen hier gefolgt.
    Leider ist die verschickte Datei gast.txt leer.

    $Empfaenger = "test@example.com";
      $Betreff = "guestbook backup neu";
      $Dateiname = "gast.txt";
      $DateinameMail = "gast.txt";
      $Header = "From:test@example.com";
      $Trenner = md5(uniqid(time()));
      $Header .= "\n";
      $Header .= "MIME-Version: 1.0";
      $Header .= "\n";
      $Header .= "Content-Type: multipart/mixed; boundary=$Trenner";
      $Header .= "\n\n";
      $Header .= "This is a multi-part message in MIME format";
      $Header .= "\n";
      $Header .= "--$Trenner";
      $Header .= "\n";
      $Header .= "Content-Type: text/plain";
      $Header .= "\n";
      $Header .= "Content-Transfer-Encoding: 8bit";
      $Header .= "\n\n";
      $Header .= "Meine erste Mail mit Anhang!";
      $Header .= "\n";
      $Header .= "--$Trenner";
      $Header .= "\n";
      $Header .= "Content-Type: text/plain; name=$DateinameMail";
      $Header .= "\n";
      $Header .= "Content-Transfer-Encoding: 8bit";
      $Header .= "\n";
      $Header .= "Content-Disposition: attachement; filename=$DateinameMail";
      $Header .= "\n\n";
      $Dateiinhalt = fread(fopen($Dateiname, "r"), filesize($Dateiname));
      $Header .= "\n";
      $Header .= "--$Trenner--";
      mail($Empfaenger, $Betreff, "", $Header);

    Finde leider den Fehler nicht, da ich das nicht alles komplett verstehe :(

    Vielleicht liest das noch jemand und kann helfen.

    Also, die Mail kommt an, der Text "Meine erste Mail mit Anhang!" ist auch da, der Anhang "gast.txt" ist auch da, eben leider nur leer (bis auf ein Zeichen (Rechteck)).

    Liebe Grüße, Stefan

    1. Hallo Stefan,

      Habe gesucht und versucht was zu lernen.

      das unterscheidet dich positiv von vielen anderen, die hier manchmal fragen.

      $Header = "From:test@example.com";

      Da wäre nach dem ':' ein Leerzeichen angesagt.

      $Trenner = md5(uniqid(time()));
        $Header .= "\n";
        $Header .= "MIME-Version: 1.0";
        $Header .= "\n";

      Erstens: Warum hängst du den Zeilenumbruch nicht gleich zusammen mit der Headerzeile an, sondern in einer separaten Anweisung? Nicht dass es im Ergebnis einen Unterschied macht, aber es wäre m.E. leichter lesbar.
      Außerdem werden Headerzeilen in Mails durch CR+LF getrennt, nicht durch einen einfachen Zeilenumbruch. Das verstehen und akzeptieren zwar auch viele Mailserver, aber korrekt ist es nicht.

      $Header .= "Content-Type: multipart/mixed; boundary=$Trenner";
        $Header .= "\n\n";

      So, und mit dem doppelten Zeilenumbruch sind die Header eigentlich zu Ende. Was danach kommt, ist eigentlich der Message Body. Warum verarbeitest du das alles noch als Header?

      $Header .= "\n\n";
        $Header .= "Meine erste Mail mit Anhang!";
        $Header .= "\n";

      Müssten hier nicht auch *zwei* Zeilenumbrüche stehen?

      $Header .= "Content-Disposition: attachement; filename=$DateinameMail";
        $Header .= "\n\n";
        $Dateiinhalt = fread(fopen($Dateiname, "r"), filesize($Dateiname));
        $Header .= "\n";

      Tja, und hier liest du den Inhalt der Datei in eine neue Variable, die du dann aber nirgends verwendest! Außerdem würde $Dateiinhalt nur einen Teil der Datei enthalten, wenn sie entsprechend lang ist, weil fread() nicht unbedingt die gesamte Datei am Stück liest.

      mail($Empfaenger, $Betreff, "", $Header);

      Okay, du übergibst zwar keinen Message Body, aber da du alles über den Parameter $Header abhandelst, würde das im Endeffekt trotzdem funktionieren - formal ist es aber eigentlich nicht richtig.

      Also, die Mail kommt an, der Text "Meine erste Mail mit Anhang!" ist auch da, der Anhang "gast.txt" ist auch da, eben leider nur leer (bis auf ein Zeichen (Rechteck)).

      Ja, das wundert mich nun nicht mehr ...  ;-)

      Schönen Abend noch,
       Martin

      --
      Butterkeksverteiler zu werden ist vermutlich eine der wenigen beruflichen Perspektiven, die sich noch bieten, wenn man einen an der Waffel hat.
        (wahsaga)
      1. hi,

        Außerdem würde $Dateiinhalt nur einen Teil der Datei enthalten, wenn sie entsprechend lang ist, weil fread() nicht unbedingt die gesamte Datei am Stück liest.

        Dafür hat er ja die Dateigröße als zweiten Parameter an fread übergeben.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hallo wahsaga,

          Außerdem würde $Dateiinhalt nur einen Teil der Datei enthalten, wenn sie entsprechend lang ist, weil fread() nicht unbedingt die gesamte Datei am Stück liest.
          Dafür hat er ja die Dateigröße als zweiten Parameter an fread übergeben.

          das hilft aber nur bedingt. Die Beschreibung zu fread() sagt, dass die Funktion spätestens nach 8192 Bytes unterbricht, aber dieses Limit scheint sogar implementierungsabhängig zu sein. Erst kürzlich berichtete hier jemand von Problemen mit fread(), weil immer nur die ersten 1024 Bytes der gewünschten Datei gelesen wurden.

          Deswegen *muss* man fread() in eine Schleife packen und solange weiterlesen, bis das Dateiende erreicht ist. Es ist kein Zufall, dass man Schleifen dieser Art häufig sieht:

          while (!feof($file))  
           { $buffer .= fread($file, BLOCKSIZE);  
           }
          

          So long,
           Martin

          --
          Mir geht es gut. Ich mag die kleinen Pillen, die sie mir dauernd geben.
          Aber warum bin ich ans Bett gefesselt?
          1. Hallo Martin.

            Es ist kein Zufall, dass man Schleifen dieser Art häufig sieht:

            while (!feof($file))

            { $buffer .= fread($file, BLOCKSIZE);
            }

              
            Bei der Existenz von [file_get_contents](http://de.php.net/manual/de/function.file-get-contents.php) durchaus.  
              
              
            Einen schönen Dienstag noch.  
              
            Gruß, Mathias  
            
            -- 
            ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)  
              
            debian/rules
            
            1. Hallo Mathias!

              Bei der Existenz von file_get_contents durchaus.

              Du würdest also beim Einlesen der Textdatei statt mit einer Schleife lieber mit file_get_contents arbeiten ... ?

              Liebe Grüße, Stefan

              1. Hallo Stefan.

                Bei der Existenz von file_get_contents durchaus.

                Du würdest also beim Einlesen der Textdatei statt mit einer Schleife lieber mit file_get_contents arbeiten ... ?

                Ja.

                Einen schönen Mittwoch noch.

                Gruß, Mathias

                --
                ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)
                debian/rules
      2. Hallo Martin!

        Hmm, das ist immer das Problem, wenn man etwas Fremdes nimmt und versucht es seinen Bedürfnissen anzupassen. Scheint ja ein paar Ungereimtheiten zu enthalten, dieses Script ... danke jedenfalls!

        Tja, und hier liest du den Inhalt der Datei in eine neue Variable, die du dann aber nirgends verwendest! Außerdem würde $Dateiinhalt nur einen Teil der Datei enthalten, wenn sie entsprechend lang ist, weil fread() nicht unbedingt die gesamte Datei am Stück liest.

        Oh, wie peinlich!! :)

        Das kam so: Hier steht (unten):
        "Neben einer GIF-Grafik als Anhang können Sie natürlich auch jede beliebige Datei anhängen, müssen dann aber den 'Content-Type' und 'Content-Transfer-Encoding' ändern sowie den Schritt der Encodierung ($Header .= chunk_split(base64_encode($Dateiinhalt)); bei 8bit-Anhängen weglassen."

        Da .txt 8bit ist, habe ich also die angesprochene Zeile wie beschrieben weggelassen. Mir ist nicht aufgefallen, dass dann mit $Dateiinhalt gar nichts mehr passiert!

        Na ja, werde mich da nochmal reinhängen ... scheint schwieriger zu sein, als man auf den ersten Blick vermutet, so einenen txt-Anhang zu verschicken.

        Liebe Grüße, Stefan

  4. Hallo,
    dank eurer Tipps funktioniert es jetzt. Ich bin mir aber nicht sicher, ob es nur funktioniert, oder ob es auch formal richtig so ist. Ich frage, weil das alles sehr neu für mich ist. Z.B. ist mir die Bedeutung der Lücken und /n in diesem Zusammenhang nicht so recht klar ...

    Also, Ziel war es ja, dass mir die Datei gast.txt also Mailanhang zugeschickt wird. Die Mail braucht keinen Text zu enthalten. Das funktioniert soweit mit folgenden Zeilen:

    $backup=file_get_contents('gast.txt');
    $Header="From: test@example.com\n";
    $Header.="MIME-Version: 1.0\n";
    $Header.="Content-Type: text/plain; name=gast.txt\n";
    $Header.="Content-Transfer-Encoding: 8bit\n";
    $Header.="Content-Disposition: attachment; filename=gast.txt";
    mail("test@example.com","guestbook backup",$backup,$Header);

    Stefan

    1. Hallo Stefan.

      dank eurer Tipps funktioniert es jetzt. Ich bin mir aber nicht sicher, ob es nur funktioniert, oder ob es auch formal richtig so ist. Ich frage, weil das alles sehr neu für mich ist. Z.B. ist mir die Bedeutung der Lücken und /n in diesem Zusammenhang nicht so recht klar ...

      Welcher Lücken?

      $Header="From: test@example.com\n";
      $Header.="MIME-Version: 1.0\n";
      $Header.="Content-Type: text/plain; name=gast.txt\n";
      $Header.="Content-Transfer-Encoding: 8bit\n";

      Wie Martin schon sagte: Mailheader müssen per CRLF (\r\n) separiert werden, LF allein wird nur von toleranten MTAs akzeptiert.

      Einen schönen Mittwoch noch.

      Gruß, Mathias

      --
      ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)
      debian/rules
      1. Danke für deine Antwort :)

        Welcher Lücken?

        Ich meine die nach From: und nach MIME-Version: usw.

        $Header="From: test@example.com\n";
        $Header.="MIME-Version: 1.0\n";
        $Header.="Content-Type: text/plain; name=gast.txt\n";
        $Header.="Content-Transfer-Encoding: 8bit\n";

        Wie Martin schon sagte: Mailheader müssen per CRLF (\r\n) separiert werden, LF allein wird nur von toleranten MTAs akzeptiert.

        Ok, dann werde ich alle \n durch \r\n ersetzen.
        Ich kannte die Abkürzung CR+LF nicht ...

        Muss nach

        Content-Disposition: attachment; filename=gast.txt

        auch \r\n oder \r\n\r\n stehen oder ist es am Ende des Headers nicht nötig?

        Stefan

        1. Hallo Stefan.

          Welcher Lücken?

          Ich meine die nach From: und nach MIME-Version: usw.

          Laut der verlinkten RFC nicht. Das Einfügen der Leerzeichen hat also lediglich optischen Charakter.

          $Header="From: test@example.com\n";
          $Header.="MIME-Version: 1.0\n";
          $Header.="Content-Type: text/plain; name=gast.txt\n";
          $Header.="Content-Transfer-Encoding: 8bit\n";

          Wie Martin schon sagte: Mailheader müssen per CRLF (\r\n) separiert werden, LF allein wird nur von toleranten MTAs akzeptiert.

          Ok, dann werde ich alle \n durch \r\n ersetzen.
          Ich kannte die Abkürzung CR+LF nicht ...

          Muss nach

          Content-Disposition: attachment; filename=gast.txt

          auch \r\n oder \r\n\r\n stehen oder ist es am Ende des Headers nicht nötig?

          Bei HTTP könnte ich dir eindeutig beantworten, beim Mailformat bin ich mir jedoch nicht sicher. Schaden kann es jedenfalls nicht, den letzten Mailheader so zu terminieren und damit den Mail-Headerbereich eindeutig zu beenden.

          Einen schönen Mittwoch noch.

          Gruß, Mathias

          --
          ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)
          debian/rules
          1. Bei HTTP könnte ich dir eindeutig beantworten, beim Mailformat bin ich mir jedoch nicht sicher. Schaden kann es jedenfalls nicht, den letzten Mailheader so zu terminieren und damit den Mail-Headerbereich eindeutig zu beenden.

            Meinst du mit "so" \r\n oder \r\n\r\n?

            Liebe Grüße, Stefan

            1. Hallo Stefan.

              Bei HTTP könnte ich dir eindeutig beantworten, beim Mailformat bin ich mir jedoch nicht sicher. Schaden kann es jedenfalls nicht, den letzten Mailheader so zu terminieren und damit den Mail-Headerbereich eindeutig zu beenden.

              Meinst du mit "so" \r\n oder \r\n\r\n?

              Einfache Header mit „\r\n“, *den letzten* mit „\r\n\r\n“.

              Einen schönen Mittwoch noch.

              Gruß, Mathias

              --
              ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)
              debian/rules
              1. Danke!

                Stefan :)