Import ezmlm-idx 0.40
[ezmlm] / ezmlm-weed.c
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 }