Domanda

Sto cercando un codice php buono/funzionante/semplice da usare per analizzare le e-mail non elaborate in parti.

Ho scritto un paio di soluzioni di forza bruta, ma ogni volta arriva un piccolo cambiamento/intestazione/spazio/qualcosa e il mio intero parser fallisce e il progetto va in pezzi.

E prima di essere indirizzato a PEAR/PECL, ho bisogno del codice vero e proprio.Il mio host ha qualche configurazione incasinata o qualcosa del genere, non riesco mai a far sì che i file .so vengano compilati correttamente.Se riesco a realizzare il .so, alcune differenze nel percorso/ambiente/php.ini non lo rendono sempre disponibile (apache vs cron vs cli).

Oh, e un'ultima cosa, sto analizzando il testo non elaborato dell'e-mail, NON POP3 e NON IMAP.Viene convogliato nello script php tramite un reindirizzamento email .qmail.

Non mi aspetto che SOF lo scriva per me, sto cercando alcuni suggerimenti/punti di partenza per farlo "nel modo giusto".Questo è uno di quei problemi della "ruota" che so che è già stato risolto.

È stato utile?

Soluzione

Cosa speri di ottenere alla fine?Il corpo, l'oggetto, il mittente, un allegato?Dovresti passare un po' di tempo con RFC2822 per capire il formato della posta, ma ecco le regole più semplici per una posta elettronica ben formata:

HEADERS\n
\n
BODY

Cioè, la prima riga vuota (doppio ritorno a capo) è il separatore tra HEADERS e BODY.UN'INTESTAZIONE assomiglia a questa:

HSTRING:HTEXT

HSTRING inizia sempre all'inizio di una riga e non contiene spazi bianchi o due punti.HTEXT può contenere un'ampia varietà di testo, inclusi i caratteri di nuova riga purché il carattere di nuova riga sia seguito da uno spazio bianco.

Il "BODY" è in realtà qualsiasi dato che segue la prima doppia riga.(Ci sono regole diverse se trasmetti posta tramite SMTP, ma elaborandola su una pipe non devi preoccuparti di questo).

Quindi, in parole povere, intorno al 1982 RFC822 termini, un'e-mail assomiglia a questa:

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

THIS IS ANY
ARBITRARY DATA
(FOR THE MOST PART)

Tuttavia, la maggior parte delle e-mail moderne è più complessa di così.Le intestazioni possono essere codificate per set di caratteri o RFC2047 mimare parole o un sacco di altre cose a cui non sto pensando in questo momento.Al giorno d'oggi è davvero difficile eseguire il proprio codice sui corpi se si desidera che siano significativi.Quasi tutte le email generate da un MUA lo saranno MIMO codificato.Potrebbe essere testo uuencoded, potrebbe essere html, potrebbe essere un foglio di calcolo Excel uuencoded.

Spero che questo aiuti a fornire un quadro per comprendere alcuni degli elementi più elementari della posta elettronica.Se fornisci maggiori informazioni su ciò che stai cercando di fare con i dati, io (o qualcun altro) potremmo essere in grado di fornire una guida migliore.

Altri suggerimenti

Prova il parser email PHP di Plancake:https://github.com/plancake/official-library-php-email-parser

L'ho usato per i miei progetti.Funziona benissimo, è solo una classe ed è open source.

L'ho messo insieme, alcuni codici non sono miei ma non so da dove provengano...Successivamente ho adottato il più robusto "MimeMailParser" ma funziona bene, gli invio la mia email predefinita utilizzando cPanel e funziona benissimo.

#!/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());
}
?>

Ci sono funzioni Mailparse che potresti provare: http://php.net/manual/en/book.mailparse.php, tuttavia non nel php conf predefinito.

Esiste una libreria per l'analisi dei messaggi di posta elettronica non elaborati nell'array php - http://flourishlib.com/api/fMailbox#parseMessage.

Il metodo statico parseMessage () può essere utilizzato per analizzare un messaggio di posta elettronica MIME completo nello stesso formato che Returns () restituisce, meno la chiave UID.

$ parsed_message = fmailbox :: parseMessage (file_get_contents ('/path/to/email'));

Ecco un esempio di messaggio analizzato:

array(
    'received' => '28 Apr 2010 22:00:38 -0400',
    'headers'  => array(
        'received' => array(
            0 => '(qmail 25838 invoked from network); 28 Apr 2010 22:00:38 -0400',
            1 => 'from example.com (HELO ?192.168.10.2?) (example) by example.com with (DHE-RSA-AES256-SHA encrypted) SMTP; 28 Apr 2010 22:00:38 -0400'
        ),
        'message-id' => '<4BD8E815.1050209@flourishlib.com>',
        'date' => 'Wed, 28 Apr 2010 21:59:49 -0400',
        'from' => array(
            'personal' => 'Will Bond',
            'mailbox'  => 'tests',
            'host'     => 'flourishlib.com'
        ),
        'user-agent'   => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4',
        'mime-version' => '1.0',
        'to' => array(
            0 => array(
                'mailbox' => 'tests',
                'host'    => 'flourishlib.com'
            )
        ),
        'subject' => 'This message is encrypted'
    ),
    'text'      => 'This message is encrypted',
    'decrypted' => TRUE,
    'uid'       => 15
);

Questo https://github.com/zbateson/MailMimeParser funziona per me e non è necessaria l'estensione mailparse.

<?php
echo $message->getHeaderValue('from');          // user@example.com
echo $message
    ->getHeader('from')
    ->getPersonName();                          // Person Name
echo $message->getHeaderValue('subject');       // The email's subject

echo $message->getTextContent();                // or getHtmlContent

La libreria Pear Mail_mimeDecode è scritta in semplice PHP che puoi vedere qui: Sorgente Mail_mimeDecode

Probabilmente non ti divertirai molto a scrivere il tuo parser MIME.Il motivo per cui trovi "pacchetti di gestione della posta troppo sviluppati" è perché MIME è un insieme davvero complesso di regole/formati/codifiche.Le parti MIME possono essere ricorsive, il che fa parte del divertimento.Penso che la soluzione migliore sia scrivere il miglior gestore MIME possibile, analizzare un messaggio, eliminare tutto ciò che non è text/plain o text/html e quindi forzare il comando nella stringa in entrata con il prefisso COMMAND:o qualcosa di simile in modo da poterlo trovare nella melma.Se inizi con regole del genere hai buone possibilità di gestire nuovi fornitori, ma dovresti essere pronto a modificare se arriva un nuovo fornitore (o diamine, se il tuo attuale fornitore sceglie di cambiare la propria architettura di messaggistica).

L'analisi della posta elettronica in PHP non è un compito impossibile.Quello che voglio dire è che non hai bisogno di un team di ingegneri per farlo;è raggiungibile come individuo.La parte più difficile che ho trovato è stata la creazione dell'FSM per l'analisi di un risultato IMAP BODYSTRUCTURE.Da nessuna parte su Internet l'avevo visto, quindi ho scritto il mio.La mia routine crea fondamentalmente un array di array nidificati dall'output del comando e la profondità dell'array corrisponde approssimativamente ai numeri di parte necessari per eseguire le ricerche.Quindi gestisce le strutture MIME annidate in modo abbastanza elegante.

Il problema è che le funzioni imap_* predefinite di PHP non forniscono molta granularità... quindi ho dovuto aprire un socket sulla porta IMAP e scrivere le funzioni per inviare e recuperare le informazioni necessarie (IMAP FETCH 1 BODY.PEEK[1.2] per esempio), e ciò implica consultare la documentazione RFC.

La codifica dei dati (quoted-printable, base64, 7bit, 8bit, ecc.), la lunghezza del messaggio, il tipo di contenuto, ecc.ti è tutto fornito;per allegati, testo, html, ecc.Potrebbe essere necessario capire anche le sfumature del tuo server di posta poiché non tutti i campi sono sempre implementati al 100%.

La chicca è l'FSM... se hai esperienza in Comp Sci può essere davvero divertente realizzarlo (la chiave è che le parentesi non sono una grammatica regolare ;));altrimenti sarà difficile e/o si otterrà un codice brutto, utilizzando i metodi tradizionali.Inoltre hai bisogno di un po' di tempo!

Spero che questo ti aiuti!

Non sono sicuro che questo ti possa essere d'aiuto - lo spero - ma aiuterà sicuramente altri interessati a saperne di più sull'e-mail. Marco Bointon ha fatto una delle migliori presentazioni dal titolo "Mail() e la vita dopo Mail()" alla conferenza PHP di Londra nel marzo di quest'anno e diapositive E MP3 sono in linea.Parla con una certa autorità, avendo lavorato a lungo con la posta elettronica e PHP a un livello profondo.

La mia percezione è che ti trovi in ​​un mondo di dolore cercando di scrivere un parser veramente generico.

EDIT - I file sembrano essere stati rimossi sul sito PHP London;ho trovato le diapositive su Marcus proprio sito: Parte 1 Parte 2 Tuttavia non sono riuscito a vedere l'MP3 da nessuna parte

sì, sono stato in grado di scrivere un parser di base, basato su quell'rfc e alcuni altri tutorial di base.ma sono i confini nidificati del mimo multiparte che continuano a incasinarmi.

ho scoperto che i messaggi MMS (non SMS) inviati dal mio telefono sono solo e-mail standard, quindi ho un sistema che legge l'e-mail in arrivo, controlla il mittente (per consentire solo dal mio telefono) e utilizza la parte del corpo per eseguire messaggi diversi comandi sul mio server.è una specie di controllo remoto tramite e-mail.

poiché il sistema è progettato per inviare immagini, contiene un sacco di parti codificate in modo diverso.una parte mms.smil.txt, una parte text/plain (che è inutile, dice solo "questo è un messaggio html"), una parte application/smil (che è la parte su cui verrebbe visualizzato il telefono), una parte text/html con una pubblicità per il mio operatore, poi il mio messaggio, ma tutto racchiuso in html, poi infine un allegato in file di testo con il mio semplice messaggio (che è la parte che utilizzo) (se inserisco un'immagine come allegato nel messaggio, viene inserita in allegato 1, codificato base64, quindi la mia porzione di testo è allegata come allegato 2)

Funzionavo con l'esatto formato di posta del mio operatore, ma quando ho inviato un messaggio dal telefono di qualcun altro attraverso di esso, ha fallito in un sacco di modi miserabili.

Ho altri progetti a cui vorrei estendere questo sistema telefono->posta->analisi->comandi, ma ho bisogno di un parser stabile/solido/generico per estrarre le diverse parti dalla posta per usarlo.

il mio obiettivo finale sarebbe quello di avere una funzione in cui poter inserire la posta non elaborata e ottenere un grande array con sottoarray associativi di intestazioni var: coppie val e uno per il corpo del testo come un'intera stringa

più cerco e più trovo la stessa cosa:giganteschi pacchetti di gestione della posta sovrasviluppati che fanno tutto ciò che è legato alla posta, o tutorial inutili (per me, in questo progetto).

Penso che dovrò stringere i denti e scrivere attentamente qualcosa da solo.

Ho riscontrato lo stesso problema, quindi ho scritto la seguente classe:Email_Parser.Prende un'e-mail grezza e la trasforma in un oggetto carino.

Richiede PEAR Mail_mimeDecode ma dovrebbe essere facile da installare tramite WHM o direttamente dalla riga di comando.

Prendilo qui : https://github.com/optimumweb/php-email-reader-parser

PhpMimeParser semplice https://github.com/breakermind/PhpMimeParser Puoi tagliare messaggi MIME da file, stringhe.Ottieni file, HTML e immagini in linea.

$str = file_get_contents('mime-mixed-related-alternative.eml');

// MimeParser
$m = new PhpMimeParser($str);

// Emails
print_r($m->mTo);
print_r($m->mFrom);

// Message
echo $m->mSubject;
echo $m->mHtml;
echo $m->mText;

// Attachments and inline images
print_r($m->mFiles);
print_r($m->mInlineList);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top