SMTP and POP3 servers are standalone only now, eliminated library loading function
[fmail.git] / backends / protocol / smtp.cpp
blob3b28aac832d64c67eecb7da41b05a8c0dd779d46
1 /*
2 SMTP Protocol Handler
4 Copyright (C) 2007 Carlos Daniel Ruvalcaba Valenzuela <clsdaniel@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <libfmail.h>
22 #include <pcrecpp.h>
24 const int SMTP_PORT = 12000; //25;
25 const char CRLF[2] = {0x0D, 0x0A};
27 const int CMD_EHLO = 1;
28 const int CMD_HELO = 2;
29 const int CMD_MAIL = 3;
30 const int CMD_RCPT = 4;
31 const int CMD_DATA = 5;
32 const int CMD_QUIT = 6;
33 const int CMD_RSET = 7;
34 const char KEY_END_DATA[6] = {0x0D, 0x0A, '.', 0x0D, 0x0A, 0x00};
36 int knhash(char v){
37 if ((v >= 65) && (v <= 90))
38 return v - 65;
40 if (v == 95)
41 return 26;
43 if ((v >= 97) && (v <= 122))
44 return v - 97;
46 if (v == ' ')
47 return -1;
49 if (v == 0x0D)
50 return -1;
52 return 255;
55 class SMTPHandler : public ProtocolHandler{
56 SearchTree<int, 27, &knhash> cmdtree;
57 public:
58 SMTPHandler(){
59 cmdtree.Insert("EHLO", 1);
60 cmdtree.Insert("HELO", 2);
61 cmdtree.Insert("MAIL", 3);
62 cmdtree.Insert("RCPT", 4);
63 cmdtree.Insert("DATA", 5);
64 cmdtree.Insert("QUIT", 6);
65 cmdtree.Insert("RSET", 7);
67 int Handle(Socket *s){
68 char buffer[255], username[255], recipent[255];
69 int r, l, ret;
70 int onrun, cmd, state;
71 FILE *fd;
72 pcrecpp::RE reCmd("\\w*:<(.*)>");
73 state = 0;
74 onrun = 1;
75 cmd = 0;
76 string mailfrom, rcpt;
79 s->Write("220 FancyMail v0.1", 18);
80 s->Write( CRLF, 2);
82 while (onrun){
83 memset(buffer, 0, 255);
84 r = s->Read(buffer, 255);
86 try{
87 cmd = cmdtree.Lookup(buffer);
88 }catch (SearchNotFound){
89 cmd = -1;
92 switch(cmd){
93 case CMD_HELO:
94 s->Write("250 ok localhost", 16);
95 s->Write(CRLF, 2);
96 state = 1;
97 break;
98 case CMD_EHLO:
99 s->Write( "502 Not implemented", 19);
100 s->Write( CRLF, 2);
101 break;
102 case CMD_MAIL:
103 if (state != 1){
104 s->Write( "502 Not implemented", 19);
105 s->Write( CRLF, 2);
106 break;
108 ret = reCmd.PartialMatch(buffer, &mailfrom);
109 printf("[Debug] Sending Mail From: %s\n", mailfrom.c_str());
110 s->Write( "250 OK", 6);
111 s->Write( CRLF, 2);
112 state = 2;
113 break;
114 case CMD_RCPT:
115 if (state != 2){
116 s->Write( "502 Not implemented", 19);
117 s->Write( CRLF, 2);
118 break;
120 reCmd.PartialMatch(buffer, &rcpt);
121 printf("[Debug] Recipent: %s\n", rcpt.c_str());
122 s->Write( "250 OK", 6);
123 s->Write( CRLF, 2);
124 state = 3;
125 break;
126 case CMD_DATA:
127 if (state != 3){
128 s->Write( "502 Not implemented", 19);
129 s->Write( CRLF, 2);
130 break;
132 printf("Reciving Data!\n");
133 s->Write( "354 OK", 6);
134 s->Write( CRLF, 2);
136 //fd = tmpfile();
138 r = 1;
139 while (r){
140 memset(buffer, 0, 255);
142 l = s->Read( buffer, 255);
143 printf("%s", buffer);
145 if (strstr(buffer, KEY_END_DATA)){
146 r = 0;
147 printf("\nEnd of Data\n");
148 }else{
149 printf("Buffer[%i]: %s\n", l, buffer);
154 s->Write( "250 OK", 6);
155 s->Write( CRLF, 2);
156 state = 1;
157 break;
158 case CMD_RSET:
159 s->Write( "250 OK", 6);
160 s->Write( CRLF, 2);
161 state = 1;
162 break;
163 case CMD_QUIT:
164 printf("Got Quit, Exiting\n");
165 s->Write( "221 Exiting", 11);
166 s->Write(CRLF, 2);
167 onrun = 0;
168 break;
169 default:
170 printf("Not implemented [State: %i]: %s\n", state, buffer);
171 s->Write( "502 Not implemented", 19);
172 s->Write( CRLF, 2);
173 break;
176 printf("[COMMAND]: %s\n", buffer);
179 printf("Closing Connection\n");
180 s->Close();
184 class SimpleLoad : public LoadHandler {
185 public:
186 int Dispatch(Socket *sock, ProtocolHandler *ph){
187 if (ph)
188 return ph->Handle(sock);
189 return 0;
193 int main(int argc, char **argv){
194 BaseServer *srv;
195 SimpleLoad *lh;
196 SMTPHandler *handler;
198 handler = new SMTPHandler();
199 lh = new SimpleLoad();
200 srv = new BaseServer(handler, SMTP_PORT);
201 srv->SetLoadhandler(lh);
202 srv->Listen();
204 while(1){
205 srv->Accept();
208 return 0;