Logo
~Sockets~
~Examples~
~Contact~


SmtpdSocket.cpp

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007  Anders Hedstrom
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 */
00023 #include "SmtpdSocket.h"
00024 #include "Parse.h"
00025 #include "Utility.h"
00026 
00027 #ifdef SOCKETS_NAMESPACE
00028 namespace SOCKETS_NAMESPACE {
00029 #endif
00030 
00031 SmtpdSocket::SmtpdSocket(ISocketHandler& h)
00032 :TcpSocket(h)
00033 ,m_hello(false)
00034 ,m_data(false)
00035 ,m_header(false)
00036 {
00037         SetLineProtocol();
00038 }
00039 
00040 
00041 void SmtpdSocket::OnAccept()
00042 {
00043         Send("220 ESMTP; \r\n");
00044 }
00045 
00046 
00047 void SmtpdSocket::OnLine(const std::string& line)
00048 {
00049         if (m_data)
00050         {
00051                 if (m_header)
00052                 {
00053                         if (!line.size())
00054                         {
00055                                 if (m_header_line.size())
00056                                 {
00057                                         Parse pa(m_header_line, ":");
00058                                         std::string key = pa.getword();
00059                                         OnHeader(key, pa.getrest());
00060                                 }
00061                                 m_header = false;
00062                                 OnHeaderComplete();
00063                         }
00064                         else
00065                         if (line[0] == ' ' || line[0] == '\t')
00066                         {
00067                                 m_header_line += line;
00068                         }
00069                         else
00070                         {
00071                                 if (m_header_line.size())
00072                                 {
00073                                         Parse pa(m_header_line, ":");
00074                                         std::string key = pa.getword();
00075                                         OnHeader(key, pa.getrest());
00076                                 }
00077                                 m_header_line = line;
00078                         }
00079                 }
00080                 else
00081                 if (line == ".")
00082                 {
00083                         m_data = false;
00084                         if (OnDataComplete())
00085                                 Send("250 OK\r\n");
00086                         else
00087                                 Send("550 Failed\r\n");
00088                 }
00089                 else
00090                 if (line.size() && line[0] == '.')
00091                 {
00092                         OnData(line.substr(1));
00093                 }
00094                 else
00095                 {
00096                         OnData(line);
00097                 }
00098                 return;
00099         }
00100         Parse pa(line);
00101         std::string cmd = Utility::ToUpper(pa.getword());
00102 
00103         if (cmd == "EHLO")
00104         {
00105                 if (!OnHello(pa.getrest()))
00106                 {
00107                         Send("550 Failed\r\n");
00108                 }
00109                 else
00110                 {
00111                         m_hello = true;
00112                         Send("250 mail.alhem.net\r\n");
00113                 }
00114         }
00115         else
00116         if (cmd == "HELO")
00117         {
00118                 if (!OnHello(pa.getrest()))
00119                 {
00120                         Send("550 Failed\r\n");
00121                 }
00122                 else
00123                 {
00124                         m_hello = true;
00125                         Send("250 mail.alhem.net\r\n");
00126                 }
00127         }
00128         else
00129         if (!m_hello)
00130         {
00131                 OnAbort(SMTP_NO_HELLO);
00132                 SetCloseAndDelete();
00133         }
00134         else
00135         if (cmd == "MAIL") // mail from:
00136         {
00137                 Parse pa(line, ":");
00138                 pa.getword(); // 'mail'
00139                 pa.getword(); // 'from'
00140                 std::string email = Utility::ToLower(pa.getrest());
00141 
00142                 EmailAddress addr( email );
00143                 if (addr.GetName().size() > 64)
00144                 {
00145                         OnAbort(SMTP_NAME_TOO_LONG);
00146                         Send("500 Name too long.\r\n");
00147                         return;
00148                 }
00149                 if (addr.GetDomain().size() > 64)
00150                 {
00151                         OnAbort(SMTP_DOMAIN_TOO_LONG);
00152                         Send("500 Domain too long.\r\n");
00153                         return;
00154                 }
00155 
00156                 if (!OnMailFrom( addr ))
00157                 {
00158                         Send("550 Failed\r\n");
00159                 }
00160                 else
00161                 {
00162                         Send("250 OK\r\n");
00163                 }
00164         }
00165         else
00166         if (cmd == "RCPT") // rcpt to:
00167         {
00168                 Parse pa(line, ":");
00169                 pa.getword(); // 'rcpt'
00170                 pa.getword(); // 'to'
00171                 std::string email = Utility::ToLower(pa.getrest());
00172                 // %! reject based on user / domain?
00173                 EmailAddress addr( email );
00174 
00175                 if (addr.GetName().size() > 64)
00176                 {
00177                         OnAbort(SMTP_NAME_TOO_LONG);
00178                         Send("500 Name too long.\r\n");
00179                         return;
00180                 }
00181                 if (addr.GetDomain().size() > 64)
00182                 {
00183                         OnAbort(SMTP_DOMAIN_TOO_LONG);
00184                         Send("500 Domain too long.\r\n");
00185                         return;
00186                 }
00187 
00188                 if (!OnRcptTo( addr ))
00189                 {
00190                         Send("553 Failed\r\n");
00191                 }
00192                 else
00193                 {
00194                         Send("250 OK\r\n");
00195                 }
00196         }
00197         else
00198         if (cmd == "DATA")
00199         {
00200                 Send("354 Enter mail, end with \".\" on a line by itself\r\n");
00201                 m_data = true;
00202                 m_header = false;
00203         }
00204         else
00205         if (cmd == "RSET")
00206         {
00207                 m_data = false;
00208                 m_header = false;
00209                 OnRset();
00210                 Send("250 OK\r\n"); // %! ???
00211         }
00212         else
00213         if (cmd == "QUIT")
00214         {
00215                 OnAbort(SMTP_QUIT);
00216                 Send("221 Bye Bye\r\n");
00217                 SetCloseAndDelete();
00218         }
00219         else
00220         if (cmd == "NOOP")
00221         {
00222                 Send("250 OK\r\n");
00223         }
00224         else
00225         {
00226                 OnNotSupported(cmd, pa.getrest());
00227         }
00228 }
00229 
00230 
00231 #ifdef SOCKETS_NAMESPACE
00232 } // namespace SOCKETS_NAMESPACE {
00233 #endif
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4