Finestre.  Virus.  I Quaderni.  Internet.  ufficio.  Utilità.  Autisti


E-mail- questo è lo strumento più importante per lo scambio di informazioni, e se lo usi per lavoro, allora devi esserti imbattuto in una situazione: arriva una lettera per posta, che contiene i dati necessari per l'elaborazione da parte di uno script. Parleremo della posta Yandex - in questo articolo condividerò con voi, cari lettori, l'esperienza di come far uscire le lettere dalla cassetta delle lettere, analizzeremo anche l'opzione quando la lettera ha un file allegato - come rilevarlo e eventualmente scaricarlo per ulteriori manipolazioni su di esso.

Io stesso ho affrontato questo compito molto tempo fa e poi, avendo poca esperienza con i programmi di posta Yandex, ho impiegato molto tempo e nervi per ottenere il risultato desiderato. Il mio primo errore è stato che, come molti sviluppatori web, ho iniziato a cercare intensamente esempi simili sul web, ma non ho utilizzato l'help (help) di Yandex stesso. Sì, ci sono informazioni utili lì, anche se sono molto piccole, ma sono abbastanza importanti per scrivere questo tipo di script (ne parleremo più avanti). A quel tempo, era necessario scrivere uno script, la cui essenza era: una lettera con un listino prezzi delle merci in formato xls veniva inviata alla posta Yandex del cliente una volta al giorno, doveva essere elaborata (analizzata e confrontata con i dati dal database del negozio online e, a seconda del risultato, qualcosa da aggiornare da qualche parte, disabilitare o abilitare).

E la prima cosa che faremo prima di scrivere la sceneggiatura è delineare il nostro piano d'azione, che consisterà in nove punti:

  1. Configurare la posta per ottenere l'accesso tramite i protocolli di posta;
  2. Descriviamo la struttura stessa Applicazioni PHP e decidere la codifica del file;
  3. Facciamo conoscenza con il protocollo di posta IMAP e le sue capacità;
  4. Connettiti alla posta Yandex tramite il login e la password dell'account e tieni traccia degli errori in questa fase;
  5. Elaboriamo l'intestazione della lettera;
  6. Riceviamo ed elaboriamo il corpo della lettera;
  7. Ottenere e salvare i file allegati;
  8. Visualizziamo il lavoro svolto;
  9. Traiamo conclusioni.

L'argomento è piuttosto voluminoso, ma cercherò di esporre tutto nel modo più compatto e chiaro possibile. Forse cominciamo.

Configurazione della posta

Vai alla tua posta e vai alle impostazioni, come mostrato nello screenshot qui sotto:



Ora siamo entrati nelle impostazioni per la posta tramite i protocolli IMAP e POP3:


Qui molti vedranno un'immagine come nell'immagine sopra, ma mi sono imbattuto, e più di una volta, quando l'accesso è disabilitato. Pertanto, se le tue impostazioni sono diverse, seleziona le caselle come nello screenshot, l'importante per noi è consentire l'accesso tramite il protocollo IMAP.

Struttura dell'applicazione e sua codifica

In questo esempio, non troveremo una struttura applicativa complessa, poiché non è necessaria, ma aggiungeremo solo ciò che è necessario (lavoro nell'editor Sublime Text):


  • tmp - cartella in cui caricheremo gli eventuali allegati dalla lettera;
  • .htaccess - impostazione lato server se ne hai server Apache;
  • functions.php - aggiungeremo qui le nostre funzioni;
  • main.css - file di stile;
  • index.php - punto di ingresso dell'applicazione;

Useremo la codifica UTF-8 e quindi riempiremo immediatamente il file .htaccess con le seguenti righe:

AddDefaultCharset utf-8 AddCharset utf-8 * CharsetSourceEnc utf-8 CharsetDefault utf-8

Protocollo IMAP

Tornando al primo punto, è chiaro che puoi lavorare anche con la posta Yandex tramite il protocollo POP3. Allora perché esattamente IMAP? Dei due, IMAP è il più nuovo e alternativo a POP3, quindi ha una serie di vantaggi (trovabili su wikipedia), ma nel nostro caso la scelta è stata influenzata solo dal fatto che è più recente. Personalmente, non vedo molta differenza su cosa usare sotto compito specifico ricevere una lettera. Se per qualche motivo è necessario utilizzare il protocollo POP3, tutte le funzioni che si applicano a IMAP funzioneranno per lui.

Connessione alla posta Yandex tramite il protocollo IMAP

Per poterci connettere alla posta, abbiamo bisogno di conoscere tre parametri: l'accesso alla posta, la sua password e l'indirizzo server email. Se non ci sono problemi con due parametri, il secondo può essere trovato in Yandex. Ho scritto di questo (il problema che ho avuto) sopra e ho scritto molti esempi sulla rete in cui il terzo parametro non è specificato correttamente e, immagina che gli errori si verifichino già nella fase di connessione, questo è almeno spiacevole. Non tergiversare e fornirò immediatamente un collegamento diretto alla pagina Yandex - collocamento programmi di posta elettronica . Ecco cosa dobbiamo collegare:


Ora puoi andare direttamente al codice stesso:

Header("Tipo di contenuto: text/html; charset=utf-8"); segnalazione_errori(0); require_once("funzioni.php"); $mail_login = "yandex_mail"; $mail_password = "mail_password"; $mail_imap = "(imap.yandex.ru:993/imap/ssl)"; // Elenco dei tipi di file da considerare $mail_filetypes = array("MSWORD"); $connessione = imap_open($mail_imap, $mail_login, $mail_password); if(!$connection)( echo("Connessione mail fallita - ".$mail_login); exit; )else( $msg_num = imap_num_msg($connection); $mails_data = array(); for($i = 1; $ i<= $msg_num; $i++){ /* Работать с каждым письмом из IMAP-потока будем тут */ } } imap_close($connection);

Prima di tutto, specifichiamo inoltre la codifica UTF-8 utilizzando l'intestazione e disattiviamo la visualizzazione degli errori. Colleghiamo il file functions.php e specifichiamo le impostazioni discusse sopra. Nell'array $mail_filetypes, specifichiamo i formati di file di cui abbiamo bisogno. Si è deciso di farlo per eliminare la spazzatura non necessaria e ricevere file specifici. La connessione alla posta viene effettuata utilizzando la funzione imap_open(), che restituisce un flusso IMAP in caso di successo e false in caso di errore (ma se abiliti la visualizzazione degli errori, non è così). Finiamo di lavorare con gli stream usando la funzione imap_close (), passandogli un indicatore di connessione. Tra queste due funzioni c'è un normale operatore condizionale.

Se la connessione ha successo, utilizzando imap_num_msg(), scopriamo il numero di lettere nella posta e aggiungiamo un array in cui inseriremo tutti i dati di cui abbiamo bisogno dallo stream. Questo è seguito da un ciclo in cui ogni lettera verrà elaborata dal suo numero (la numerazione inizia da 1) separatamente.

Elaborazione dell'intestazione dell'e-mail

Per ottenere l'intestazione dell'email, è necessario utilizzare la funzione imap_header(), il cui secondo parametro è il numero dell'email:

// Intestazione email $msg_header = imap_header($connessione, $i);

A questo punto, riceveremo un oggetto da cui estrarremo i dati di cui abbiamo bisogno, salvandoli nell'array $mails_data. Ecco un esempio di una delle lettere:

Questo screenshot mostra che tutti i dati sono duplicati, ma questo non gioca un ruolo speciale, tiriamo ciò che è più conveniente. Molto più importante è la codifica della riga dell'oggetto. Può essere qualsiasi cosa e questo momento deve essere controllato. La stessa situazione è con il corpo della lettera e con i file allegati.

$mails_data[$i]["time"] = ora($msg_header->MailDate); $mails_data[$i]["date"] = $msg_header->MailDate; foreach($msg_header->a as $data)( $mails_data[$i]["to"] = $data->mailbox."@".$data->host; ) foreach($msg_header->from as $ data)( $mails_data[$i]["from"] = $data->mailbox."@".$data->host; )

Memorizziamo nel nostro array: un timestamp, la data di ricezione della lettera, l'email del destinatario e del mittente e procediamo a ricevere l'oggetto della lettera. Per fare ciò, dobbiamo prima aggiungere tre funzioni al file functions.php:

Funzione check_utf8($charset)( if(strtolower($charset) != "utf-8")( return false; ) return true; ) function convert_to_utf8($in_charset, $str)( return iconv(strtolower($in_charset), "utf-8", $str); ) funzione get_imap_title($str)( $mime = imap_mime_header_decode($str); $title = ""; foreach($mime as $key => $m)( if(!check_utf8 ($m->charset))( $title .= convert_to_utf8($m->charset, $m->text); )else( $title .= $m->text; ) ) return $title; )

I nomi sono autoesplicativi e, credo, valga la pena spiegare solo l'ultima funzione. Prende una stringa codificata e la decodifica usando imap_mime_header_decode() , che restituisce un array di oggetti, ognuno dei quali ha due proprietà charset (codifica) e text (testo del tema). Quindi tutto è semplice: in un ciclo, controllando la codifica, lo convertiamo in UTF-8 e incolliamo l'oggetto in un'unica intestazione e lo restituiamo.

Ora torniamo al file index.php ed estraiamo l'ultimo parametro:

$mails_data[$i]["title"] = get_imap_title($msg_header->subject);

Questo completa l'elaborazione dell'intestazione della lettera.

Lavorare con il corpo della lettera

Continuiamo a formare gradualmente il nostro array con i dati e-mail elaborati e ora dobbiamo utilizzare due funzioni per ottenere il corpo:

// Corpo del messaggio $msg_structure = imap_fetchstructure($connection, $i); $msg_body = imap_fetchbody($connessione, $i, 1);

La prima variabile $msg_structure contiene la struttura della lettera - questo è un oggetto in cui puoi trovare la massa informazioni utili, un esempio di parte di questo oggetto è mostrato di seguito:

Cosa è importante per risolvere il nostro problema:

  • tipo - il tipo principale del corpo della lettera, a seconda di ciò che ci arriva per posta, può variare da 0 a 7 (ogni cifra indica il proprio tipo di contenuto che si trova nel corpo della lettera);
  • encoding - body transfer encoding, varia da 0 a 5 (0 - 7BIT, 1 - 8BIT, 2 - BINARY, 3 - BASE64, 4 - QUOTED-PRINTABLE, 5 - OTHER);
  • parts è un array di parti di lettere che corrisponde alla struttura dell'oggetto di un livello superiore.

Diamo un'occhiata più da vicino alla proprietà delle parti. La prima cosa da dire è che nella cella zero di questo array ci sono informazioni che corrispondono esattamente al testo della lettera e, a partire dalla prima, ai file allegati. Inoltre, in ogni tipo di oggetto è specificato e nei parametri la codifica è esplicita e implicita.

La struttura della lettera può essere annidata quanto vuoi, almeno ho avuto casi in cui ha raggiunto quattro o cinque livelli, quindi per irritarla, come si suol dire, dovremo scrivere una funzione ricorsiva in futuro.

La seconda funzione imap_fetchbody() recupera una parte specifica dell'e-mail, il più delle volte in forma codificata.

Ora aggiungiamo una variabile in cui salveremo la versione elaborata del corpo della lettera:

$corpo = "";

Torniamo al file functions.php e scriviamo una funzione ricorsiva:

Funzione recursive_search($structure)( $encoding = ""; if($structure->subtype == "HTML" || $structure->type == 0)( if($structure->parameters->attribute == " charset")( $charset = $structure->parameters->value; ) return array("encoding" => $structure->encoding, "charset" => strtolower($charset), "subtype" => $structure- >sottotipo); )else( if(isset($struttura->parti))( return ricerca_ricorsiva($struttura->parti); )else( if($struttura->parametri->attributo == "charset")( $ charset = $struttura->parametri->valore; ) return array("codifica" => $struttura->codifica, "charset" => strtolower($charset), "sottotipo" => $struttura->sottotipo); ) ) )

La funzione recursive_search() accetta un parametro: la struttura della lettera, dove controlla in sequenza le proprietà e ottiene tre parametri: encoding, charset, subtype. Il punto di uscita dalla ricorsione è l'assenza della proprietà delle parti con cella zero. Non c'è altro da spiegare qui, penso che sia chiaro dal codice cosa sta succedendo e come.

Aggiungiamo un'altra funzione per convertire il corpo della lettera, di cui avremo bisogno in futuro:

Function structure_encoding($encoding, $msg_body)( switch((int) $encoding)( case 4: $body = imap_qprint($msg_body); break; case 3: $body = imap_base64($msg_body); break; case 2: $body = imap_binary($msg_body); break; case 1: $body = imap_8bit($msg_body); break; case 0: $body = $msg_body; break; default: $body = ""; break; ) return $body ;)

$recursive_data = recursive_search($msg_structure); if($recursive_data["encoding"] == 0 || $recursive_data["encoding"] == 1)( $body = $msg_body; ) if($recursive_data["encoding"] == 4)( $body = structure_encoding($recursive_data["encoding"], $msg_body); ) if($recursive_data["encoding"] == 3)( $body = structure_encoding($recursive_data["encoding"], $msg_body); ) if($ recursive_data["encoding"] == 2)( $body = structure_encoding($recursive_data["encoding"], $msg_body); ) if(!check_utf8($recursive_data["charset"]))( $body = convert_to_utf8($ recursive_data["charset"], $msg_body); )

Dopo aver ricevuto i dati dalla ricorsione, controlliamo gradualmente la codifica di trasferimento e, in base a ciò, chiamiamo la funzione structure_encoding () con i parametri appropriati. Nell'ultimo dichiarazione condizionale prendiamo in considerazione che stiamo lavorando in UTF-8 e se dopo tutte le manipolazioni otteniamo qualcosa di diverso dalla codifica, lo ricodificheremo.

Resta da tracciare una linea:

$mails_data[$i]["body"] = base64_encode($body);

Il corpo della lettera può contenere sia testo semplice che markup HTML con i propri stili. Codifichiamo in BASE64 in modo che il nostro layout non vada storto durante il rendering.

Files allegati

Qui, stiamo gradualmente arrivando alla fine della scrittura della nostra applicazione:

// File nidificati if(isset($msg_structure->parts))( for($j = 1, $f = 2; $j< count($msg_structure->parti); $j++, $f++)( if(in_array($msg_structure->parts[$j]->subtype, $mail_filetypes))( $mails_data[$i]["attachs"][$j]["type"] = $msg_structure->parti[$j]->sottotipo; $mails_data[$i]["attachs"][$j]["size"] = $msg_structure->parti[$j]->bytes; $mails_data[ $i]["attachs"][$j]["name"] = get_imap_title($msg_structure->parts[$j]->parameters->value); $mails_data[$i]["attachs"][$ j]["file"] = structure_encoding($msg_structure->parts[$j]->encoding, imap_fetchbody($connection, $i, $f)); file_put_contents("tmp/".iconv("utf-8" , "cp1251", $mails_data[$i]["attachs"][$j]["name"]), $mails_data[$i]["attachs"][$j]["file"]); ) ) )

Il pezzo responsabile dell'elaborazione del file allegato è molto più piccolo, e ora - perché esattamente. Il principio di lavorare con un file è simile a quello di lavorare con il corpo di una lettera, solo che questa fase inizia con la sua presenza nell'array della proprietà parts. Non dimenticare di filtrare quelli non necessari, facendo riferimento all'elenco dei tipi. Usando la semplice funzione file_put_contents(), salviamo il nostro file sul nostro server nella cartella tmp.

Voglio vedere il risultato!

Nel corso del lavoro, abbiamo formato un array con i dati $mails_data e per la visualizzazione lavoreremo già direttamente con esso. In questo articolo, ho usato una lettera di prova che avevo per posta, vediamo cosa abbiamo ottenuto alla fine:


Questo è il tipo di array che dovresti ottenere, ahimè, ho dovuto nascondere il contenuto del file per motivi personali. Ora passiamo al nostro markup HTML:

Posta Yandex |<?php echo($mail_login);?>

Posta Yandex (Posta in arrivo) |

Numero di lettere:

niente lettere
$mail):?>
Timestamp:
Data di:
A cui:
Da:
Soggetto:
Lettera in base64:
Files allegati:
$allegare):?>
Tipo:
Dimensione (in byte):
Nome:
Corpo:

Non aggiungerò stili qui, poiché non svolgono un ruolo speciale, di conseguenza:


E sul server nella cartella tmp avrai un file.

Conclusione

Dopo aver completato tutti i passaggi dell'articolo, otterrai il risultato corretto, ma non tutto è così semplice come potrebbe sembrare: ci sono delle insidie ​​​​che devono essere prese in considerazione. Quando si scrive una sceneggiatura per un'attività specifica, è necessario seguire la codifica in tutte le fasi, le lettere possono provenire da messaggi diversi, ognuno dei quali può avere le proprie sfumature. Sarà inoltre importante tenere conto del fatto che la posta Yandex e la relativa documentazione vengono aggiornate periodicamente, pertanto potrebbero essere visualizzate varie voci secondarie per lavorare con i programmi di posta. Questo è tutto per me, spero che questo articolo ti sia utile quando lavori con una versione di livello inferiore della posta Yandex.

Impossibile ricevere e-mail con allegato
se la posta viene inviata con un file - qualsiasi - il testo della lettera scompare

aiutami per favore

È chiaro ... se trasferisci la posta da Yandex a Yandex, allora tutto funziona ...
tipo di capito
ma è per questo che questo script non accetta altri file oltre a Word, non è chiaro ... c'è una riga MSWORD accanto, separata da virgole, metti sia PDF che JPG e PNG - solo Word legge e salva normalmente ... . qualcosa come questo

Un possibile utilizzo delle funzioni imap è creare un demone di posta che gestirà l'iscrizione e la cancellazione degli utenti dalla tua mailing list. Per eseguire questa operazione, nelle mailing list vengono generalmente utilizzati due metodi. Il primo presuppone che l'utente debba accedere a una determinata pagina e confermare le proprie azioni, il secondo richiede l'invio di un'e-mail. Il secondo richiede anche che il gestore di script venga eseguito regolarmente da cron daemon-om. Per questo motivo, non è così popolare come il primo metodo.

Ma, come puoi vedere, gli invii più seri utilizzano il secondo metodo. Quindi, se hai la possibilità di usare cron, usalo.

In realtà, capire le funzioni non è difficile. Possono sorgere alcune difficoltà con l'analisi delle intestazioni delle lettere che lo script elaborerà.

L'algoritmo dello script stesso è facile da inventare. Il demone stabilisce una connessione al server di posta e verifica la presenza di messaggi su di esso. Se non ci sono lettere, lo script si interrompe. Se sono presenti lettere, vengono analizzate le intestazioni della prima lettera. Vengono cercati i campi from e subject. Se il campo oggetto contiene una delle due opzioni di intestazione valide (sottoscrizione o disiscrizione), allora il record corrispondente al valore del campo from diventa attivo (confermato) o rimosso dalla tabella. In entrambi i casi, una notifica corrispondente sulle azioni dello script viene inviata all'indirizzo specificato nel campo from. L'e-mail viene quindi contrassegnata per l'eliminazione. Se l'oggetto non contiene oggetti validi, viene inviata una notifica di errore e anche l'e-mail viene contrassegnata per l'eliminazione. Lo script passa quindi all'e-mail successiva. Dopo aver finito di analizzare tutte le lettere, cancella la scatola.

La funzione imap_open viene utilizzata per aprire la casella di posta. Poiché PHP supporta più protocolli, è necessario specificare esplicitamente quale protocollo viene utilizzato per lavorare con il box. Nel nostro caso si tratta di pop3 sulla porta 110 (standard). Assegniamo il risultato dell'esecuzione dello script alla variabile $my_box.

$my_box = imap_open("(you.pop.host/pop3:110)", "login", "password");

Successivamente vedrai che questa variabile verrà utilizzata in quasi tutte le funzioni imap. Quindi, controlla la cassetta postale per le lettere. Il controllo viene eseguito dalla funzione imap_num_msg.

$n = imap_num_msg($my_box);

Di conseguenza, la variabile $n conterrà il numero di lettere nella casella di posta. Questo numero può essere maggiore di zero o uguale ad esso (se la casella è vuota). Se ci sono lettere, nel ciclo while analizziamo le lettere, aumentando in sequenza il numero della lettera di uno. Si noti che la prima lettera nella casella avrà il numero 0, così come il primo elemento dell'array. Per aumentare il numero della lettera, assegniamo il valore 0 alla variabile $m, e poi, nelle condizioni del ciclo, lo incrementiamo di un $m++.

Due funzioni sono sufficienti per analizzare le intestazioni che ci interessano: imap_header e imap_fetch_overview . Per eseguire ciascuno di essi, oltre alla casella, è necessario indicare il numero della lettera. Nel nostro caso, all'interno del ciclo, sarà uguale alla variabile $m.

imap_header restituisce un oggetto contenente informazioni esaustive sull'intestazione del messaggio come risultato dell'esecuzione. Tra l'altro, questo oggetto contiene un array da cui contiene quattro valori. Questi sono personali, adl, casella di posta e host. Di questi, siamo interessati solo alla casella di posta e all'host. Sostituendoli, otterremo l'indirizzo da cui è stata inviata la lettera.

$h = imap_header($my_box, $m); $h = $h->da; foreach ($h as $k => $v) ( $mailbox = $v->mailbox; $host = $v->host; $personal = $v->personal; $email = $mailbox . "@" . $host;

imap_fetch_overview - ci permetterà di scoprire l'oggetto della lettera. Per gli stessi scopi, potrebbe essere utilizzato anche imap_header, ma per una serie di motivi a volte potrebbe non funzionare. Dall'array restituito da questa funzione, abbiamo solo bisogno del campo oggetto

$s = imap_fetch_overview($my_box, $m); foreach ($s as $k => $v) $subj = $v->subject;

I nostri prossimi passi sono estrarre l'e-mail dal database e, se è presente, contrassegnare l'intera riga con questa voce come o eliminarla. Supponiamo che dopo aver compilato il modulo di posta sul sito, all'abbonato venga assegnato lo stato 0 e, dopo aver confermato l'iscrizione, passi a 1.

If ($subj == "subscribe") ( mysql_query("update subscribe set stat=1 where email=$my_email"); $del = imap_delete($my_box, $m); mail($email, $add_sbj, $add_text , $headers); ) else if ($subj == "unsubscribe") ( mysql_query("cancella da subscribe where email = $my_email"); $del = imap_delete($my_box, $m); mail($email, $ del_sbj, $del_text, $headers); ) else ( $del = imap_delete($my_box, $m); mail($email, $err_sbj, $err_text, $headers); ) dopo tutte le azioni, lo script cancella la casella. $clear = imap_expunge($my_box);

Questo programma semplicissimo è solo una dimostrazione del fatto che PHP può scrivere non solo siti che cambiano dinamicamente, ma anche servizi che non sono affatto visibili all'utente.

Elenco dell'intero programma ad eccezione dei parametri di connessione al database:

includere "config.php"; // connessione al database $my_box = imap_open("(you.pop.host/pop3:110)", "login", "password"); $n = imap_num_msg($my_box); $ m = 0; $add_text = "Grazie per aver confermato la tua iscrizione"; $add_sbj = "hai aggiunto!"; $del_text = "Sei stato rimosso dalla mailing list. "; $del_sbj = "elimina dalla lista"; $err_text = "Spiacente, ma questa casella di posta è utilizzata solo per l'amministrazione della mailing list"; $err_sbj = "errore"; $headers = "da: sottoscrivi robot x-mailer: php4 content-type: text/plain; charset=windows-1251 "; if($n != 0) ( while($m++< $n) { $h = imap_header($my_box, $m); $s = imap_fetch_overview($my_box, $m); $h = $h->da; foreach ($h as $k =>$v) ( $mailbox = $v->mailbox; $host = $v->host; $personal = $v->personal; $email = $mailbox . "@" . $host; $my_email = mysql_escape_string($email); ) foreach ($s as $k => $v) $subj = $v->subject; if ($subj == "iscriviti") ( mysql_query("update table set stat=1 where email=$my_email"); //print mysql_error(); $del = imap_delete($my_box, $m); mail($ email, $add_sbj, $add_text, $headers); ) else if ($subj == "unsubscribe") ( mysql_query("cancella dalla tabella dove email = $my_email"); $del = imap_delete($my_box, $m) ; mail($email, $del_sbj, $del_text, $headers); ) else ( $del = imap_delete($open_box, $m); mail($email, $err_sbj, $err_text, $headers); ) $clear = imap_expunge($mia_scatola); )

Nell'elenco mancano alcuni dettagli, come una possibile conversione da win a koi, controllo della casella di posta del mittente, ecc. Questi sono già eccessi funzionali che tutti possono aggiungere secondo necessità.

Un possibile utilizzo delle funzioni imap è creare un demone di posta che gestirà l'iscrizione e la cancellazione degli utenti dalla tua mailing list. Per eseguire questa operazione, nelle mailing list vengono generalmente utilizzati due metodi. Il primo presuppone che l'utente debba accedere a una determinata pagina e confermare le proprie azioni, il secondo richiede l'invio di un'e-mail. Il secondo richiede anche che il gestore di script venga eseguito regolarmente da cron daemon?om. Per questo motivo, non è così popolare come il primo metodo.

Ma, come puoi vedere, gli invii più seri utilizzano il secondo metodo. Pertanto, se hai l'opportunità di usare crond, usalo.

In realtà, capire le funzioni non è così difficile. Una persona che ha lavorato in precedenza per PHP capirà facilmente come lavorare con loro. Possono sorgere alcune difficoltà con l'analisi delle intestazioni delle lettere che lo script elaborerà.

L'algoritmo dello script stesso è facile da inventare. Il demone stabilisce una connessione al server di posta e verifica la presenza di messaggi su di esso. Se non ci sono lettere, lo script si interrompe.
Se sono presenti lettere, vengono analizzate le intestazioni della prima lettera. Vengono cercati i campi from e subject. Se il campo oggetto contiene una delle due opzioni di intestazione valide (sottoscrizione o disiscrizione), allora il record corrispondente al valore del campo from diventa attivo (confermato) o rimosso dalla tabella. In entrambi i casi, una notifica corrispondente sulle azioni dello script viene inviata all'indirizzo specificato nel campo from. L'e-mail viene quindi contrassegnata per l'eliminazione. Se l'oggetto non contiene oggetti validi, viene inviata una notifica di errore e anche l'e-mail viene contrassegnata per l'eliminazione. Lo script passa quindi all'e-mail successiva.
Dopo aver finito di analizzare tutte le lettere, cancella la scatola.

Non annoierò il lettore con i diagrammi di flusso, quindi andiamo dritti al punto. La funzione imap_open viene utilizzata per aprire la casella di posta. Poiché PHP supporta più protocolli, è necessario specificare in modo esplicito quale protocollo viene utilizzato per lavorare con la casella. Nel nostro caso si tratta di POP3 sulla porta 110 (standard). Assegniamo il risultato dell'esecuzione dello script alla variabile $my_box.


Successivamente vedrai che questa variabile verrà utilizzata in quasi tutte le funzioni imap. Quindi, controlla la cassetta postale per le lettere. Il controllo viene eseguito dalla funzione imap_num_msg.

$n = imap_num_msg ($my_box );

Di conseguenza, la variabile $n conterrà il numero di lettere nella casella di posta. Questo numero può essere maggiore di zero o uguale ad esso (se la casella è vuota).
Se ci sono lettere, nel ciclo while analizziamo le lettere, aumentando in sequenza il numero della lettera di uno. Si noti che la prima lettera nella casella avrà il numero 0, così come il primo elemento dell'array.
Per aumentare il numero della lettera, assegniamo il valore 0 alla variabile $m, e poi, nelle condizioni del ciclo, lo incrementiamo di un $m++.

Per analizzare gli header che ci interessano bastano due funzioni: imap_header e imap_fetch_overview. Per eseguire ciascuno di essi, oltre alla casella, è necessario indicare il numero della lettera. Nel nostro caso, all'interno del ciclo, sarà uguale alla variabile $m.

Imap_header restituisce come risultato dell'esecuzione un oggetto contenente informazioni complete sull'intestazione del messaggio. Tra l'altro, questo oggetto contiene un array da cui contiene quattro valori. Questi sono personali, adl, casella di posta e host. Di questi, siamo interessati solo alla casella di posta e all'host. Sostituendoli, otterremo l'indirizzo da cui è stata inviata la lettera.


$h = $h -> da ;
UN
foreach ($h as $k => $v ) (
$cassetta postale = $v -> casella postale ;
$host = $v -> host ;
$personale = $v -> personale ;
$e-mail = $casella di posta . ? @¬. $ host ;

imap_fetch_overview - ci farà sapere l'oggetto dell'e-mail. Per gli stessi scopi, potrebbe essere utilizzato anche imap_header, ma per una serie di motivi a volte potrebbe non funzionare. Dall'array restituito da questa funzione, abbiamo solo bisogno del campo oggetto


foreach ($s as $k => $v ) (
$subj = $v -> soggetto ;
}

I nostri prossimi passi sono estrarre l'e-mail dal database e, se è presente, contrassegnare l'intera riga con questa voce come "verificata" o eliminarla. Supponiamo che dopo aver compilato il modulo di posta sul sito, all'abbonato venga assegnato lo stato 0 e, dopo aver confermato l'iscrizione, passi a 1.

if ($subj == "ISCRIVITI" ) (
mysql_query( "UPDATE iscriviti SET stat=1 WHERE email=$my_email");

}
mysql_query( "CANCELLA DA iscriviti WHERE email = $mia_email");
$del = imap_delete ($my_box , $m );
}
altro(
$del = imap_delete ($my_box , $m );
}

come accennato in precedenza, dopo aver eseguito tutte le azioni, lo script cancella la casella.


Questo semplicissimo programma è solo una dimostrazione del fatto che in PHP è possibile scrivere non solo siti che cambiano dinamicamente, ma anche servizi che non sono affatto visibili all'utente. Ovviamente, in termini di shell scripting, PHP non è applicabile, a differenza del suo concorrente Perl, ma comunque ...

Elenco dell'intero programma ad eccezione dei parametri di connessione al database (db.php):

includere "db.php" ;
$my_box = imap_open ("(you.pop.host/pop3:110)" , "login" , "password" );
$n = imap_num_msg ($my_box );
$ m = 0 ;
$aggiungi_testo = "

Grazie per aver confermato la tua iscrizione " ;
$add_sbj = "Hai aggiunto!" ;
$del_testo = "

Siamo spiacenti, ma questa casella di posta è in uso.
solo per l'amministrazione della distribuzione" ;
$err_sbj = "Errore" ;
$intestazioni = Da: Iscriviti Robot

Mailer: PHP4

Tipo di contenuto: testo/semplice; set di caratteri=UTF-8
" ;
if($n != 0 ) (
mentre($m++< $n ) {
$h = imap_header ($my_box , $m );
$s = imap_fetch_overview ($my_box , $m );
$h = $h -> da ;
foreach ($h as $k => $v ) (
$cassetta postale = $v -> casella postale ;
$host = $v -> host ;
$personale = $v -> personale ;
$e-mail = $casella di posta . "@". $ host ;
$mia_email = mysql_escape_string($email );
}
foreach ($s as $k => $v ) (
$subj = $v -> soggetto ;
}
if ($subj == "ISCRIVITI" ) (
mysql_query( "UPDATE table SET stat=1 WHERE email=$my_email");
//stampa mysql_error();
$del = imap_delete ($my_box , $m );
mail ($email, $add_sbj, $add_text, $headers);
}
elseif ($subj == "UNSUBSCRIBE" ) (
mysql_query( "DELETE FROM tabella WHERE email = $mia_email");
$del = imap_delete ($my_box , $m );
posta ($email, $del_sbj, $del_testo, $headers);
}
altro(
$del = imap_delete ($open_box , $m );
mail ($email, $err_sbj, $err_text, $headers);
}
}
$clear = imap_expunge($my_box);
}
?>

L'altro giorno ho avuto l'incarico di scrivere un piccolo modulo PHP che mi permettesse di lavorare con la posta in arrivo. Cercando un po 'su Google, ho visto che uno dei protocolli mi si addice per questo compito POP3 E IMAP.
Ma la scelta era ovvia che avrei utilizzato IMAP, poiché è più funzionale e più moderno del protocollo POP3.

Ora dovevo capire rapidamente come lavorare con i protocolli IMAP, come ricevere lettere dal server di posta Yandex/Google.

Per un lavoro più conveniente, ho scelto la biblioteca PhpImap, poiché può implementare rapidamente e facilmente tutte le attività di cui ho bisogno.

Connessione a un server di posta.

Ora che abbiamo deciso la scelta del protocollo e la scelta della libreria, proveremo a connetterci al server di posta.

Affinché PHP funzioni completamente con il protocollo IMAP, è necessario connettere l'estensione php_imap.dll/imap.so nel file php.ini.

Per cominciare, proviamo a connetterci alla posta Yandex, poiché ho avuto meno problemi con essa.

//Includi librerie include("/phpImap/Mailbox.php"); include("/phpImap/IncomingMail.php"); //Per comodità, creiamo delle costanti per la connessione al server di posta. define("MAIL_IMAP_SERVER", "imap.yandex.ru"); define("MAIL_IMAP_SERVER_PORT", 993); define("MAIL_IMAP_LOGIN", " "); define("MAIL_IMAP_PASS", "example_pass"); define("MAIL_IMAP_PATH", "(".MAIL_IMAP_SERVER.":".MAIL_IMAP_SERVER_PORT."/imap/ssl)INBOX"); $mailbox = new PhpImap\Mailbox(MAIL_IMAP_PATH, MAIL_IMAP_LOGIN, MAIL_IMAP_PASS, __DIR__); try ( $mailbox->getImapStream(); ) catch (Exception $e) ( die($e->getMessage()); )

Come vediamo il costruttore di classe Cassetta postale accetta i seguenti argomenti:

  • MAIL_IMAP_PATH- Contiene l'indirizzo del server (MAIL_IMAP_SERVER), la porta di connessione (MAIL_IMAP_SERVER_PORT), il tipo di connessione (imap) e indica che la connessione sarà crittografata (ssl). Dopo le parentesi graffe specifichiamo la cartella alla quale ci collegheremo, in questo caso, ai messaggi in arrivo (INBOX).
  • MAIL_IMAP_LOGIN- La casella di posta a cui ci collegheremo.
  • MAIL_IMAP_PASS- Password (molto spesso questa è la password della casella di posta).
  • __DIR__- Questo è il percorso della cartella in cui verranno salvati gli allegati e i messaggi di posta.

Successivamente, verificheremo se la nostra connessione è stata creata tramite il metodo getImapStream() se per qualche motivo la connessione non viene creata, l'applicazione genera eccezioni con il motivo della connessione non riuscita.

È importante tenere conto del fatto che nelle impostazioni della posta Yandex potresti avere la possibilità di connetterti utilizzando il protocollo IMAP disabilitato.

Ora confrontiamo la connessione alla posta di Gmail.

Define("MAIL_IMAP_SERVER", "imap.gmail.com"); define("MAIL_IMAP_SERVER_PORT", 993); define("MAIL_IMAP_LOGIN", " "); define("MAIL_IMAP_PASS", "example_pass"); define("MAIL_IMAP_PATH", "(".MAIL_IMAP_SERVER.":".MAIL_IMAP_SERVER_PORT."/imap/ssl)INBOX");

Come possiamo vedere, praticamente non differisce dalla connessione precedente, ma molto probabilmente otterrai un'eccezione quando ti connetti al server.
Questo problema è legato al fatto che Il protocollo IMAP di Gmail è disabilitato per impostazione predefinita. Puoi abilitarlo nelle impostazioni nella scheda Inoltro e POP/IMAP nell'opzione Accesso IMAP ⇒ Abilita IMAP.

Dopo aver abilitato il protocollo IMAP, dobbiamo farlo creare la password dell'app. Per poterlo creare, dobbiamo creare un'autorizzazione a due fattori per questo profilo. Quindi puoi iniziare a crearlo. Quando creiamo una nuova password per l'applicazione, dovremo inserirla nella costante MAIL_IMAP_PASS per connetterci al server.

Tieni presente che durante la creazione di una password per l'applicazione, potresti non essere in grado di connetterti al server, ciò è dovuto al fatto che questa password non è stata ancora completamente applicata al servizio Gmail, in genere sono necessari 5-60 minuti.

Campionamento dei dati

Dopo una connessione riuscita, possiamo eseguire una richiesta per ricevere messaggi di flusso dal server. Per questo useremo il metodo searchMailBox(stringa $criteri) che è essenzialmente un metodo wrapper imap_search. È importante capire qui che l'argomento $criteria è un certo criterio per trovare i messaggi di cui abbiamo bisogno, il metodo stesso restituisce gli identificatori degli elementi che in seguito ci saranno utili per ottenere informazioni dettagliate sul messaggio di posta.

$mailsIds = $mailbox->searchMailBox("ALL");

Come avrai intuito, qui riceviamo tutti i messaggi.
E ora proviamo a trattare con altri criteri di ricerca altrettanto importanti:

//Tutti i messaggi per 3 giorni. $mailsIds = $mailbox->searchMailBox("SINCE "".date("d-M-Y",strtotime("-3 day"))."""); //Messaggi non letti per 3 giorni. $mailsIds = $mailbox->searchMailBox("UNSEEN SINCE "".date("d-M-Y",strtotime("-3 day"))."""); //Cerca i messaggi con questa corrispondenza nell'intestazione TEXT. $mailsIds = $mailbox->searchMailBox("TESTO "Newsletter""); //Cerca i messaggi con questa corrispondenza nell'intestazione BODY. $mailsIds = $mailbox->searchMailBox("BODY "Messaggio informativo""); //Cerca per email del mittente. $mailsIds = $mailbox->searchMailBox("FROM " ""); //Ricevi i messaggi in base all'intestazione SUBJECT $mailsIds = $mailbox->searchMailBox("SUBJECT "Sono stati rilasciati aggiornamenti per il tuo telefono"");

Questo esempio cattura bene le basi dell'utilizzo dei criteri di ricerca.

Ricevere le informazioni

Ora che abbiamo un array di ID messaggio, siamo pronti per elaborarlo:

//Ottiene l'ID dell'ultimo messaggio dall'array. $id = fine($mailsIds); //Ottieni un'istanza dell'oggetto classe IncomingMail che contiene informazioni sul messaggio. $mail = $casella->getMail($id); //Prendi i file allegati a questo messaggio se esiste. $mail->getAttachments(); //Visualizza i messaggi. echo $posta->testoHtml;

Quindi abbiamo ricevuto messaggi dalla nostra lettera e dai suoi allegati senza problemi.

Caratteristiche aggiuntive.

Questa libreria contiene anche una serie di metodi utili per un lavoro più conveniente con i messaggi di posta:

Salviamo i messaggi in base al suo ID.

$casella->saveMail($id,$id..eml");

Imposta i messaggi come non letti in base al loro ID.

$casella di posta->markMailAsUnread($id);

Imposta i messaggi come letti dal loro id.

$casella di posta->markMailAsRead($id);

Mettiamo un segno sul messaggio con il suo id.

$casella di posta->markMailAsImportant($id);

Elimina i messaggi in base al loro ID.

Alcune applicazioni Web potrebbero richiedere un'e-mail specifica per l'utente. In tal caso, possiamo scrivere il nostro codice e-mail SquirrelMail o Roundcube. Indipendentemente da quale scegli, sapere come lavorare con la posta IMAP sarà utile.

Come lavorare con IMAP in PHP è descritto su due pagine. Nella prima pagina, le funzioni necessarie per connettersi ai server di posta e leggere i messaggi. Nella seconda pagina parleremo di lavorare con la posta elettronica, ad esempio, eliminare messaggi, scaricare applicazioni, ecc...

Per dimostrare la funzionalità, verranno utilizzati esempi di codice che possono essere utilizzati per eseguire script del client di posta nativo.

Parametri URL per chiamare le funzioni richieste:

  • func - il tipo di funzione necessaria (ad esempio: leggere la posta, visualizzare la casella di posta, eliminare il messaggio)
  • cartella - nome della cartella della casella di posta per la connessione (ad esempio: Posta in arrivo, Posta inviata, spam)
  • uid - identificatore di posta elettronica univoco

I parametri possono essere recuperati con $_GET e switch può essere utilizzato per invocare le azioni appropriate.

Connessione a un server IMAP

Per stabilire una connessione al server IMAP, utilizziamo la funzione imap_connect(), come mostrato di seguito:

Il percorso del messaggio, il nome utente e la password sono i parametri richiesti per connettersi al server. Puoi conoscere le opzioni aggiuntive nel manuale.

Il percorso della casella di posta è una stringa che identifica il server e la porta tra parentesi graffe specifica il nome della cartella di posta desiderata.

Ecco alcune righe per la cartella posta in arrivo Servizi Postali:

  • Posta in arrivo di Gmail (imap.gmail.com: 993/imap/ssl).
  • Posta in arrivo di Yahoo (imap.mail.yahoo.com: 993/imap/ssl).
  • AOL (imap.aol.com: 993/imap/ssl) INBOX

Alcuni server non hanno SSL abilitato, nel qual caso dovrai omettere "SSL" dalla riga. Altri server possono utilizzare i propri certificati, in cui è necessario includere "NOVALIDATE-CERT".

Con la connessione al server di posta aperta, possiamo ora dare un'occhiata alle funzioni utilizzate per le seguenti attività:

  • Visualizza un elenco di cartelle della casella di posta nel tuo account di posta elettronica
  • Visualizza un elenco di messaggi e-mail in una cartella
  • Visualizza il contenuto dell'e-mail di un autore

Cartelle di posta elettronica

posta in arrivo , Inviato , Spazzatura E Spam- Queste cartelle sono visibili in quasi tutti gli account di posta elettronica e gli utenti possono spesso creare le proprie cartelle. Per visualizzare i messaggi in queste cartelle, dobbiamo modificare la nostra stringa di connessione. Ad esempio, applicare "INBOX" (Posta in arrivo) nella stringa del percorso in precedenza. Se hai bisogno di connetterti alla tua cartella spam, usa invece qualcosa come "Spam". Ma mentre può essere elencato come Spam a un account di posta elettronica, se visualizzato tramite un client di posta elettronica, il nome effettivo delle cartelle in background potrebbe essere diverso. Possiamo elencare tutte le cartelle esistenti in un account usando imap_list() .

"; foreach ($cartelle come $cartella) ( $cartella = str_replace("(imap.gmail..php?folder=" . $cartella . "&func=view">" . $cartella . ""; ) eco "";

Dobbiamo passare l'handle di connessione ottenuto da imap_open() come parametro iniziale a imap_list() . Dobbiamo anche passare il percorso (senza la cartella, ad esempio "INBOX"). Come terzo parametro, richiedi tutte le cartelle disponibili.

Notifica messaggio

Ogni cartella contiene un elenco di messaggi di posta elettronica disponibili, quindi vediamo come possiamo creare un elenco di messaggi nella nostra casella di posta.

Per prima cosa devi ottenere il numero di messaggi disponibili con imap_num_msg() . Possiamo quindi utilizzare la funzione imap_header() per ottenere informazioni per l'intestazione di ciascun messaggio.

Diciamo se vogliamo le ultime 20 email:

($numMessaggi - 20); $i--) ( $header = imap_header($imap, $i); $fromInfo = $header->from; $replyInfo = $header->reply_to; $details = array("fromAddr" => (isset($ fromInfo->mailbox) && isset($fromInfo->host)) ?$fromInfo->mailbox ."@" .$fromInfo->host: "", "fromName" => (isset($fromInfo->personal)) ?$fromInfo->personal: "", "replyAddr" => (isset($replyInfo->mailbox) && isset($replyInfo->host)) ?$replyInfo->mailbox . "@" . $replyInfo->host : "", "replyName" => (isset($replyTo->personal)) ? $replyto->personal: "", "subject" => (isset($header->subject)) ? $header->subject : "", "udate" => (isset($header->udate)) ? $header->udate: ""); $uid = imap_uid($imap, $i); echo "

    "; eco "
  • Da:" . $dettagli["daNome"]; echo " " . $dettagli["daAddr"] . "
  • "; eco "
  • Soggetto:" .$dettagli["oggetto"] ..php?folder=" . $cartella. "&id=" . $uid ..php?folder=" . $cartella . "&uid=" . $uid . "&func=delete">Elimina
  • "; eco "
"; }

Le connessioni $Imap devono essere aperte nella cartella corretta. Possiamo quindi scorrere le ultime 20 e-mail utilizzando il numero di messaggi ricevuti da imap_num_msg() . Il contatto e il numero di posta elettronica vengono forniti a imap_header() per ottenere informazioni sull'intestazione, che possono quindi essere scambiate per informazioni interessanti dal mittente, indirizzo e-mail, nome, oggetto, ecc.

Si prega di notare che il numero di posta elettronica dal numero totale di messaggi non è un identificatore univoco per il messaggio. Se hai 100 email nella tua casella di posta, l'ultimo numero sarà 100, il precedente sarà 99 e così via. Se elimini il messaggio numero 100 e poi ricevi un nuovo messaggio, il suo numero sarà 100.

Per procedere con i seguenti passaggi, è necessario ottenere un identificatore univoco per l'e-mail. Ogni e-mail ha un ID univoco chiamato UID che possiamo ottenere fornendo l'e-mail, la funzione per il numero imap_uid() UID è univoca e non cambierà nel tempo.

Visualizzazione del contenuto di un messaggio

Leggere la posta elettronica non è così facile come le attività precedenti, quindi è necessario utilizzare le classi di posta sviluppate da Mitul Koradia. La classe ha adattato le seguenti tre funzioni per il nostro esempio qui sotto:

encoding) ( caso 3: return imap_base64($text); caso 4: return imap_qprint($text); default: return $text; ) ) // multipart if ($structure->type == 1) ( foreach ($structure ->parts as $index => $subStruct) ( $prefix = ""; if ($partNumber) ( $prefix = $partNumber . "."; ) $data = get_part($imap, $uid, $mimetype, $ subStruct, $prefix .($index + 1)); if ($data) ( return $data; ) ) ) ) return false; ) funzione get_mime_type($structure) ( $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); if ($structure ->subtype) ( return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype; ) return "TEXT/PLAIN"; )

La funzione GetBody() ottiene il contenuto dell'e-mail passando la sua connessione UID e IMAP. All'interno della funzione, chiamiamo la funzione get_part() con il tipo di contenuto text / HTML. I messaggi di posta elettronica in testo normale sono molto più facili da leggere. Quindi proviamo prima a trovare il contenuto HTML all'interno dell'e-mail.

Quindi leggiamo la struttura dell'email usando la funzione imap_fetchstructure(). Abbiamo cambiato le funzioni della libreria per usare l'UID invece di passare sempre l'FT_UID.

Quindi otteniamo il tipo MIME del messaggio di posta elettronica utilizzando la funzione get_mime_type(). Esistono otto tipi MIME restituiti da questa funzione come numeri interi:

  • 0-TESTO
  • 1 - MULTIPART
  • 2 - MESSAGGIO
  • 3 – DOMANDA
  • 4-AUDIO
  • 5 - IMMAGINE
  • 6 - VIDEO
  • 7-ALTRO

Trasformiamo il ritorno nel tipo MIME effettivo della stringa usando array di tipi MIME.

I messaggi composti possono avere un gran numero di sottotipi, quindi esaminiamo ricorsivamente tutti i sottotipi utilizzando la parte numerica e recuperiamo l'e-mail utilizzando imap_fetchBody() quando viene trovato quello corretto utilizzando il tipo mime.

Quindi, utilizziamo la funzione di decodifica appropriata in base alla codifica del tipo di messaggio e restituiamo il contenuto. Elenco completo dei tipi di codifica disponibili:

  • 0-7bit
  • 1-8bit
  • 2-BINARIO
  • 3-BASE64
  • 4 - CITATO-STAMPABILE
  • 5-ALTRO

Conclusione

Abbiamo finito di rivedere le basi della connessione a un server IMAP, elencando i messaggi all'interno delle cartelle disponibili e finito di leggere il contenuto di un messaggio di posta elettronica. Nella pagina successiva del post, parleremo delle funzioni che possono essere utilizzate per implementare funzionalità aggiuntive del client di posta, come l'eliminazione dei messaggi e l'elaborazione degli allegati.

Se noti un errore, seleziona una parte di testo e premi Ctrl + Invio
CONDIVIDERE: