Bogofilter adapter for OpenSMTPD in C++
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.
 
 

118 lines
3.4 KiB

#include <util.hpp>
#include <protocol/protocol.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace util;
//config|smtpd-version|6.6.1
//config|smtp-session-timeout|300
//config|subsystem|smtp-in
const bool debug = true;
namespace protocol {
void protocol_t::set_handlers(const handler_map_t handlers) {
size_t length = 0;
for(auto&& [pattern, handler] : handlers) {
for(auto&& [index, token] : pattern) {
if(index + 1 > length) {
length = index + 1;
}
}
}
debug && cerr << "Maximum handler pattern length is " << length << endl;
this->handlers = handlers;
max_pattern_length = length;
}
void protocol_t::send(const token::list_t& tokens) {
this->emit(token::compose(tokens));
}
void protocol_t::absorb(const std::string& input) {
auto tokens = token::decompose(input, max_pattern_length);
auto pattern = token::pattern_t(tokens, false);
debug && cerr << "Received pattern " << pattern << endl;
auto element = handlers.find(pattern);
if(element == handlers.end()) {
debug && cerr << "Unknown pattern " << pattern << endl;
} else {
element->second(*this, {input, element->first});
}
}
void protocol_t::send_result(const session_key_t& session_key, token::list_t tokens) {
token::list_t result{"filter-result", session_key.session, session_key.token};
for(auto& token : tokens) {
result.push_back(token);
}
send(result);
}
void protocol_t::proceed(const session_key_t& session_key) {
send_result(session_key, {"proceed"});
}
void protocol_t::fail(const session_key_t& session_key) {
send_result(session_key, {"disconnect", "451 Aborted"});
}
void protocol_t::send_data_line(const session_key_t& session_key, const string& data_line) {
send({"filter-dataline", session_key.session, session_key.token, data_line});
}
void protocol_t::submit_message(const session_key_t& session_key, const vector<string>& header, const vector<string>& body) {
for(auto& data_line : header) {
send_data_line(session_key, data_line);
}
send_data_line(session_key, "");
for(auto& data_line : body) {
if(data_line == ".") {
send_data_line(session_key, "..");
continue;
}
send_data_line(session_key, data_line);
}
send_data_line(session_key, ".");
}
ios_protocol_t::ios_protocol_t(std::istream& in, std::ostream& out) :
in(in), out(out) { }
void ios_protocol_t::emit(const std::string& output) {
out << output << endl;
}
void ios_protocol_t::run() {
while(!in.eof()) {
string line;
std::getline(in, line);
absorb(line);
}
}
bool operator==(const session_key_t& l, const session_key_t& r) {
return l.session == r.session && l.token == r.token;
}
session_key_t session_key_from(const token::list_t& tokens) {
auto session_id = tokens.at(5);
auto session_token = tokens.at(6);
return {session_id, session_token};
}
session_key_t session_key_from(const message_t& message) {
auto tokens = token::decompose(message.input);
return session_key_from(tokens);
}
}