Implemented reject and redirect.
Showing
1 changed file
with
330 additions
and
2 deletions
... | @@ -76,8 +76,158 @@ sieve_action_fileinto (sieve_machine_t mach, list_t args, list_t tags) | ... | @@ -76,8 +76,158 @@ sieve_action_fileinto (sieve_machine_t mach, list_t args, list_t tags) |
76 | } | 76 | } |
77 | 77 | ||
78 | int | 78 | int |
79 | stream_printf (stream_t stream, size_t *off, const char *fmt, ...) | ||
80 | { | ||
81 | va_list ap; | ||
82 | char *buf = NULL; | ||
83 | size_t size, bytes; | ||
84 | int rc; | ||
85 | |||
86 | va_start (ap, fmt); | ||
87 | vasprintf (&buf, fmt, ap); | ||
88 | va_end (ap); | ||
89 | size = strlen (buf); | ||
90 | rc = stream_write (stream, buf, size, *off, &bytes); | ||
91 | if (rc) | ||
92 | return rc; | ||
93 | *off += bytes; | ||
94 | if (bytes != size) | ||
95 | return EIO; | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int | ||
100 | sieve_get_message_sender (message_t msg, char **ptext) | ||
101 | { | ||
102 | int rc; | ||
103 | envelope_t envelope; | ||
104 | char *text; | ||
105 | size_t size; | ||
106 | |||
107 | rc = message_get_envelope (msg, &envelope); | ||
108 | if (rc) | ||
109 | return rc; | ||
110 | |||
111 | rc = envelope_sender (envelope, NULL, 0, &size); | ||
112 | if (rc) | ||
113 | return rc; | ||
114 | |||
115 | if (!(text = malloc (size + 1))) | ||
116 | return ENOMEM; | ||
117 | envelope_sender (envelope, text, size + 1, NULL); | ||
118 | *ptext = text; | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int | ||
123 | build_mime (mime_t *pmime, message_t msg, const char *text) | ||
124 | { | ||
125 | mime_t mime = NULL; | ||
126 | char datestr[80]; | ||
127 | |||
128 | mime_create (&mime, NULL, 0); | ||
129 | { | ||
130 | message_t newmsg; | ||
131 | stream_t stream; | ||
132 | time_t t; | ||
133 | struct tm *tm; | ||
134 | char *sender; | ||
135 | size_t off = 0; | ||
136 | header_t hdr; | ||
137 | body_t body; | ||
138 | |||
139 | message_create (&newmsg, NULL); | ||
140 | message_get_body (newmsg, &body); | ||
141 | body_get_stream (body, &stream); | ||
142 | |||
143 | time (&t); | ||
144 | tm = localtime (&t); | ||
145 | strftime (datestr, sizeof datestr, "%a, %b %d %H:%M:%S %Y %Z", tm); | ||
146 | |||
147 | sieve_get_message_sender (msg, &sender); | ||
148 | |||
149 | stream_printf (stream, &off, | ||
150 | "\nThe original message was received at %s from %s.\n", | ||
151 | datestr, sender); | ||
152 | free (sender); | ||
153 | stream_printf (stream, &off, | ||
154 | "Message was refused by recipient's mail filtering program.\n"); | ||
155 | stream_printf (stream, &off, "Reason given was as follows:\n"); | ||
156 | stream_printf (stream, &off, "%s", text); | ||
157 | stream_close (stream); | ||
158 | mime_add_part (mime, newmsg); | ||
159 | } | ||
160 | |||
161 | /* message/delivery-status */ | ||
162 | { | ||
163 | message_t newmsg; | ||
164 | stream_t stream; | ||
165 | header_t hdr; | ||
166 | size_t off = 0; | ||
167 | body_t body; | ||
168 | |||
169 | message_create (&newmsg, NULL); | ||
170 | message_get_header (newmsg, &hdr); | ||
171 | header_set_value (hdr, "Content-Type", "message/delivery-status", 1); | ||
172 | message_get_body (newmsg, &body); | ||
173 | body_get_stream (body, &stream); | ||
174 | stream_printf (stream, &off, "Reporting-UA: sieve; %s\n", PACKAGE_STRING); | ||
175 | stream_printf (stream, &off, "Arrival-Date: %s\n", datestr); | ||
176 | stream_printf (stream, &off, "Final-Recipient: RFC822; %s\n", | ||
177 | mu_get_user_email (NULL)); | ||
178 | stream_printf (stream, &off, "Action: deleted\n"); | ||
179 | stream_printf (stream, &off, | ||
180 | "Disposition: automatic-action/MDN-sent-automatically;deleted\n"); | ||
181 | stream_printf (stream, &off, "Last-Attempt-Date: %s\n", datestr); | ||
182 | stream_close (stream); | ||
183 | mime_add_part(mime, newmsg); | ||
184 | } | ||
185 | |||
186 | /* Quote original message */ | ||
187 | { | ||
188 | message_t newmsg; | ||
189 | stream_t istream, ostream; | ||
190 | header_t hdr; | ||
191 | size_t ioff = 0, ooff = 0, n; | ||
192 | char buffer[512]; | ||
193 | body_t body; | ||
194 | |||
195 | message_create (&newmsg, NULL); | ||
196 | message_get_header (newmsg, &hdr); | ||
197 | header_set_value (hdr, "Content-Type", "message/rfc822", 1); | ||
198 | message_get_body (newmsg, &body); | ||
199 | body_get_stream (body, &ostream); | ||
200 | message_get_stream (msg, &istream); | ||
201 | |||
202 | while (stream_read (istream, buffer, sizeof buffer - 1, ioff, &n) == 0 | ||
203 | && n != 0) | ||
204 | { | ||
205 | size_t sz; | ||
206 | stream_write (ostream, buffer, n, ooff, &sz); | ||
207 | if (sz != n) | ||
208 | return EIO; | ||
209 | ooff += n; | ||
210 | ioff += n; | ||
211 | } | ||
212 | stream_close (ostream); | ||
213 | mime_add_part (mime, newmsg); | ||
214 | } | ||
215 | |||
216 | *pmime = mime; | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | int | ||
79 | sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags) | 222 | sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags) |
80 | { | 223 | { |
224 | mime_t mime = NULL; | ||
225 | mailer_t mailer = sieve_get_mailer (mach); | ||
226 | int rc; | ||
227 | message_t newmsg; | ||
228 | char *addrtext; | ||
229 | address_t from, to; | ||
230 | |||
81 | sieve_value_t *val = sieve_value_get (args, 0); | 231 | sieve_value_t *val = sieve_value_get (args, 0); |
82 | if (!val) | 232 | if (!val) |
83 | { | 233 | { |
... | @@ -87,22 +237,200 @@ sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags) | ... | @@ -87,22 +237,200 @@ sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags) |
87 | sieve_log_action (mach, "REJECT", NULL); | 237 | sieve_log_action (mach, "REJECT", NULL); |
88 | if (sieve_is_dry_run (mach)) | 238 | if (sieve_is_dry_run (mach)) |
89 | return 0; | 239 | return 0; |
90 | return 0; | 240 | |
241 | rc = build_mime (&mime, mach->msg, val->v.string); | ||
242 | |||
243 | mime_get_message (mime, &newmsg); | ||
244 | |||
245 | sieve_get_message_sender (mach->msg, &addrtext); | ||
246 | rc = address_create (&to, addrtext); | ||
247 | if (rc) | ||
248 | { | ||
249 | sieve_error (mach, | ||
250 | "%d: reject - can't create to address <%s>: %s\n", | ||
251 | sieve_get_message_num (mach), | ||
252 | addrtext, mu_errstring (rc)); | ||
253 | free (addrtext); | ||
254 | goto end; | ||
255 | } | ||
256 | free (addrtext); | ||
257 | |||
258 | rc = address_create (&from, sieve_get_daemon_email (mach)); | ||
259 | if (rc) | ||
260 | { | ||
261 | sieve_error (mach, | ||
262 | "%d: reject - can't create from address <%s>: %s\n", | ||
263 | sieve_get_message_num (mach), | ||
264 | sieve_get_daemon_email (mach), | ||
265 | mu_errstring (rc)); | ||
266 | goto end; | ||
267 | } | ||
268 | |||
269 | rc = mailer_open (mailer, 0); | ||
270 | if (rc) | ||
271 | { | ||
272 | url_t url = NULL; | ||
273 | mailer_get_url (mailer, &url); | ||
274 | |||
275 | sieve_error (mach, | ||
276 | "%d: redirect - can't open mailer %s: %s\n", | ||
277 | sieve_get_message_num (mach), | ||
278 | url_to_string (url), | ||
279 | mu_errstring (rc)); | ||
280 | goto end; | ||
281 | } | ||
282 | |||
283 | rc = mailer_send_message (mailer, newmsg, from, to); | ||
284 | mailer_close (mailer); | ||
285 | |||
286 | end: | ||
287 | sieve_mark_deleted (mach->msg, rc == 0); | ||
288 | mime_destroy (&mime); | ||
289 | address_destroy (&from); | ||
290 | address_destroy (&to); | ||
291 | |||
292 | return rc; | ||
293 | } | ||
294 | |||
295 | /* rfc3028 says: | ||
296 | "Implementations SHOULD take measures to implement loop control," | ||
297 | We do this by appending an "X-Sender" header to each message | ||
298 | being redirected. If one of the "X-Sender" headers of the message | ||
299 | contains our email address, we assume it is a loop and bail out. */ | ||
300 | |||
301 | static int | ||
302 | check_redirect_loop (message_t msg) | ||
303 | { | ||
304 | header_t hdr = NULL; | ||
305 | size_t i, num = 0; | ||
306 | char buf[512]; | ||
307 | int loop = 0; | ||
308 | char *email = mu_get_user_email (NULL); | ||
309 | |||
310 | message_get_header (msg, &hdr); | ||
311 | header_get_field_count (hdr, &num); | ||
312 | for (i = 1; !loop && i <= num; i++) | ||
313 | { | ||
314 | header_get_field_name (hdr, i, buf, sizeof buf, NULL); | ||
315 | if (strcasecmp (buf, "X-Sender") == 0) | ||
316 | { | ||
317 | size_t j, cnt = 0; | ||
318 | address_t addr; | ||
319 | |||
320 | header_get_field_value (hdr, i, buf, sizeof buf, NULL); | ||
321 | if (address_create (&addr, buf)) | ||
322 | continue; | ||
323 | |||
324 | address_get_count (addr, &cnt); | ||
325 | for (j = 1; !loop && j <= cnt; j++) | ||
326 | { | ||
327 | address_get_email (addr, j, buf, sizeof buf, NULL); | ||
328 | if (strcasecmp (buf, email) == 0) | ||
329 | loop = 1; | ||
330 | } | ||
331 | address_destroy (&addr); | ||
332 | } | ||
333 | } | ||
334 | return loop; | ||
91 | } | 335 | } |
92 | 336 | ||
93 | int | 337 | int |
94 | sieve_action_redirect (sieve_machine_t mach, list_t args, list_t tags) | 338 | sieve_action_redirect (sieve_machine_t mach, list_t args, list_t tags) |
95 | { | 339 | { |
340 | message_t msg, newmsg = NULL; | ||
341 | address_t addr = NULL, from = NULL; | ||
342 | header_t hdr = NULL; | ||
343 | int rc; | ||
344 | size_t size; | ||
345 | char *fromaddr; | ||
346 | mailer_t mailer = sieve_get_mailer (mach); | ||
347 | |||
96 | sieve_value_t *val = sieve_value_get (args, 0); | 348 | sieve_value_t *val = sieve_value_get (args, 0); |
97 | if (!val) | 349 | if (!val) |
98 | { | 350 | { |
99 | sieve_error (mach, "redirect: can't get address!"); | 351 | sieve_error (mach, "redirect: can't get address!"); |
100 | sieve_abort (mach); | 352 | sieve_abort (mach); |
101 | } | 353 | } |
354 | |||
355 | rc = address_create (&addr, val->v.string); | ||
356 | if (rc) | ||
357 | { | ||
358 | sieve_error (mach, | ||
359 | "%d: redirect - parsing to `%s' failed: %s\n", | ||
360 | sieve_get_message_num (mach), | ||
361 | val->v.string, mu_errstring (rc)); | ||
362 | return 1; | ||
363 | } | ||
364 | |||
102 | sieve_log_action (mach, "REDIRECT", "to %s", val->v.string); | 365 | sieve_log_action (mach, "REDIRECT", "to %s", val->v.string); |
103 | if (sieve_is_dry_run (mach)) | 366 | if (sieve_is_dry_run (mach)) |
104 | return 0; | 367 | return 0; |
105 | return 0; | 368 | |
369 | msg = sieve_get_message (mach); | ||
370 | if (check_redirect_loop (msg)) | ||
371 | { | ||
372 | sieve_error (mach, "%d: Redirection loop detected", | ||
373 | sieve_get_message_num (mach)); | ||
374 | goto end; | ||
375 | } | ||
376 | |||
377 | rc = sieve_get_message_sender (msg, &fromaddr); | ||
378 | if (rc) | ||
379 | { | ||
380 | sieve_error (mach, | ||
381 | "%d: redirect - can't get envelope sender: %s\n", | ||
382 | sieve_get_message_num (mach), mu_errstring (rc)); | ||
383 | goto end; | ||
384 | } | ||
385 | |||
386 | rc = address_create (&from, fromaddr); | ||
387 | if (rc) | ||
388 | { | ||
389 | sieve_error (mach, | ||
390 | "%d: redirect - can't create from address <%s>: %s\n", | ||
391 | sieve_get_message_num (mach), | ||
392 | fromaddr, mu_errstring (rc)); | ||
393 | free (fromaddr); | ||
394 | goto end; | ||
395 | } | ||
396 | |||
397 | free (fromaddr); | ||
398 | |||
399 | rc = message_create_copy (&newmsg, msg); | ||
400 | if (rc) | ||
401 | { | ||
402 | sieve_error (mach, "%d: can't copy message: %s", | ||
403 | sieve_get_message_num (mach), | ||
404 | mu_errstring (rc)); | ||
405 | goto end; | ||
406 | } | ||
407 | message_get_header (newmsg, &hdr); | ||
408 | header_set_value (hdr, "X-Sender", mu_get_user_email (NULL), 0); | ||
409 | |||
410 | rc = mailer_open (mailer, 0); | ||
411 | if (rc) | ||
412 | { | ||
413 | url_t url = NULL; | ||
414 | mailer_get_url (mailer, &url); | ||
415 | |||
416 | sieve_error (mach, | ||
417 | "%d: redirect - can't open mailer %s: %s\n", | ||
418 | sieve_get_message_num (mach), | ||
419 | url_to_string (url), | ||
420 | mu_errstring (rc)); | ||
421 | goto end; | ||
422 | } | ||
423 | |||
424 | rc = mailer_send_message (mailer, newmsg, from, addr); | ||
425 | mailer_close (mailer); | ||
426 | |||
427 | end: | ||
428 | sieve_mark_deleted (mach->msg, rc == 0); | ||
429 | message_destroy (&newmsg, NULL); | ||
430 | address_destroy (&from); | ||
431 | address_destroy (&addr); | ||
432 | |||
433 | return rc; | ||
106 | } | 434 | } |
107 | 435 | ||
108 | sieve_data_type fileinto_args[] = { | 436 | sieve_data_type fileinto_args[] = { | ... | ... |
-
Please register or sign in to post a comment