Logo
~Sockets~
~Examples~
~Contact~


SmtpdSocket Class Reference

Smtp server base class. More...

#include <SmtpdSocket.h>

Inheritance diagram for SmtpdSocket:

Inheritance graph
[legend]
Collaboration diagram for SmtpdSocket:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 SmtpdSocket (ISocketHandler &)
void OnAccept ()
 Called when an incoming connection has been completed.
void OnLine (const std::string &)
 Callback fires when a socket in line protocol has read one full line.
virtual bool OnHello (const std::string &domain)=0
 
Returns:
'false' to abort

virtual bool OnMailFrom (const EmailAddress &addr)=0
 
Returns:
'false' to abort

virtual bool OnRcptTo (const EmailAddress &addr)=0
 
Returns:
'false' to abort

virtual void OnHeader (const std::string &key, const std::string &value)=0
virtual void OnHeaderComplete ()=0
virtual void OnData (const std::string &line)=0
virtual bool OnDataComplete ()=0
 
Returns:
'false' if message write failed (message will probably be resent)

virtual void OnRset ()=0
virtual void OnAbort (reason_t)=0
virtual void OnNotSupported (const std::string &cmd, const std::string &arg)=0

Protected Types

enum  reason_t { SMTP_NO_HELLO, SMTP_NAME_TOO_LONG, SMTP_DOMAIN_TOO_LONG, SMTP_QUIT }

Private Member Functions

std::string ToLower (const std::string &str)
std::string ToUpper (const std::string &str)

Private Attributes

bool m_hello
bool m_data
bool m_header
std::string m_header_line

Classes

class  EmailAddress

Detailed Description

Smtp server base class.

Definition at line 36 of file SmtpdSocket.h.


Member Enumeration Documentation

enum SmtpdSocket::reason_t [protected]

Enumerator:
SMTP_NO_HELLO 
SMTP_NAME_TOO_LONG 
SMTP_DOMAIN_TOO_LONG 
SMTP_QUIT 

Definition at line 39 of file SmtpdSocket.h.

00039                      {
00040                 SMTP_NO_HELLO,
00041                 SMTP_NAME_TOO_LONG,
00042                 SMTP_DOMAIN_TOO_LONG,
00043                 SMTP_QUIT,
00044         } reason_t;


Constructor & Destructor Documentation

SmtpdSocket::SmtpdSocket ( ISocketHandler  ) 

Definition at line 27 of file SmtpdSocket.cpp.

References TcpSocket::SetLineProtocol().

00028 :TcpSocket(h)
00029 ,m_hello(false)
00030 ,m_data(false)
00031 ,m_header(false)
00032 {
00033         SetLineProtocol();
00034 }


Member Function Documentation

void SmtpdSocket::OnAccept (  )  [virtual]

Called when an incoming connection has been completed.

Reimplemented from Socket.

Definition at line 37 of file SmtpdSocket.cpp.

References TcpSocket::Send().

00038 {
00039         Send("220 ESMTP; \r\n");
00040 }

void SmtpdSocket::OnLine ( const std::string &  line  )  [virtual]

Callback fires when a socket in line protocol has read one full line.

Parameters:
line Line read

Reimplemented from TcpSocket.

Definition at line 43 of file SmtpdSocket.cpp.

References Parse::getrest(), Parse::getword(), m_data, m_header, m_header_line, m_hello, OnAbort(), OnData(), OnDataComplete(), OnHeader(), OnHeaderComplete(), OnHello(), OnMailFrom(), OnNotSupported(), OnRcptTo(), OnRset(), TcpSocket::Send(), Socket::SetCloseAndDelete(), SMTP_DOMAIN_TOO_LONG, SMTP_NAME_TOO_LONG, SMTP_NO_HELLO, SMTP_QUIT, ToLower(), and ToUpper().

00044 {
00045         if (m_data)
00046         {
00047                 if (m_header)
00048                 {
00049                         if (!line.size())
00050                         {
00051                                 if (m_header_line.size())
00052                                 {
00053                                         Parse pa(m_header_line, ":");
00054                                         std::string key = pa.getword();
00055                                         OnHeader(key, pa.getrest());
00056                                 }
00057                                 m_header = false;
00058                                 OnHeaderComplete();
00059                         }
00060                         else
00061                         if (line[0] == ' ' || line[0] == '\t')
00062                         {
00063                                 m_header_line += line;
00064                         }
00065                         else
00066                         {
00067                                 if (m_header_line.size())
00068                                 {
00069                                         Parse pa(m_header_line, ":");
00070                                         std::string key = pa.getword();
00071                                         OnHeader(key, pa.getrest());
00072                                 }
00073                                 m_header_line = line;
00074                         }
00075                 }
00076                 else
00077                 if (line == ".")
00078                 {
00079                         m_data = false;
00080                         if (OnDataComplete())
00081                                 Send("250 OK\r\n");
00082                         else
00083                                 Send("550 Failed\r\n");
00084                 }
00085                 else
00086                 if (line.size() && line[0] == '.')
00087                 {
00088                         OnData(line.substr(1));
00089                 }
00090                 else
00091                 {
00092                         OnData(line);
00093                 }
00094                 return;
00095         }
00096         Parse pa(line);
00097         std::string cmd = ToUpper(pa.getword());
00098 
00099         if (cmd == "EHLO")
00100         {
00101                 if (!OnHello(pa.getrest()))
00102                 {
00103                         Send("550 Failed\r\n");
00104                 }
00105                 else
00106                 {
00107                         m_hello = true;
00108                         Send("250 mail.alhem.net\r\n");
00109                 }
00110         }
00111         else
00112         if (cmd == "HELO")
00113         {
00114                 if (!OnHello(pa.getrest()))
00115                 {
00116                         Send("550 Failed\r\n");
00117                 }
00118                 else
00119                 {
00120                         m_hello = true;
00121                         Send("250 mail.alhem.net\r\n");
00122                 }
00123         }
00124         else
00125         if (!m_hello)
00126         {
00127                 OnAbort(SMTP_NO_HELLO);
00128                 SetCloseAndDelete();
00129         }
00130         else
00131         if (cmd == "MAIL") // mail from:
00132         {
00133                 Parse pa(line, ":");
00134                 pa.getword(); // 'mail'
00135                 pa.getword(); // 'from'
00136                 std::string email = ToLower(pa.getrest());
00137 
00138                 EmailAddress addr( email );
00139                 if (addr.GetName().size() > 64)
00140                 {
00141                         OnAbort(SMTP_NAME_TOO_LONG);
00142                         Send("500 Name too long.\r\n");
00143                         return;
00144                 }
00145                 if (addr.GetDomain().size() > 64)
00146                 {
00147                         OnAbort(SMTP_DOMAIN_TOO_LONG);
00148                         Send("500 Domain too long.\r\n");
00149                         return;
00150                 }
00151 
00152                 if (!OnMailFrom( addr ))
00153                 {
00154                         Send("550 Failed\r\n");
00155                 }
00156                 else
00157                 {
00158                         Send("250 OK\r\n");
00159                 }
00160         }
00161         else
00162         if (cmd == "RCPT") // rcpt to:
00163         {
00164                 Parse pa(line, ":");
00165                 pa.getword(); // 'rcpt'
00166                 pa.getword(); // 'to'
00167                 std::string email = ToLower(pa.getrest());
00168                 // %! reject based on user / domain?
00169                 EmailAddress addr( email );
00170 
00171                 if (addr.GetName().size() > 64)
00172                 {
00173                         OnAbort(SMTP_NAME_TOO_LONG);
00174                         Send("500 Name too long.\r\n");
00175                         return;
00176                 }
00177                 if (addr.GetDomain().size() > 64)
00178                 {
00179                         OnAbort(SMTP_DOMAIN_TOO_LONG);
00180                         Send("500 Domain too long.\r\n");
00181                         return;
00182                 }
00183 
00184                 if (!OnRcptTo( addr ))
00185                 {
00186                         Send("553 Failed\r\n");
00187                 }
00188                 else
00189                 {
00190                         Send("250 OK\r\n");
00191                 }
00192         }
00193         else
00194         if (cmd == "DATA")
00195         {
00196                 Send("354 Enter mail, end with \".\" on a line by itself\r\n");
00197                 m_data = true;
00198                 m_header = false;
00199         }
00200         else
00201         if (cmd == "RSET")
00202         {
00203                 m_data = false;
00204                 m_header = false;
00205                 OnRset();
00206                 Send("250 OK\r\n"); // %! ???
00207         }
00208         else
00209         if (cmd == "QUIT")
00210         {
00211                 OnAbort(SMTP_QUIT);
00212                 Send("221 Bye Bye\r\n");
00213                 SetCloseAndDelete();
00214         }
00215         else
00216         if (cmd == "NOOP")
00217         {
00218                 Send("250 OK\r\n");
00219         }
00220         else
00221         {
00222                 OnNotSupported(cmd, pa.getrest());
00223         }
00224 }

virtual bool SmtpdSocket::OnHello ( const std::string &  domain  )  [pure virtual]

Returns:
'false' to abort

Referenced by OnLine().

virtual bool SmtpdSocket::OnMailFrom ( const EmailAddress addr  )  [pure virtual]

Returns:
'false' to abort

Referenced by OnLine().

virtual bool SmtpdSocket::OnRcptTo ( const EmailAddress addr  )  [pure virtual]

Returns:
'false' to abort

Referenced by OnLine().

virtual void SmtpdSocket::OnHeader ( const std::string &  key,
const std::string &  value 
) [pure virtual]

Referenced by OnLine().

virtual void SmtpdSocket::OnHeaderComplete (  )  [pure virtual]

Referenced by OnLine().

virtual void SmtpdSocket::OnData ( const std::string &  line  )  [pure virtual]

Referenced by OnLine().

virtual bool SmtpdSocket::OnDataComplete (  )  [pure virtual]

Returns:
'false' if message write failed (message will probably be resent)

Referenced by OnLine().

virtual void SmtpdSocket::OnRset (  )  [pure virtual]

Referenced by OnLine().

virtual void SmtpdSocket::OnAbort ( reason_t   )  [pure virtual]

Referenced by OnLine().

virtual void SmtpdSocket::OnNotSupported ( const std::string &  cmd,
const std::string &  arg 
) [pure virtual]

Referenced by OnLine().

std::string SmtpdSocket::ToLower ( const std::string &  str  )  [private]

Definition at line 227 of file SmtpdSocket.cpp.

Referenced by OnLine().

00228 {
00229         std::string r;
00230         for (size_t i = 0; i < str.size(); i++)
00231         {
00232                 if (str[i] >= 'A' && str[i] <= 'Z')
00233                         r += str[i] | 32;
00234                 else
00235                         r += str[i];
00236         }
00237         return r;
00238 }

std::string SmtpdSocket::ToUpper ( const std::string &  str  )  [private]

Definition at line 241 of file SmtpdSocket.cpp.

Referenced by OnLine().

00242 {
00243         std::string r;
00244         for (size_t i = 0; i < str.size(); i++)
00245         {
00246                 if (str[i] >= 'a' && str[i] <= 'z')
00247                         r += (char)(str[i] - 32);
00248                 else
00249                         r += str[i];
00250         }
00251         return r;
00252 }


Member Data Documentation

bool SmtpdSocket::m_hello [private]

Definition at line 119 of file SmtpdSocket.h.

Referenced by OnLine().

bool SmtpdSocket::m_data [private]

Definition at line 120 of file SmtpdSocket.h.

Referenced by OnLine().

bool SmtpdSocket::m_header [private]

Definition at line 121 of file SmtpdSocket.h.

Referenced by OnLine().

std::string SmtpdSocket::m_header_line [private]

Definition at line 122 of file SmtpdSocket.h.

Referenced by OnLine().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4