Conexiune La Un Server Pop3

10
Conexiune la un server POP3 prin Socket Mirela Andronescu Exemplul din acest numar realizeaza un program prin care se poate citi posta electronica de pe un server POP3. Am scris acest program sub forma unui aplet pentru ca v-am aratat in numerele trecute cum sa creati o interfata cu butoane, campuri de text s.a.m.d. DAR acest program nu va functiona intr-un browser datorita limitarilor impuse apleturilor (voi prezenta intr-un articol urmator aceste limitari). Printre acestea se afla si cea care spune ca un aplet nu poate comunica cu alta masina in afara de serverul de unde a fost incarcat. Prin urmare nu poate trimite date si citi date catre si de la un server POP3, ceea isi propune acest program sa realizeze. Puteti rula acest program insa din Mediul de dezvoltare Java pe care il folositi (eu folosesc Borland JBuilder sau Symantec Visual Cafe). Astfel, daca rulati programul dintr-un astfel de mediu ca pe oricare alt aplet, aplicatia Applet Viewer va deschide o fereastra de dimensiunile date in program, pe care il va rula. In felul acesta, vom putea "pacali" programul nostru sa treaca peste aceasta limitare impusa de un aplet. Iata o imagine a programului: Atunci cand vreti sa va cititi posta dintr-un client de POP3 (Netscape Messenger, Eudora Light, Pegasus Mail, OutLook Express sau oricare altul), de fapt va conectati la serverul POP3 de obicei la portul 110. O conectare la serverul POP3 "geniu", de exemplu, se poate face si deschizand o sesiune telnet (daca serverul permite acest lucru) astfel: telnet geniu 110 Odata conectat, puteti folosi comenzile urmatoare: USER nume - logheaza utilizatorul la server PASS parola - autentifica ulizatorul logat prin parola; STAT - afiseaza numarul de mesaje; RETR numar - afiseaza mesajul cu numarul specificat; DELE numar - marcheaza pentru stergere mesajul cu numarul respectiv; RSET numar - anuleaza comanda de stergere facuta anterior; QUIT - incheie sesiunea. Iata mai jos un exemplu simplu de conexiune telnet la portul de POP3 (110) in care am folosit comenzile de mai sus: +OK geniu POP3 Server (Version 1.006d) ready at <Tue Mar 02 23:04:09 2000> USER test +OK please send PASS command PASS test +OK 1 messages ready for test in /var/spool/mail/test

description

Conexiune la un server POP3 prin Socket

Transcript of Conexiune La Un Server Pop3

Conexiune la un server

Conexiune la un server POP3 prin Socket

Mirela Andronescu Exemplul din acest numar realizeaza un program prin care se poate citi posta electronica de pe un server POP3. Am scris acest program sub forma unui aplet pentru ca v-am aratat in numerele trecute cum sa creati o interfata cu butoane, campuri de text s.a.m.d.DAR acest program nu va functiona intr-un browser datorita limitarilor impuse apleturilor (voi prezenta intr-un articol urmator aceste limitari). Printre acestea se afla si cea care spune ca un aplet nu poate comunica cu alta masina in afara de serverul de unde a fost incarcat. Prin urmare nu poate trimite date si citi date catre si de la un server POP3, ceea isi propune acest program sa realizeze. Puteti rula acest program insa din Mediul de dezvoltare Java pe care il folositi (eu folosesc Borland JBuilder sau Symantec Visual Cafe). Astfel, daca rulati programul dintr-un astfel de mediu ca pe oricare alt aplet, aplicatia Applet Viewer va deschide o fereastra de dimensiunile date in program, pe care il va rula. In felul acesta, vom putea "pacali" programul nostru sa treaca peste aceasta limitare impusa de un aplet. Iata o imagine a programului:

Atunci cand vreti sa va cititi posta dintr-un client de POP3 (Netscape Messenger, Eudora Light, Pegasus Mail, OutLook Express sau oricare altul), de fapt va conectati la serverul POP3 de obicei la portul 110. O conectare la serverul POP3 "geniu", de exemplu, se poate face si deschizand o sesiune telnet (daca serverul permite acest lucru) astfel: telnet geniu 110 Odata conectat, puteti folosi comenzile urmatoare: USER nume - logheaza utilizatorul la server PASS parola - autentifica ulizatorul logat prin parola; STAT - afiseaza numarul de mesaje; RETR numar - afiseaza mesajul cu numarul specificat; DELE numar - marcheaza pentru stergere mesajul cu numarul respectiv; RSET numar - anuleaza comanda de stergere facuta anterior; QUIT - incheie sesiunea.

Iata mai jos un exemplu simplu de conexiune telnet la portul de POP3 (110) in care am folosit comenzile de mai sus:

+OK geniu POP3 Server (Version 1.006d) ready at USER test +OK please send PASS command PASS test +OK 1 messages ready for test in /var/spool/mail/test STAT +OK 1 344 RETR 1 +OK message 1 (344 octets): X-POP3-Rcpt: test@geniu Return-Path: Received: (from root@localhost) by geniu.mirele.ro (8.9.3/8.9.3) id WAA00286 for test; Tue, 2 Mar 1999 22:59:41 -0400 Date: Tue, 2 Mar 1999 22:59:41 -0400 From: [email protected] Message-Id: To: [email protected] Subject: Test

Test Test

. DELE 1 +OK message 1 marked for deletion RSET 1 +OK 1 messages ready for test in /var/spool/mail/test QUIT +OK geniu POP3 Server (Version 1.006d) shutdown.

Observati ca un raspuns corect la o comanda incepe cu "+OK". Daca dadeam o comanda care nu exista, raspunsul incepea cu "-ERR".

Atentie! Protocoalele telnet si POP3 sunt protocoale NEcriptate!

Aceleasi comenzi le vom folosi in program pentru a citi posta. Pentru a face o conexiune la un alt calculator, trebuie sa-i trimitem un "socket". Un socket realizeaza o comunicatie intre doua masini. El trimite date de la o masina la alta. Datele de intrare permit masinii client sa citeasca datele trimise de server, iar datele de iesire permit masinii client sa trimita sau sa scrie date catre masina server. Deci pentru a realiza comunicatia intre cele doua masini, vom folosi clasele urmatoare: - Socket, care se afla in pachetul java.net; - DataInputStream (din pachetul java.io) pentru datele de intrare (ce citim de la server); - DataOutputStream (din pachetul java.io) pentru datele de iesire (ceea ce trimitem catre server).

Programul contine doua clase: ConectarePOP3 si MailApplet, aceasta din urma mostenind clasa Applet. Clasa "ConectarePOP3" realizeaza conexiunea catre un server POP3 si foloseste comenzile POP3 descrise mai sus. Urmariti pasii de mai jos, odata cu sursa acestei prime clase, care urmeaza dupa descrierea pasilor: 1. Cream clasa ConectarePOP3 care implicit extinde clasa Object; 2. Cream cite o instanta ale celor trei clase de mai sus; 3. Cream variabile in care vom pastra numele serverului (host), portul (port), numele celui care se logheaza (user), parola lui (parola) si o instanta a clasei MailApplet (parinte). Vom folosi variabila parinte pentru a trimite mesaje pe care apletul le va afisa pe ecran in casuta de mesaje. 4. Cream constructorul, prin care transmitem acestei instante ale clasei ConectarePOP3 apletul parinte si variabilele host, port, user si parola pe care le transmite utilizatorul prin aplet; 5. Cream functia RaspundeCuEroare care primeste ca parametru un sir de caractere pe post de comanda si testeaza daca primul caracter este "+". Daca da, functia returneaza false, daca nu, returneaza true. Vom folosi aceasta functie ca sa verificam daca mesajul transmis de server este corect sau nu. 6. Cream functia ExecutaComanda care primeste un sir de caractere reprezentand comanda respectiva. Aceasta functie trimite comanda ca date de iesire, deci catre server, prin outStream. Apoi citeste raspunsul serverului prin inStream, care are rol de date de intrare. Aceasta functie "arunca" o exceptie de tip IOException (recititi articolul din luna februarie, care trateaza exceptiile in Java!) in cazul in care conexiunea nu poate avea loc. 7. Cream functia Conectare(). In aceasta functie cream instantele pop3sock, inStream si outStream, cu ajutorul carora vom comunica cu serverul. textAreaInfo este o instanta a clasei TextArea, membra a clasei MailApplet, si care reprezinta casuta in care vom afisa diferite mesajele. Acest lucru se face cu ajutorul functiei append(String sir). Incearca sa execute comanda USER, iar daca nu reuseste arunca o exceptie. Apoi incearca sa trimita parola. In acelasi timp, trimite catre aplet raspunsurile serverului; 8. Cream functia ExtrageNumarulDeMesaje() care trimite serverului comanda STAT. Ati observat mai sus ca aceasta comanda a returnat linia: "+OK 1 344". Numarul 1 reprezinta numarul de mesaje, iar 344 dimensiunea mesajelor. In continuare functia incearca sa extraga numarul de mesaje folosind functiile clasei String; 9. Functia ExtrageDate() returneaza un vector de siruri de caractere reprezentand un mesaj efectiv. Mesajul se termina la intalnirea caracterului "." pe o singura linie. Aceasta functie va fi folosita de functia urmatoare; 10. Functia CitesteMesaj primeste ca parametru numarul mesajului si executa comanda RETR. Serverul va raspunde prin a trimite corpul mesajului. Folosim functia descrisa anterior pentru a citi mesajul primit; 11. Functia StergeMesaj executa comanda DELE; 12. Functia UnSterge (nu am gasit un nume mai sugestiv pentru aceasta functie!) executa comanda RSET; 13. A mai ramas comanda de deconectare de la server (QUIT), care este executata de functia Deconectare().

import java.io.*;

import java.net.*;

import java.util.*;

public class ConectarePOP3 {

protected Socket pop3Sock;

protected DataInputStream inStream;

protected DataOutputStream outStream;

public String host;

public int port;

public String user;

public String parola;

public MailApplet parinte;

public ConectarePOP3(MailApplet parinte, String host, String

user, String parola) {

this.host = host;

this.port = 110;

this.user = user;

this.parola = parola;

this.parinte = parinte;

}

protected boolean RaspundeCuEroare(String str) {

return str.charAt(0) != '+';

}

protected String ExecutaComanda(String comanda) throws

IOException {

outStream.writeBytes(comanda+"\n");

String raspuns = inStream.readLine();

return raspuns;

}

public void Conectare() throws IOException {

pop3Sock = new Socket(host, port);

inStream = new DataInputStream(pop3Sock.getInputStream());

outStream =

new DataOutputStream(pop3Sock.getOutputStream());

parinte.textAreaInfo.append(inStream.readLine()+"\n");

String raspuns = ExecutaComanda("USER "+user);

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

parinte.textAreaInfo.append(raspuns+"\n");

raspuns = ExecutaComanda("PASS "+parola);

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

parinte.textAreaInfo.append(raspuns+"\n");

}

public int ExtrageNumarulDeMesaje() throws IOException {

String raspuns = ExecutaComanda("STAT");

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

parinte.textAreaInfo.append(raspuns+"\n");

try {

int numar =

Integer.valueOf(raspuns.substring(4,raspuns.indexOf(' ',

4))).intValue();

return numar;

}

catch (Exception e) {

throw new IOException(raspuns);

}

}

protected String[] ExtrageDate() throws IOException {

Vector linii = new Vector();

String linie;

while ((linie = inStream.readLine()) != null) {

if (linie.equals(".")) {

String raspuns[] = new String[linii.size()];

linii.copyInto(raspuns);

return raspuns;

}

if ((linie.length() > 0) && (linie.charAt(0) == '.')) {

linie = linie.substring(1);

}

linii.addElement(linie);

}

throw new IOException("Conexiune intrerupta.");

}

public String[] CitesteMesaj(int NrMesaj) throws IOException {

String raspuns = ExecutaComanda("RETR "+NrMesaj);

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

return ExtrageDate();

}

public void StergeMesaj(int NrMesaj) throws IOException {

String raspuns = ExecutaComanda("DELE "+NrMesaj);

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

parinte.textAreaInfo.append(raspuns+"\n");

}

public void UnSterge() throws IOException {

String raspuns = ExecutaComanda("RSET");

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

}

public void Deconectare() throws IOException {

String raspuns = ExecutaComanda("QUIT");

if (RaspundeCuEroare(raspuns)) {

throw new IOException(raspuns);

}

}

}

In constructia clasei-aplet am folosit elemente API pe care le-am descris in numerele trecute. Apar foarte putine elemente noi, pe care le voi descrie pe scurt: 1. Declaram variabilele; 2. Cream functia init() in care vom adauga toate elementele API; 3. Facem ca in casuta de parola sa apara stelute in loc de parola cu ajutorul functiei setEchoChar('*'); 4. Facem astfel incat casutele de tip TextArea sa nu poata fi editabile prin functia setEditable(false). Implicit este true. 5. Functia action executa functiile variabilei pop3 corespunzatoare fiecarui buton.

import java.io.*;

import java.applet.Applet;

import java.awt.*;

public class MailApplet extends Applet {

String host;

String user;

String parola;

Label labelHost = new Label();

Label labelUser = new Label();

Label labelParola = new Label();

Label labelNrMesaj = new Label();

TextField textFieldHost = new TextField();

TextField textFieldUser = new TextField();

TextField textFieldParola = new TextField();

TextField textFieldNrMesaj = new TextField();

public TextArea textAreaInfo = new TextArea();

public TextArea textAreaMesaje = new TextArea();

Button buttonConectare = new Button();

Button buttonCiteste = new Button();

Button buttonSterge = new Button();

Button buttonUnSterge = new Button();

ConectarePOP3 pop3;

int nrMesaje;

int mesajCurent;

public void init() {

setLayout(null);

resize(500,500);

labelHost.setText("Server POP3");

labelHost.reshape(10,4,80,24);

add(labelHost);

labelUser.setText("User");

labelUser.reshape(100,4,80,24);

add(labelUser);

labelParola.setText("Parola");

labelParola.reshape(190,4,80,24);

add(labelParola);

textFieldHost.setText("");

textFieldHost.reshape(10,28,80,24);

add(textFieldHost);

textFieldUser.setText("");

textFieldUser.reshape(100,28,80,24);

add(textFieldUser);

textFieldParola.setText("");

textFieldParola.setEchoChar('*');

vtextFieldParola.reshape(190,28,80,24);

add(textFieldParola);

buttonConectare.setLabel("Conectare");

buttonConectare.reshape(280,28,80,24);

add(buttonConectare);

textAreaInfo.reshape(10,55,360,90);

textAreaInfo.setEditable(false);

textAreaInfo.setBackground(Color.lightGray);

add(textAreaInfo);

labelNrMesaj.setText("Mesaj:");

labelNrMesaj.reshape(10,150,40,24);

add(labelNrMesaj);

textFieldNrMesaj.setText("");

textFieldNrMesaj.reshape(50,150,40,24);

add(textFieldNrMesaj);

buttonCiteste.setLabel("Citeste");

buttonCiteste.reshape(100,150,80,24);

add(buttonCiteste);

buttonSterge.setLabel("Sterge");

buttonSterge.reshape(190,150,80,24);

add(buttonSterge);

buttonUnSterge.setLabel("UnSterge");

buttonUnSterge.reshape(280,150,80,24);

add(buttonUnSterge);

textAreaMesaje.reshape(10,180,360,210);

textAreaMesaje.setEditable(false);

add(textAreaMesaje);

}

public boolean action(Event evt, Object arg) {

if(evt.target instanceof Button) {

if(arg == "Conectare") {

host = textFieldHost.getText();

user = textFieldUser.getText();

parola = textFieldParola.getText();

pop3 = new ConectarePOP3(this,host,user,parola);

try {

pop3.Conectare();

nrMesaje=pop3.ExtrageNumarulDeMesaje();

textAreaInfo.append("Sunt "+nrMesaje+ " mesaje pe

server.\n");

buttonConectare.setLabel("Deconectare");

}

catch(IOException e) {

textAreaInfo.append(e.getMessage()+"\n");

}

}

else if(arg == "Deconectare") {

try {

pop3.Deconectare();

textAreaInfo.setText("Deconectat\n");

buttonConectare.setLabel("Conectare");

}

catch(IOException e) {

textAreaInfo.append(e.getMessage()+"\n");

}

}

else if(arg == "Citeste") {

if(buttonConectare.getLabel().equals("Conectare")) {

textAreaInfo.append("Neconectat la un server POP3.\n");

return true;

}

try {

mesajCurent=Integer.valueOf(textFieldNrMesaj.getText()).intValue();

if(mesajCurentnrMesaje)

textAreaInfo.append("Nu exista mesaj cu numarul

"+mesajCurent+".\n");

else {

try {

String[] corpMesaj = pop3.CitesteMesaj(mesajCurent);

textAreaMesaje.setText("");

for(int i=0;inrMesaje)

textAreaInfo.append("Nu exista mesaj cu numarul

"+mesajCurent+".\n");

else {

try {

pop3.StergeMesaj(mesajCurent);

}

catch (IOException e) {

textAreaInfo.append(e.getMessage()+"\n");

}

}

}

catch (NumberFormatException e) {

textAreaInfo.append("Format invalid.\n");

}

}

else if(arg == "UnSterge") {

if(buttonConectare.getLabel().equals("Conectare")) {

textAreaInfo.append("Neconectat la un server POP3.\n");

return true;

}

try {

pop3.UnSterge();

textAreaInfo.append("Toate mesajele sterse anterior au

fost recuperate.\n");

}

catch (IOException e) {

textAreaInfo.append(e.getMessage()+"\n");

}

}

}

return true;

}

}

Bineinteles ca acest program poate avea o interfata mult mai interesanta, dar va las voua placerea ca pana la articolul urmator sa realizati un program mai frumos de citire a postei prin protocolul POP3