diff --git a/BMAMail b/BMAMail index ff2a408..9045895 100755 Binary files a/BMAMail and b/BMAMail differ diff --git a/MailFileSystem.cpp b/MailFileSystem.cpp new file mode 100644 index 0000000..bdba7e9 --- /dev/null +++ b/MailFileSystem.cpp @@ -0,0 +1,43 @@ + +#include "MailFileSystem.h" +# include "INotify.h" + +namespace mail { + + MailFileSystem::MailFileSystem(std::string mailPath) : mailPath(mailPath) {} + + bool MailFileSystem::ifMailBoxExists(std::string mailbox) { + std::cout << "{" << mailbox << "}" << std::endl; + + if(stat(getMailBoxPath(mailbox).c_str(), &statbuf) != -1) + if(S_ISDIR(statbuf.st_mode)) + return true; + return false; + } + + bool MailFileSystem::ifAliasExists(std::string alias) { + if(stat(getMailBoxPath(alias).c_str(), &statbuf) != -1) + if(S_ISREG(statbuf.st_mode)) + return true; + return false; + } + + std::string MailFileSystem::getMailBoxPath(std::string mailbox) { + coreutils::ZString email(mailbox); + email.split("@", 1); + std::cout << email[0] << "-" << email[1] << std::endl; + std::string path = mailPath + "/" + email[1].str() + "/" + email[0].str(); + std::cout << "{" << path << "}" << std::endl; + return path; + } + + std::vector MailFileSystem::getAliasMailboxes(std::string alias) { + std::vector returnValue; + return returnValue; + } + + std::string MailFileSystem::getMailPath() { + return mailPath; + } + +} diff --git a/MailFileSystem.h b/MailFileSystem.h index d61a67f..be32f40 100644 --- a/MailFileSystem.h +++ b/MailFileSystem.h @@ -1,45 +1,22 @@ #ifndef __MailFileSystem_h__ # define __MailFileSystem_h__ +# include "ZString.h" # include # include # include -# include "INotify.h" -# include "ZString.h" namespace mail { class MailFileSystem { public: - MailFileSystem(std::string mailPath) : mailPath(mailPath) {} - - bool ifMailBoxExists(std::string mailbox) { - if(stat(getMailBoxPath(mailbox).c_str(), &statbuf) != -1) - if(S_ISDIR(statbuf.st_mode)) - return true; - return false; - } - - bool ifAliasExists(std::string alias) { - if(stat(getMailBoxPath(alias).c_str(), &statbuf) != -1) - if(S_ISREG(statbuf.st_mode)) - return true; - return false; - } - - std::string getMailBoxPath(std::string mailbox) { - coreutils::ZString email(mailbox); - email.split("@"); - std::string path = mailPath + "/" + email[1].str() + "/" + email[0].str(); - return path; - } - + MailFileSystem(std::string mailPath); + bool ifMailBoxExists(std::string mailbox); + bool ifAliasExists(std::string alias); + std::string getMailBoxPath(std::string mailbox); std::vector getAliasMailboxes(std::string alias); - - std::string getMailPath() { - return mailPath; - } + std::string getMailPath(); private: std::string mailPath; diff --git a/POP3Command.cpp b/POP3Command.cpp new file mode 100644 index 0000000..3da174d --- /dev/null +++ b/POP3Command.cpp @@ -0,0 +1,13 @@ +#include "POP3Command.h" + +namespace mail { + + int POP3Command::processCommand(coreutils::ZString &request, core::TCPSession &session) { + return processCommand(request, (POP3Session &)session, (POP3Server &)session.server); + } + + int POP3Command::processCommand(coreutils::ZString request, POP3Session &session, POP3Server &server) { + return 0; + } + +} diff --git a/POP3Command.h b/POP3Command.h index a6e179e..d30a299 100644 --- a/POP3Command.h +++ b/POP3Command.h @@ -2,7 +2,6 @@ # define __POP3Command_h__ # include "Command.h" -# include "TCPSession.h" # include "POP3Session.h" namespace mail { @@ -12,13 +11,8 @@ namespace mail { class POP3Command : public core::Command { public: - virtual int processCommand(coreutils::ZString &request, core::TCPSession &session) override { - return processCommand(request, (POP3Session &)session, (POP3Server &)session.server); - } - - virtual int processCommand(coreutils::ZString request, POP3Session &session, POP3Server &server) { - return 0; - } + virtual int processCommand(coreutils::ZString &request, core::TCPSession &session) override; + virtual int processCommand(coreutils::ZString request, POP3Session &session, POP3Server &server); }; diff --git a/POP3Session.h b/POP3Session.h index d2f70da..9de0b80 100644 --- a/POP3Session.h +++ b/POP3Session.h @@ -4,7 +4,10 @@ namespace mail { class POP3Session : public core::TCPSession { - + enum AuthState { + USER_UNKNOWN, USER_QUERY, USER_SECRET_QUERY, USER_KNOWN + }; + public: std::string clientDomainName; std::string userName; diff --git a/SMTPCommand.cpp b/SMTPCommand.cpp new file mode 100644 index 0000000..aa545a5 --- /dev/null +++ b/SMTPCommand.cpp @@ -0,0 +1,21 @@ +#include "SMTPCommand.h" + +namespace mail { + + int SMTPCommand::processCommand(coreutils::ZString &request, core::TCPSession &session) { + return processCommand(request, (SMTPSession &)session, (SMTPServer &)session.server); + } + + int SMTPCommand::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { + return 0; + } + + void SMTPCommand::grabInput(SMTPSession &session) { + session.server.commands.grabInput(session, *this); + } + + void SMTPCommand::clearGrab(SMTPSession &session) { + session.server.commands.clearGrab(session); + } + +} diff --git a/SMTPCommand.h b/SMTPCommand.h index ce96663..e124336 100644 --- a/SMTPCommand.h +++ b/SMTPCommand.h @@ -13,22 +13,10 @@ namespace mail { class SMTPCommand : public core::Command { public: - - virtual int processCommand(coreutils::ZString &request, core::TCPSession &session) override { - return processCommand(request, (SMTPSession &)session, (SMTPServer &)session.server); - } - - virtual int processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { - return 0; - } - - void grabInput(SMTPSession &session) { - session.server.commands.grabInput(session, *this); - } - - void clearGrab(SMTPSession &session) { - session.server.commands.clearGrab(session); - } + virtual int processCommand(coreutils::ZString &request, core::TCPSession &session); + virtual int processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server); + void grabInput(SMTPSession &session); + void clearGrab(SMTPSession &session); }; diff --git a/SMTPServer.h b/SMTPServer.h index 743cc7a..01958de 100644 --- a/SMTPServer.h +++ b/SMTPServer.h @@ -25,7 +25,7 @@ namespace mail { public: SMTPServer(core::EPoll &ePoll, std::string hostName, MailFileSystem &mailFileSystem, core::IPAddress ipAddress) - : core::TCPServer(ePoll, ipAddress, " ", 10, "SMTP Server"), core::INotify(ePoll), hostName(hostName), mailFileSystem(mailFileSystem) { + : core::TCPServer(ePoll, ipAddress, " ", 1, "SMTP Server"), core::INotify(ePoll), hostName(hostName), mailFileSystem(mailFileSystem) { commands.add(_smtp_auth, "AUTH"); commands.add(_smtp_data, "DATA"); commands.add(_smtp_ehlo, "EHLO"); diff --git a/SMTPSession.cpp b/SMTPSession.cpp new file mode 100644 index 0000000..55913d9 --- /dev/null +++ b/SMTPSession.cpp @@ -0,0 +1,12 @@ +# include "SMTPSession.h" + +namespace mail { + + SMTPSession::SMTPSession(core::EPoll &ePoll, core::TCPServer &server) + : TCPSession(ePoll, server, "SMTP Client Session") {} + + void SMTPSession::onConnected() { + out << "220 localhost BMAMail" << CRLF; + } + +} diff --git a/SMTPSession.h b/SMTPSession.h index 3d3147d..654a4fa 100644 --- a/SMTPSession.h +++ b/SMTPSession.h @@ -3,6 +3,7 @@ # include "TCPSession.h" # include "TCPServer.h" +# include "MString.h" # define CRLF "\r\n" @@ -15,23 +16,20 @@ namespace mail { class SMTPSession : public core::TCPSession { public: - SMTPSession(core::EPoll &ePoll, core::TCPServer &server) - : TCPSession(ePoll, server, "SMTP Client Session") {} - - void onConnected() override { - out << "220 localhost BMAMail" << CRLF; - } + SMTPSession(core::EPoll &ePoll, core::TCPServer &server); - std::string clientDomainName; - std::string userName; - std::string password; + void onConnected() override; + + coreutils::MString clientDomainName; + coreutils::MString userName; + coreutils::MString password; std::stringstream mailData; State state = CONNECT; AuthState authState = USER_UNKNOWN; Mode mode = WAIT_FOR_DATA; bool relay = false; - std::string sender; - std::vector recipientList; + coreutils::MString sender; + std::vector recipientList; }; diff --git a/__SMTP_DATA.cpp b/__SMTP_DATA.cpp index db27c00..74d43e5 100644 --- a/__SMTP_DATA.cpp +++ b/__SMTP_DATA.cpp @@ -4,8 +4,6 @@ #include #include -#define CRLF "\r\n" - namespace mail { int __SMTP_DATA::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { @@ -21,7 +19,7 @@ namespace mail { session.mailData.str(""); session.mode = RECEIVE_DATA; grabInput(session); - // setTimer(120.0f); +// session.setTimer(120.0f); break; case MAIL: @@ -36,8 +34,8 @@ namespace mail { break; case RECEIVE_DATA: - if(request.str() != ".") - session.mailData << request.str() << CRLF; + if(request != ".") + session.mailData << request << CRLF; else { session.mode = WAIT_FOR_DATA; session.state = READY; @@ -45,7 +43,7 @@ namespace mail { // if(filterMessage(session.mailData)) { if(session.recipientList.size() > 0) { if(session.mailData.str().size() > 0) { - std::string ID = queueMail(server, session.sender, session.recipientList, session.mailData); + coreutils::MString ID = queueMail(server, session.sender, session.recipientList, session.mailData); if(ID != "") { coreutils::Log(coreutils::LOG_INFO) << "Queued message " << ID << "."; session.out << "250 OK Queued message " << ID << CRLF; @@ -64,22 +62,22 @@ namespace mail { return 1; } - std::string __SMTP_DATA::generateMailFileName() { - std::stringstream temp; + coreutils::MString __SMTP_DATA::generateMailFileName() { struct timespec timex; clock_gettime(CLOCK_REALTIME, &timex); - temp << timex.tv_sec << "." << std::setfill('0') << std::setw(9) << timex.tv_nsec; - return temp.str(); + std::stringstream temp; + temp << timex.tv_sec << "." << std::setfill('0') << std::setw(9) << timex.tv_nsec; + return coreutils::MString(temp.str()); } - std::string __SMTP_DATA::queueMail(SMTPServer &server, std::string sender, std::vector recipientList, std::stringstream &mailData) { - std::string fileName = server.mailFileSystem.getMailPath() + "/.queue/" + generateMailFileName(); + coreutils::MString __SMTP_DATA::queueMail(SMTPServer &server, coreutils::MString &sender, std::vector &recipientList, std::stringstream &mailData) { + coreutils::MString fileName(server.mailFileSystem.getMailPath() + "/.queue/" + generateMailFileName().str()); coreutils::File mailFile(fileName, O_CREAT | O_WRONLY, 0660); mailFile.write(mailData.str()); - for(std::string recipient: recipientList) { - std::string newName = fileName + recipient; - link(fileName.c_str(), newName.c_str()); + for(coreutils::MString recipient: recipientList) { + coreutils::MString newName(fileName.write(recipient)); + link(fileName.c_str(), newName.c_str()); } unlink(fileName.c_str()); diff --git a/__SMTP_DATA.h b/__SMTP_DATA.h index 37f7959..2fe6c2e 100644 --- a/__SMTP_DATA.h +++ b/__SMTP_DATA.h @@ -12,8 +12,8 @@ namespace mail { int processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) override; - std::string generateMailFileName(); - std::string queueMail(SMTPServer &server, std::string sender, std::vector recipientList, std::stringstream &mailData); + coreutils::MString generateMailFileName(); + coreutils::MString queueMail(SMTPServer &server, coreutils::MString &sender, std::vector &recipientList, std::stringstream &mailData); }; diff --git a/__SMTP_EHLO.cpp b/__SMTP_EHLO.cpp index 08686a6..91e9f4c 100644 --- a/__SMTP_EHLO.cpp +++ b/__SMTP_EHLO.cpp @@ -5,8 +5,8 @@ namespace mail { int __SMTP_EHLO::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { - session.clientDomainName = request[1].str(); - + session.clientDomainName = request[1]; + std::cout << "{" << session.clientDomainName << "}" << std::endl; session.out << "250-" << server.hostName << CRLF; // cout << "250-STARTTLS" << CRLF; // cout << "250-PIPELINING" << CRLF; diff --git a/__SMTP_MAIL.cpp b/__SMTP_MAIL.cpp index 4c9852a..0f68a82 100644 --- a/__SMTP_MAIL.cpp +++ b/__SMTP_MAIL.cpp @@ -3,20 +3,20 @@ namespace mail { int __SMTP_MAIL::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { - - if(request.ifNext("MAIL FROM:")) { - request.skipWhitespace(); - if(request.ifNext("<")) { - session.sender = request.getTokenExclude(">").str(); - if(session.authState = USER_KNOWN) { - session.out << "250 OK" << CRLF; - session.recipientList.clear(); - session.state = MAIL; - } - } else - session.out << "550 Usage: MAIL FROM:" << CRLF; + + if(request[1].ifNext("FROM:")) { + request[1].skipWhitespace(); + if(request[1].ifNext("<")) { + session.sender = request[1].getTokenExclude(">"); + if(session.authState = USER_KNOWN) { + session.out << "250 OK" << CRLF; + session.recipientList.clear(); + session.state = MAIL; + } + } else + session.out << "550 Usage: MAIL FROM:" << CRLF; } else - session.out << "550 Usage: MAIL FROM:" << CRLF; + session.out << "550 Usage: MAIL FROM:" << CRLF; return 1; } diff --git a/__SMTP_RCPT.cpp b/__SMTP_RCPT.cpp index c5d46cf..94c76b6 100644 --- a/__SMTP_RCPT.cpp +++ b/__SMTP_RCPT.cpp @@ -3,14 +3,13 @@ namespace mail { - int __SMTP_RCPT::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { - + int __SMTP_RCPT::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) { if((session.state == MAIL) || (session.state == RCPT)) { std::string recipient; - if(request.ifNext("RCPT TO:")) { - request.skipWhitespace(); - if(request.ifNext("<")) { - recipient = request.getTokenExclude(">").str(); + if(request[1].ifNext("TO:")) { + request[1].skipWhitespace(); + if(request[1].ifNext("<")) { + recipient = request[1].getTokenExclude(">").str(); if(server.mailFileSystem.ifMailBoxExists(recipient)) { session.recipientList.push_back(recipient); session.out << "250 OK" << CRLF; @@ -27,7 +26,6 @@ namespace mail { session.out << "550 Usage: RCPT TO:" << CRLF; } else session.out << "503 Please use MAIL first" << CRLF; - return 1; } diff --git a/tests/testsmtp b/tests/testsmtp index 3eccb91..6879ab5 100755 --- a/tests/testsmtp +++ b/tests/testsmtp @@ -1,9 +1,8 @@ #!/bin/bash nc localhost 25 > /dev/null << EOL EHLO barant.com -MAIL FROM: -RCPT TO: -RCPT TO: +MAIL FROM: +RCPT TO: DATA From: brad.arant@barant.com To: barant@barant.com