diff --git a/BMAMail.project b/BMAMail.project
index 86b7586..4b8795b 100644
--- a/BMAMail.project
+++ b/BMAMail.project
@@ -2,6 +2,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -15,8 +36,15 @@
+
+
-
+
+
+
+
+
+
@@ -92,15 +120,4 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/__SMTP_AUTH.h b/__SMTP_AUTH.h
new file mode 100644
index 0000000..a606280
--- /dev/null
+++ b/__SMTP_AUTH.h
@@ -0,0 +1,98 @@
+#ifndef ____SMTP_AUTH_h__
+#define ____SMTP_AUTH_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_AUTH : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data);
+
+ data << "" << std::endl;
+
+
+ //---------------------------------------------------------------------------
+ // AUTH command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "AUTH") {
+
+ if(input.length() > 5) {
+ string method = input.substr(5);
+
+ string userName;
+ string password;
+
+ //--------------------------------
+ // Check for AUTH LOGIN method.
+ //--------------------------------
+
+ if(method == "LOGIN") {
+
+ cout << "334 VXNlcm5hbWU6" << CRLF;
+
+ alarm(10);
+
+ if(!getline(cin, userName)) {
+ return -1;
+ }
+
+ alarm(0);
+
+ if(userName[userName.length() - 1] == '\r')
+ userName.erase(userName.length() - 1);
+
+ cout << "334 UGFzc3dvcmQ6" << CRLF;
+
+ alarm(10);
+
+ if(!getline(cin, password)) {
+ return -1;
+ }
+ alarm(0);
+
+ if(password[password.length() - 1] == '\r')
+ password.erase(password.length() - 1);
+
+ BASE64 base64;
+
+ log.message("Logging in with user '" + base64.decode(userName) + "' using password '" + base64.decode(password) + "'.");
+
+ if(authLogin(base64.decode(userName), base64.decode(password))) {
+ cout << "235 Authentication successful" << CRLF;
+ log.message("Response: 235 Authentication successful.");
+ relay = true;
+ }
+
+ else {
+ cout << "530 Login was unsuccessful." << CRLF;
+ log.message("Response: 530 Login was unsuccessful.");
+ }
+ }
+
+ else {
+ cout << "530 AUTH method not supported." << CRLF;
+ log.message("Response: 530 AUTH method not supported.");
+ }
+
+ }
+
+ else {
+
+
+ }
+
+ }
+
+
+ httpRequest.response.addHeader("Content-Type", "script/javascript");
+
+ return 0;
+ }
+
+ };
+
+}
+
+#endif
diff --git a/__SMTP_DATA.h b/__SMTP_DATA.h
new file mode 100644
index 0000000..a5e9c11
--- /dev/null
+++ b/__SMTP_DATA.h
@@ -0,0 +1,164 @@
+ //---------------------------------------------------------------------------
+ // DATA command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "DATA") {
+
+ //--------------------------------------------------------------
+ // We must have recipients before we can send data.
+ //--------------------------------------------------------------
+
+ if(state == "RCPT") {
+
+ //---------------------------------------------------------
+ // Prompt for client to begin entering mail message data.
+ //---------------------------------------------------------
+
+ cout << "354 Enter the mail message terminated by ." << CRLF;
+
+ mailData = "";
+
+ //-----------------------------------------------------------
+ // Receive mail message one line at a time and keep an eye
+ // out for the terminating period character.
+ //-----------------------------------------------------------
+
+ do {
+
+ alarm(120);
+
+ if(!getline(cin, input)) {
+ return -1;
+ }
+
+ if(input[input.length() - 1] == '\r')
+ input.erase(input.length() - 1);
+
+ alarm(0);
+ if(input != ".") {
+
+ //--------------------------------------------------------------
+ // If there was a period for the first character but it wasn't
+ // the only character then remove and ignore the first period.
+ // This is the transparency mode capability.
+ //--------------------------------------------------------------
+
+ if(input[0] == '.') {
+ mailData += input.substr(1) + CRLF;
+ }
+
+ else {
+ mailData += input + CRLF;
+ }
+
+ }
+
+ } while(input != ".");
+
+ //------------------------------------------------------------------
+ // Run the received message through an external filter program if
+ // one is configured into the system settings.
+ //------------------------------------------------------------------
+
+ string ID;
+
+ if(filterMessage(mailData)) {
+
+ if(recipientList != "") {
+
+ if(mailData.length() > 0) {
+
+ //------------------------------------------------------------------
+ // We have the message and we have a list of recipients. Send the
+ // message to the queue since we know everyone in the recipient
+ // list has passed the test.
+ //------------------------------------------------------------------
+
+ ID = queueMail(sender, recipientList, mailData, clientIP, log, sql, "N");
+
+ if(ID != "") {
+
+ log.message("Response: 250 OK Queued message " + ID);
+
+ //------------------------------
+ // Tell the client we sent it.
+ //------------------------------
+
+ cout << "250 OK Queued message " << ID << CRLF;
+ }
+
+ else {
+
+ log.message("Response: 550 Mail message too big.");
+
+ //---------------------------------
+ // Tell the client it was too big.
+ //---------------------------------
+
+ cout << "550 Mail message too big" << CRLF;
+ }
+
+ }
+
+ //------------------------------------------------------------------------
+ // The mail message is empty so we are going to error out. We don't like
+ // getting empty messages.
+ //------------------------------------------------------------------------
+
+ else {
+
+ log.message("Response: 550 Mail message was empty.");
+ cout << "550 Mail message was empty" << CRLF;
+
+ }
+
+ }
+
+ else {
+
+ log.message("Response: 250 OK Queued message. (We actually discarded it due to empty recipient list)");
+
+ //------------------------------
+ // Tell the client we sent it.
+ //------------------------------
+
+ cout << "250 OK Queued message " << ID << CRLF;
+
+ }
+
+ }
+
+ //----------------------------------------------------
+ // Error out cause it did not pass the filter test.
+ //----------------------------------------------------
+
+ else {
+
+ cout << "550 Message is probably spam" << CRLF;
+ log.message("Response: 550 Message is probably spam.");
+ }
+
+ //----------------------------
+ // Return to the READY state.
+ //----------------------------
+
+ state = "READY";
+ }
+ //--------------------------------------------------------
+ // Generate an error cause we are not in the right state.
+ //--------------------------------------------------------
+
+ else {
+
+ if(state == "MAIL") {
+ cout << "503 Please use RCPT first" << CRLF;
+ log.message("Response: 503 Please use RCPT first.");
+ }
+
+ else {
+ cout << "503 Please use MAIL first" << CRLF;
+ log.message("Response: 503 Please use MAIL first.");
+ }
+
+ }
+ }
diff --git a/__SMTP_EHLO.h b/__SMTP_EHLO.h
new file mode 100644
index 0000000..3d51ef0
--- /dev/null
+++ b/__SMTP_EHLO.h
@@ -0,0 +1,25 @@
+ //---------------------------------------------------------------------------
+ // EHLO command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "EHLO") {
+
+ if(input.length() > 5) {
+ string hostName = input.substr(5);
+ }
+
+ else {
+
+ // TODO: Provide error message demanding identity here.
+ //
+ }
+
+ cout << "250-" << getHostName() << CRLF;
+ // cout << "250-STARTTLS" << CRLF;
+ // cout << "250-PIPELINING" << CRLF;
+ // cout << "250-8BITMIME" << CRLF;
+ cout << "250-AUTH LOGIN" << CRLF;
+ cout << "250 HELP" << CRLF;
+ state = "READY";
+ }
+
\ No newline at end of file
diff --git a/__SMTP_HELO.h b/__SMTP_HELO.h
new file mode 100644
index 0000000..6f8dd8f
--- /dev/null
+++ b/__SMTP_HELO.h
@@ -0,0 +1,19 @@
+ //---------------------------------------------------------------------------
+ // HELO command request handling.
+ //---------------------------------------------------------------------------
+
+ if(command(input) == "HELO") {
+
+ if(input.length() > 5) {
+ string hostName = input.substr(5);
+ }
+
+ else {
+
+ // TODO: Provide error message demanding identity here.
+ //
+ }
+
+ cout << "250 " << getHostName() << CRLF;
+ state = "READY";
+ }
\ No newline at end of file
diff --git a/__SMTP_MAIL.h b/__SMTP_MAIL.h
new file mode 100644
index 0000000..6cc816d
--- /dev/null
+++ b/__SMTP_MAIL.h
@@ -0,0 +1,25 @@
+ //---------------------------------------------------------------------------
+ // MAIL command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "MAIL") {
+
+ sender = cleanEMail(input.substr(5));
+
+ //-------------------------------------------------------------
+ // Verify that the senders domain name resolves to an address
+ // with an MX record. If not and there is a bounce then we
+ // will not be able to return the bounce message so it is
+ // probably a spammer anyway.
+ //-------------------------------------------------------------
+
+ if(verifyDomainMX(domainOnly(sender))) {
+
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+ recipientList = "";
+ state = "MAIL";
+ }
+
+
+ }
diff --git a/__SMTP_NOOP.h b/__SMTP_NOOP.h
new file mode 100644
index 0000000..df17538
--- /dev/null
+++ b/__SMTP_NOOP.h
@@ -0,0 +1,21 @@
+#ifndef ____SMTP_AUTH_h__
+#define ____SMTP_AUTH_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_AUTH : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data);
+
+ data << "" << std::endl;
+
+ //---------------------------------------------------------------------------
+ // NOOP command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "NOOP") {
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+ }
diff --git a/__SMTP_QUIT.h b/__SMTP_QUIT.h
new file mode 100644
index 0000000..24c3619
--- /dev/null
+++ b/__SMTP_QUIT.h
@@ -0,0 +1,23 @@
+#ifndef ____SMTP_AUTH_h__
+#define ____SMTP_AUTH_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_AUTH : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data);
+
+ data << "" << std::endl;
+
+ //---------------------------------------------------------------------------
+ // QUIT command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "QUIT") {
+ cout << "221 " << getHostName() << CRLF;
+ log.message("Response: 221 " + getHostName() + ".");
+ state = "QUIT";
+ break;
+ }
\ No newline at end of file
diff --git a/__SMTP_RCPT.h b/__SMTP_RCPT.h
new file mode 100644
index 0000000..de6ae35
--- /dev/null
+++ b/__SMTP_RCPT.h
@@ -0,0 +1,165 @@
+#ifndef ____SMTP_AUTH_h__
+#define ____SMTP_AUTH_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_AUTH : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data);
+
+ data << "" << std::endl;
+
+ //---------------------------------------------------------------------------
+ // RCPT command request handling.
+ //---------------------------------------------------------------------------
+
+ else if(command(input) == "RCPT") {
+
+ if((state == "MAIL") || (state == "RCPT")) {
+
+ bool done = false;
+
+ //--------------------------------------
+ // Obtain the recipient's email address.
+ //--------------------------------------
+
+ string recipient = input.substr(5);
+
+ //-----------------------------------------------
+ // Fetch the recipient list for the alias.
+ //-----------------------------------------------
+
+ string aliasRecipients;
+
+ if(getAliasList(cleanEMail(recipient), aliasRecipients)) {
+
+ //-----------------------------------------------
+ // If the list is not blank then add the list
+ // to the recipient list and accept the request.
+ //-----------------------------------------------
+
+ recipientList += aliasRecipients;
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+ state = "RCPT";
+ done = true;
+ }
+ //-------------------------------------------------
+ // No alias entry for the mailbox so check if it
+ // is a hard mailbox.
+ //-------------------------------------------------
+
+ if(!done) {
+
+ //--------------------------------------
+ // Check to see if the user is a local
+ // address to deliver to.
+ //--------------------------------------
+
+ if(localUser(cleanEMail(recipient))) {
+
+ //------------------------------------------
+ // They're local so lets queue it for them.
+ //------------------------------------------
+
+ recipientList += cleanEMail(recipient) + " ";
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+ state = "RCPT";
+ done = true;
+ }
+
+ }
+
+ //--------------------------------------------------
+ // There is no mailbox either so do domain check.
+ //--------------------------------------------------
+
+ if(!done) {
+
+ //---------------------------------------------------
+ // Check to see if the domain is good at least and
+ // if there is a default mailbox address..
+ //---------------------------------------------------
+ string defaultMailbox;
+
+ if(localDomain(domainOnly(cleanEMail(recipient)), defaultMailbox)) {
+
+ //--------------------------------------------------
+ // The domain is local so if there is a default
+ // mailbox then let's send it to the queue with the
+ // default address attached instead.
+ //--------------------------------------------------
+
+ if(defaultMailbox != "*NONE") {
+
+ //---------------------------------------------------------
+ // If the default mailbox is *DISCARD then we do not want
+ // to add the mailbox to the recipient list but we still
+ // want to say we have a mailbox.
+ //---------------------------------------------------------
+
+ if(defaultMailbox != "*DISCARD")
+ recipientList += defaultMailbox + " ";
+
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+
+ state = "RCPT";
+ done = true;
+ }
+
+ //--------------------------------------------------
+ // If there is no default address then we will tell
+ // the client that the mailbox does not exist.
+ //--------------------------------------------------
+
+ else {
+
+ cout << "553 Mailbox does not exist" << CRLF;
+ log.message("Response: 553 Mailbox does not exist.");
+
+ done = true;
+ }
+
+ }
+
+ }
+
+ //--------------------------------------------------------------
+ // If we are not done then this is a relay request.
+ //--------------------------------------------------------------
+
+ if (!done) {
+
+ //---------------------------------------------------------
+ // If relaying is enabled for this conversation then
+ // queue the mail.
+ //---------------------------------------------------------
+
+ if(relay) {
+ recipientList += cleanEMail(recipient) + " ";
+ cout << "250 OK" << CRLF;
+ log.message("Response: 250 OK.");
+ state = "RCPT";
+ }
+
+ //----------------------------------------
+ // Otherwise send an error.
+ //----------------------------------------
+
+ else {
+ cout << "553 Server requires authentication to relay" << CRLF;
+ log.message("Response: 553 Server requires authentication to relay.");
+ }
+
+ }
+
+ }
+ else {
+ cout << "503 Please use MAIL first" << CRLF;
+ log.message("Response: 503 Please use MAIL first.");
+ }
+ }
\ No newline at end of file
diff --git a/__SMTP_RSET.h b/__SMTP_RSET.h
new file mode 100644
index 0000000..5f2a014
--- /dev/null
+++ b/__SMTP_RSET.h
@@ -0,0 +1,20 @@
+#ifndef ____SMTP_RSET_h__
+#define ____SMTP_RSET_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_RSET : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data);
+ state = "READY";
+ data << "250 OK" << CRLF;
+ return 0;
+ }
+
+ };
+
+}
+
+#endif
diff --git a/__SMTP_VRFY.h b/__SMTP_VRFY.h
new file mode 100644
index 0000000..453b670
--- /dev/null
+++ b/__SMTP_VRFY.h
@@ -0,0 +1,19 @@
+#ifndef ____SMTP_VRFY_h__
+#define ____SMTP_VRFY_h__
+
+#include "Command.h"
+
+namespace http {
+
+ class __SMTP_VRFY : public core::Command {
+
+ int processCommand(std::string request, Session *session, std::stringstream &data) {
+ data << "252 You must know who the mail is for" << CRLF;
+ return 0;
+ }
+
+ };
+
+}
+
+#endif