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