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 
00026 
00027 SmtpdSocket::SmtpdSocket(ISocketHandler& h)
00028 :TcpSocket(h)
00029 ,m_hello(false)
00030 ,m_data(false)
00031 ,m_header(false)
00032 {
00033         SetLineProtocol();
00034 }
00035 
00036 
00037 void SmtpdSocket::OnAccept()
00038 {
00039         Send("220 ESMTP; \r\n");
00040 }
00041 
00042 
00043 void SmtpdSocket::OnLine(const std::string& line)
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 }
00225 
00226 
00227 std::string SmtpdSocket::ToLower(const std::string& str)
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 }
00239 
00240 
00241 std::string SmtpdSocket::ToUpper(const std::string& str)
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 }
00253 
00254 
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4