A handle to the background task is returned. This can be used to determine if the asynchronous part has finished.
1 import vibe.data.json : parseJsonString; 2 import std.algorithm.comparison : among; 3 4 void main() 5 { 6 auto config = parseJsonString( 7 `[ 8 {"filter": "bayes"}, 9 {"filter": "blacklist", 10 "settings": { 11 "ips": ["124.51.45.1", "41.23.11.5"] 12 } 13 } 14 ]`); 15 16 auto antispam = new AntispamState; 17 antispam.loadConfig(config); 18 19 AntispamMessage msg; 20 msg.headers["Subject"] = "8uy CH34P V14GR4!!11"; 21 msg.message = cast(const(ubyte)[])"Just look here: http://bestdrugdealz.c0m"; 22 msg.peerAddress = ["123.52.433.1", "vps12315.some.provider.n3t"]; 23 24 antispam.filterMessage!( 25 (status) { 26 if (status.among(SpamAction.revoke, SpamAction.block)) 27 throw new Exception("Your message has been rejected!"); 28 // otherwise store message... 29 }, 30 (async_status) { 31 if (async_status.among!(SpamAction.revoke, SpamAction.block)) { 32 // Flag or delete the stored message. 33 } 34 35 // It could also theoretically happen here that async_status is amnesty 36 // or pass, so that a message that was already rejected in the first 37 // phase would be accepted in retrospective. You'll have to decides on 38 // a per-application basis if it makes sense to support this case, or 39 // if immediate rejections always have precedence. 40 } 41 )(msg); 42 }
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.