php çiğ e-posta ayrıştırma

10 Cevap php

Ben iyi / çalışma / bölüme ham e-posta ayrıştırma için php kodu kullanmak için basit arıyorum.

Ben kaba kuvvet çözümleri bir çift yazdım, ama her zaman, küçük bir değişim / başlık / alan / bir şey gelir ve benim bütün ayrıştırıcı başarısızsa ve proje yıkılır.

Ben ARMUT / PECL'de işaret olsun önce Ve, ben gerçek kodu gerekir. Benim ev sahibi bazı garip yapılandırma ya da bir şey var, ben almak gibi asla. Çok doğru inşa etmek bulunuyor. Ben alırım. Yani, yapılan yol / çevre / php.ini bazı fark zaman (CLI vs cron vs apache) kullanılabilir yapmaz.

Oh, ve son bir şey, ben çiğ e-posta metnini, DEĞİL POP3, IMAP ve DEĞİL ayrıştırma. Bu bir. Qmail e-posta yönlendirme vasıtasıyla php komut dosyası içine taşınıyor ediliyor.

Benim için yazmak SOF bekliyor değilim, ben "doğru" yapıyor bazı ipuçları / başlangıç ​​noktaları arıyorum. Bu zaten çözüldüğünü bilenler "tekerlek" sorunlardan biridir.

10 Cevap

Ne sonunda ile sona umuyor? Vücut, konu, gönderen, bir eki? Siz posta biçimini anlamak için RFC2822 ile biraz zaman harcamak gerekir, ama burada iyi biçimlendirilmiş e-posta için basit kurallar var:

HEADERS\n
\n
BODY

Yani ilk boş satır (çift satır) başlıklar ve gövde arasındaki ayırıcı vardır. Bir HEADER Bu gibi görünüyor:

HSTRING:HTEXT

HSTRING her bir satırın başında başlar ve herhangi bir beyaz boşluk veya iki nokta üst üste içermiyor. HTEXT sürece satır karakter boşluk tarafından takip edildiğinden satırsonu içeren bir metin çeşitli içerebilir.

"BODY" Gerçekten ilk çift yeni satır aşağıdaki sadece herhangi bir veridir. (SMTP üzerinden mail iletirken, ama bu konuda endişelenmenize gerek yok, bir boru onu üzerine işliyoruz eğer farklı kurallar vardır).

Yani, gerçekten basit, yaklaşık 1982 RFC822 açısından, bir e-posta bu gibi görünüyor:

HEADER: HEADER TEXT
HEADER: MORE HEADER TEXT
  INCLUDING A LINE CONTINUATION
HEADER: LAST HEADER

THIS IS ANY
ARBITRARY DATA
(FOR THE MOST PART)

En modern e-posta, o düşünceden daha karmaşık. Başlıkları karakter setlerinin veya RFC2047 mim kelime, ya da şu an düşünmüyorum, diğer şeyler bir ton için kodlanmış olabilir. Organları bunları anlamlı olmasını istiyorsanız eğer bu gün için kendi kodunuzu rulo gerçekten zor. Bir MUA tarafından oluşturulan oluyor hemen hemen tüm e-posta MIME kodlanmış olacaktır. Bu metin uuencoded olabilir, bu html olabilir, bu bir uuencoded excel elektronik tablo olabilir.

Bu e-postanın çok element kova bazıları anlamak için bir çerçeve sağlamak yardımcı olur umarım. Eğer ben (veya bir başkası) daha iyi yön vermek mümkün olabilir verilerle yapmak için çalışıyoruz ne daha fazla arka plan sağlamak durumunda.

Try the Plancake PHP Email parser: https://github.com/plancake/official-library-php-email-parser

Benim projeler için kullanmıştır. Bu harika çalışıyor, sadece bir sınıf ve açık kaynak.

Ben, birlikte bu Arnavut kaldırımlı bazı kod benim değil ama nereden geldi bilmiyorum ... Ben daha sonra daha güçlü "MimeMailParser" kabul ama bu cPanel kullanarak buna ben boru varsayılan e-posta, gayet iyi çalışıyor ve işe yarıyor harika.

#!/usr/bin/php -q
<?php
// Config
$dbuser = 'emlusr';
$dbpass = 'pass';
$dbname = 'email';
$dbhost = 'localhost';
$notify= 'services@.com'; // an email address required in case of errors
function mailRead($iKlimit = "") 
    { 
        // Purpose: 
        //   Reads piped mail from STDIN 
        // 
        // Arguements: 
        //   $iKlimit (integer, optional): specifies after how many kilobytes reading of mail should stop 
        //   Defaults to 1024k if no value is specified 
        //     A value of -1 will cause reading to continue until the entire message has been read 
        // 
        // Return value: 
        //   A string containing the entire email, headers, body and all. 

        // Variable perparation         
            // Set default limit of 1024k if no limit has been specified 
            if ($iKlimit == "") { 
                $iKlimit = 1024; 
            } 

            // Error strings 
            $sErrorSTDINFail = "Error - failed to read mail from STDIN!"; 

        // Attempt to connect to STDIN 
        $fp = fopen("php://stdin", "r"); 

        // Failed to connect to STDIN? (shouldn't really happen) 
        if (!$fp) { 
            echo $sErrorSTDINFail; 
            exit(); 
        } 

        // Create empty string for storing message 
        $sEmail = ""; 

        // Read message up until limit (if any) 
        if ($iKlimit == -1) { 
            while (!feof($fp)) { 
                $sEmail .= fread($fp, 1024); 
            }                     
        } else { 
            while (!feof($fp) && $i_limit < $iKlimit) { 
                $sEmail .= fread($fp, 1024); 
                $i_limit++; 
            }         
        } 

        // Close connection to STDIN 
        fclose($fp); 

        // Return message 
        return $sEmail; 
    }  
$email = mailRead();

// handle email
$lines = explode("\n", $email);

// empty vars
$from = "";
$subject = "";
$headers = "";
$message = "";
$splittingheaders = true;
for ($i=0; $i < count($lines); $i++) {
    if ($splittingheaders) {
        // this is a header
        $headers .= $lines[$i]."\n";

        // look out for special headers
        if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) {
            $subject = $matches[1];
        }
        if (preg_match("/^From: (.*)/", $lines[$i], $matches)) {
            $from = $matches[1];
        }
        if (preg_match("/^To: (.*)/", $lines[$i], $matches)) {
            $to = $matches[1];
        }
    } else {
        // not a header, but message
        $message .= $lines[$i]."\n";
    }

    if (trim($lines[$i])=="") {
        // empty line, header section has ended
        $splittingheaders = false;
    }
}

if ($conn = @mysql_connect($dbhost,$dbuser,$dbpass)) {
  if(!@mysql_select_db($dbname,$conn))
    mail($email,'Email Logger Error',"There was an error selecting the email logger database.\n\n".mysql_error());
  $from    = mysql_real_escape_string($from);
  $to    = mysql_real_escape_string($to);
  $subject = mysql_real_escape_string($subject);
  $headers = mysql_real_escape_string($headers);
  $message = mysql_real_escape_string($message);
  $email   = mysql_real_escape_string($email);
  $result = @mysql_query("INSERT INTO email_log (`to`,`from`,`subject`,`headers`,`message`,`source`) VALUES('$to','$from','$subject','$headers','$message','$email')");
  if (mysql_affected_rows() == 0)
    mail($notify,'Email Logger Error',"There was an error inserting into the email logger database.\n\n".mysql_error());
} else {
  mail($notify,'Email Logger Error',"There was an error connecting the email logger database.\n\n".mysql_error());
}
?>

Muhtemelen kendi MIME çözümleyici yazma çok eğlenmek için gitmiyoruz. MIME kurallar / biçimleri / kodlamaları gerçekten karmaşık bir dizi olduğu için "overdeveloped posta işleme paketleri" buluyor nedenidir. MIME parçaları eğlenceli bir parçası olan, özyinelemeli olabilir. Veya benzer bir şey: Ben senin en iyi bahis text / plain veya text / html değil her şeyi atmak, bir mesajı ayrıştırmak, size en iyi MIME işleyicisi yazmak ve sonra KOMUTANLIĞI önek gelen dize komutu zorlamak için olduğunu düşünüyorum Eğer muck bulabilirsiniz böylece. Eğer yeni sağlayıcılar elleçleme iyi bir şans var, ama yeni bir sağlayıcı (geçerli sağlayıcı mesajlaşma mimarisini değiştirmek seçerse, halt ya da) birlikte geliyor eğer oynamak için hazır olması gerektiği gibi kuralları ile başlarsanız.

http://php.net/manual/en/book.mailparse.php, değil varsayılan php conf, ancak: Eğer deneyebilirsiniz Mailparse İşlevleri vardır.

PHP e-posta ayrıştırma imkansız bir görev değildir. Demek istediğim, bunu yapmak için mühendis bir ekip gerekmez; bir birey olarak ulaşılabilir. Gerçekten ben buldum zor kısmı bir IMAP BODYSTRUCTURE sonuç ayrıştırma için FSM yaratıyor. Nowhere internette bu yüzden ben kendi yazdım bu görmüştü. Benim rutin temelde komut çıkışından iç içe diziler bir dizi oluşturur ve derinlik bir dizide kabaca aramaları gerçekleştirmek için gerekli parça numarası (ler) karşılık olduğunu. Bu yüzden oldukça zarif iç içe MIME yapılarını yönetir.

Sorun bu yüzden (IMAP 1 BODY.PEEK [1.2] getirme IMAP bağlantı noktasına bir yuva açmaya ve gerekli bilgileri göndermek ve almak için fonksiyonları yazmak zorunda kaldım ... PHP'nin varsayılan imap_ * fonksiyonları çok parçalı yapı sağlamak kalmamasıdır örneğin), ve RFC belgelerine bakarak içerir.

Veri (alıntı-basılabilir base64, 7bit, 8bit, vb) kodlama, mesaj, içerik türü, vb uzunluğu tüm size verilen; vb ekleri, metin, html, için Sen de tüm alanlar her zaman% 100 uygulanmaktadır beri posta sunucusu nüansları anlamaya olabilir.

Mücevher FSM ... Eğer Bil bir arka plan varsa (onlar anahtar parantez düzenli bir dilbilgisi ;) olmamasıdır) bu yapmak için gerçekten eğlenceli olabilir; aksi takdirde geleneksel yöntemlerle, çirkin kod bir mücadele ve / veya sonuç olacaktır. Ayrıca biraz zamana ihtiyacım var!

Bu yardımcı olur umarım!

Bu size yardımcı olacaktır emin değilim - Umarım - ama kesinlikle e-posta hakkında daha fazla şey öğrenmek isteyen başkalarına yardımcı olacaktır. Marcus Bointon başlıklı sunumlar iyi birini yaptı "(Posta) ve Mail ardından hayat ()" PHP Londra Mart konferansta bu yıl slides ve {at [(2)] } çevrimiçi. O derin bir düzeyde e-posta ve PHP ile yoğun çalışmış olan bazı yetki ile konuşur.

Düşüncem Eğer gerçekten jenerik ayrıştırıcı yazmaya çalışıyorum acı bir dünya için olmasıdır.

EDIT - dosyalar PHP Londra sitede kaldırılmış gibi görünüyor; Part 1 Part 2 olsa her yerde MP3 göremiyordu: own site Marcus 'üzerinde slaytlar bulundu

Armut lib Mail_mimeDecode Burada görebileceğiniz düz PHP ile yazılmış: Mail_mimeDecode source

evet, RFC ve diğer bazı temel eğitimlerini kapalı dayalı bir temel ayrıştırıcı, yazabilirler ive. ancak çok parçalı mim beni karıştırmasını devam sınırları iç içe.

benim telefona gönderilen MMS (değil SMS) mesajları sadece standart e-postalar vardır, bu yüzden gelen e-postaları okuyan bir sisteme sahip olduğunu öğrendim, (sadece benim telefon izin vermeyi) den denetler ve farklı çalıştırmak için vücut parçası kullanır benim sunucuda komutları. e-posta ile bir uzaktan kumanda gibi onun tür.

Sistem resim göndermek üzere tasarlanmış olmasıdır, onun farklı kodlanmış parçaları bir grup var. Bir mms.smil.txt parçası, bir metin / düz (yararsız olduğunu, sadece 'bu bir html mesaj' diyor), bir uygulama / smil bölüm (telefonları üzerinde pic olacağını parçası), bir metin / html parçası Benim taşıyıcı, sonra benim mesajın, ama bir reklam ile tüm html sarılmış, (i kullanma parçası olan) benim düz mesajıyla sonra nihayet bir Textfile eki (i mesajda ek olarak bir görüntü kıpırdamak ise, kendi put at eki 1, base64 kodlanıyor, sonra benim metin kısmı) eki 2 olarak takılır

i benim taşıyıcı tam posta biçiminde çalışma vardı, ama bunun üzerinden başkasının telefonundan mesaj çalıştırdığınızda, bu sefil yollarından bir sürü başarısız.

i bu telefon-> mail-> parse-> komut sistemini genişletmek istiyorum diğer projeleri var, ama kullanmak için postanın dışında farklı bölümlerini almak için kararlı / katı / jenerik ayrıştırıcı olması gerekir.

Benim nihai hedef i ham postayı taşınıyor yem olabilir işleve sahip olmak, ve birleştirici başlıklar var alt-dizileri ile büyük bir dizi geri almak istiyorum: val çiftleri, ve bir bütün dize olarak gövde metni için bir

postalara ilişkin güneş thats altındaki her şeyi, ya da (bu projede, benim için) yararsız öğreticiler yapılacak dev overdeveloped posta işleme paketleri: daha ben bu arama, daha fazla i aynı şeyi bulabilirsiniz.

i kabullenmesini ve sadece dikkatle benim öz bir şey yazmak zorunda gidiyorum düşünüyorum.