Sunteți pe pagina 1din 8

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
STAT
+OK 1 344
RETR 1
+OK message 1 (344 octets):
X-POP3-Rcpt: test@geniu
Return-Path: <root>
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: root@geniu.mirele.ro
Message-Id: <199903030259.WAA00286@geniu.mirele.ro>

To: test@geniu.mirele.ro
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(mesajCurent<1 || mesajCurent>nrMesaje)
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

S-ar putea să vă placă și