tutorials.de Buch-Aktion 05/2012
  • Emails per IMAP in MySQL-DB und Anhänge speichern

    Für meine Seite habe ich ein Script geschrieben, welches Emails per IMAP-Verbindung ausließt.
    Hierfür verwende ich eine Catch-All Adresse, somit muss ich für registrierte Benutzer keine Adressen registrieren.
    Anhand der Empfänger-Adresse wird der User ermittel.

    Der Text wird ausgelesen, von unnötigem Content befreit und in einer MySQL-Datenbank abgespeichert.
    Attachments werden im jeweiligen Benutzer-Ordner abgespeichert, somit habe ich eine gute Kontrolle über den verbrauchten Speicherplatz des Benutzers.
    Danach wird die Email aus dem Postfach gelöscht.


    Somit kommen wir zum Code:

    Datenbank-Verbindung herstellen:
    PHP-Code:

    <?php
        $con
    mysql_connect('localhost','benutzer','passwort') or die(mysql_error());
         
    mysql_select_db('datenbankname',$con) or die(mysql_error());

    ?>
    IMAP-Verbindung herstellen:
    PHP-Code:

    <?php

    #-C-O-N-F-I-G---
    $imaphost="imap.yourdomain.com";
    $port=143;
    $username "....";
    $password "....";
    #---------------

    $mailbox '{'.$imaphost.':'.$port.'}INBOX';
    $msgp imap_open($mailbox$username$password);

    ?>
    Funktionen: (irrelevant)
    getRandomCode gibt einen Zufalls-Code mit einer bestimmten Länge zurück (a-z und 0-9)
    Somit kann man Attachments eindeutig und unique als Datei abspeichern und den Originaltitel z.b. in der Datenbank abspeichern.
    Beim Aufrufen der Datei könnte dann z.b. eine neue Datei mit dem Originaltitel erzeugt und als Header gesendet werden.

    getReqName um selbstverständlich Umlaute und Leerzeichen zu entfernen.
    PHP-Code:

    <?php

    function getRandomCode($length){
        
    $range=array('a'=>'z',0=>9);
        
    $set=array();
        foreach(
    $range as $from=>$to) {while($from<$to$set[]=$from++; $set[]=$to;}
        
    $code="";
        while(
    strlen($code)<$length$code .= $set[rand(0,count($set)-1)];
        return 
    $code;
    }


    function 
    getRepName($str){
        
    $str=strtolower($str);
        
    $str=iconv("ISO-8859-1","UTF-8",$str);
        
    $search=array('ä','ö','ü','ß',' ');
        
    $rep=array('ae','oe','ue','ss','_');
        
    $str=str_ireplace($search,$rep,$str);
        return 
    $str;
    }

    ?>


    Und dann noch der Hauptcode:
    PHP-Code:

    <?php

    if($msgp)
    {
        
    // Mailbox pruefen und Anzahl der Mails
        
    $hdr imap_check($msgp);
        if (
    $hdr) {
            
    $msgcount $hdr->Nmsgs;
        }

        
    // Header-Informationen der Email
        
    $overview=imap_fetch_overview($msgp,"1:$msgcount",0);
        
    $size=sizeof($overview);

       for(
    $i=$size-1;$i>=0;$i--){
           
    // Informationen lesen (Absender, Datum, Groesse, Betreff)
            
    $val=$overview[$i];
        
    $msg=$val->msgno;
            
    $to=$val->to;
            
    $from=$val->from;
            
    $msize=$val->size;
          
    $date=$val->date;
        
    $subj=$val->subject;


            
    // Empfänger aus Header lesen
            
    $header=imap_fetchheader($msgp,$msg);
            
    $header=str_replace('<','',$header);
            
    $header=str_replace('>','',$header);

            
    $start=strrpos($header,' To:')+4;
            
    $end=strrpos($header,'Subject:');
            
    $endb=strrpos($header,'References:');

            if(
    $endb<$end && $endb>$start$end=$endb;
            
    $headerto=trim(substr($header,$start,$end-$start));

            
    // Empfaenger auslesen (unterschiedliche Empfaenger)
            
    $accounts=array();
            foreach(
    explode(",",$headerto) as $vala)
                foreach(
    explode(' ',$vala) as $valb)
                    if(
    eregi('@',$valb) && eregi('yourdomain.com',$valb))  // nur Adressen deiner Domain
                        
    foreach(explode('@',$valb) as $valc)
                            if(!
    eregi('yourdomain.com',$valc)) $accounts[]=trim($valc);


             
    // falls header ungenügend, nimm Adresse aus overview
            
    if(empty($accounts) && ereg("@yourdomain.com",$to)){
                
    $toarr=explode("@",$to);
                
    $accounts[]=$toarr[0];
            }




            
    // DB-Eintrag vorbereiten
            
    $userarr=array();
            foreach(
    $assounts as $mailboxname)
            {
                
    $sql="select UserID,folder from usertable where mailboxname like '$mailboxname' limit 1";
                
    $result=mysql_query($sql);
                if(
    mysql_num_rows($result)){
                    
    $mailuser=mysql_fetch_assoc($result);  // User-id und Ordner
                    
    $folder=$mailuser['folder'];
                    
    $mailuser=$mailuser['UserID'];
                    
    $userarr[$mailuser]=$folder;
                }
            }
            


            
    // Informationen ausgeben (Absender, Datum, Groesse, Betreff)
            
    $msize=round($msize/1024);
            list(
    $dayName,$day,$month,$year,$time) = split(" ",$date);
            
    $time substr($time,0,5);
            
    $date $day ." "$month ." "$year " "$time;
            
    $from ereg_replace(array("\"","<",">"),array("","(",")"),$from);
            echo 
    "$from | $date | $subj | $msize KB<br>";



            
    // Text lesen
            
    $structure imap_fetchstructure($msgp$msg);
            
    $text=imap_fetchbody($msgp,$msg,1);
            if(
    $structure->encoding == 3) {  
                 
    // generelles Encoding der Email (auch in den parts möglich)
                 // foreach ($structure->parts as $part)  if($part->encoding == 3)...
                
    $text=imap_base64($text);         
            } else if(
    $structure->encoding == 4) {
                
    $text=imap_qprint($text);    
            }

            
            
    // Anhaenge lesen
            
    unset($attachment);
            
    $numparts count($structure->parts); // Anzahl der Part in der Mail
            
    if ($numparts 1) {  // Std.-mäßig Anhänge im imap_fetchbody ab $j=2
                
    $attachment=array();
                
    $j=2;
                foreach (
    $structure->parts as $part) {
                    if (
    eregi("attachment",$part->disposition)) {
                        
    $dateiname=$part->dparameters[0]->value;
                        
    $attachment[]=array($dateiname,imap_fetchbody($msgp,$msg,$j));
                        
    $j++;
                    }
                }
            }



            
    // Text vorbereiten
            
    $text=trim(strip_tags(nl2br($text)));
            
    $ignore=array('NextPart','Content-Type','charset=','Content-Transfer');   // Header und Boundary entfernen
            
    $arrtext=explode("\n",$text);
            foreach(
    $arrtext as $key=>$val){
                foreach(
    $ignore as $wrong) if(eregi($wrong,$val)) unset($arrtext[$key]);
                
    $cval=strip_tags(trim($val));     // html entfernen
                
    if(empty($cval)) unset($arrtext[$key]);
            }
            
    $arrtext=array_unique($arrtext);    // Doppelte Texteinträge entfernen  (Text ist in Mails mit Anhängen doppelt enthalten)
            
    $text=implode("<br>",$arrtext);
            echo 
    "$text<br>";



           
    // Mail speichern
            
    $subj=trim(mysql_real_escape_string($subj));
            
    $from=trim(mysql_real_escape_string($from));
            
    $sql="select ID from mailtable order by id desc limit 1";  // neue Mail-ID ermitteln
            
    $lastmailid=mysql_fetch_assoc(mysql_query($sql));
            
    $newmailid=$lastmailid['ID']+1;

            
    $savemail=false;
            foreach(
    $userarr as $userid=>$folder)
            {
                
    $sql="insert into mailtable (ID,UserID,betreff,text,datum,fromextern) values ($newmailid,$userid,'$subj','$text',NOW(),'$from')";
                if(
    mysql_query($sql)){
                    
    $savemail=true;
                    
    // Anhaenge speichern
                    
    foreach($attachment as $value){
                        
    $code=getRandomCode(20);
                        
    $fname=getRepName($value[0]);
                        
    $end=explode(".",$fname);
                        
    $end=$end[count($end)-1];
                        if(
    eregi("txt",$end)) $fvalue=imap_qprint($value[1]);  // für Textdateien
                        
    else $fvalue=imap_base64($value[1]);
                        
    $fvalue=imap_base64($value[1]);
                        
    $sqlatt="insert into UNET_attachments (mailid,user,titel,dateiname) values ($newmailid,$userid,'$fname','$code')";
                        if(
    mysql_query($sqlatt)){
                            echo 
    $dir="../".$folder."/".$code;
                            
    $fp=fopen($dir,'w');
                            
    fwrite($fp,$fvalue);
                            echo 
    "<b>saved</b><br>";
                        }
                    }
                }
            }
            
    // Delete-Flag setzen
            
    if($savemailimap_delete($msgp$msg);
        }


        
    // Nachrichten loeschen
        
    imap_expunge($msgp);
        
    // Verbindung schließen
        
    imap_close($msgp);
    }

    ?>

    Hierzu noch ein paar infos:

    $msgcount = Anzahl Mails im Postfach

    $overview = Auszug aus Nachrichten-Header imap_fetch_overview("der imap-Stream von imap_open()","Sequenz, also Nachricht von 1 bis $countmsg (1:5 z.b.)","Option siehe beschreibung");
    -> http://us2.php.net/imap_fetch_overview

    $headerto = trim(substr(......)) = alle Empfänger werden aus dem Header-Text als Teilstring geliefert,
    d.h. nur zwischen $start="To:" und $end="Subject:" wird der String zurückgeliefert
    und danach in den gestaffelten Foreach bearbeitet so das nur der Mailboxname überbleibt.


    $text=imap_fetchbody("imap_stream","nachrichtennummer","partnummer")
    Part 1 ist jeweils der Text und folgende Parts Anhänge
    dgawin bedankt sich. 


    Kommentare Kommentar schreiben

    Klicke hier, um dich anzumelden

    Was ist grün und kann quaken?