/* This file is part of Bolixo. Bolixo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Bolixo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Bolixo. If not, see . */ /* This is a small server that acts as an email server. It support the SMTP protocol minimally and log everthing it receives in a file. This is used for testing and preproduction where we do not want test email to go out, yet we want to test the complete sequence (even exim configuration). */ #include #include #include #include #include #include #include using namespace std; struct HANDLE_INFO: public ARRAY_OBJ{ enum class STATE { init, helo, from, to, data, quit} state = STATE::init; string from; string to; string data; }; static const char *ivld500 = "500 unrecognized command\r\n"; int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *port = "2025"; glocal const char *logfile = "/var/log/email-log.log"; glocal const char *user = "bolixo"; glocal bool daemon = false; glocal const char *pidfile = "/var/run/email-log.pid"; glocal.ret = (argc,argv); setproginfo ("email-log",VERSION,"Listen on port 25 and log everything received"); setarg ('l',"logfile","Log file path",glocal.logfile,false); setarg ('p',"port","TCP port",glocal.port,false); setarg (' ',"user","Run the program as this user",glocal.user,false); setarg (' ',"daemon","Run in background",glocal.daemon,false); setarg (' ',"pidfile","File holding the PID of the process",glocal.pidfile,false); int ret = -1; glocal FILE *flog = fopen (glocal.logfile,"a"); if (glocal.flog == NULL){ tlmp_error ("Can't open log file %s (%s)\n",glocal.logfile,strerror(errno)); exit(-1); } (glocal.port,10); info.data = new HANDLE_INFO; send ("220 email-log SMTP\r\n"); HANDLE_INFO *c = (HANDLE_INFO*)info.data; fprintf (glocal.flog,"-------\nfrom: %s\nto: %s\ndata\n%s\n" ,c->from.c_str(),c->to.c_str(),c->data.c_str()); fflush (glocal.flog); HANDLE_INFO *c = (HANDLE_INFO*)info.data; if (strcmp(line,"quit")==0){ endclient = true; }else{ const char *pt; switch(c->state){ case HANDLE_INFO::STATE::init: if (is_start_any_ofnc(line,pt,"helo","ehlo")){ sendf ("250 helo %s email-log\r\n",pt); c->state = HANDLE_INFO::STATE::helo; }else{ send (ivld500); } break; case HANDLE_INFO::STATE::helo: if (is_start_any_ofnc(line,pt,"mail from:")){ send ("250 OK\r\n"); c->state = HANDLE_INFO::STATE::from; c->from = pt; }else{ send (ivld500); } break; case HANDLE_INFO::STATE::from: if (is_start_any_ofnc(line,pt,"rcpt to:")){ send ("250 Accepted\r\n"); c->state = HANDLE_INFO::STATE::to; c->to = pt; }else{ send (ivld500); } break; case HANDLE_INFO::STATE::to: if (strcasecmp(line,"data")==0){ send ("354 Enter message, ending with \".\" on a line by itself\r\n"); c->state = HANDLE_INFO::STATE::data; }else{ send (ivld500); } break; case HANDLE_INFO::STATE::data: if (strcmp(line,".")==0){ send ("250 OK id=1hF33o-0002JA-4g\r\n"); c->state = HANDLE_INFO::STATE::quit; }else{ c->data += line; c->data += "\r\n"; } break; case HANDLE_INFO::STATE::quit: if (strcasecmp(line,"quit")==0){ send ("221 closing connection\r\n"); endclient = true; }else{ send (ivld500); } break; } } if (o.is_ok()){ if (glocal.daemon){ daemon_init(glocal.pidfile,glocal.user); } o.loop(); } return ret; return glocal.ret; }