Exemple #1
0
/* Build a mime response message from original message MSG. TEXT
   is the message text.
*/
static int
build_mime (mu_sieve_machine_t mach, mu_list_t tags, mu_mime_t *pmime,
	    mu_message_t msg, const char *text)
{
  mu_mime_t mime = NULL;
  mu_message_t newmsg;
  mu_stream_t stream, input;
  mu_header_t hdr;
  mu_body_t body;
  const char *header =
    "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n"
    "Content-Transfer-Encoding: 8bit\n\n";
  int rc;
  
  mu_mime_create (&mime, NULL, 0);
  mu_message_create (&newmsg, NULL);
  mu_message_get_body (newmsg, &body);

  if ((rc = mu_static_memory_stream_create (&input, text, strlen (text))))
    {
      mu_sieve_error (mach,
		      _("cannot create temporary stream: %s"),
		      mu_strerror (rc));
      mu_mime_destroy (&mime);
      mu_message_destroy (&newmsg, NULL);
      return 1;
    }

  if (mu_sieve_tag_lookup (tags, "mime", NULL))
    {
      mu_stream_t fstr;
      rc = mu_filter_create (&fstr, input, "base64",
			     MU_FILTER_ENCODE, 
			     MU_STREAM_READ);
      mu_stream_unref (input); 
      if (rc == 0) 
	{
	  header = "Content-Type: text/plain;charset=" MU_SIEVE_CHARSET "\n"
	           "Content-Transfer-Encoding: base64\n\n";
	  input = fstr;
	}
    }

  rc = mu_body_get_streamref (body, &stream);
  if (rc)
    {
      mu_sieve_error (mach,
		      _("cannot get input body stream: %s"),
		      mu_strerror (rc));
      mu_mime_destroy (&mime);
      mu_message_destroy (&newmsg, NULL);
      mu_stream_destroy (&input);
      return 1;
    }

  rc = mu_stream_copy (stream, input, 0, NULL);
  if (rc)
    {
      mu_sieve_error (mach,
		      _("stream copy failed: %s"),
		      mu_strerror (rc));
      mu_mime_destroy (&mime);
      mu_message_destroy (&newmsg, NULL);
      mu_stream_destroy (&input);
      mu_stream_destroy (&stream);
      return 1;
    }

  mu_stream_destroy (&input);
  
  mu_header_create (&hdr, header, strlen (header));
  mu_message_set_header (newmsg, hdr, NULL);

  mu_mime_add_part (mime, newmsg);
  mu_message_unref (newmsg);

  *pmime = mime;

  return 0;
}
Exemple #2
0
/* Check and update the vacation database. Return 0 if the mail should
   be answered, 0 if it should not, and throw exception if an error
   occurs. */
static int
check_db (mu_sieve_machine_t mach, mu_list_t tags, char *from)
{
  mu_property_t prop;
  char *file;
  mu_sieve_value_t *arg;
  unsigned int days;
  int rc;
  mu_stream_t str;
  mu_locker_t locker;
  
  if (mu_sieve_tag_lookup (tags, "days", &arg))
    {
      days = arg->v.number;
      if (days > DAYS_MAX)
	days = DAYS_MAX;
    }
  else
    days = DAYS_DEFAULT;

  file = mu_tilde_expansion ("~/.vacation", MU_HIERARCHY_DELIMITER, NULL);
  if (!file)
    {
      mu_sieve_error (mach, _("%lu: cannot build db file name"),
		      (unsigned long) mu_sieve_get_message_num (mach));
      mu_sieve_abort (mach);
    }

  rc = mu_locker_create (&locker, file, 0);
  if (rc)
    {
      mu_sieve_error (mach, _("%lu: cannot lock %s: %s"),
		      (unsigned long) mu_sieve_get_message_num (mach),
		      file,
		      mu_strerror (rc));
      free (file);
      mu_sieve_abort (mach);
    }

  rc = mu_file_stream_create (&str, file, MU_STREAM_RDWR|MU_STREAM_CREAT);
  if (rc)
    {
      mu_sieve_error (mach, "%lu: mu_file_stream_create(%s): %s",
		      (unsigned long) mu_sieve_get_message_num (mach),
		      file,
		      mu_strerror (rc));
      mu_locker_destroy (&locker);
      free (file);
      mu_sieve_abort (mach);
    }
  
  free (file);

  rc = mu_property_create_init (&prop, mu_assoc_property_init, str);
  if (rc)
    {
      mu_sieve_error (mach, "%lu: mu_property_create_init: %s",
		      (unsigned long) mu_sieve_get_message_num (mach),
		      mu_strerror (rc));
      mu_locker_destroy (&locker);
      mu_sieve_abort (mach);
    }

  rc = mu_locker_lock (locker);
  if (rc)
    {
      mu_sieve_error (mach, "%lu: cannot lock vacation database: %s",
		      (unsigned long) mu_sieve_get_message_num (mach),
		      mu_strerror (rc));
      mu_property_destroy (&prop);
      mu_sieve_abort (mach);
    }

  rc = test_and_update_prop (prop, from, time (NULL), days, mach);
  mu_property_destroy (&prop);
  mu_locker_unlock (locker);
  mu_locker_destroy (&locker);
  if (rc == -1)
    mu_sieve_abort (mach);

  return rc;
}
/* Syntax: deleteheader [:index <fieldno: number> [:last]]
                        [COMPARATOR] [MATCH-TYPE]
                        <field-name: string>
                        [<value-patterns: string-list>]
 */
int
sieve_deleteheader (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
  mu_sieve_value_t *val;
  const char *field_name;
  const char *field_pattern;
  mu_message_t msg;
  mu_header_t hdr;
  int rc;
  mu_sieve_comparator_t comp;
  mu_iterator_t itr;
  unsigned long i, idx = 0;
  
  val = mu_sieve_value_get (args, 0);
  if (!val)
    {
      mu_sieve_error (mach, "%lu: %s",
		      (unsigned long) mu_sieve_get_message_num (mach),
		      _("cannot get field name"));
      mu_sieve_abort (mach);
    }
  field_name = val->v.string;

  val = mu_sieve_value_get (args, 1);
  if (!val)
    {
      field_pattern = NULL;
      mu_sieve_log_action (mach, "DELETEHEADER", "%s", field_name);
    }
  else
    {
      switch (val->type)
	{
	case SVT_STRING_LIST:
	  if (mu_list_get (val->v.list, 0, (void**)&field_pattern))
	    {
	      mu_sieve_error (mach, "%lu: %s",
			      (unsigned long) mu_sieve_get_message_num (mach),
			      _("cannot get list item"));
	      mu_sieve_abort (mach);
	    }
	  mu_sieve_log_action (mach, "DELETEHEADER", "%s: (regexp)",
			       field_name);
	  break;
	  
	case SVT_STRING:
	  field_pattern = val->v.string;
	  mu_sieve_log_action (mach, "DELETEHEADER", "%s: %s", field_name,
			       field_pattern);
	  break;

	default:
	  mu_sieve_error (mach, "%lu: %s: %d",
			  (unsigned long) mu_sieve_get_message_num (mach),
			  _("unexpected value type"), val->type);
	  mu_sieve_abort (mach);
	  
	}
    }
  
  if (mu_sieve_is_dry_run (mach))
    return 0;

  msg = mu_sieve_get_message (mach);
  rc = mu_message_get_header (msg, &hdr);
  if (rc)
    {
      mu_sieve_error (mach, "%lu: %s: %s",
		      (unsigned long) mu_sieve_get_message_num (mach),
		      _("cannot get message header"),
		      mu_strerror (rc));
      mu_sieve_abort (mach);
    }

  mu_header_get_iterator (hdr, &itr);
  if (mu_sieve_tag_lookup (tags, "last", NULL))
    {
      int backwards = 1;
      mu_iterator_ctl (itr, mu_itrctl_set_direction, &backwards);
    }
  comp = mu_sieve_get_comparator (mach, tags);

  if (mu_sieve_tag_lookup (tags, "index", &val))
    idx = val->v.number;
  
  for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      const char *fn, *fv;

      mu_iterator_current_kv (itr, (const void **)&fn, (void **)&fv);
      if (strcmp (field_name, fn))
	continue;
      if (idx && ++i < idx)
	continue;
	  
      if (field_pattern)
	{
	  if (comp (field_pattern, fv))
	    mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	}
      else
	mu_iterator_ctl (itr, mu_itrctl_delete, NULL);

      if (idx)
	break;
    }
  mu_iterator_destroy (&itr);
  return 0;
}
Exemple #4
0
static int
moderator_action (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
  mu_message_t msg, orig;
  int rc;
  size_t nparts = 0;
  int discard = 0;
  int ismime;
  
  if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
    {
      mu_sieve_locus_t locus;
      mu_sieve_get_locus (mach, &locus);
      mu_sieve_debug (mach, "%s:%lu: moderator_test %lu\n",
		      locus.source_file,
		      (u_long) locus.source_line,
		      (u_long) mu_sieve_get_message_num (mach));
    }

  msg = mu_sieve_get_message (mach);
  mu_message_is_multipart (msg, &ismime);

  if (!ismime)
    {
      mu_sieve_error (mach, _("message is not multipart"));
      mu_sieve_abort (mach);
    }

  mu_message_get_num_parts (msg, &nparts);

  if (nparts != 3) /* Mailman moderation requests have three parts */
    {
      mu_sieve_error (mach, _("expected 3 parts, but found %lu"),
		      (unsigned long) nparts);
      mu_sieve_abort (mach);
    }

  if ((rc = moderator_message_get_part (mach, msg, 2, &orig)))
    mu_sieve_abort (mach);

  rc = moderator_filter_message (mach, tags, orig, &discard);
  mu_message_unref (orig);
  if (rc)
    mu_sieve_abort (mach);

  if (discard && !mu_sieve_is_dry_run (mach))
    {
      mu_message_t request;
      char *from = NULL;
      mu_sieve_value_t *arg;
      
      if ((rc = moderator_message_get_part (mach, msg, 3, &request)))
	{
	  mu_sieve_error (mach, _("cannot get message part #3: %s"),
			  mu_strerror (rc));
	  mu_sieve_abort (mach);
	}

      if (mu_sieve_tag_lookup (tags, "address", &arg))
	from = arg->v.string;
      
      if (moderator_discard_message (mach, request, from))
	discard = 0;
      else
	{
	  if (!mu_sieve_tag_lookup (tags, "keep", NULL))
	    {
	      mu_attribute_t attr = 0;

	      if (mu_message_get_attribute (msg, &attr) == 0)
		mu_attribute_set_deleted (attr);
	    }
	  else
	    discard = 0;
	}
      mu_message_unref (request);
    }

  mu_sieve_log_action (mach, "MODERATOR", 
		       discard ? _("discarding message") :
		       _("keeping message"));
  return 0;
}
Exemple #5
0
/* Handler for the timestamp test */
static int
timestamp_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
  mu_sieve_value_t *h, *v;
  mu_header_t hdr;
  char *val;
  time_t now = time (NULL);
  time_t tlimit, tval;
  int rc;
  
  if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
    {
      mu_sieve_locus_t locus;
      mu_sieve_get_locus (mach, &locus);
      mu_sieve_debug (mach, "%s:%lu: TIMESTAMP\n",
		   locus.source_file,
		   (unsigned long) locus.source_line);
    }

  /* Retrieve required arguments: */
  /* First argument: header name */
  h = mu_sieve_value_get (args, 0);
  if (!h)
    {
      mu_sieve_arg_error (mach, 1);
      mu_sieve_abort (mach);
    }
  /* Second argument: date displacement */
  v = mu_sieve_value_get (args, 1);
  if (!v)
    {
      mu_sieve_arg_error (mach, 2);
      mu_sieve_abort (mach);
    }

  if (mu_parse_date (v->v.string, &tlimit, &now))
    {
      mu_sieve_error (mach, _("cannot parse date specification (%s)"),
		   v->v.string);
      mu_sieve_abort (mach);
    }

  rc = mu_message_get_header (mu_sieve_get_message (mach), &hdr);
  if (rc)
    {
      mu_sieve_error (mach, "mu_message_get_header: %s", mu_strerror (rc));
      mu_sieve_abort (mach);
    }
  
  if (mu_header_aget_value (hdr, h->v.string, &val))
    return 0;

  if (mu_parse_date (val, &tval, &now))
    {
      mu_sieve_error (mach,
		   "cannot parse header date specification (%s)",
		   val);
      free (val);
      mu_sieve_abort (mach);
    }
  free (val);

  rc = tval > tlimit;
    
  if (mu_sieve_tag_lookup (tags, "before", NULL))
    rc = !rc;  

  return rc;
}