svn cleanup
[anytun.git] / Sockets / SmtpdSocket.cpp
blob0d62925c2630ba4b3efdcb90f876bd9472078841
1 /**
2 ** \file SmtpdSocket.cpp
3 ** \date 2007-05-10
4 ** \author grymse@alhem.net
5 **/
6 /*
7 Copyright (C) 2007 Anders Hedstrom
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "SmtpdSocket.h"
24 #include "Parse.h"
25 #include "Utility.h"
27 #ifdef SOCKETS_NAMESPACE
28 namespace SOCKETS_NAMESPACE {
29 #endif
31 SmtpdSocket::SmtpdSocket(ISocketHandler& h)
32 :TcpSocket(h)
33 ,m_hello(false)
34 ,m_data(false)
35 ,m_header(false)
37 SetLineProtocol();
41 void SmtpdSocket::OnAccept()
43 Send("220 ESMTP; \r\n");
47 void SmtpdSocket::OnLine(const std::string& line)
49 if (m_data)
51 if (m_header)
53 if (!line.size())
55 if (m_header_line.size())
57 Parse pa(m_header_line, ":");
58 std::string key = pa.getword();
59 OnHeader(key, pa.getrest());
61 m_header = false;
62 OnHeaderComplete();
64 else
65 if (line[0] == ' ' || line[0] == '\t')
67 m_header_line += line;
69 else
71 if (m_header_line.size())
73 Parse pa(m_header_line, ":");
74 std::string key = pa.getword();
75 OnHeader(key, pa.getrest());
77 m_header_line = line;
80 else
81 if (line == ".")
83 m_data = false;
84 if (OnDataComplete())
85 Send("250 OK\r\n");
86 else
87 Send("550 Failed\r\n");
89 else
90 if (line.size() && line[0] == '.')
92 OnData(line.substr(1));
94 else
96 OnData(line);
98 return;
100 Parse pa(line);
101 std::string cmd = Utility::ToUpper(pa.getword());
103 if (cmd == "EHLO")
105 if (!OnHello(pa.getrest()))
107 Send("550 Failed\r\n");
109 else
111 m_hello = true;
112 Send("250 mail.alhem.net\r\n");
115 else
116 if (cmd == "HELO")
118 if (!OnHello(pa.getrest()))
120 Send("550 Failed\r\n");
122 else
124 m_hello = true;
125 Send("250 mail.alhem.net\r\n");
128 else
129 if (!m_hello)
131 OnAbort(SMTP_NO_HELLO);
132 SetCloseAndDelete();
134 else
135 if (cmd == "MAIL") // mail from:
137 Parse pa(line, ":");
138 pa.getword(); // 'mail'
139 pa.getword(); // 'from'
140 std::string email = Utility::ToLower(pa.getrest());
142 EmailAddress addr( email );
143 if (addr.GetName().size() > 64)
145 OnAbort(SMTP_NAME_TOO_LONG);
146 Send("500 Name too long.\r\n");
147 return;
149 if (addr.GetDomain().size() > 64)
151 OnAbort(SMTP_DOMAIN_TOO_LONG);
152 Send("500 Domain too long.\r\n");
153 return;
156 if (!OnMailFrom( addr ))
158 Send("550 Failed\r\n");
160 else
162 Send("250 OK\r\n");
165 else
166 if (cmd == "RCPT") // rcpt to:
168 Parse pa(line, ":");
169 pa.getword(); // 'rcpt'
170 pa.getword(); // 'to'
171 std::string email = Utility::ToLower(pa.getrest());
172 // %! reject based on user / domain?
173 EmailAddress addr( email );
175 if (addr.GetName().size() > 64)
177 OnAbort(SMTP_NAME_TOO_LONG);
178 Send("500 Name too long.\r\n");
179 return;
181 if (addr.GetDomain().size() > 64)
183 OnAbort(SMTP_DOMAIN_TOO_LONG);
184 Send("500 Domain too long.\r\n");
185 return;
188 if (!OnRcptTo( addr ))
190 Send("553 Failed\r\n");
192 else
194 Send("250 OK\r\n");
197 else
198 if (cmd == "DATA")
200 Send("354 Enter mail, end with \".\" on a line by itself\r\n");
201 m_data = true;
202 m_header = false;
204 else
205 if (cmd == "RSET")
207 m_data = false;
208 m_header = false;
209 OnRset();
210 Send("250 OK\r\n"); // %! ???
212 else
213 if (cmd == "QUIT")
215 OnAbort(SMTP_QUIT);
216 Send("221 Bye Bye\r\n");
217 SetCloseAndDelete();
219 else
220 if (cmd == "NOOP")
222 Send("250 OK\r\n");
224 else
226 OnNotSupported(cmd, pa.getrest());
231 #ifdef SOCKETS_NAMESPACE
232 } // namespace SOCKETS_NAMESPACE {
233 #endif