Mails mit Dateianlagen per Upload-Formular senden mit PHP

Eine Beschreibung wie man Maildateien mit Attachments erstellt und an sendmail übergibt

Der hier vorliegende Artikel zeigt, wie das Versenden von Mails mit Dateianlagen über PHP gemacht werden kann, hier geht es also um das Verstehen. Von daher wurde auch das Uploadformular so einfach wie möglich gehalten:

<form Enctype="multipart/form-data" method="POST">
  <textarea style="width:100%" rows="7" name="mesg">
  </textarea>
  <input type="file" name="upspot[]" multiple>
  <button name="mail" value="1">Senden</button>
</form>

Dieses Formular erlaubt also das Upload mehrerer Dateien über ein Uploadfeld mit dem Namen upspot[], beachte die eckigen Klammen die dem Attribut multipart entsprechen und damit das Hochladen mehrerer Dateien über ein Uploadfeld ermöglichen. Als Nächstes betrachten wir das Template mail.attach.txt für die Maildatei:

From: %from%
To: %to%
Subject: %subject%
MIME-Version: 1.0
Content-Type: multipart/alternative;
    boundary=ABCDEFGHIJKLMNOPQRSTUVWXYZ

--ABCDEFGHIJKLMNOPQRSTUVWXYZ
Content-Type: text/plain; Charset=UTF-8
Content-Transfer-Encoding: 8Bit

%mesg%
<TMPL_LOOP NAME="attach">
--ABCDEFGHIJKLMNOPQRSTUVWXYZ
Content-Type: %type%; filename="%filename%"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="%filename%"

%base64%
</TMPL_LOOP>
--ABCDEFGHIJKLMNOPQRSTUVWXYZ--

Wie das Template zeigt, gibt es einen Schleifenkörper für jede hochgeladene Datei die da Base64-kodiert eingebaut wird. Das Template selbst wird später mit HTML::Template (PHP) gerendert. Nun zum PHP-CODE serverseitig:

# Diese Funktion arbeitet das $_FILE Array so auf
# daß es an HTML::Template übergeben werden kann
# d.h., die Platzhalter bekommen hier ihre Werte zugewiesen
function x_files($fieldname){
    $files = array();
    foreach($_FILES[$fieldname]['name'] as $i => $value){
        $hunt = array(
            'filename' => $value,
            'type'     => $_FILES[$fieldname]['type'][$i],
            'size'     => $_FILES[$fieldname]['size'][$i],
            'error'    => $_FILES[$fieldname]['error'][$i],
        );
        if( $error = $hunt['error']  ){
            continue;
        }
        if( $hunt['filename'] && $hunt['type'] ){
            $hunt['base64'] = base64_encode(
                file_get_contents($_FILES[$fieldname]['tmp_name'][$i])
            );
            array_push($files, $hunt);
        }
    }
    return $files;
}

Das nächste und auch das letzte Stückchen CODE zeigt schließlich die Verarbeitung und das Versenden der Mail infolge Übergabe an das lokale Mailtrogramm:

    if( $this->param('mail') ){
        $tmpl = file_get_contents($this->TMPLDIR."/mail.attach.txt");
        # Maildatei wird über das Template gerendert
        $mailfi = $this->xr( $tmpl, array(
            'subject' => 'Mail von '.$_SERVER['SERVER_NAME'],
            'from'    => 'from@example.com',
            'to'      => 'to@example.com',
            'mesg'    => $this->param('mesg'),
            'attach'  => $this->x_files('upspot')
        ));
        # Pipe auf das lokale Malprogramm
        if( $fh = popen("/usr/sbin/sendmail -t", "w") ){
            fputs($fh, $mailfi);
            # Monitoring zur Kontrolle
            $this->CONTENT = $mailfi;
            header("Content-Type: text/plain");
        }
        else{
            dd("Mailprogramm nicht zugänglich");
        }
    }

Hinweis: Der Pfad zum lokalen Mailprogramm ist beim Provider zu erfragen. Der hier beschriebene Mailversand ist unabhängig davon ob die Mail unverschlüsselt oder verschlüsselt übertragen wird, Letzeres fällt auch in den Zuständigkeitsbereich des Providers.


Datenschutzerklärung: Diese Seite dient rein privaten Zwecken. Auf den für diese Domäne installierten Seiten werden grundsätzlich keine personenbezogenen Daten erhoben. Das Loggen der Zugriffe mit Ihrer Remote Adresse erfolgt beim Provider soweit das technisch erforderlich ist. s​os­@rolf­rost.de.