Protokol POP3

Transkrypt

Protokol POP3
Odbieranie wiadomości elektronicznych.
Aplikacja KlientPop
dr Zbigniew Lipiński
Instytut Matematyki i Informatyki UO
ul. Oleska 48, 50-204 Opole
[email protected]
Protokół POP3
POP3, (ang.) Post Office Protocol version 3.
RFC 1939,J. Myers, M. Rose, Post Office Protocol - Version 3, May 1996, Obsoletes RFC 1725, Updated-By RFC 1957,
RFC 2449
RFC 1957, R. Nelson, Some Observations on Implementations of the Post Office Protocol (POP3), June 1996, Updates RFC 1939, Status: INFO.
RFC 2449, R. Gellens, C. Newman, L. Lundblade, POP3 Extension Mechanism, November 1998, Updates RFC 1939, Updated-By RFC 5034.
Protokół służący do odbierania wiadomości email ze skrzynek pocztowych (ang. mailboxes) znajdujących się na
serwerach POP3.
W warstwie transportowej serwery POP3 wykorzystuje protokół TCP, port 110.
Komunikaty POP mają strukturę wiadomości tekstowej w formacie 'Internet text messages‘, RFC 5322.
RFC 5322, P. Resnick, Internet Message Format, 2008, Obsoletes RFC 2822, Status: DRAFT STANDARD
2
Obiór wiadomości z serwera POP3
Klient POP3 może połączyć sie z serwerem i pobrać wszystkie wiadomości z katalogu Inbox serwera.
Sesja między klientem a serwerem POP podzielona jest na stany:
•
stan uwierzytelnienia i autoryzacji (AUTHORIZATION state),
•
stan transakcji (TRANSACTION state),
•
stan uaktualniania (UPDATE state).
3
Obiór wiadomości z serwera POP3
Po nawiązaniu połączenia TCP klienta z serwerem POP3, następuje rozpoczęcie sesji POP.
Proces odbioru poczty z serwera POP:
• nawiązanie połączenia klienta z serwerem (budowa połączenia TCP),
• serwer wysyła sygnał gotowości (wiadomość 'greeting‘),
• identyfikacja klienta na serwerze (uwierzytelnienie), przyznanie praw dostępu (autoryzacja),
• pytanie o liczbę wiadomości do odbioru (stan transakcji),
• wyznaczenie wielkości każdej wiadomości do odbioru (stan transakcji),
• odbiór wiadomości (stan transakcji),
• uaktualnianie stanu konta pocztowego po otrzymaniu komendy QUIT od klienta (stan aktualniania),
• zamknięcie sesji przez serwer wiadomością 'goodbye', (stan uaktualniania).
4
Przykład sesji POP3
S: <wait for connection on TCP port 110>
...
C: <open connection>
S: +OK POP3 server ready
<[email protected]>
C: APOP mrose
c4c9334bac560ecc979e58001b3e22fb
S: +OK mrose's maildrop has 2 messages
(320 octets)
C: STAT
S: +OK 2 320
C: LIST
S: +OK 2 messages (320 octets)
S: 1 120
S: 2 200
S: .
C: RETR 1
S: +OK 120 octets
S: <the POP3 server sends message 1>
S: .
C: DELE 1
S: +OK message 1 deleted
C: RETR 2
S: +OK 200 octets
S: <the POP3 server sends message 2>
S: .
C: DELE 2
S: +OK message 2 deleted
C: QUIT
S: +OK deley POP3 server signing off (maildrop empty)
C: <close connection>
S: <wait for next connection>
5
Komendy klienta POP3 – stan uwierzytelnienia
Komendy klienta POP3 w stanie uwierzytelnienia:
USER name
- nazwa użytkownika.
PASS password
- hasło użytkownika (string).
QUIT
- koniec sesji, brak argumentów.
Stan uwierzytelnienia sesji POP zaczyna się gdy serwer potwierdzi gotowość odbioru wiadomości:
S: +OK POP3 server ready
W stanie uwierzytelnienia sesji klient wysyła do serwera nazwę skrzynki i hasło.
Przykład: Użycie komendy USER.
C: USER frated
S: -ERR sorry, no mailbox for frated here
Przykład: Użycie komendy USER i PASS.
C: USER mrose
S: +OK mrose is a real hoopy frood
C: PASS secret
S: +OK mrose's maildrop has 2 messages (320 octets)
Przykład: Użycie komendy PASS.
C: PASS secret
S: -ERR maildrop already locked
6
Komendy klienta POP3 – stan uwierzytelnienia
Przed przejściem do stanu transakcji serwer POP blokuje skrzynkę do wyłącznego użycia przez
klienta POP w otwartej sesji.
Do momentu przejścia do stanu uaktualniania nie jest możliwa modyfikacja lub usunięcie wiadomości
ze skrzynki.
Po potwierdzeniu przez serwer blokady skrzynki komenda +OK, sesja przechodzi w stan transakcji.
7
Komendy klienta POP3 – stan transakcji
Komendy klienta POP w stanie transakcji:
STAT
Pytanie o widomości, brak argumentów.
Składania: STAT
Odpowiedź: +OK liczbaMaili wielkoscMaili
LIST
Pytanie o wszystkie wiadomości lub wiadomości o określonym numerze maila (message-id).
Składania: LIST [message-id]
Odpowiedź: +OK liczbaMaili wielkoscMaili
+OK kolejnyNumerMaila wielkoscMailia
RETR
Polecenie wysłania wiadomości o danym identyfikatorze (id).
Składania: RETR message-id
Odpowiedź: +OK wielkoscMailia, przesyłane są kolejno pakiety z danymi.
DELE
Polecenie usunięcia wiadomości, serwer zaznacza wiadomość jako: 'do usunięcia'. Usunięcie następuje w
stanie uaktualniania.
Składania: DELE message-id
Odpowiedź: +OK message deleted lub -ERR no such message
NOOP
Oznacza brak działania serwera, brak argumentów. Po tej komendzie serwer POP3 zwraca komunikat: +OK.
Składania: NOOP
Odpowiedź: +OK
RSET
Brak argumentów, serwer usuwa status wiadomości 'do usunięcia', ostatnia wiadomość uzyskuje numer 0.
Składania: RSET
Odpowiedz: +OK liczbaWiadomosci.
LAST
Brak argumentów, serwer zwraca numer ostatniej wiadomości.
Składania: LAST
Odpowiedz: +OK nn
8
Komendy klienta POP3 – stan uaktualniania
Komendy klienta POP w stanie uaktualniania:
QUIT
serwer usuwa odebrane wiadomości przez klienta.
Składania: QUIT
Odpowiedz: +OK
9
Opcjonalne komendy klienta POP3
Komendy opcjonalne w stanie uwierzytelnienia:
APOP
uwierzytelnienie bez wysyłania hasła, serwer przy powitaniu wysyła znacznik czasu (timestamp),
np. <process-ID.clock@nazwa_serweraPOP>, klient POP wysyła user_id i liczbę 'digest‘ wyliczoną ze
znacznika czasu algorytmem MD5).
Składania: C: APOP nazwaSkrzynki digest
Odpowiedź: S: +OK maildrop locked and ready
lub -ERR permission denied
Komendy opcjonalne w stanie transakcji:
TOP
serwer zwraca nagłówek wiadomości i liczbę linii wiadomości.
Składania: TOP message-id n
Odpowiedź: +OK,
kolejne wiadomości zawierają: nagłówek, pusta linia, n linii wiadomości, lub -ERR
UIDL
Komenda 'unique-id listing'.
Serwer zwraca identyfikatory wszystkich wiadomości lub identyfikator wiadomości o danym numerze msg.
Identyfikator wiadomości to max. 70 bajtowy string (z zakresu 0x21 - 0x7E) nadawany przez serwer POP3
każdej wiadomości.
Po komendzie UIDL wiadomości zaznaczone jako usunięte nie są zawracane przez serwer.
Składania: UIDL [msg]
Odpowiedź: +OK
[numerWiadmosci] identyfikatory
10
Opcjonalne komendy klienta POP3
Przykład: Użycie komendy APOP.
S: +OK POP3 server ready <[email protected]>
C: APOP mrose c4c9334bac560ecc979e58001b3e22fb
S: +OK maildrop has 1 message (369 octets)
Przykład: Użycie komendy UIDL.
C: UIDL
S: +OK
S: 1 whqtswO00WBw418f9t5JxYwZ
S: 2 QhdPYR:00WBw1Ph7x7
S: .
...
C: UIDL 2
S: +OK 2 QhdPYR:00WBw1Ph7x7
...
C: UIDL 3
S: -ERR no such message, only 2 messages in maildrop
11
Rozszerzania Protokołu POP3. RFC 2449.
RFC 2449 definiują rozszerzania protokołu POP3 o mechanizmy zarządzania serwerem POP.
Wprowadzono nowe polecenia:
SASL, RESP-CODES, LOGIN-DELAY, PIPELINING, EXPIRE, IMPLEMENTATION.
SASL - Simple Authentication and Security Layer.
Lista 'możliwości' serwera - capabilities list zwracana jest po komendzie CAPA.
Komenda CAPA może być stosowana w stanie uwierzytelnienia i w stanie transakcji.
Składania: CAPA
Początkowa lista parametrów (Initial Set of Capabilities):
TOP
polecenie TOP jest obsługiwane przez serwer.
USER
polecenia USER, PASS są obsługiwane przez serwer.
SASL
mechanizm identyfikacji SASL jest obsługiwany.
RESP-CODES
informacja, że tekst odpowiedzi w nawiasach ‘ [ ..] ‘ jest rozszerzeniem kodu odpowiedzi.,
LOGIN-DELAY
określa min. czas (w sekundach) między logowaniami.
PIPELINING
serwer akceptuje przesłanie listy komend, zamiast trybu: polecenie-odpowiedź.
EXPIRE
serwer informuje klienta jak długo wiadomość będzie przechowywana na serwerze.
UIDL
polecenie UIDL jest obsługiwane przez serwer.
IMPLEMENTATION
serwer zwraca informacje o implementacji.
12
Przykład listy parametrów
Przykład listy parametrów zwracanych przez serwer POP:
C: CAPA
S: +OK Capability list follows
S: TOP
S: USER
S: SASL CRAM-MD5 KERBEROS_V4
S: RESP-CODES
S: LOGIN-DELAY 900
S: PIPELINING
S: EXPIRE 60
S: UIDL
S: IMPLEMENTATION Shlemazle-Plotz-v302
S: .
13
Klient POP
Namespace: Microsoft.Crm.Tools.Email.Providers
Assembly: Microsoft.Crm.Tools.EmailProviders.dll
E-mail Provider Object Model
E-mail Provider Base Classes
// Provides an overview of the e-mail provider base classes.
Service Logging Classes
// Provides an overview of the classes used to log errors.
Configuration Classes
// Provides an overview of the classes used to read information from E-mail Router configuration file.
14
E-mail Provider Base Classes
15
Klient POP
Microsoft.Crm.Tools.Email.Providers Classes (wybór)
EmailMessage
//Represents an e-mail message.
EmailProvider
//Provides a base class for all providers.
ExchangeEmailMessage
//Represents an Exchange e-mail message.
MimeEmailMessage
//Represents an e-mail message in MIME format.
Pop3Client
//Provides the protocol for communications with a POP3 e-mail server.
Pop3EmailMessage
//Represents a POP3 e-mail message.
16
Pop3Client class
Constructors
Pop3Client // Initializes a new instance of the Pop3Client class.
public
public
public
public
Pop3Client(IPAddress pop3Address,
Pop3Client(string pop3Server, int
Pop3Client(IPAddress pop3Address,
Pop3Client(string pop3Server, int
Static method
CertificateValidationCallback
int connectionTimeout);
connectionTimeout);
int pop3Port, int connectionTimeout);
pop3Port, int connectionTimeout);
// Validates a server certificate.
public static bool CertificateValidationCallback(
Object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
);
17
Pop3Client class
Instance methods
AuthenticateClearText
AuthenticateNtlm
Connect
//Authenticates to the POP3 server using clear text.
//Authenticates to the POP3 server using NTLM.
//Connects to the POP3 server.
public void Connect(
DeleteMessage
bool
useSsl);
// Deletes a message.
public void DeleteMessage( int
messagePos);
Disconnect
Dispose
DownloadHeaders
DownloadMessage
// Disconnects from the POP3 server.
// Disposes the Pop3Client object instance.
// Downloads message headers.
// Downloads the entire message (body and header).
public string DownloadMessage(int messagePos);
RetrieveMessageCount
// Retrieves the message count.
public int RetrieveMessageCount();
18
Pop3Client class
Instance Property
ConnectionState
Pop3Port
Pop3Server
WelcomeBanner
// Gets the connection state.
public ConnectionState ConnectionState {get;}
Disconnected 0, Authorization 1,Transaction 2, Update 3
// Gets the POP3 server port.
// Gets the POP3 server name.
// Gets the POP3 server welcome banner.
19
IPAddress Class
Public property (wybór)
AddressFamily
IsIPv4MappedToIPv6
IsIPv6Multicast
IsIPv6SiteLocal
ScopeId
Public methods (wybór)
GetAddressBytes
GetHashCode
GetType
GetAddressBytes
MapToIPv4
ToString
//Gets the address family of the IP address.
//Gets whether the IP address is an IPv4-mapped IPv6 address.
//Gets whether the address is an IPv6 multicast global address.
//Gets whether the address is an IPv6 site local address.
//Gets or sets the IPv6 address scope identifier.
//Provides a copy of the IPAddress as an array of bytes.
//Returns a hash value for an IP address.
//Gets the Type of the current instance.
//Provides a copy of the IPAddress as an array of bytes.
//Maps the IPAddress object to an IPv4 address.
//Converts an Internet address to its standard notation.
Public methodStatic (wybór)
HostToNetworkOrder(Int32) //Converts an integer value from host byte order to network byte order.
NetworkToHostOrder(Int32) //Converts an integer value from network byte order to host byte order.
IsLoopback
//Indicates whether the specified IP address is the loopback address.
Parse
//Converts an IP address string to an IPAddress instance.
TryParse
//Determines whether a string is a valid IP address.
MapToIPv4
//Maps the IPAddress object to an IPv4 address.
20
Klient POP
using
using
using
using
using
using
using
using
using
System;
System.Collections;
System.IO;
System.Net;
System.Net.Sockets;
System.Threading;
System.Text;
System.Text.RegularExpressions;
System.Diagnostics;
namespace Pop3
{
public class Pop3Client
{
private Pop3Credential m_credential;
private const int m_pop3port = 110;
private const int MAX_BUFFER_READ_SIZE = 256;
private
private
private
private
long m_inboxPosition = 0;
long m_directPosition = -1;
Socket m_socket = null;
Pop3Message m_pop3Message = null;
21
public
{
set
get
}
public
Pop3Credential UserDetails
{ m_credential = value; }
{ return m_credential; }
string From
{
get { return m_pop3Message.From; }
}
public string To
{
get { return m_pop3Message.To; }
}
public string Subject
{
get { return m_pop3Message.Subject; }
}
public string Body
{
get { return m_pop3Message.Body; }
}
public IEnumerator MultipartEnumerator
{
get { return m_pop3Message.MultipartEnumerator; }
}
public bool IsMultipart
{
get { return m_pop3Message.IsMultipart; }
}
public Pop3Client(string user, string pass, string server)
{
m_credential = new Pop3Credential(user,pass,server);
}
22
Klient POP
private Socket GetClientSocket()
{
Socket s = null;
try
{
IPHostEntry hostEntry = null;
// Get host related information.
hostEntry = Dns.Resolve(m_credential.Server);
foreach(IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, m_pop3port);
Socket tempSocket = new Socket(ipe.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
tempSocket.Connect(ipe);
if(tempSocket.Connected)
{ // we have a connection return this socket
s = tempSocket;
break;
}
else
{
continue;
}
}
}
23
Klient POP
catch(Exception e)
{
throw new Pop3ConnectException(e.ToString());
}
// throw exception if can't connect ...
if(s == null)
{
throw new Pop3ConnectException("Error : connecting to "
+m_credential.Server);
}
return s;
}
24
Klient POP
//send the data to server
private void Send(String data)
{
if(m_socket == null)
{
throw new Pop3MessageException("Pop3 connection is closed");
}
try
{
// Convert the string data to byte data
// using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data+"\r\n");
// Begin sending the data to the remote device.
m_socket.Send(byteData);
}
catch(Exception e)
{
throw new Pop3SendException(e.ToString());
}
}
25
Klient POP
private string GetPop3String()
{
if(m_socket == null)
{
throw new
Pop3MessageException("Connection to POP3 server is closed");
}
byte[] buffer = new byte[MAX_BUFFER_READ_SIZE];
string line = null;
try
{
int byteCount =
m_socket.Receive(buffer,buffer.Length,0);
line =
Encoding.ASCII.GetString(buffer, 0, byteCount);
}
catch(Exception e)
{
throw new Pop3ReceiveException(e.ToString());
}
return line;
}
26
Klient POP
private void LoginToInbox()
{
string returned;
// send username ...
Send("user "+m_credential.User);
// get response ...
returned = GetPop3String();
if( !returned.Substring(0,3).Equals("+OK") )
{
throw new Pop3LoginException("login not excepted");
}
// send password ...
Send("pass "+m_credential.Pass);
// get response ...
returned = GetPop3String();
if( !returned.Substring(0,3).Equals("+OK") )
{
throw new
Pop3LoginException("login/password not accepted");
}
}
27
Klient POP
public long MessageCount
{
get
{
long count = 0;
if(m_socket==null)
{
throw new Pop3MessageException("Pop3 server not connected");
}
Send("stat");
string returned = GetPop3String();
// if values returned ...
if( Regex.Match(returned,
@"^.*\+OK[ |
]+([0-9]+)[ |
]+.*$").Success )
{
// get number of emails ...
count = long.Parse( Regex.Replace(returned.Replace("\r\n","")
, @"^.*\+OK[ |
]+([0-9]+)[ |
]+.*$" ,"$1") );
}
return(count);
}
}
28
Klient POP
public void CloseConnection()
{
Send("quit");
m_socket = null;
m_pop3Message = null;
}
public bool DeleteEmail()
{
bool ret = false;
Send("dele "+m_inboxPosition);
string returned = GetPop3String();
if( Regex.Match(returned,
@"^.*\+OK.*$").Success )
{
ret = true;
}
return ret;
}
29
public bool NextEmail(long directPosition)
{
bool ret;
if( directPosition >= 0 )
{
m_directPosition = directPosition;
ret = NextEmail();
}
else
{
throw new Pop3MessageException("Position less than zero");
}
return ret;
}
public bool NextEmail()
{
string returned;
long pos;
if(m_directPosition == -1)
{
if(m_inboxPosition == 0)
{
pos = 1;
}
else
{
pos = m_inboxPosition + 1;
}
}
else
{
pos = m_directPosition+1;
m_directPosition = -1;
}
30
Klient POP
// send username ...
Send("list "+pos.ToString());
// get response ...
returned = GetPop3String();
// if email does not exist at this position
// then return false ...
if( returned.Substring(0,4).Equals("-ERR") )
{
return false;
}
m_inboxPosition = pos;
// strip out CRLF ...
string[] noCr = returned.Split(new char[]{ '\r' });
// get size ...
string[] elements = noCr[0].Split(new char[]{ ' ' });
long size = long.Parse(elements[2]);
// ... else read email data
m_pop3Message = new Pop3Message(m_inboxPosition,size,m_socket);
return true;
}
31
Klient POP
public void OpenInbox()
{
// get a socket ...
m_socket = GetClientSocket();
// get initial header from POP3 server ...
string header = GetPop3String();
if( !header.Substring(0,3).Equals("+OK") )
{
throw new Exception("Invalid initial POP3 response");
}
// send login details ...
LoginToInbox();
}
}
}
32
33

Podobne dokumenty