Sunteți pe pagina 1din 35

MINISTERUL EDUCAIEI al REPUBLICII MOLDOVA

UNIVERSITATEA TEHNIC a MOLDOVEI


FACULTATEA CALCULATOARE, INFORMATIC
i MICROELECTRONIC
CATEDRA AUTOMATIC i TEHNOLOGII INFORMAIONALE

Proiect de curs
Disciplina: APPOO
Tema: Elaborarea i proiectarea unui Mail Client

A efectuat:

st. gr. SI-111


Curechi Adrian

A verificat:

lect.sup.
Postaru A.

Chiinu 2014

Curechi Adrian SI-111

Cuprins
Introducere.............................................................................................................................3
1. Sarcina tehnic a sistemului............................................................................................4
2. Elaborarea diagramelor UML.........................................................................................5
2.1.

Elaborarea diagramelor cazurilor de utilizare........................................................5

2.2.

Elaborarea diagramelor de clas............................................................................8

2.3.

Elaborarea diagramelor de secven......................................................................9

2.4.

Elaborarea diagramelor de activiti....................................................................12

2.5.

Elaborarea diagramelor de stri...........................................................................13

2.6.

Elaborarea diagramelor de componente..............................................................14

3. Interfaa sistemului........................................................................................................15
Concluzie.............................................................................................................................18
Bibliografie..........................................................................................................................19
Anexa A SMTPClient.cs...................................................................................................20
Anexa B IMAPClient.cs...................................................................................................22
Anexa C Tools.cs..............................................................................................................26
Anexa D Form1.cs............................................................................................................29

Curechi Adrian SI-111

Introducere.
Programarea orientat pe obiecte (OOP Object Oriented Programming) este
tehnica cea mai utilizat ncepnd cu nceputul anilor 90, cnd paradigmele sale
principale au fost adoptate i dezvoltate i de cele mai utilizate limbaje ale perioadei
respective: C++, Pascal, Basic, Ada, Java, etc. Conceptele de baz ale OOP au fost totui
dezvoltate nc din anii 60, odat cu proiectarea limbajului Simula67.
Programarea orientat pe obiect (Programare Orientat Obiectual) este unul din cei
mai importani pai fcui n evoluia limbajelor de programare spre o mai puternic
abstractizare n implementarea programelor. Ea a aprut din necesitatea exprimrii
problemei ntr-un mod mai natural fiinei umane. Astfel unitile care alctuiesc un
program se apropie mai mult de modul nostru de a gndi dect modul de lucru al
calculatorului.
Pn la apariia programrii orientate pe obiect programele erau implementate n
limbaje de programare procedurale (C, Pascal) sau n limbaje care nici mcar nu ofereau o
modalitate de grupare a instruciunilor n uniti logice (funcii, proceduri) cum este cazul
limbajului de asamblare (assembler). Altfel spus o problem preluat din natur trebuia
fragmentat n repetate rnduri astfel nct s se identifice elementele distincte,
implementabile ntr-un limbaj de programare. O mare problem a programrii procedurale
era separarea datelor de unitile care prelucrau datele (subrutinele), ceea ce fcea foarte
dificil extinderea i ntreinerea unui program. Astfel s-a pus problema ca aceste dou
entiti (date i subrutine) s fie grupate ntr-un anumit mod, astfel nct subrutinele s
"tie" n permanen ce date prelucreaz i, mai mult dect att, ele s formeze un modul,
adic o unitate care separ implementarea de interfa, ceea ce implic posibilitatea
refolosirii codului.
Conceptele de baz ale programrii orientate pe obiecte:
obiectul: o instanta a unei clase;
abstractizarea: Este posibilitatea ca un program s ignore unele aspecte ale
informaiei pe care o manipuleaz, adic posibilitatea de a se concentra asupra
esenialului. Este procesul prin care se identific i se rein numai caracteristicile
eseniale ale realitii modelate. Cel mai des, abstractizarea este ntlnit atunci cnd
obiectele cu aceleai atribute i acelai comportament sunt grupate n tipuri abstracte
numite clase. Clasele sunt reprezentri (modele) abstracte, conceptuale ale unor
entiti;
clasa: descriere a unei multitudini de obiecte cu aceleasi atribute si metode;
ncapsularea (ascunderea de informaii);
motenirea: extinderea unei clase ;
polimorfismul: Este abilitatea de a procesa obiectele n mod diferit, n funcie de
tipul sau de clasa lor. Mai exact, este abilitatea de a redefini metode pentru clasele
derivate.
3

Curechi Adrian SI-111


persistena: descrie durata de via a unui obiect n raport cu aplicaia ce l-a creat.

1. Sarcina tehnic a sistemului


Aplicaia va fi implementat folosing platforma .Net, i anume limbajul C#. Pentru
transmiterea email-urilor se va crea o clas SMTP Client, n aceast clas se va face o
conexiune, folosind protocolul TCP(prin intermediul clasei TcpClient), la server, i
folosind comenzile protocolului SMTP, se va crea i se va transmite un email nou. Pentru
extragerea email-urilor de pe server se va folosi protocolul IMAP, de asemeni se va crea o
clas de genul IMAP Client, care tot se va conecta la server folosind protocolul TCP. Toate
conexiunile dintre aplicaie i server vor fi securizate, folosind protocolul SSL, pentru
aceasta se va folosi clasa SslStream, care primind stream-ul conexiunii TCP, l nlocuiete
cu unul securizat.
Interfaa aplicaiei va fi fcut folosind Windows Forms. La pornirea aplicaiei, va fi o
fereastr, n care se va cere utilizatorului s se introduc setarile serverului(host-ul
serverului i port-ul acestuia), i credenialele(email-ul i password-ul). Dup introducerea
tuturor datelor, utiliatorului i se va afia lista tuturor email-urilor. Apsnd pe subiectul
unui email, se va deschide coninutul acestuia(coninutul email-ului se va afia ori ntr-o
fereastr nou, ori ntr-un tab nou, ori n acceai fereastr dar cu apariia unui buton pentru
nchiderea email-ului si ntoarcerea la lista email-urilor). Forma pentru trimiterea unui
email nou va ntr-un alt tab, sau pe fereastra princial va fi un buton, care va deschide o
fereast nou cu aceast form.
Programul va fi format din 2 proiecte:
1. Un proiect de clase, n care vor fi clasele SMTP Client, IMAP Client, i alte
clase auxiliare.
2. Un proiect Windows Forms, care va conine interfaa aplicaiei, i totul ce rive te
interaciunea cu utilizatorul. Acest proiect va folosi clasele din primul proiect.

Curechi Adrian SI-111

2. Elaborarea diagramelor UML


Elaborarea diagramelor UML au ca scop reprezentarea sistemulu ntr-o form att
neleas de utilziatori ct i de developeri, din toate aspectele , att func ional ct i
structural. Diagramele le-am elaborat cu ajutorul instrumentului Enterprise Architect.

2.1. Elaborarea diagramelor cazurilor de utilizare

Figura 1. Diagrama caz de utilizare pentru configurare

Aplicaia Mail Client nu va fi valabila doar pentru un animit serviciu email, ci


pentru oricare serviciu dorete utilizatorul s foloseasc. Pentru aceasta, la pornirea
aplicaiei, utilizatorului i se va cere sa introduc setrile necesare pentru conectarea la
serverul potei electronice, aa cum este artat n fig.1.
Pentru a se conecta la serverul serviciului email, utilizatorul trebuie s introduc
host-ul seriviului IMAP i portul acestui serviciu, date ca vor fi folosite la extragerea
email-urilor de pe server. De asemeni utilizatorul trebuie s introduc si host-ul serviciul
SMTP i portul pentru acest serviuciu, pentru a putea transmite email-uri din aplicaie.
5

Curechi Adrian SI-111


Utilizatorul, pe lng introducerea setrilor necesare, trebuie s introduc i
credenialele sale (email-ul i parola), pentru a putea folosi protocoale IMAP i SMTP,
acest lucru este reprezentat n diagrama cazurilor de utilizare din fig.2.

Figura 2. Diagrama caz de utilizare pentru autentificare

Curechi Adrian SI-111

Figura 3. Diagrama caz de utilizare pentru vizualizare email-urilor


n fig.3 sunt reprezentate cazurile de utilizare, ce arata modul de vizualizare a listei
email-urilor. Majoritatea serviciilor email, ofer posibilitatea de a mpr i email-urile n
mape, ncepnd cu cele standarte (Inbox, Draft, Sent, Trash etc.) i terminnd cu mape
definite de utilizator. Aplicaia va permite vizualizarea listei mapelor, i ncrcarea emailurilor din mapa selectat de utilizator. Lista de email-uri va oferi a a informa ii ca:
subiectul email-ului, email-ul surs i email-ul destinaie(important n cazul n care se face
redirecionare de pe o alt csu potal).

Curechi Adrian SI-111

Figura 4. Diagrama caz de utilizare pentru aciuni asupra email-ului


Din lista cu email-uri, utilizatorul poate executa careva manipulaii cu email-ul,
acestea sunt artate n fig.4. n dreptul ficrui email din list va fi cte un buton Delete,
care va permite stergerea email-ului respectiv. Apsnd pe subiectul email-ului va fi afi at
coninutul email-ului.
Pentru a trimite o scrisoare, utilizatorul trebuie s introduc elementele principale:
subiectul email-ului, coninutul acestuia i adresa destinatarului. Far unul din aceste
elemente trimiterea email-ului nu va fi posibil (butonul de trimitere, nu va func iona).
Cazurile de utilizare pentru acestea sunt reprezentate n fig.5.

Curechi Adrian SI-111

Figura 5. Diagrama caz de utilizare pentru trimiterea unui email

2.2. Elaborarea diagramelor de clas

Curechi Adrian SI-111


Figura 6. Diagrama de clase
Am creat doar o singur diagram de clase, deoarece proiectul nu conine multe
clase, acestea sunt reprezentate de diagrama din fig.6. Clasa de baz a proiectului este
MyMailClient, aceasta conine cte un obiect al claselor SMTPClient i IMAPCLient, i o
colecie de obiecte de tip MyMail. De asemeni clasa MyMailClient conine i elemente de
interfa a aplicaiei, care nu au fost introducse n diagrama de clase, deoarece nu joaca rol
n funcionarea logic a aplicaiei.
Clasa MyMail nu are metode, ci doar atribute. Aceast clas se folosete pentru
stocarea datelor email-ului(subjet, body, from, to).
Clasa Tools conine doar metode, ea este format dintr-o colecie
funcii(codificatoare, decodificatoare, parsere) folosite de alte clase.
Clasa SMTPClient este folosit pentru transmiterea email-urilor. Aceasta are doar 2
metode funcionale: conectarea la server, si transmiterea email-ului.
Clasa IMAPClient ofer posibilitatea de extragere a email-urilor dintr-o map anumit.
Printre funcionalitile acesteia sunt:
conecatarea la server;
extragerea listei de mape n csua potal;
selectarea unei mape;
extragerea email-urilor din mapa selectat;
tergerea unui email.

10

Curechi Adrian SI-111

2.3. Elaborarea diagramelor de secven

Figura 7. Diagrama de secven pentru autentificare


n fig.7 este reprezentat modul de autentificare a utilizatorului. La pornirea aplica iei
utilizatorului i se cere s introduc datele necesare pentru funcionarea acesteia, acestea
sunt:
adresa serverului IMAP i portul respectiv;
adresa serverului SMTP i portul respectiv;
login-ul i parola utilizatorului.

11

Curechi Adrian SI-111

Figura 8. Diagrama de secven pentru afiarea email-urilor


Fig.8 arat cum are loc afiarea listei email-urilor. Dup autentificare, aplica ia prin
intermediul clasei IMAPClient se conecteaz la server, cere lista de mape i o fieaz
utilizatorului. Predefinit la pornirea aplicaiei, se selecteaz prima map din list i se
extrag email-urile din acea map. Dup asta utilizatoarul poate selecta alt map, i se vor
extrage email-urile deja din mapa nou aleas.
Utilizatorul are posibilitatea de a terge un email, modul de tergere este reprezentat
de diagrama de secven din fig.9. Dup autentificare i afiarea listei email-urilor,
utilizatorul poate terge email-ul prin apsarea butonului Delete. Dup apsarea
butonului, prin intermediul clasei IMAPClient, se transmite la server un mesaj pentru
marcarea email-ului pentru tergere, dup care se transmite alt mesaj, pentru tergerea
tuturor mesajelor marcate pentru tergere.

12

Curechi Adrian SI-111

Figura 9. Diagrama de secven pentru stergerea unui email

13

Curechi Adrian SI-111


Figura 10. Diagrama de secven pentru trimiterea unui email
Pentru a trimite un email, utilizatorul trebuie s introduc subiectul email-ului,
textul email-ului i adresa destinatarului. Dup introducerea tuturor datelor, trebuie s
apese butonul Send, dac nu au fost introduse toate datele, butonul nu v-a func iona. La
apsarea butonului, prin intermediul SMTPClient, se face o conexiune la server, se ncarc
toate datele n SMTPClient, i se transmit la server conform protocolului. n caz c emailul a fost transmis cu succes, utilizatorului i se va afia un mesaj despre acesta. Aceasta este
reprezentat n diagrama de secven din fig.10.

2.4. Elaborarea diagramelor de activiti

Figura 11. Diagrama de activitate pentru vizualizarea unui email


Pentru a putea vizualiza coninutul unui email utilizatorul trebuie s execute un set
de aciuni, pentru a arta aceste aciuni, am elaborat diagrama de activit i, care este
prezentat de fig.11. ncepnd cu desciderea aplicaiei, utilizatorul trebuie s se
auntentifice, s selecteze mapa n care se afl email-ul dorit, s-l selecteze din list, dup
care poate s vizualize coninutul acestuia.
Transmiterea unui email, de asemeni, necesit un set de activit i executate de
utilizator. Dup deschiderea aplicaiei i logare, acesta trebuie s introduc datele emailului, nu neaprat ntr-o ordine aumit, dar obligatoriu pe toate. Activit ile date sunt
reprezentate de diagrama de activiti din fig.12.

14

Curechi Adrian SI-111

Figura 12. Diagrama de activitate pentru trimiterea unui email

2.5. Elaborarea diagramelor de stri

15

Curechi Adrian SI-111


Figura 13. Diagrama de stari: stergerea unui email
n cadrul execuiei, sistemul trece prin mai multe stri. Fig.13 arat strile prin care
trece sitemul n timpul stergerii unui email. Dup pornirea aplica iei, se a teapt ca
utilizatorul s introduc datele de autentificare, dup aceasta se conecteaz la server i se
afl n starea respectiv. Dup ce ncarc lista mapelor, sistemul a teapt ca utilizatorul s
selecteze mapa dorit. Cnd email-urile sunt afiate, sistemul se afl n a teptarea selectarii
email-ului de ctre utilizator. La selectarea email-ului se trimite comanda la server, pentru
a-l terge. Dup ce email-ul a fost ters, sistemul se ntoarce la starea cnd este afi at lista
cu email-uri, i ateapt ori selectarea altui email, ori nchiderea aplicaiei.

2.6. Elaborarea diagramelor de componente

Figura 14. Diagrama de componente a sistemului


Diagrama de componente reprezentat n fig.14 arat cum este organizat sistemul.
Sistemul este format din 2 proiecte:
AppInterface: interfaa aplicaiei i toate componentele de interaciune cu
utilizatorul;
AppCore: clasele ce cuprind logica sistemului
o IMAPClient;
o SMTPClient;
o MyMail;
o Tools.

16

Curechi Adrian SI-111

3. Interfaa sistemului

Figura 15. Pagina de star a aplicaiei

Figura 16. Tab-ul cu lista email-urilor dintr-o map


17

Curechi Adrian SI-111

Firgura 17. Tab-ul cu coninutul unui email

Figura 18. Tab-ul cu lista mapelor

18

Curechi Adrian SI-111

Figura 19. Tab-ul n care se scrie un email nou

19

Curechi Adrian SI-111

Concluzie
Paradigma programarii orientate pe obiecte ne da posibilitatea sa divizam sistemul
complex in mai multe module, independente la nivel de implementare, care
interactioneaza si creaza un tot intreg. POO ne ofera mai multe nivele de abstractizare si
astfel la fiecare din aceste nivele ne vom conentra atentia asupra principalului si nu a supra
detaliilor, deoarece acestea vor fi ascunse de la un nivel la alt nivel de abstractizare.
Mostenirea, polimorfismul si incapsularea ne ofera posibilitatea de elaborare a softurilor
intr-o maniera bine structurata din punc de vedere a logicii. POO deasemenea ne pune la
dispozitie o depanare mai usoara a modulelor si depistarea mai rapida a erorilor ce pot
aparea la etapa de dezvoltare.
Efectund acest proiect de an, am realizat diagramele caz de utilizare pentru a
modela sistemul propus, Mail Client. Cu ajutorul diagramelor caz de utilizare am
specificat aciunile pe care le poate executa utilizatorul asupra unui email, sau ac iunile
care trebuie numaidect executate. Pentru a reprezenta destinaia funcional a sistemului
am elaborat diagrama cazurilor de utilizare, iar pentru a reprezenta interac iunea n timp i
spaiu dintre obiectele ce particip la formarea sistemului, am elaborat diagrama de
interaciune compus din diagrame de secvena. n cazul n care am descris structura
intern a sistemului, am realizat diagrama claselor. Diagrama de stare am realizat-o cu
scopul de a evidenia comportamentul obectelor pe parcursul ciclurilor sale de via a,
specificnd strile n care obiectele pot trece i tranziiile respective dintre aceste stri. Am
reprezentat arhitectura sistemului prin deretminarea dependenelor dintre componente.
In viziunea mea, limbajul UML ofera o descriere la nivel logic, conceptual si fizic a
sistemului elaborat, ceea ce prmite o percepere mai clara a structurii si functionalitatilor
sistemului.

20

Curechi Adrian SI-111

Bibliografie
1. MSDN-the microsoft developer network [Resurs electronic] http://msdn.microsoft.com
2. INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 [Resurs
electronic] - https://tools.ietf.org/html/rfc3501
3. Simple Mail Transfer Protocol [Resurs electronic] https://tools.ietf.org/html/rfc5321
4. STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES
[Resurs electronic] - https://tools.ietf.org/html/rfc822
5. UML 2 Tutorial [Resurs electronic] http://www.sparxsystems.com.au/resources/uml2_tutorial/

21

Curechi Adrian SI-111

Anexa A SMTPClient.cs
using
using
using
using

System;
System.IO;
System.Net.Security;
System.Text;

namespace AppooProjectClasses
{
public class SMTPClient : System.Net.Sockets.TcpClient
{
private SslStream sslStream;
private StreamWriter writer;
private StreamReader reader;
public
public
public
public
public
public
public

String Email { get; set; }


String Password { get; set; }
String EmailTo { get; set; }
String Subject { get; set; }
String Body { get; set; }
String Host { get; set; }
Int32 Port { get; set; }

public SMTPClient()
{
}
public void Connect()
{
Connect(Host, Port);
sslStream = new SslStream(GetStream());
sslStream.AuthenticateAsClient(Host);
writer = new StreamWriter(sslStream);
reader = new StreamReader(sslStream);
String response = reader.ReadLine();
if (response.Substring(0, 3) != "220")
{
throw new Exception(response);
}
}
public void Send()
{
String response;
writer.WriteLine("helo");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "250")
{
throw new Exception(response);
}
writer.WriteLine("auth login");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "334")
{
throw new Exception(response);
}

22

Curechi Adrian SI-111


String base64Email = Tools.ToBase64(Email);
writer.WriteLine(base64Email);
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "334")
{
throw new Exception(response);
}
String base64Password = Tools.ToBase64(Password);
writer.WriteLine(base64Password);
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "235")
{
throw new Exception(response);
}
writer.WriteLine("mail from:<" + Email + ">");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "250")
{
throw new Exception(response);
}
writer.WriteLine("rcpt to:<" + EmailTo + ">");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "250")
{
throw new Exception(response);
}
writer.WriteLine("data");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "354")
{
throw new Exception(response);
}
writer.WriteLine("from:" + Email);
writer.WriteLine("to:" + EmailTo);
writer.WriteLine("subject:" + Subject);
writer.WriteLine(Body);
writer.WriteLine(".");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "250")
{
throw new Exception(response);
}
writer.WriteLine("quit");
writer.Flush();
response = reader.ReadLine();
if (response.Substring(0, 3) != "221")
{
throw new Exception(response);
}
}

23

Curechi Adrian SI-111


}

24

Curechi Adrian SI-111

Anexa B IMAPClient.cs
using
using
using
using
using
using
using

System;
System.Collections.Generic;
System.IO;
System.Net.Security;
System.Net.Sockets;
System.Text;
System.Text.RegularExpressions;

namespace AppooProjectClasses
{
public class IMAPClient : IDisposable
{
private TcpClient client;
private SslStream sslStream;
private StreamReader reader;
private StreamWriter writer;
public String Host { get; set; }
public Int32 Port { get; set; }
public Int32 MailsCount { get; set; }
public MyMail GetMail(Int32 index)
{
MyMail mail = new MyMail();
mail.hasAttachments = false;
String command = ". fetch " + (index + 1) + " (body[header.fields (to from subject)])";
Command(command);
String temp;
StringBuilder stringBuilder = new StringBuilder();
while (!(temp = reader.ReadLine()).StartsWith(". "))
{
stringBuilder.Append(temp + "\n");
}
String response = stringBuilder.ToString();
response = response.Replace("\n)", "");
mail.Subject = Tools.GetSubject(response);
mail.From = Tools.GetSender(response);
mail.To = Tools.GetDestination(response);
command = String.Format(". fetch {0} (body[header.fields (Content-Type Content-TransferEncoding)])", index + 1);
Command(command);
stringBuilder.Clear();
temp = reader.ReadLine();
while (!(temp = reader.ReadLine()).StartsWith(". OK"))
{
if (temp != "" && temp != ")")
{
stringBuilder.Append(temp + "\n");
}
}
response = stringBuilder.ToString();
String contentType = Tools.GetContentType(response);
if (contentType.Contains("multipart"))
{
if (contentType.Contains("mixed"))
{
command = String.Format(". fetch {0} (body[1.2.mime])", index + 1);
mail.hasAttachments = true;
}
else

25

Curechi Adrian SI-111


{
command = String.Format(". fetch {0} (body[2.mime])", index + 1);
}
Command(command);
stringBuilder.Clear();
temp = reader.ReadLine();
while (!(temp = reader.ReadLine()).StartsWith(". OK"))
{
if (temp != "" && temp != ")")
{
stringBuilder.Append(temp + "\n");
}
}
response = stringBuilder.ToString();
if (contentType.Contains("mixed"))
{
command = String.Format(". fetch {0} (body[1.2])", index + 1);
}
else
{
command = String.Format(". fetch {0} (body[2])", index + 1);
}
}
else
{
command = String.Format(". fetch {0} (body[text])", index + 1);
}
Command(command);
stringBuilder.Clear();
temp = reader.ReadLine();
while (!(temp = reader.ReadLine()).StartsWith(". OK"))
{
if (temp != "" && temp != ")")
{
stringBuilder.Append(temp + "\n");
}
}
String mailBody = stringBuilder.ToString().Trim();
if (!String.IsNullOrEmpty(mailBody) && mailBody[mailBody.Length - 1] == ')')
{
mailBody = mailBody.Substring(0, mailBody.Length - 1);
}
//Get charset
Regex charsetRegex = new Regex("charset=\"?(?<charset>[^\\s\";]+)\"?;?\n?");
Match charsetMatch = charsetRegex.Match(response);
String charset = charsetMatch.Groups["charset"].Value;
//Get encoding
Regex encodingRegex = new Regex(
"Content-Transfer-Encoding: \"?(?<encoding>.*)\"?\n",
RegexOptions.IgnoreCase);
Match encodingMatch = encodingRegex.Match(response);
String encodeing = encodingMatch.Groups["encoding"].Value;
switch (encodeing)
{
case "base64":
{
Byte[] base64Bytes = Convert.FromBase64String(mailBody);
mail.Body = Encoding.GetEncoding(charset).GetString(base64Bytes);
break;
}
case "quoted-printable":
{

26

Curechi Adrian SI-111


mail.Body = Tools.DecodeQP(mailBody, charset);
break;

}
default:
{
mail.Body = mailBody;
break;
}

}
return mail;

public void DeleteMail(Int32 index)


{
String response;
//Delete mail
String command = String.Format(". fetch {0} uid",index + 1);
Command(command);
response = reader.ReadLine();
Regex uidRegex = new Regex("\\(UID\\s(?<uid>\\d+)\\)");
Match uidMatch = uidRegex.Match(response);
String uid = uidMatch.Groups["uid"].Value;
reader.ReadLine();
command = String.Format(". uid store {0} +flags (\\Deleted)", uid);
Command(command);
reader.ReadLine();
reader.ReadLine();
Command(". expunge");
while (!(response = reader.ReadLine()).StartsWith(". ")) ;
}
private void Command(String command)
{
writer.WriteLine(command);
writer.Flush();
}
public void Connect(String email, String password)
{
try
{
client = new TcpClient();
client.Connect(Host, Port);
sslStream = new SslStream(client.GetStream());
sslStream.AuthenticateAsClient(Host);
reader = new StreamReader(sslStream);
writer = new StreamWriter(sslStream);
StringBuilder stringBuilder = new StringBuilder();
String temp;
while (!(temp = reader.ReadLine()).StartsWith("* OK"))
{
stringBuilder.Append(temp + "\n");
}
stringBuilder.Append(temp);
Command(". login " + email + " " + password);
stringBuilder.Clear();
while ((temp = reader.ReadLine()).StartsWith("*"))
{
stringBuilder.Append(temp + "\n");
}
if (!temp.Contains(". OK"))
{
throw new Exception("Invalid credential");

27

Curechi Adrian SI-111


}
}
catch
{
CloseConnection();
throw;
}
}
public List<Folder> GetFolders()
{
List<Folder> folders = new List<Folder>();
Command(". list \"\" \"*\"");
StringBuilder stringBuilder = new StringBuilder();
String temp;
while ((temp = reader.ReadLine()).StartsWith("*"))
{
if (!temp.Contains("Noselect"))
{
String[] strarr = temp.Split('"');
folders.Add(new Folder(strarr[3]));
}
}
return folders;
}
public void SelectFolder(String Folder)
{
Command(". select \"" + Folder + "\"");
StringBuilder stringBuilder = new StringBuilder();
String temp;
MailsCount = -1;
while ((temp = reader.ReadLine()).StartsWith("*"))
{
if (temp.Contains("EXISTS"))
{
String[] strarr = temp.Trim().Split(' ');
MailsCount = Convert.ToInt32(strarr[1]);
}
}
}
private void CloseConnection()
{
//Close connection
Command("logout");
reader.ReadLine();
reader.Close();
writer.Close();
sslStream.Close();
client.Close();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{

28

Curechi Adrian SI-111


CloseConnection();
}
}

Anexa C Tools.cs
using
using
using
using

System;
System.Collections.Generic;
System.Text;
System.Text.RegularExpressions;

namespace AppooProjectClasses
{
public struct MyMail
{
public String To;
public String From;
public String Subject;
public String Body;
public Boolean hasAttachments;
}
public struct Folder
{
public String name;
public Folder(String _name)
{
name = _name;
}
}
public class Tools
{
public static String ToBase64(String input)
{
Byte[] inputStringBytes = ASCIIEncoding.ASCII.GetBytes(input);
return Convert.ToBase64String(inputStringBytes);
}
#region MailHeaderInfo
public static String GetSubject(String mailSourceCode)
{
//Find Subject
Regex subjectRegex = new Regex(
"[sS]ubject:(?<subject>(\\s+.+)?)\n",
RegexOptions.IgnoreCase);
Match subjectMatch = subjectRegex.Match(mailSourceCode);
String subject = subjectMatch.Groups["subject"].Value;
if (Regex.IsMatch(subject, "=\\?[^\\?]*\\?[qQbB]\\?"))
{
return QPorBase64ToString(subject).Trim();
}
else
{
return subject.Trim();
}
}
public static String GetSender(String mailSourceCode)
{

29

Curechi Adrian SI-111


//Find Sender
Regex fromRegex = new Regex(
"[fF]rom:\\s(\"?(?<name>[^\"<\n]*)\"?\\s*)?(?<email>\\s?<?[^:]*>?)\n",
RegexOptions.IgnoreCase);
Match fromMatch = fromRegex.Match(mailSourceCode);
String senderName = fromMatch.Groups["name"].Value;
String senderEmail = fromMatch.Groups["email"].Value;
if (Regex.IsMatch(senderName, "=\\?[^\\?]*\\?[qQbB]\\?"))
{
return QPorBase64ToString(senderName).Trim() + " " + senderEmail.Trim();
}
else
{
return senderName.Trim() + " " + senderEmail.Trim();
}
}
public static String GetDestination(String mailSourceCode)
{
//Find destination
Regex toRegex = new Regex(
"[tT]o:\\s(\"?(?<name>[^\"<\n]*)\"?\\s*)?(?<email>\\s?<?[^:]*>?)\n",
RegexOptions.IgnoreCase);
Match toMatch = toRegex.Match(mailSourceCode);
String toName = toMatch.Groups["name"].Value;
String toEmail = toMatch.Groups["email"].Value;
if (Regex.IsMatch(toName, "=\\?[^\\?]*\\?[qQbB]\\?"))
{
return QPorBase64ToString(toName).Trim() + " " + toEmail.Trim();
}
else
{
return toName.Trim() + " " + toEmail.Trim();
}
}
public static String GetContentType(String mailSourceCode)
{
Regex typeRegex = new Regex(
"Content-Type:\\s+?(?<type>[^;]+)\n?",
RegexOptions.IgnoreCase);
Match typeMatch = typeRegex.Match(mailSourceCode);
String Type = typeMatch.Groups["type"].Value;
return Type;
}
#endregion MailHeaderInfo
#region Decoders
private static String QPorBase64ToString(String encodedString)
{
Regex encodeRegex = new Regex(
"=\\?(?<charset>[^\\?]*)\\?(?<encodetype>[qQbB])\\?(?<encoded>\\S*)\\?=");
MatchCollection encodedMatches = encodeRegex.Matches(encodedString);
String decodedString = String.Empty;
Encoding encoder;
foreach (Match encodedMatch in encodedMatches)
{
String encodeType = encodedMatch.Groups["encodetype"].Value;
String charset = encodedMatch.Groups["charset"].Value;
String encodedText = encodedMatch.Groups["encoded"].Value;
if (encodeType == "B" || encodeType == "b")
{
encoder = Encoding.GetEncoding(charset);

30

Curechi Adrian SI-111


Byte[] base64Bytes = Convert.FromBase64String(encodedText);
decodedString += encoder.GetString(base64Bytes);

}
else
{
decodedString += DecodeQP(encodedText, charset);
}
}
return decodedString;
}

public static String DecodeQP(String input, String encode)


{
input = input.Replace("=\n", "");
Encoding enc;
try
{
enc = Encoding.GetEncoding(encode);
}
catch
{
enc = Encoding.UTF8;
}
List<Byte> bytesList = new List<Byte>();
for (Int32 i = 0; i < input.Length; i++)
{
if (i < input.Length - 2 && Regex.IsMatch(
input.Substring(i, 3),
"=[A-F0-9]{2}"))
{
Byte hexByte = Convert.ToByte(input.Substring(i + 1, 2), 16);
bytesList.Add(hexByte);
i += 2;
}
else
{
bytesList.Add(Convert.ToByte(input[i]));
}
}
return enc.GetString(bytesList.ToArray());
}
#endregion Decoders

31

Curechi Adrian SI-111

Anexa D Form1.cs
using
using
using
using
using
using

AppooProjectClasses;
System;
System.Collections.Generic;
System.ComponentModel;
System.Threading;
System.Windows.Forms;

namespace AppooProjectInterface
{
public partial class MyMailClient : Form
{
IMAPClient imapClient;
String email;
String password;
List<MyMail> myMails;
Int32 count;
String currentFolder;
public MyMailClient()
{
InitializeComponent();
imapClient = new IMAPClient();
myMails = new List<MyMail>();
mailFolders.SelectedIndexChanged += mailFolders_SelectedIndexChanged;
mailsTable.CellClick += mailsTable_CellContentClick;
mailLoader.DoWork += mailLoader_DoWork;
mailLoader.ProgressChanged += mailLoader_ProgressChanged;
mailLoader.RunWorkerCompleted += mailLoader_RunWorkerCompleted;
mailSender.DoWork += mailSender_DoWork;
mailSender.RunWorkerCompleted += mailSender_RunWorkerCompleted;
mailSender.WorkerSupportsCancellation = true;
mailsTable.MouseHover += (sender, evnt) =>
{
(sender as DataGridView).Focus();
};
this.Disposed += (sender, evnt) =>
{
if (mailLoader.IsBusy)
{
mailLoader.CancelAsync();
}
if (mailSender.IsBusy)
{
mailSender.CancelAsync();
}
imapClient.Dispose();
};
}
void mailLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
mailFolders.Enabled = true;
}
void mailLoader_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if ((sender as BackgroundWorker).CancellationPending == true)
{
return;

32

Curechi Adrian SI-111


}
progressBar.Value = e.ProgressPercentage + 1;
mailCountLabel.Text = "[" + (e.ProgressPercentage + 1) + "/" + count + "]";
mailsTable.Rows.Add();
mailsTable.Rows[e.ProgressPercentage].Cells[0].Value = myMails[e.ProgressPercentage].Subject;
mailsTable.Rows[e.ProgressPercentage].Cells[1].Value = myMails[e.ProgressPercentage].From;
mailsTable.Rows[e.ProgressPercentage].Cells[2].Value = myMails[e.ProgressPercentage].To;
mailsTable.Rows[e.ProgressPercentage].Cells[3].Value =
myMails[e.ProgressPercentage].hasAttachments;
mailsTable.Rows[e.ProgressPercentage].Cells[4].Tag = e.ProgressPercentage.ToString();
}
void mailLoader_DoWork(object sender, DoWorkEventArgs e)
{
for (Int32 i = 0; i < count; i++)
{
if ((sender as BackgroundWorker).CancellationPending == true)
{
return;
}
MyMail mail = imapClient.GetMail(i);
myMails.Add(mail);
(sender as BackgroundWorker).ReportProgress(i);
}
}
void mailFolders_SelectedIndexChanged(object sender, EventArgs e)
{
mailFolders.Enabled = false;
mailsTable.Rows.Clear();
myMails.Clear();
currentFolder = mailFolders.Items[mailFolders.SelectedIndex].ToString();
imapClient.SelectFolder(currentFolder);
count = imapClient.MailsCount;
progressBar.Value = 0;
progressBar.Maximum = count;
mailCountLabel.Text = "[0/" + count + "]";
if (count >= 0)
{
mailLoader.RunWorkerAsync();
}
else
{
MessageBox.Show("Error on selecting folder.", "Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
void mailSender_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
toTextBox.Text = String.Empty;
subjectTextBox.Text = String.Empty;
bodyTextBox.Text = String.Empty;
newMailBox.Enabled = true;
}
void mailSender_DoWork(object sender, DoWorkEventArgs e)
{
SMTPClient smtpClient = new SMTPClient();
smtpClient.Host = smtpHost.Text;
smtpClient.Port = Convert.ToInt32(smtpPort.Value);
smtpClient.Email = email;
smtpClient.Password = password;

33

Curechi Adrian SI-111


smtpClient.EmailTo = toTextBox.Text;
smtpClient.Subject = subjectTextBox.Text;
smtpClient.Body = bodyTextBox.Text;
smtpClient.Connect();
try
{
smtpClient.Send();
MessageBox.Show("Mail sent successfully.", "Sent", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while sending mail.\n" + ex.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
smtpClient.Close();
}
private void sendMailButton_Click(object sender, EventArgs e)
{
Boolean anddressIsEntred = !String.IsNullOrEmpty(toTextBox.Text);
Boolean subjectIsEntred = !String.IsNullOrEmpty(subjectTextBox.Text);
if (anddressIsEntred && subjectIsEntred)
{
if (mailSender.IsBusy == false)
{
mailSender.RunWorkerAsync();
}
newMailBox.Enabled = false;
}
else
{
MessageBox.Show("Enter all new mail data.");
}
}
private void mailsTable_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
{
Int32 mailIndex = Int32.Parse((sender as
DataGridView).Rows[e.RowIndex].Cells[4].Tag.ToString());
MyMail mail = myMails[mailIndex];
if (!mail.Body.Contains("<br>"))
{
mail.Body = mail.Body.Replace("\n", "<br>");
}
webBrowser1.DocumentText = mail.Body;
tabControl.SelectedTab = mailContentPage;
}
if (e.ColumnIndex == 4 && e.RowIndex >= 0)
{
try
{
Int32 mailIndex = Int32.Parse((sender as
DataGridView).Rows[e.RowIndex].Cells[4].Tag.ToString());
imapClient.DeleteMail(mailIndex);
(sender as DataGridView).Rows.RemoveAt(e.RowIndex);
count--;
mailCountLabel.Text = "[" + count + "/" + count + "]";
}
catch (Exception ex)
{

34

Curechi Adrian SI-111


MessageBox.Show("An error occurred while deleting mail.\n" + ex.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void loadButton_Click(object sender, EventArgs e)
{
this.email = emailTextBox.Text;
this.password = passwordTextBox.Text;
imapClient.Host = imapHost.Text;
imapClient.Port = Convert.ToInt32(imapPort.Value);
try
{
imapClient.Connect(email, password);
}
catch (Exception excpt)
{
MessageBox.Show(excpt.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
List<Folder> folders = imapClient.GetFolders();
foreach (var folder in folders)
{
this.mailFolders.Items.Add(folder.name);
}
this.mailFolders.SelectedIndex = 0;
this.progressBar.Visible = true;
this.tabControl.Controls.Add(this.mailListPage);
this.tabControl.Controls.Add(this.mailContentPage);
this.tabControl.Controls.Add(this.newMailPage);
this.tabControl.Controls.Remove(authenticationPage);
}
}

35