#include #include #include #include #include #include #include #include const bool debug = true; using namespace std; mail::session_map_t sessions; void on_ready(protocol::protocol_t& protocol, protocol::message_t message) { debug && cerr << "Ready" << endl; protocol.send({"register", "filter", "smtp-in", "data"}); protocol.send({"register", "filter", "smtp-in", "data-line"}); protocol.send({"register", "filter", "smtp-in", "commit"}); protocol.send({"register", "ready"}); } void on_data(protocol::protocol_t& protocol, protocol::message_t message) { debug && cerr << "New message" << endl; auto session_key = protocol::session_key_from(message); auto session_token = protocol::session_token_from(message); sessions.emplace(session_key, mail::session_t{}); protocol.proceed(session_key, session_token); } void on_data_line(protocol::protocol_t& protocol, protocol::message_t message) { debug && cerr << "Received data line" << endl; auto tokens = protocol::token::decompose(message.input); auto session_key = protocol::session_key_from(tokens); auto session_token = protocol::session_token_from(tokens); try { auto& session = sessions.at(session_key); auto& data_line = tokens.at(7); if(!session.has_header) { if(data_line == "") { session.has_header = true; return; } session.message.header.push_back(data_line); return; } if(data_line == ".") { return; } if(data_line == "..") { session.message.body.push_back("."); return; } session.message.body.push_back(data_line); } catch(out_of_range& e) { debug && cerr << "Unknown session key" << endl; protocol.fail(session_key, session_token); } } 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); try { auto& session = sessions.at(session_key); protocol.submit_message(session_key, session_token, session.message.header, session.message.body); sessions.erase(session_key); protocol.proceed(session_key, session_token); } catch(out_of_range& e) { debug && cerr << "Unknown session key" << endl; protocol.fail(session_key, session_token); } } int main(int argc, char** argv) { protocol::ios_protocol_t protocol(cin, cout); protocol::handler_map_t handlers; handlers.emplace("config|ready", on_ready); handlers.emplace("filter|*|*|smtp-in|data", on_data); handlers.emplace("filter|*|*|smtp-in|data-line", on_data_line); handlers.emplace("filter|*|*|smtp-in|commit", on_commit); if(debug) { cerr << "Handler patterns:" << endl; for(auto&& [first, second] : handlers) { cerr << "\t" << first << endl; } } protocol.set_handlers(handlers); protocol.run(); return 0; }