diff --git a/include/mail.hpp b/include/mail.hpp index cc063d6..ccbea7f 100644 --- a/include/mail.hpp +++ b/include/mail.hpp @@ -9,6 +9,13 @@ #include namespace mail { + namespace status { + const int SPAM = 0; + const int HAM = 1; + const int UNSURE = 2; + const int ERROR = 3; + } + struct message_t { std::vector header; std::vector body; @@ -18,6 +25,7 @@ namespace mail { bool has_header = 0; protocol::token::string_t token; message_t message; + int status = status::UNSURE; }; using session_map_t = std::unordered_map; diff --git a/src/bogofilter-smtpd.cpp b/src/bogofilter-smtpd.cpp index ed575e4..a7c20e0 100644 --- a/src/bogofilter-smtpd.cpp +++ b/src/bogofilter-smtpd.cpp @@ -1,12 +1,13 @@ #include #include +#include #include #include #include #include #include -#include +#include const bool debug = true; @@ -52,6 +53,16 @@ void on_data_line(protocol::protocol_t& protocol, protocol::message_t message) { if(data_line == ".") { protocol.submit_message(session_key, session_token, session.message.header, session.message.body); + FILE* f = popen("bogofilter", "w"); + for(string& line : session.message.header) { + fprintf(f, "%s\n", line); + } + fwrite("\n", 1, 1, f); + for(string& line : session.message.body) { + fprintf(f, "%s\n", line); + } + session.status = pclose(f); + return; } @@ -71,7 +82,31 @@ void on_commit(protocol::protocol_t& protocol, protocol::message_t message) { debug && cerr << "Message committed" << endl; auto session_key = protocol::session_key_from(message); auto session_token = protocol::session_token_from(message); - protocol.proceed(session_key, session_token); + try { + auto& session = sessions.at(session_key); + + switch(session.status) { + case mail::status::SPAM: + debug && cerr << "Classified as spam" << endl; + protocol.junk(session_key, session_token); + break; + + case mail::status::HAM: + case mail::status::UNSURE: + debug && cerr << "Classified as ham or unsure" << endl; + protocol.proceed(session_key, session_token); + break; + + default: + debug && cerr << "Bogofilter error (" << session.status << ")" << endl; + protocol.fail(session_key, session_token); + break; + } + } catch(out_of_range& e) { + debug && cerr << "Unknown session key" << endl; + protocol.fail(session_key, session_token); + } + sessions.erase(session_key); }