MokaByte
Numero 02 - Novembre 1996
|
|||
|
|
||
Luca Bertoncello |
lettura della posta sul server mail in Java | ||
Dopo che il
mese scorso abbiamo visto come inviare messaggi di posta elettronica in
Java, in questo numero Bertoncello ci insegna come leggere i messaggi da
un server di mail attraverso un semplice esempio scritto in Java.
Ricezione di messaggi dal server POP3
Il mese scorso si era parlato di come spedire mail usando il protocollo SMTP. Questa volta si parlerà di un protocollo “complementare”: POP3. POP3, che sta per Post Office Protocol version 3 è un insieme di comandi come SMTP che serve per ricevere la posta da quei server che accettano collegamenti via modem (ciò vuol dire che, in buona parte dei casi, sono esclusi quei server NON usati come provider, come ad esempio ditte private o università). Anche in questo caso è necessario collegarsi con il proprio provider utilizzando una porta Socket. Per essere precisi occorre usare la porta 110. POP3 dispone di alcuni semplici comandi che consentono all’utente di loggarsi e richiedere i messaggi. I principali sono:
PASS
LIST
TOP [msg] [n]
RETR [msg]
QUIT
Importante però notare una cosa: questo NON è un’Applet, quindi non gira da Netscape, ma da riga di comando lanciando il comando Java POP3 <Host> <User> <Passwd>, dove Host è il nome del vostro server, User è il vostro login e Passwd la vostra password.
Vediamo dunque la prima procedura, quella che chiama tutte le altre. Questa funzione (Popper) si connette via socket al vostro provider e chiama la OpenComm per connettersi e, se non ci sono stati errori, la List per richiamare l’header dei messaggi. Questo header è composto da Dimensione del messaggio, Mittente, Data e Soggetto. La procedura Popper è descritta di seguito:
Come si può vedere è tutto molto semplice. Si apre il socket, come per l’applet del mese scorso, si chiamano le funzioni per comunicare e si chiude la comunicazione (QUIT). Fin qui non c’è nulla di strano, vediamo ora la funzione OpenComm. Questa funzione provvede a mandare al provider al quale si è connessi il proprio identificativo (Login) e la propria Password. La funzione, inoltre, provvede a verificare se non ci sono errori (Utente non presente nel sistema, Password non valida) e ritorna true se tutto è andato bene, false in caso contrario. La OpenComm è descritta di seguito:public static void Popper(String Host,String User,String Passwd) throws IOException { // Procedura che legge l’header della mail. Questa procedura apre un // socket sulla porta 110 (quella di POP3) e lancia la funzione // List, la quale provvede fisicamente all’azione di lettura Header. // Apertura Socket e inizializzazione degli Stream di Input e Output Socket mailSocket=new Socket(Host,110); os=new PrintStream(mailSocket.getOutputStream()); is=new DataInputStream(mailSocket.getInputStream()); // Se l’utente e’ loggato correttamente, legge gli Header if(OpenComm(User,Passwd)==true) List(); // Chiude la comunicazione con POP3 e si disconnette os.println(“QUIT”); is.readLine(); is.close(); os.close(); mailSocket.close(); }
Qui c’è qualcosa da dire. Per prima cosa si manda, tramite lo Stream aperto dalla Popper la stringa USER seguita dal nome utente, poi si controlla, tramite l’altro Stream aperto, se il messaggio di ritorno è un errore o meno. Nel caso tutto sia andato a buon fine si procede a spedire la password, eseguendo gli stessi controlli. Dopo essersi loggati nel sistema è possibile quindi agire sulla propria casella postale. Nel caso di questo esempio ci limiteremo a prendere le prime righe del messaggio e costruire l’header, ma se si volesse leggerlo tutto non c’è nient’altro da fare che spedire un comando RETR al posto del comando TOP. Vediamo ora nel dettaglio il comportamento della funzione List, che è il cuore di tutto il programma. Il listato è il seguente:public static boolean OpenComm(String User,String Passwd) throws IOException { // Questa procedura si “logga” con il server, fornendo UserName e Password. // Visualizza messaggi di errore nel caso UserName o Password siano errati // Ritorna TRUE se si e’ loggato, FALSE altrimenti String s; boolean Ret=true; s=is.readLine(); os.println(“USER “+User); s=is.readLine(); if(s.substring(0,3).compareTo(“+OK”)==0) { os.println(“PASS “+Passwd); s=is.readLine(); if(s.substring(0,3).compareTo(“+OK”)!=0) { System.out.println(“Errore: Password Errata”); Ret=false; } else System.out.println(“Connesso come “+User); } else { System.out.println(“Errore: User-ID Errato”); Ret=false; } return(Ret); }
Come si può notare le operazioni sono piuttosto semplici. Per prima cosa mando il comando LIST, che mi ritorna il numero di messaggi presenti, mi salvo quindi questo numero in una variabile. Da notare che vengono usate due funzioni, atoi e atol, che NON sono comprese nel pacchetto di classi forniti a corredo del linguaggio, ma che ho scritto io, prendendo spunto dalle loro omonime del linguaggio C. Sarà possibile vederle nel listato in fondo a questo articolo, in ogni caso, dirò che la atoi converte una stringa in un intero, mentre le atol converte la stringa in un long. Dopo questa breve considerazione cicliamo per tutti i messaggi, chiedendo al server le prime 13 righe del messaggio. In queste righe, in posizioni che variano con il provider e il tipo di mailer usato per la spedizione, troviamo il Mittente, la Data e il Soggetto, mentre la dimensione è sempre ritornata subito. Quindi ci si limita a controllare tutte le righe che ci vengono passate e verificare se contengono le informazioni richieste. In ogni caso, il prefisso (From, Date, Subject) è standard, quindi è sufficiente controllare se la riga inizia con uno di questi per concludere che si ha l’informazione desiderata. Alla fine di tutto si stampano le informazioni e si conclude il ciclo.public static void List() throws IOException { // Questa procedura e’ il cuore del programma. // Provvede a spedire i comandi POP3 e a visualizzarne i risultati. // Si veda l’apposita sezione dove spiego i comandi POP3 per // comprendere il flusso dei dati. String s,s1,From,Date,Subj; int NMsg,l; long Dim; From=Date=Subj=””; // Chiede quanti messaggi ci sono nel server os.println(“LIST”); s=is.readLine(); s1=s.substring(4); NMsg=atoi(s1); for(l=0;l<NMsg;l++) s=is.readLine(); s=is.readLine(); System.out.println(“”+NMsg+”Messaggi”); System.out.println(); // Cicla per ogni messaggio for(l=0;l<NMsg;l++) { System.out.println(“Messaggio n “+(l+1)); // Prende le prime 13 righe del messaggio numero (l+1) os.println(“TOP “+(l+1)+” 13"); s=is.readLine(); // Viene subito ritornata anche la dimensione della Mail s1=s.substring(4); Dim=atol(s1); s=is.readLine(); while(is.available()!=0) { s=is.readLine(); // Cerca i campi From, Date e Subject if(s.length()>5) { if(s.substring(0,6).compareTo(“From: “)==0) From=s.substring(6); if(s.substring(0,6).compareTo(“Date: “)==0) Date=s.substring(6); } if(s.length()>8) if(s.substring(0,9).compareTo(“Subject: “)==0) Subj=s.substring(9); } } System.out.println(“Da: “+From); System.out.println(“Data: “+Date); System.out.println(“Soggetto: “+Subj); System.out.println(“Dimensione: “+Dim+” bytes”); System.out.println(); }
Bene, questo è tutto! Come si può vedere, anche il protocollo utilizzato per richiamare i messaggi è semplice quasi quanto quello per spedirlo e, comunque, non presenta nessuna particolare difficoltà di implementazione. Anche in questo caso, gran parte del lavoro è svolto dalle classi che gestiscono i Socket e gli Stream, quindi dobbiamo ancora ringraziare i tecnici della Sun.
Di seguito riporto, per completezza, il listato commentato del programma. Per ogni dubbio o problema è possibile consultare la RFC1225, oppure contattarmi direttamente.
Listato completo del programma POP3
import java.awt.*; import java.io.*; import Java.net.*; public class POP3 { public static long atol(Strings) { // Converte la string passato in un long Long tempInt; String s1; int l,k; long q=0; for(l=-1,k=0;(k<s.length()) &&(l==-1);k++) if((s.charAt(k)<‘0’) || (s.charAt(k)>’9')) l=k; if(l==-1) s1=s; else if(l!=0) { s1=s.substring(0,l); tempInt = Long.valueOf(s1); q=tempInt.longValue(); } return(q); } public static int atoi(Strings){ // Converte la string passato in un integer Integer tempInt; String s1; int k,l; for(l=-1,k=0;(k<s.length()) &&(l==-1);k++) if((s.charAt(k)<‘0’) || (s.charAt(k)>’9')) l=k; if(l==-1) s1=s; else if(l!=0) { s1=s.substring(0,l); tempInt = Integer.valueOf(s1); k=tempInt.intValue(); } else k=0; return(k); } public static void List() throws IOException { // Questa procedura e’ il cuore del programma. // Provvede a spedire i comandi POP3 e a visualizzarne // i risultati. Si veda l’apposita sezione dove spiego // i comandi POP3 per comprendere il flusso dei dati String s,s1,From,Date,Subj; int NMsg,l; long Dim; From=Date=Subj=””; // Chiede quanti messaggi ci sono nel server os.println(“LIST”); s=is.readLine(); s1=s.substring(4); NMsg=atoi(s1); for(l=0;l<NMsg;l++) s=is.readLine(); s=is.readLine(); System.out.println(“”+NMsg+”Messaggi”); System.out.println(); // Cicla per ogni messaggio for(l=0;l<NMsg;l++){ System.out.println(“Messaggio n “+(l+1)); // Prende le prime 13 righe del messaggio numero (l+1) os.println(“TOP “+(l+1)+” 13"); s=is.readLine(); // Viene subito ritornata anche la dimensione della MaiL s1=s.substring(4); Dim=atol(s1); s=is.readLine(); while(is.available()!=0) { s=is.readLine(); // Cerca i campi From, Date e Subject if(s.length()>5) { if(s.substring(0,6).compareTo(“From: “)==0) From=s.substring(6); if(s.substring(0,6).compareTo(“Date: “)==0) Date=s.substring(6); } if(s.length()>8) if(s.substring(0,9).compareTo(“Subject: “)==0) Subj=s.substring(9); } System.out.println(“Da: “+From); System.out.println(“Data: “+Date); System.out.println(“Soggetto:“+Subj); System.out.println(“Dimensione: “+Dim+” bytes”); System.out.println(); } public static DataInputStream is; public static PrintStream os; public static boolean OpenComm(String User,String Passwd) throws IOException { // Questa procedura si “logga” con il server,fornendo // UserName e Password. Visualizza messaggi di errore // nel caso UserName o Password siano errati // Ritorna TRUE se si e’ loggato, FALSE altrimenti String s; boolean Ret=true; s=is.readLine(); os.println(“USER “+User); s=is.readLine(); if(s.substring(0,3).compareTo(“+OK”)==0) { os.println(“PASS“+Passwd); s=is.readLine(); if(s.substring(0,3).compareTo(“+OK”)!=0) { System.out.println(“Errore: Password Errata”); Ret=false; } else System.out.println(“Connesso come “+User); } else { System.out.println(“Errore: User-ID Errato”); Ret=false; } return(Ret); } public static void Popper(String Host,String User,String Passwd) throws IOException { // Procedura che legge l’header della mail. // Questa procedura apre un socket sulla porta 110 // (quella di POP3) e lancia la funzione List, la // quale provvede fisicamente all’azione di lettura Header. // Apertura Socket e inizializzazione degli Stream di Input e Output Socket mailSocket=new Socket(Host,110); os=new PrintStream(mailSocket.getOutputStream()); is=new DataInputStream(mailSocket.getInputStream()); // Se l’utente e’ loggato correttamente, legge gli Header if(OpenComm(User,Passwd)==true) List(); // Chiude la comunicazione con POP3 e si disconnette os.println(“QUIT”); is.readLine(); is.close(); os.close(); mailSocket.close(); } public static void main(String args[]) { try{ // Chiama la funzione Popper passando Host, //UserName e Password Popper(args[0],args[1],args[2]); } catch(Exception e) { System.out.println(“Eccezione “+e); } } }
Luca Bertoncello è un programmatore in C++ e Java (da poco dopo i suoi esordi). Diplomato in Informatica all'ITIS di Ivrea, lavora presso una ditta che ha creato due anni fa. È specializzato in programmi sistemistici per il gioco del Lotto, ma non disdegna altri programmi e speculazioni mentali sui vari sistemi. Può essere contattato a: lucabert@biella.alpcom.it (per messaggi privati) bdb@usa.net softserv@biella.alpcom.it (per lavoro) |
|
||
|
||
MokaByte ricerca
nuovi collaboratori
|
||
|