You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.8 KiB
135 lines
3.8 KiB
#include <smtpd/smtpd.hpp>
|
|
#include <log.hpp>
|
|
|
|
#include <functional>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <iostream>
|
|
#include <cstdio>
|
|
|
|
const bool debug = false;
|
|
|
|
using namespace std;
|
|
|
|
smtpd::SessionMap sessions;
|
|
|
|
/*
|
|
void on_ready(smtpd::PProtocol pProtocol, smtpd::Message message) {
|
|
cerr << "Ready to accept messages from SMTPD" << endl;
|
|
}
|
|
|
|
void on_data(const smtpd::PMessage message) {
|
|
cerr << "Accepting new message from SMTPD" << endl;
|
|
smtpd::PSession session = make_shared<smtpd::Session>(message->protocol, message->sessionID(), message->sessionToken());
|
|
sessions.insert({message->sessionID(), session});
|
|
session->proceed(true);
|
|
}
|
|
|
|
void on_data_line(const smtpd::PMessage message) {
|
|
debug && cerr << "Received data line from SMTPD" << endl;
|
|
|
|
auto tokens = smtpd::split(message->input);
|
|
try {
|
|
auto& session = sessions.at(message->sessionID());
|
|
auto& data_line = tokens.at(7);
|
|
|
|
if(!session->mail.hasHeader) {
|
|
if(data_line == "") {
|
|
session->mail.hasHeader = true;
|
|
return;
|
|
}
|
|
|
|
if(data_line.substr(0, 6) == "X-Spam" ||
|
|
data_line.substr(0, 10) == "X-Bogosity") {
|
|
cerr << "Found and stripped incoming spam filter header:" << endl;
|
|
cerr << data_line << endl;
|
|
return;
|
|
}
|
|
|
|
if(data_line.substr(0, 5) == "From:" ||
|
|
data_line.substr(0, 8) == "Subject:") {
|
|
cerr << data_line << endl;
|
|
}
|
|
|
|
session->mail.header.push_back(data_line);
|
|
return;
|
|
}
|
|
|
|
if(data_line == ".") {
|
|
FILE* f = popen("true", "w");
|
|
//FILE* f = popen("bogofilter -v 1>&2", "w");
|
|
for(string& line : session->mail.header) {
|
|
fprintf(f, "%s\n", line.c_str());
|
|
}
|
|
fwrite("\n", 1, 1, f);
|
|
for(string& line : session->mail.body) {
|
|
fprintf(f, "%s\n", line.c_str());
|
|
}
|
|
int status = pclose(f);
|
|
|
|
switch(WEXITSTATUS(status)) {
|
|
case 0:
|
|
debug && cerr << "Classified as spam" << endl;
|
|
session->mail.header.push_back("X-Spam: Yes");
|
|
session->proceed(false);
|
|
break;
|
|
|
|
case 1:
|
|
case 2:
|
|
debug && cerr << "Classified as ham or unsure" << endl;
|
|
session->proceed(false);
|
|
break;
|
|
|
|
case 3:
|
|
debug && cerr << "Bogofilter error" << endl;
|
|
session->fail(false);
|
|
return;
|
|
}
|
|
|
|
session->submit_mail(session->mail.header, session->mail.body);
|
|
|
|
return;
|
|
}
|
|
|
|
if(data_line == "..") {
|
|
session->mail.body.push_back(".");
|
|
return;
|
|
}
|
|
|
|
session->mail.body.push_back(data_line);
|
|
} catch(out_of_range& e) {
|
|
cerr << "Unknown session key from SMTPD" << endl;
|
|
smtpd::Session{message->protocol, message->sessionID(), message->sessionToken()}.fail(false);
|
|
}
|
|
}
|
|
|
|
void on_commit(smtpd::PMessage message) {
|
|
debug && cerr << "Commit request from SMTPD" << endl;
|
|
try {
|
|
auto& session = sessions.at(message->sessionID());
|
|
session->proceed(true);
|
|
sessions.erase(message->sessionID());
|
|
} catch(out_of_range& e) {
|
|
cerr << "Unknown session key from SMTPD" << endl;
|
|
smtpd::Session{message->protocol, message->sessionID(), message->sessionToken()}.fail(true);
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
|
|
//int main(int argc, char** argv) {
|
|
int main() {
|
|
log::setLevel(log::DEBUG);
|
|
|
|
smtpd::IOSProtocol protocol{cin, cout};
|
|
|
|
cerr << "Bogofilter-SMTPD started" << endl;
|
|
|
|
protocol.run();
|
|
|
|
cerr << "Bogofilter-SMTP stopped" << endl;
|
|
|
|
return 0;
|
|
} |