Bunch of changes.

This commit is contained in:
brad Arant 2025-07-03 12:01:16 -07:00
parent 0a4d17e6e6
commit 641368ea85
15 changed files with 441 additions and 1327 deletions

63
#main.cpp# Normal file
View File

@ -0,0 +1,63 @@
#include <string>
#include "EPoll.h"
#include "ConsoleServer.h"
#include "Exception.h"
#include "File.h"
#include "Log.h"
#include "IPAddress.h"
#include "MailFileSystem.h"
#include "SMTPServer.h"
#include "POP3Server.h"
#include "IMAPServer.h"
#include "SendMail2.h"
#define BUFFER_SIZE 1000000
int main(int argc, char **argv) {
coreutils::Log(new coreutils::File("/var/log/barantmail.log", O_WRONLY | O_APPEND | O_CREAT, 0644));
coreutils::Log(coreutils::LOG_INFO) << "BMAMAIL called with link " << argv[0];
if(strcmp(argv[0], "./sendmail2") == 0) {
try {
coreutils::Log(coreutils::LOG_INFO) << "Starting Mail Injector. Build " << __DATE__ << " " << __TIME__;
char buffer[BUFFER_SIZE];
int len = read(0, buffer, BUFFER_SIZE);
core::EPoll ePoll;
mail::SendMail2(ePoll, argv[1], argv[2]);
}
catch(coreutils::Exception exception) {
std::cout << exception.text << " Error reason is '" << strerror(exception.errorNumber) << "' in file " << exception.file << " at line " << exception.line << std::endl;
}
} else {
try {
coreutils::Log(coreutils::LOG_INFO) << "BMAMail Server starting. Build " << __DATE__ << " " << __TIME__;
std::string hostName = "localhost";
std::string ipAddress = "0.0.0.0";
coreutils::ZString mailPath("/var/mail");
mail::MailFileSystem mailFileSystem(mailPath);
core::EPoll ePoll;
ePoll.start(1, 1000);
mail::SMTPServer smtpServer(ePoll, hostName, mailFileSystem, core::IPAddress(ipAddress, 9025));
// mail::POP3Server pop3Server(ePoll, hostName, mailFileSystem, core::IPAddress(ipAddress, 110));
// mail::IMAPServer imapServer(ePoll, hostName, mailFileSystem, core::IPAddress(ipAddress, 143));
core::ConsoleServer consoleServer(ePoll, core::IPAddress(ipAddress, 1027));
consoleServer.commands.add(consoleServer.commands, "help");
consoleServer.commands.add(smtpServer.commands, "smtp");
while(true)
sleep(3600);
ePoll.stop();
}
catch(coreutils::Exception exception) {
std::cout << exception.text << " Error reason is '" << strerror(exception.errorNumber) << "' in file " << exception.file << " at line " << exception.line << std::endl;
}
}
}

BIN
BMAMail

Binary file not shown.

View File

@ -6,24 +6,24 @@
#include <resolv.h>
namespace mail {
SendMail::SendMail(core::EPoll &ePoll, std::string from, std::string recipient, std::string mailFileName)
: core::TCPSession2(ePoll, "Send Mail Agent"), from(from), recipient(recipient), mailFileName(mailFileName),
: core::TCPSession2(ePoll, "Send Mail Agent"), from(from), recipient(recipient), mailFileName(mailFileName),
mailData(mailFileName), Timer(ePoll, 0.00f), ePoll(ePoll) {
coreutils::Log(coreutils::LOG_DEBUG_1) << this->recipient;
this->recipient.split("@");
coreutils::Log(coreutils::LOG_DEBUG_1) << this->recipient[1];
u_char nsbuff[4096];
char *domain = this->recipient[1].c_str();
int len = res_query(domain, ns_c_any, ns_t_mx, nsbuff, sizeof(nsbuff));
coreutils::Log(coreutils::LOG_DEBUG_1) << ">" << len;
ns_msg msg;
ns_initparse(nsbuff, len, &msg);
len = ns_msg_count(msg, ns_s_an);
char dispbuf[4096];
ns_rr rr;
for (int i = 0; i < 1; i++) {
@ -31,102 +31,100 @@ namespace mail {
ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf));
printf ("%s\n", dispbuf);
}
coreutils::ZString mxArray(dispbuf);
mxArray.split("\t");
mxArray[3].split(" ");
coreutils::Log(coreutils::LOG_DEBUG_1) << "MX: " << mxArray[3][1];
coreutils::ZString mxArray(dispbuf);
mxArray.split("\t");
mxArray[3].split(" ");
coreutils::Log(coreutils::LOG_DEBUG_1) << "MX: " << mxArray[3][1];
core::IPAddress mxAddress(mxArray[3][1].c_str(), 25);
connect(mxAddress);
ePoll.registerSocket((TCPSession2 *)(this));
coreutils::Log(coreutils::LOG_DEBUG_1) << "SendMail initiated...";
}
}
SendMail::SendMail(const SendMail &copy) : core::TCPSession2(ePoll, "Send Mail Agent"), from(copy.from), recipient(copy.recipient), mailFileName(copy.mailFileName),
mailData(mailFileName), Timer(ePoll, 0.00f), ePoll(copy.ePoll) {}
SendMail::~SendMail() {
ePoll.unregisterSocket((TCPSession2 *)(this));
coreutils::Log(coreutils::LOG_DEBUG_1) << "SendMail destructing...";
}
void SendMail::onTimeout() {
state = stateOnTimeout;
coreutils::Log(coreutils::LOG_DEBUG_1) << "onTimeout...";
protocol(buffer);
TCPSession2::send();
}
void SendMail::protocol(coreutils::ZString &data) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "[" << data << "..." << state;
switch (state) {
case CONNECT:
// read recipient
// parse email for name and domain name
// open tcpsocket with connect
// wait for greeting
if(data.asInteger() == 220) {
out << "EHLO " << "mail.barant.com" << CRLF;
state = READY;
}
break;
case READY:
buffer = data;
setTimer(.05);
stateOnTimeout = READYX;
break;
case READYX:
if(buffer.asInteger() == 250) {
out << "MAIL FROM:<" << from << ">" << CRLF;
state = MAIL;
}
break;
case MAIL:
if(data.asInteger() == 250) {
out << "RCPT TO:<" << recipient << ">" << CRLF;
state = RCPT;
}
break;
case RCPT:
if(data.asInteger() == 250) {
out << "DATA" << CRLF;
state = DATA;
}
break;
case DATA:
if(data.asInteger() == 354) {
while(!mailData.eof()) {
mailData.readLine();
out << mailData.asZString() << CRLF;
}
out << "." << CRLF;
state = SENT;
}
break;
case SENT:
if(data.asInteger() == 250) {
out << "QUIT" << CRLF;
}
break;
case CONNECT:
// read recipient
// parse email for name and domain name
// open tcpsocket with connect
// wait for greeting
if(data.asInteger() == 220) {
out << "EHLO " << "mail.barant.com" << CRLF;
state = READY;
}
break;
case READY:
buffer = data;
setTimer(.05);
stateOnTimeout = READYX;
break;
case READYX:
if(buffer.asInteger() == 250) {
out << "MAIL FROM:<" << from << ">" << CRLF;
state = MAIL;
}
break;
case MAIL:
if(data.asInteger() == 250) {
out << "RCPT TO:<" << recipient << ">" << CRLF;
state = RCPT;
}
break;
case RCPT:
if(data.asInteger() == 250) {
out << "DATA" << CRLF;
state = DATA;
}
break;
case DATA:
if(data.asInteger() == 354) {
while(!mailData.eof()) {
mailData.readLine();
out << mailData.asZString() << CRLF;
}
out << "." << CRLF;
state = SENT;
}
break;
case SENT:
if(data.asInteger() == 250) {
out << "QUIT" << CRLF;
}
break;
}
}
std::vector<coreutils::MString>& SendMail::extractRecipientList() {
return recipientList;
}
}

View File

@ -7,7 +7,11 @@
#include "Timer.h"
#define CRLF "\r\n"
#define CRLF "\r\n"
#ifndef ___state_defined___
#define ___state_defined___
typedef enum {CONNECT, READY, READYX, MAIL, RCPT, DATA, SENT} State;
#endif
namespace mail {

184
SendMail2.cpp Normal file
View File

@ -0,0 +1,184 @@
#include "SendMail2.h"
#include "ZString.h"
#include <chrono>
#include <string>
#include <cstdio>
#include <iostream>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "Log.h"
#define BUFFER_SIZE 1048576
namespace mail {
SendMail2::SendMail2(core::EPoll &ePoll, coreutils::MString from, coreutils::MString recipient, coreutils::MString message)
: core::TCPSession2(ePoll, "Send Mail Injector"), from(from), recipient(recipient),
Timer(ePoll, 30.00f), ePoll(ePoll), message(message) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "SendMail2 constructed.";
}
int SendMail2::send() {
waiter.lock();
coreutils::Log(coreutils::LOG_DEBUG_1) << this->recipient;
this->recipient.split("@");
coreutils::Log(coreutils::LOG_DEBUG_1) << this->recipient[1];
u_char nsbuff[4096];
char *domain = this->recipient[1].c_str();
int len = res_search(domain, C_IN, T_MX, nsbuff, sizeof(nsbuff));
ns_msg msg;
ns_initparse(nsbuff, len, &msg);
len = ns_msg_count(msg, ns_s_an);
char dispbuf[4096];
ns_rr rr;
for (int i = 0; i < 1; i++) {
ns_parserr(&msg, ns_s_an, i, &rr);
ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf));
}
coreutils::Log(coreutils::LOG_DEBUG_1) << "dispbuf: " << dispbuf;
coreutils::ZString mxArray(dispbuf);
mxArray.find("MX");
mxArray.ifNext("MX");
mxArray.skipWhitespace();
mxArray.getTokenInclude("0123456789");
mxArray.skipWhitespace();
coreutils::Log(coreutils::LOG_DEBUG_1) << "MX: " << mxArray.unparsed();
core::IPAddress mxAddress(mxArray.unparsed().c_str(), 25);
coreutils::Log(coreutils::LOG_DEBUG_1) << "IP: " << mxAddress.getClientAddressAndPort();
connect(mxAddress);
coreutils::Log(coreutils::LOG_DEBUG_1) << "SendMail2 injector initiated...";
return 0;
}
SendMail2::SendMail2(const SendMail2 &copy) : core::TCPSession2(ePoll, "Send Mail Injector"), from(copy.from), recipient(copy.recipient),
Timer(ePoll, 30.00f), ePoll(copy.ePoll), message(copy.message) {}
SendMail2::~SendMail2() {
coreutils::Log(coreutils::LOG_DEBUG_1) << "SendMail destructing...";
}
void SendMail2::onTimeout() {
coreutils::Log(coreutils::LOG_DEBUG_1) << "onTimeout..." << state;
returnValue << "timeout in " << state;
state = SENT;
waiter.unlock();
}
void SendMail2::protocol(coreutils::ZString &data) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "[" << data << "..." << state;
switch (state) {
case CONNECT:
if(data.asInteger() == 220) {
out << "EHLO " << "drinkwise.barant.com" << CRLF;
coreutils::Log(coreutils::LOG_DEBUG_1) << ">EHLO";
state = READY;
}
break;
case READY:
buffer = data;
setTimer(30);
stateOnTimeout = READYX;
state = READYX;
break;
case READYX:
if(buffer.asInteger() == 250) {
coreutils::Log(coreutils::LOG_DEBUG_1) << ">MAIL FROM:<" << from << ">";
out << "MAIL FROM:<" << from << ">" << CRLF;
state = MAIL;
}
break;
case MAIL:
if(data.asInteger() == 250) {
coreutils::Log(coreutils::LOG_DEBUG_1) << ">RCPT TO:<" << recipient << ">";
out << "RCPT TO:<" << recipient << ">" << CRLF;
state = RCPT;
}
break;
case RCPT:
if(data.asInteger() == 250) {
out << "DATA" << CRLF;
state = DATA;
}
break;
case DATA:
if(data.asInteger() == 354) {
out << message << CRLF;
out << "." << CRLF;
state = SENT;
} else if (data.asInteger() == 421) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Error 421";
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
} else if (data.asInteger() == 450) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Error 450";
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
} else if (data.asInteger() == 451) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Error 451";
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
} else if (data.asInteger() == 452) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Error 452";
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
} else if (data.asInteger() == 550) {
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
} else if (data.asInteger() == 552) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Error 552";
data.split(" ", 2);
returnValue = data;
state = SENT;
waiter.unlock();
}
break;
case SENT:
returnValue = data;
out << "QUIT" << CRLF;
waiter.unlock();
break;
}
}
coreutils::MString SendMail2::wait() {
waiter.lock();
waiter.unlock();
return returnValue;
}
std::vector<coreutils::MString>& SendMail2::extractRecipientList() {
return recipientList;
}
}

51
SendMail2.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef __SendMail2_h__
#define __SendMail2_h__
#include "EPoll.h"
#include "TCPSession2.h"
#include "MString.h"
#include "Timer.h"
#include <mutex>
#define CRLF "\r\n"
#ifndef ___state_defined___
#define ___state_defined___
typedef enum {CONNECT, READY, READYX, MAIL, RCPT, DATA, SENT} State;
#endif
namespace mail {
class SendMail2 : public core::TCPSession2, private core::Timer {
public:
SendMail2(core::EPoll &ePoll, coreutils::MString from, coreutils::MString recipient, coreutils::MString message);
SendMail2(const SendMail2 &copy);
~SendMail2();
void protocol(coreutils::ZString &data) override;
int send();
coreutils::MString wait();
coreutils::MString returnValue;
private:
std::vector<coreutils::MString>& extractRecipientList();
void onTimeout() override;
core::EPoll &ePoll;
coreutils::MString from;
coreutils::MString recipient;
coreutils::MString buffer;
coreutils::MString message;
std::vector<coreutils::MString> recipientList;
State state = CONNECT;
State stateOnTimeout = CONNECT;
std::mutex waiter;
};
}
#endif

View File

@ -3,11 +3,11 @@
#include "SMTPServer.h"
namespace mail {
int __SMTP_AUTH::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) {
switch(session.authState) {
case USER_UNKNOWN:
if(request[1].equals("LOGIN")) {
session.out << "334 VXNlcm5hbWU6" << CRLF;
@ -19,7 +19,7 @@ namespace mail {
session.out << "504 AUTH method not supported." << CRLF;
}
return 1;
case USER_QUERY:
session.userName = request[0];
// setTimer(0.0f);
@ -27,7 +27,7 @@ namespace mail {
// setTimer(10.0f);
session.authState = USER_SECRET_QUERY;
return 1;
case USER_SECRET_QUERY:
session.password = request[0];
// setTimer(0.0f);
@ -45,13 +45,13 @@ namespace mail {
}
return 0;
}
bool __SMTP_AUTH::authLogin(coreutils::ZString &userName, coreutils::ZString &password, SMTPServer &server) {
coreutils::MString secretPath;
secretPath << server.mailFileSystem.getMailBoxPath(userName) << "/.password";
coreutils::File secret(secretPath);
secret.read();
return password == secret.asString();
return password == secret.asZString();
}
}

27
compile
View File

@ -1,23 +1,23 @@
#!/bin/bash
for file in *.cpp
do
filename="${file%.*}"
list="$list $filename.o"
echo -n "Compiling $filename..."
g++ -g -c -std=c++17 -I../CoreUtils -I../ServerCore $file
if [ $? = '0' ]
then
echo "OK"
else
echo "ERROR"
exit -1
fi
do
filename="${file%.*}"
list="$list $filename.o"
echo -n "Compiling $filename..."
g++ -g -c -std=c++17 -I../CoreUtils -I../ServerCore $file
if [ $? = '0' ]
then
echo "OK"
else
echo "ERROR"
exit -1
fi
done
wait
echo -n "Building executable BMAMail..."
g++ -g -std=c++17 -o BMAMail $list -L../CoreUtils -lCoreUtils -L../ServerCore -lServerCore -lpthread -luuid -lssl -lcrypto -lresolv
g++ -g -std=c++17 -o BMAMail $list -I../CoreUtils -I../ServerCore -L../CoreUtils -lCoreUtils -L../ServerCore -lServerCore -lpthread -luuid -lssl -lcrypto -lresolv
if [ $? = '0' ]
then
echo "OK"
@ -25,6 +25,7 @@ else
echo "ERROR"
exit -1
fi
rm *~
rm *.o

1207
error.log

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,41 @@
#include "SMTPServer.h"
#include "POP3Server.h"
#include "IMAPServer.h"
#include "SendMail2.h"
#include <fcntl.h>
#include <iostream>
int main(int argc, char **argv) {
coreutils::Log(new coreutils::File("/var/log/barantmail.log", O_WRONLY | O_APPEND | O_CREAT, 0644));
coreutils::Log(coreutils::LOG_INFO) << "BMAMAIL called with link " << argv[0];
std::string arg = argv[0];
if(arg.substr(arg.find_last_of("\\/") + 1) == "sendmail2") {
try {
coreutils::Log(coreutils::LOG_INFO) << "Starting Mail Injector. Build " << __DATE__ << " " << __TIME__;
char buffer[1000000];
int index = 0;
int len = 0;
while((len = read(0, &buffer[index], 1000000)) > 0)
index += len;
coreutils::MString message(buffer, index);
coreutils::Log(coreutils::LOG_DEBUG_1) << "Number of bytes read: " << index;
core::EPoll ePoll;
ePoll.start(1, 1000);
mail::SendMail2 mail2(ePoll, argv[1], argv[2], message);
mail2.send();
coreutils::Log(coreutils::LOG_DEBUG_1) << "waiting...";
coreutils::MString rc(mail2.wait());
coreutils::Log(coreutils::LOG_DEBUG_1) << "rc: " << rc;
std::cout << rc;
}
catch(coreutils::Exception exception) {
std::cout << exception.text << " Error reason is '" << strerror(exception.errorNumber) << "' in file " << exception.file << " at line " << exception.line << std::endl;
}
} else {
try {
coreutils::Log(new coreutils::File("/var/log/mail.log", O_WRONLY | O_APPEND | O_CREAT, 0644));
coreutils::Log(coreutils::LOG_INFO) << "BMAMail Server starting. Build " << __DATE__ << " " << __TIME__;
std::string hostName = "localhost";
@ -42,5 +71,5 @@ int main(int argc, char **argv) {
catch(coreutils::Exception exception) {
std::cout << exception.text << " Error reason is '" << strerror(exception.errorNumber) << "' in file " << exception.file << " at line " << exception.line << std::endl;
}
}
}

BIN
main.hpp.gch Normal file

Binary file not shown.

View File

@ -1,11 +0,0 @@
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
}

1
sendmail2 Symbolic link
View File

@ -0,0 +1 @@
BMAMail

After

Width:  |  Height:  |  Size: 7 B

5
tests/testemail.email Normal file
View File

@ -0,0 +1,5 @@
From: <brad.arant@drinkwise.com>
To: <brad.arant@gmail.com>
Subject: An email test
This is a test

View File

@ -1,5 +1,3 @@
#!/bin/bash
nc localhost 9025 > /dev/null << EOL
EHLO barant.com
MAIL FROM: <brad.arant@barant.com>
RCPT TO: <brad.arant@barant.com>
@ -12,5 +10,3 @@ Subject: test email system
This is a test
.
QUIT
EOL