////////////////// // skrewt.c // // scrutinize email // #include #include /* for exit() */ #include /* for strcmp() */ #include /* toupper */ #include /* perror */ #include #include #include #include /* getpid */ #include /* getpid */ using namespace std; void usage(const int sts){ (sts ? cerr : cout) << "Usage: skrewt [options]\n" "\n" " Scrutinizes email. Reads stdin, copies it to stdout.\n" " Exit result 0 means good, 21 means rejection (spam).\n" " Writes reason for rejection to stderr.\n" "\n" " Typically used as a filter in a pipeline, along with spamc -E\n" " Options\n" " -help print this msg (and exit immediately).\n" " -maxsize ii msg size in bytes; anything bigger will be rejected.\n" " -strict exit early if errors have been detected.\n" " -note nnnn annotate logfile entries.\n" "\n" " Messages containing the string '-please-bounce-this-' will be rejected.\n" " Messages with no date will be rejected.\n" ; exit(sts); } #include "libskrewt.h" #include "utils.h" string progname, progid; int mypid; /* Content-Type: text/plain; charset="us-ascii" */ /* Content-Type: multipart/mixed; boundary="1170861315-1262462055-1341954763=:92165" */ // #if 0 /* typical "Received: from" lines */ Received: from lists.sourceforge.net (216.34.181.88) by cloud.av8n.com with SMTP; 31 Jul 2012 22:13:48 -0000 Received: from 24-145-119-127-dhcp.gsv.md.atlanticbb.net (HELO mail.phys-l.org) (24.145.119.127) by cloud.av8n.com with SMTP; 14 Jul 2012 23:56:54 -0000 Received: from ip68-231-191-153.tc.ph.cox.net (HELO asclepias.av8n.net) (smtp@68.231.191.153) by cloud.av8n.com with SMTP; 15 Jul 2012 14:39:58 -0000 #endif #if 0 /* good for testing */ // random mail from FAA /home/jsd/Maildir/cur/1343769926.24228.cloud\:2\, // has a good SPF result buried inside, at an earlier hop: /home/jsd/Maildir/cur/1342372942.24810.cloud:2, // has a good SPF as delivered to us: /home/jsd/Maildir/cur/1343671179.10420.cloud:2, // The following msg has no message-id, but does have an // authorized submitter: /home/jsd/Maildir/cur/1342363199.24320.cloud:2, #endif //////////////////////////////////////////////////////////// int main(int _argc, const char** _argv){ int argc(_argc); const char **argv(_argv); { progname = *argv++; argc--; mypid = getpid(); stringstream binder; binder << basename(progname) << "[" << mypid << "]"; progid = binder.str(); } skrewt mysk; // cerr << "maxsize: " << mysk.maxsize << endl; argParser ARGS(argc, argv); try {while (ARGS.size()) { string arg = ARGS.next(); if (arg.substr(0,2) == "--") arg = arg.substr(1); if (ARGS.prefix("-help")) { usage(0); } if (0) { } else if (ARGS.prefix("-mid-required")) { mysk.mid_required++; } else if (ARGS.prefix("-error-exit") || ARGS.prefix("-strict")) { mysk.strictness++; } else if (ARGS.prefix("-note", 1)) { mysk.note = ARGS.shift(); } else if (ARGS.prefix("-maxsize", 1)) { mysk.maxsize = atoi(ARGS.shift().c_str()); } else if (arg.substr(0,1) == "-") { cerr << "Unrecognized option '" << arg << "'" << endl; cerr << "For help, try: " << progname << " -help" << endl; exit(ex_usage); } else { cerr << "Extraneous verbiage '" << arg << "'" << endl; cerr << "For help, try: " << progname << " -help" << endl; exit(ex_usage); } }} catch (int) { exit(ex_usage); } progid += mysk.note; int rslt = mysk.headers(cin); if (rslt) return rslt; mysk.dump_bigbuf(cout); mysk.headerbuf = mysk.bigbuf; mysk.bigbuf = vector(0); // Headers are done. // Do some early-stage thinking. rslt = mysk.interstage(); if (rslt) return rslt; rslt = mysk.body(cin, cout); if (rslt) return rslt; mysk.dump_bigbuf(cout); return 0; }