#ifndef __SpamAssassinFilter_h__ #define __SpamAssassinFilter_h__ #include namespace mail { /// /// Pipes a message through the local spamd (via the spamc protocol, /// spoken directly over a socket rather than shelling out to the /// spamc binary) on the local-delivery path in /// SMTPServer::inCreate() - spamd hands back the message with its /// usual X-Spam-Status/X-Spam-Level/X-Spam-Report headers added (and, /// once a message is over its own report_safe threshold, rewrapped /// into a text/plain report). This class applies no threshold of its /// own - spamd's required_score (/etc/spamassassin/local.cf, 5.0 on /// this host) is what actually decides Yes/No; isSpam below just /// reads that verdict back out of the X-Spam-Status header spamd /// already wrote, the same way any other MTA's spam tag would be /// read by a downstream filter. /// /// Fails open: if spamd can't be reached at all, delivery proceeds /// with the original, unscanned message rather than blocking mail /// on a scanner outage. /// class SpamAssassinFilter { public: struct Result { bool ok = false; // true if spamd actually scanned the message bool isSpam = false; // parsed from X-Spam-Status: Yes/No - meaningless if !ok std::string scanned; // the (possibly tagged/rewritten) message; == input verbatim if !ok }; static Result scan(const std::string &message); private: static bool talkToSpamd(const std::string &message, std::string &response); }; } #endif