summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsieve/actions.c332
1 files changed, 330 insertions, 2 deletions
diff --git a/libsieve/actions.c b/libsieve/actions.c
index 2efaac5c8..e4069dac1 100644
--- a/libsieve/actions.c
+++ b/libsieve/actions.c
@@ -76,8 +76,158 @@ sieve_action_fileinto (sieve_machine_t mach, list_t args, list_t tags)
}
int
+stream_printf (stream_t stream, size_t *off, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf = NULL;
+ size_t size, bytes;
+ int rc;
+
+ va_start (ap, fmt);
+ vasprintf (&buf, fmt, ap);
+ va_end (ap);
+ size = strlen (buf);
+ rc = stream_write (stream, buf, size, *off, &bytes);
+ if (rc)
+ return rc;
+ *off += bytes;
+ if (bytes != size)
+ return EIO;
+ return 0;
+}
+
+int
+sieve_get_message_sender (message_t msg, char **ptext)
+{
+ int rc;
+ envelope_t envelope;
+ char *text;
+ size_t size;
+
+ rc = message_get_envelope (msg, &envelope);
+ if (rc)
+ return rc;
+
+ rc = envelope_sender (envelope, NULL, 0, &size);
+ if (rc)
+ return rc;
+
+ if (!(text = malloc (size + 1)))
+ return ENOMEM;
+ envelope_sender (envelope, text, size + 1, NULL);
+ *ptext = text;
+ return 0;
+}
+
+static int
+build_mime (mime_t *pmime, message_t msg, const char *text)
+{
+ mime_t mime = NULL;
+ char datestr[80];
+
+ mime_create (&mime, NULL, 0);
+ {
+ message_t newmsg;
+ stream_t stream;
+ time_t t;
+ struct tm *tm;
+ char *sender;
+ size_t off = 0;
+ header_t hdr;
+ body_t body;
+
+ message_create (&newmsg, NULL);
+ message_get_body (newmsg, &body);
+ body_get_stream (body, &stream);
+
+ time (&t);
+ tm = localtime (&t);
+ strftime (datestr, sizeof datestr, "%a, %b %d %H:%M:%S %Y %Z", tm);
+
+ sieve_get_message_sender (msg, &sender);
+
+ stream_printf (stream, &off,
+ "\nThe original message was received at %s from %s.\n",
+ datestr, sender);
+ free (sender);
+ stream_printf (stream, &off,
+ "Message was refused by recipient's mail filtering program.\n");
+ stream_printf (stream, &off, "Reason given was as follows:\n");
+ stream_printf (stream, &off, "%s", text);
+ stream_close (stream);
+ mime_add_part (mime, newmsg);
+ }
+
+ /* message/delivery-status */
+ {
+ message_t newmsg;
+ stream_t stream;
+ header_t hdr;
+ size_t off = 0;
+ body_t body;
+
+ message_create (&newmsg, NULL);
+ message_get_header (newmsg, &hdr);
+ header_set_value (hdr, "Content-Type", "message/delivery-status", 1);
+ message_get_body (newmsg, &body);
+ body_get_stream (body, &stream);
+ stream_printf (stream, &off, "Reporting-UA: sieve; %s\n", PACKAGE_STRING);
+ stream_printf (stream, &off, "Arrival-Date: %s\n", datestr);
+ stream_printf (stream, &off, "Final-Recipient: RFC822; %s\n",
+ mu_get_user_email (NULL));
+ stream_printf (stream, &off, "Action: deleted\n");
+ stream_printf (stream, &off,
+ "Disposition: automatic-action/MDN-sent-automatically;deleted\n");
+ stream_printf (stream, &off, "Last-Attempt-Date: %s\n", datestr);
+ stream_close (stream);
+ mime_add_part(mime, newmsg);
+ }
+
+ /* Quote original message */
+ {
+ message_t newmsg;
+ stream_t istream, ostream;
+ header_t hdr;
+ size_t ioff = 0, ooff = 0, n;
+ char buffer[512];
+ body_t body;
+
+ message_create (&newmsg, NULL);
+ message_get_header (newmsg, &hdr);
+ header_set_value (hdr, "Content-Type", "message/rfc822", 1);
+ message_get_body (newmsg, &body);
+ body_get_stream (body, &ostream);
+ message_get_stream (msg, &istream);
+
+ while (stream_read (istream, buffer, sizeof buffer - 1, ioff, &n) == 0
+ && n != 0)
+ {
+ size_t sz;
+ stream_write (ostream, buffer, n, ooff, &sz);
+ if (sz != n)
+ return EIO;
+ ooff += n;
+ ioff += n;
+ }
+ stream_close (ostream);
+ mime_add_part (mime, newmsg);
+ }
+
+ *pmime = mime;
+
+ return 0;
+}
+
+int
sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags)
{
+ mime_t mime = NULL;
+ mailer_t mailer = sieve_get_mailer (mach);
+ int rc;
+ message_t newmsg;
+ char *addrtext;
+ address_t from, to;
+
sieve_value_t *val = sieve_value_get (args, 0);
if (!val)
{
@@ -87,22 +237,200 @@ sieve_action_reject (sieve_machine_t mach, list_t args, list_t tags)
sieve_log_action (mach, "REJECT", NULL);
if (sieve_is_dry_run (mach))
return 0;
- return 0;
+
+ rc = build_mime (&mime, mach->msg, val->v.string);
+
+ mime_get_message (mime, &newmsg);
+
+ sieve_get_message_sender (mach->msg, &addrtext);
+ rc = address_create (&to, addrtext);
+ if (rc)
+ {
+ sieve_error (mach,
+ "%d: reject - can't create to address <%s>: %s\n",
+ sieve_get_message_num (mach),
+ addrtext, mu_errstring (rc));
+ free (addrtext);
+ goto end;
+ }
+ free (addrtext);
+
+ rc = address_create (&from, sieve_get_daemon_email (mach));
+ if (rc)
+ {
+ sieve_error (mach,
+ "%d: reject - can't create from address <%s>: %s\n",
+ sieve_get_message_num (mach),
+ sieve_get_daemon_email (mach),
+ mu_errstring (rc));
+ goto end;
+ }
+
+ rc = mailer_open (mailer, 0);
+ if (rc)
+ {
+ url_t url = NULL;
+ mailer_get_url (mailer, &url);
+
+ sieve_error (mach,
+ "%d: redirect - can't open mailer %s: %s\n",
+ sieve_get_message_num (mach),
+ url_to_string (url),
+ mu_errstring (rc));
+ goto end;
+ }
+
+ rc = mailer_send_message (mailer, newmsg, from, to);
+ mailer_close (mailer);
+
+ end:
+ sieve_mark_deleted (mach->msg, rc == 0);
+ mime_destroy (&mime);
+ address_destroy (&from);
+ address_destroy (&to);
+
+ return rc;
+}
+
+/* rfc3028 says:
+ "Implementations SHOULD take measures to implement loop control,"
+ We do this by appending an "X-Sender" header to each message
+ being redirected. If one of the "X-Sender" headers of the message
+ contains our email address, we assume it is a loop and bail out. */
+
+static int
+check_redirect_loop (message_t msg)
+{
+ header_t hdr = NULL;
+ size_t i, num = 0;
+ char buf[512];
+ int loop = 0;
+ char *email = mu_get_user_email (NULL);
+
+ message_get_header (msg, &hdr);
+ header_get_field_count (hdr, &num);
+ for (i = 1; !loop && i <= num; i++)
+ {
+ header_get_field_name (hdr, i, buf, sizeof buf, NULL);
+ if (strcasecmp (buf, "X-Sender") == 0)
+ {
+ size_t j, cnt = 0;
+ address_t addr;
+
+ header_get_field_value (hdr, i, buf, sizeof buf, NULL);
+ if (address_create (&addr, buf))
+ continue;
+
+ address_get_count (addr, &cnt);
+ for (j = 1; !loop && j <= cnt; j++)
+ {
+ address_get_email (addr, j, buf, sizeof buf, NULL);
+ if (strcasecmp (buf, email) == 0)
+ loop = 1;
+ }
+ address_destroy (&addr);
+ }
+ }
+ return loop;
}
int
sieve_action_redirect (sieve_machine_t mach, list_t args, list_t tags)
{
+ message_t msg, newmsg = NULL;
+ address_t addr = NULL, from = NULL;
+ header_t hdr = NULL;
+ int rc;
+ size_t size;
+ char *fromaddr;
+ mailer_t mailer = sieve_get_mailer (mach);
+
sieve_value_t *val = sieve_value_get (args, 0);
if (!val)
{
sieve_error (mach, "redirect: can't get address!");
sieve_abort (mach);
}
+
+ rc = address_create (&addr, val->v.string);
+ if (rc)
+ {
+ sieve_error (mach,
+ "%d: redirect - parsing to `%s' failed: %s\n",
+ sieve_get_message_num (mach),
+ val->v.string, mu_errstring (rc));
+ return 1;
+ }
+
sieve_log_action (mach, "REDIRECT", "to %s", val->v.string);
if (sieve_is_dry_run (mach))
return 0;
- return 0;
+
+ msg = sieve_get_message (mach);
+ if (check_redirect_loop (msg))
+ {
+ sieve_error (mach, "%d: Redirection loop detected",
+ sieve_get_message_num (mach));
+ goto end;
+ }
+
+ rc = sieve_get_message_sender (msg, &fromaddr);
+ if (rc)
+ {
+ sieve_error (mach,
+ "%d: redirect - can't get envelope sender: %s\n",
+ sieve_get_message_num (mach), mu_errstring (rc));
+ goto end;
+ }
+
+ rc = address_create (&from, fromaddr);
+ if (rc)
+ {
+ sieve_error (mach,
+ "%d: redirect - can't create from address <%s>: %s\n",
+ sieve_get_message_num (mach),
+ fromaddr, mu_errstring (rc));
+ free (fromaddr);
+ goto end;
+ }
+
+ free (fromaddr);
+
+ rc = message_create_copy (&newmsg, msg);
+ if (rc)
+ {
+ sieve_error (mach, "%d: can't copy message: %s",
+ sieve_get_message_num (mach),
+ mu_errstring (rc));
+ goto end;
+ }
+ message_get_header (newmsg, &hdr);
+ header_set_value (hdr, "X-Sender", mu_get_user_email (NULL), 0);
+
+ rc = mailer_open (mailer, 0);
+ if (rc)
+ {
+ url_t url = NULL;
+ mailer_get_url (mailer, &url);
+
+ sieve_error (mach,
+ "%d: redirect - can't open mailer %s: %s\n",
+ sieve_get_message_num (mach),
+ url_to_string (url),
+ mu_errstring (rc));
+ goto end;
+ }
+
+ rc = mailer_send_message (mailer, newmsg, from, addr);
+ mailer_close (mailer);
+
+ end:
+ sieve_mark_deleted (mach->msg, rc == 0);
+ message_destroy (&newmsg, NULL);
+ address_destroy (&from);
+ address_destroy (&addr);
+
+ return rc;
}
sieve_data_type fileinto_args[] = {

Return to:

Send suggestions and report system problems to the System administrator.