| 1 | #include "stralloc.h" |
| 2 | #include "str.h" |
| 3 | #include "byte.h" |
| 4 | #include "readwrite.h" |
| 5 | #include "substdio.h" |
| 6 | #include "getln.h" |
| 7 | #include "strerr.h" |
| 8 | #include "errtxt.h" |
| 9 | |
| 10 | char buf0[256]; |
| 11 | substdio ss0 = SUBSTDIO_FDBUF(read,0,buf0,sizeof(buf0)); |
| 12 | |
| 13 | #define FATAL "ezmlm-weed: fatal: " |
| 14 | |
| 15 | void die_nomem() |
| 16 | { |
| 17 | strerr_die2x(111,FATAL,ERR_NOMEM); |
| 18 | } |
| 19 | |
| 20 | void get(sa) |
| 21 | stralloc *sa; |
| 22 | { |
| 23 | int match; |
| 24 | if (getln(&ss0,sa,&match,'\n') == -1) |
| 25 | strerr_die2sys(111,FATAL,ERR_READ_INPUT); |
| 26 | if (!match) _exit(0); |
| 27 | } |
| 28 | |
| 29 | stralloc line = {0}; |
| 30 | stralloc line1 = {0}; |
| 31 | stralloc line2 = {0}; |
| 32 | stralloc line3 = {0}; |
| 33 | stralloc line4 = {0}; |
| 34 | stralloc line5 = {0}; |
| 35 | stralloc line6 = {0}; |
| 36 | stralloc line7 = {0}; |
| 37 | stralloc line8 = {0}; |
| 38 | |
| 39 | stralloc boundary = {0}; |
| 40 | stralloc dsnline = {0}; |
| 41 | |
| 42 | char warn1[] = " **********************************************"; |
| 43 | char warn2[] = " ** THIS IS A WARNING MESSAGE ONLY **"; |
| 44 | char warn3[] = " ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **"; |
| 45 | char warn4[] = " **********************************************"; |
| 46 | |
| 47 | int flagmds = 0; |
| 48 | int flagsw = 0; |
| 49 | int flagsr = 0; |
| 50 | int flagas = 0; |
| 51 | int flagbw = 0; |
| 52 | int flagdsn = 0; |
| 53 | |
| 54 | int isboundary() |
| 55 | /* returns 1 if line.len contains the mime bondary, 0 otherwise */ |
| 56 | { |
| 57 | if (line.s[0] == '-' && line.s[1] == '-' && line.len >= boundary.len + 3) |
| 58 | if (!byte_diff(line.s + 2,boundary.len,boundary.s)) /* boundary */ |
| 59 | return 1; |
| 60 | return 0; |
| 61 | } |
| 62 | |
| 63 | void main() |
| 64 | { |
| 65 | unsigned int i,j; |
| 66 | |
| 67 | for (;;) { |
| 68 | get(&line); |
| 69 | if (line.len == 1) break; |
| 70 | if (line.s[0] == ' ' || line.s[0] == '\t') { /* continuation */ |
| 71 | if (flagdsn) { |
| 72 | if (!stralloc_catb(&dsnline,line.s,line.len - 1)) die_nomem(); |
| 73 | continue; |
| 74 | } |
| 75 | } |
| 76 | flagdsn = 0; |
| 77 | if (stralloc_starts(&line,"Subject: success notice")) |
| 78 | _exit(99); |
| 79 | if (stralloc_starts(&line,"Subject: deferral notice")) |
| 80 | _exit(99); |
| 81 | if (stralloc_starts(&line,"Precedence: bulk")) |
| 82 | _exit(99); |
| 83 | if (stralloc_starts(&line,"Precedence: junk")) |
| 84 | _exit(99); |
| 85 | /* for Novell Groupwise */ |
| 86 | if (stralloc_starts(&line,"Subject: Message status - delivered")) |
| 87 | _exit(99); |
| 88 | if (stralloc_starts(&line,"Subject: Message status - opened")) |
| 89 | _exit(99); |
| 90 | if (stralloc_starts(&line,"Subject: Out of Office AutoReply:")) |
| 91 | _exit(99); |
| 92 | |
| 93 | if (stralloc_starts(&line,"From: Mail Delivery Subsystem <MAILER-DAEMON@")) |
| 94 | flagmds = 1; |
| 95 | if (stralloc_starts(&line,"Subject: Warning: could not send message")) |
| 96 | flagsw = 1; |
| 97 | if (stralloc_starts(&line,"Subject: Returned mail: warning: cannot send message")) |
| 98 | flagsr = 1; |
| 99 | if (stralloc_starts(&line,"Auto-Submitted: auto-generated (warning")) |
| 100 | flagas = 1; |
| 101 | if (case_startb(line.s,line.len,"Content-type: multipart/report")) |
| 102 | if (!stralloc_copyb(&dsnline,line.s,line.len - 1)) die_nomem(); |
| 103 | flagdsn = 1; |
| 104 | } /* end of header */ |
| 105 | |
| 106 | if (flagdsn) { /* always only one recipient/action */ |
| 107 | flagdsn = 0; /* will be set for correct report type */ |
| 108 | for (i=0; i < dsnline.len; i += 1+byte_chr(dsnline.s+i,dsnline.len-i,';')) { |
| 109 | while (dsnline.s[i] == ' ' || dsnline.s[i] == '\t') |
| 110 | if (++i >= dsnline.len) break; |
| 111 | if (case_startb(dsnline.s + i,dsnline.len - i,"report-type=")) { |
| 112 | i += 12; |
| 113 | while (dsnline.s[i] ==' ' || dsnline.s[i] =='\t' || dsnline.s[i] =='"') |
| 114 | if (++i >= dsnline.len) break; |
| 115 | if (case_startb(dsnline.s + i,dsnline.len - i,"delivery-status")) |
| 116 | flagdsn = 1; |
| 117 | } else if (case_startb(dsnline.s + i,dsnline.len - i,"boundary=")) { |
| 118 | i += 9; |
| 119 | while (dsnline.s[i] ==' ' || dsnline.s[i] =='\t') |
| 120 | if (++i >= dsnline.len) break; |
| 121 | if (dsnline.s[i] == '"') { |
| 122 | if (++i >= dsnline.len) break; |
| 123 | j = i + byte_chr(dsnline.s + i,dsnline.len - i,'"'); |
| 124 | if (j >= dsnline.len) break; |
| 125 | } else { |
| 126 | j = i; |
| 127 | while (dsnline.s[j] !=' ' && dsnline.s[j] !='\t' && |
| 128 | dsnline.s[j] !=';') |
| 129 | if (++j >= dsnline.len) break; |
| 130 | } /* got boundary */ |
| 131 | if (!stralloc_copyb(&boundary,dsnline.s+i,j-i)) die_nomem(); |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | if (flagdsn && boundary.len) { /* parse DSN message */ |
| 136 | get(&line); /* if bad format we exit(0) via get() */ |
| 137 | for (;;) { |
| 138 | if (isboundary()) { |
| 139 | if (line.len == boundary.len + 5 && line.s[line.len - 1] == '-' |
| 140 | && line.s[line.len - 2] == '-') |
| 141 | _exit(99); /* end: not failure report */ |
| 142 | get(&line); /* Content-type */ |
| 143 | if (case_startb(line.s,line.len,"content-type:")) { |
| 144 | i = 13; |
| 145 | while (line.s[i] == ' ' || line.s[i] == '\t') |
| 146 | if (++i >= line.len) break; |
| 147 | if (case_startb(line.s+i,line.len-i,"message/delivery-status")) { |
| 148 | for (;;) { |
| 149 | get(&line); |
| 150 | if (isboundary()) break; |
| 151 | if (case_startb(line.s,line.len,"action:")) { |
| 152 | i = 8; |
| 153 | while (line.s[i] == ' ' || line.s[i] == '\t') |
| 154 | if (++i >= line.len) break; |
| 155 | if (case_startb(line.s + i, line.len - i,"failed")) |
| 156 | _exit(0); /* failure notice */ |
| 157 | else |
| 158 | _exit(99); /* there shouldn't be more than 1 action */ |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | } else |
| 164 | get(&line); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | get(&line1); |
| 169 | get(&line2); |
| 170 | get(&line3); |
| 171 | get(&line4); |
| 172 | get(&line5); |
| 173 | get(&line6); |
| 174 | get(&line7); |
| 175 | get(&line8); |
| 176 | |
| 177 | if (stralloc_starts(&line1,"This is a MIME-encapsulated message")) |
| 178 | if (stralloc_starts(&line3,"--")) |
| 179 | if (stralloc_starts(&line5,warn1)) |
| 180 | if (stralloc_starts(&line6,warn2)) |
| 181 | if (stralloc_starts(&line7,warn3)) |
| 182 | if (stralloc_starts(&line8,warn4)) |
| 183 | flagbw = 1; |
| 184 | |
| 185 | if (stralloc_starts(&line1,warn1)) |
| 186 | if (stralloc_starts(&line2,warn2)) |
| 187 | if (stralloc_starts(&line3,warn3)) |
| 188 | if (stralloc_starts(&line4,warn4)) |
| 189 | flagbw = 1; |
| 190 | |
| 191 | if (flagmds && flagsw && flagas && flagbw) _exit(99); |
| 192 | if (flagmds && flagsr && flagbw) _exit(99); |
| 193 | |
| 194 | _exit(0); |
| 195 | } |