A handle to the background task is returned. This can be used to determine if the asynchronous part has finished.
import vibe.data.json : parseJsonString; import std.algorithm.comparison : among; void main() { auto config = parseJsonString( `[ {"filter": "bayes"}, {"filter": "blacklist", "settings": { "ips": ["124.51.45.1", "41.23.11.5"] } } ]`); auto antispam = new AntispamState; antispam.loadConfig(config); AntispamMessage msg; msg.headers["Subject"] = "8uy CH34P V14GR4!!11"; msg.message = cast(const(ubyte)[])"Just look here: http://bestdrugdealz.c0m"; msg.peerAddress = ["123.52.433.1", "vps12315.some.provider.n3t"]; antispam.filterMessage!( (status) { if (status.among(SpamAction.revoke, SpamAction.block)) throw new Exception("Your message has been rejected!"); // otherwise store message... }, (async_status) { if (async_status.among!(SpamAction.revoke, SpamAction.block)) { // Flag or delete the stored message. } // It could also theoretically happen here that async_status is amnesty // or pass, so that a message that was already rejected in the first // phase would be accepted in retrospective. You'll have to decides on // a per-application basis if it makes sense to support this case, or // if immediate rejections always have precedence. } )(msg); }
Default implementation of full message filtering.
The function invokes each filter in the filter chain and combines the results to get a final answer in the for of a SpamAction status.
It first determines the immediate spam status, calling the on_immediate_status callback with the result. Then it starts a background task to determine the asynchronous state and, if different to the immediate status, passes the result to the on_async_status callback.
Afterwards it will call AntispamState.classify to update any self-learning filters in the chain.