summaryrefslogtreecommitdiff
path: root/tools/skrewt.c
blob: cd2144f22072d50f51b2a5a2a3afa6779e4b9835 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//////////////////
// skrewt.c
//
// scrutinize email
//

#include <iostream>
#include <stdlib.h>             /* for exit() */
#include <string>               /* for strcmp() */
#include <ctype.h>              /* toupper */

#include <stdio.h>              /* perror */
#include <sstream>
#include <vector>
#include <list>

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<string>(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;
}