예제 #1
0
static int
_attachment_setup (mu_mime_io_buffer_t *pinfo, mu_message_t msg,
		   mu_stream_t *pstream)
{
  int ret;
  mu_body_t body;
  mu_mime_io_buffer_t info;
  mu_stream_t stream;
    
  if ((ret = mu_message_get_body (msg, &body)) != 0 ||
      (ret = mu_body_get_streamref (body, &stream)) != 0)
    return ret;
  *pstream = stream;
  if (*pinfo)
    {
      info = *pinfo;
      info->refcnt++;
    }
  else
    {
      ret = mu_mime_io_buffer_create (&info);
      if (ret)
	return ret;
    }
  
  *pinfo = info;
  return 0;
}
예제 #2
0
int
moderator_message_get_part (mu_sieve_machine_t mach,
			    mu_message_t msg, size_t index, mu_message_t *pmsg)
{
  int rc;
  mu_message_t tmp;
  mu_header_t hdr = NULL;
  char *value;

  if ((rc = mu_message_get_part (msg, index, &tmp)))
    {
      mu_sieve_error (mach, _("cannot get message part #%lu: %s"),
		      (unsigned long) index, mu_strerror (rc));
      return 1;
    }
  
  mu_message_get_header (tmp, &hdr);
  if (mu_header_aget_value (hdr, MU_HEADER_CONTENT_TYPE, &value) == 0
      && memcmp (value, "message/rfc822", 14) == 0)
    {
      mu_stream_t str;
      mu_body_t body;

      free (value);
      mu_message_get_body (tmp, &body);
      mu_body_get_stream (body, &str);

      rc = mu_stream_to_message (str, pmsg);
      if (rc)
	{
	  mu_sieve_error (mach,
			  _("cannot convert MIME part stream to message: %s"),
			  mu_strerror (rc));
	  return 1;
	}
    }
  else if (value)
    {
      mu_sieve_error (mach,
		      _("expected message type message/rfc822, but found %s"),
		      value);
      free (value);
      return 1;
    }
  else
    {
      mu_sieve_error (mach, _("no Content-Type header found"));
      return 1;
    }
  return 0;
}
예제 #3
0
static void
print_message_part_sizes (mu_message_t part, int indent)
{
  mu_body_t body;
  mu_header_t hdr;
  size_t msize, mlines, hsize, hlines, bsize, blines;
  
  MU_ASSERT (mu_message_size (part, &msize));
  MU_ASSERT (mu_message_lines (part, &mlines));
  MU_ASSERT (mu_message_get_header (part, &hdr));
  MU_ASSERT (mu_header_size (hdr, &hsize));
  MU_ASSERT (mu_header_lines (hdr, &hlines));
  MU_ASSERT (mu_message_get_body (part, &body));
  MU_ASSERT (mu_body_size (body, &bsize));
  MU_ASSERT (mu_body_lines (body, &blines));
  printf ("%*.*sMessage part size - %lu/%lu: %lu/%lu, %lu/%lu\n",
	  indent, indent, "",
	  (unsigned long) msize, (unsigned long) mlines,
	  (unsigned long) hsize, (unsigned long) hlines,
	  (unsigned long) bsize, (unsigned long) blines);
}
예제 #4
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;
}
예제 #5
0
int
main (int argc, char **argv)
{
  int i;
  char *host = NULL;
  char *infile = NULL;
  char *port = NULL;
  int tls = 0;
  int raw = 1;
  int flags = 0;
  mu_stream_t stream;
  mu_smtp_t smtp;
  mu_stream_t instr;
  char *from = NULL;
  mu_list_t rcpt_list = NULL;
  mu_list_t meth_list = NULL;
  mu_list_t skiphdr_list = NULL;
  struct mu_sockaddr *sa;
  struct mu_sockaddr_hints hints;
  
  mu_set_program_name (argv[0]);
  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
  
  if (argc < 2)
    usage ();

  memset (&hints, 0, sizeof (hints)); 
  hints.flags = MU_AH_DETECT_FAMILY;
  hints.port = 25;
  hints.protocol = IPPROTO_TCP;
  hints.socktype = SOCK_STREAM;

  MU_ASSERT (mu_smtp_create (&smtp));

  for (i = 1; i < argc; i++)
    {
      if (strncmp (argv[i], "port=", 5) == 0)
	port = argv[i] + 5;
      else if (strncmp (argv[i], "family=", 7) == 0)
	{
	  hints.flags &= ~MU_AH_DETECT_FAMILY;
	  switch (argv[i][7])
	    {
	    case '4':
	      hints.family = AF_INET;
	      break;
	    case '6':
	      hints.family = AF_INET6;
	      break;
	    default:
	      mu_error ("invalid family name: %s", argv[i]+7);
	      exit (1);
	    }
	}
      else if (strncmp (argv[i], "trace=", 6) == 0)
	{
	  char *arg = argv[i] + 6;

	  if (mu_isdigit (arg[0]))
	    mu_smtp_trace (smtp, atoi (argv[i] + 6) ?
			   MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR);
	  else
	    {
	      mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
	      if (strcmp (arg, "secure") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_SECURE);
	      else if (strcmp (arg, "payload") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_PAYLOAD);
	    }
	}
      else if (strncmp (argv[i], "tls=", 4) == 0)
	tls = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "domain=", 7) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN,
				      argv[i] + 7));
      else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE,
				      argv[i] + 8));
      else if (strncmp (argv[i], "realm=", 6) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM,
				      argv[i] + 6));
      else if (strncmp (argv[i], "host=", 5) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST,
				      argv[i] + 5));
      else if (strncmp (argv[i], "url=", 4) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL,
				      argv[i] + 4));
      else if (strncmp (argv[i], "input=", 6) == 0)
	infile = argv[i] + 6;
      else if (strncmp (argv[i], "raw=", 4) == 0)
	raw = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "rcpt=", 5) == 0)
	{
	  if (!rcpt_list)
	    MU_ASSERT (mu_list_create (&rcpt_list));
	  MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5));
	}
      else if (strncmp (argv[i], "from=", 5) == 0)
	from = argv[i] + 5;
      else if (strncmp (argv[i], "auth=", 5) == 0)
	update_list (&meth_list, argv[i] + 5);
      else if (strncmp (argv[i], "skiphdr=", 8) == 0)
	{
	  update_list (&skiphdr_list, argv[i] + 8);
	  raw = 0;
	}
      else if (host)
	{
	  mu_error ("server name already given: %s, new name %s?",
		    host, argv[i]);
	  exit (1);
	}
      else
	host = argv[i];
    }

  if (!host)
    usage ();

  if (!raw)
    flags = MU_STREAM_SEEK;
  if (infile)
    MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
  else
    MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags));
  
  host = argv[1];

  MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints));

  MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR));
  
  mu_smtp_set_carrier (smtp, stream);
  mu_stream_unref (stream);
  
  if (!from)
    {
      from = getenv ("USER");
      if (!from)
	{
	  mu_error ("cannot determine sender name");
	  exit (1);
	}
    }

  if (raw && !rcpt_list)
    {
      mu_error ("no recipients");
      exit (1);
    }
  
  MU_ASSERT (mu_smtp_open (smtp));
  MU_ASSERT (mu_smtp_ehlo (smtp));

  if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
    {
      MU_ASSERT (mu_smtp_starttls (smtp));
      MU_ASSERT (mu_smtp_ehlo (smtp));
    }

  if (meth_list)
    {
      int status;
      
      MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list));
      status = mu_smtp_auth (smtp);
      switch (status)
	{
	case 0:
	  MU_ASSERT (mu_smtp_ehlo (smtp));
	  break;
	  
	case ENOSYS:
	case MU_ERR_NOENT:
	  /* Ok, skip it */
	  break;

	default:
	  mu_error ("authentication failed: %s", mu_strerror (status));
	  exit (1);
	}
    }
  
  MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL));
  mu_list_foreach (rcpt_list, send_rcpt_command, smtp);
  
  if (raw)
    {
      /* Raw sending mode: send from the stream directly */
      MU_ASSERT (mu_smtp_send_stream (smtp, instr));
    }
  else
    {
      /* Message (standard) sending mode: send a MU message. */

      mu_message_t msg;
      mu_stream_t ostr, bstr;
      mu_header_t hdr;
      mu_iterator_t itr;
      mu_body_t body;

      if (skiphdr_list)
	mu_list_set_comparator (skiphdr_list, headercmp);
      
      MU_ASSERT (mu_stream_to_message (instr, &msg));
      mu_stream_unref (instr);
      MU_ASSERT (mu_smtp_data (smtp, &ostr));
      MU_ASSERT (mu_message_get_header (msg, &hdr));
      MU_ASSERT (mu_header_get_iterator (hdr, &itr));
      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
	   mu_iterator_next (itr))
	{
	  const char *name;
	  void *value;

	  mu_iterator_current_kv (itr, (void*) &name, &value);
	  if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0)
	    continue;

	  mu_stream_printf (ostr, "%s: %s\n", name, (char*)value);
	}
      mu_iterator_destroy (&itr);
      MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL));
      
      MU_ASSERT (mu_message_get_body (msg, &body));
      MU_ASSERT (mu_body_get_streamref (body, &bstr));
      MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL));
      mu_stream_destroy (&bstr);
      mu_stream_close (ostr);
      mu_stream_destroy (&ostr);
    }
  MU_ASSERT (mu_smtp_dot (smtp));
  MU_ASSERT (mu_smtp_quit (smtp));
  
  mu_smtp_destroy (&smtp);
  mu_stream_close (instr);
  mu_stream_destroy (&instr);
  return 0;
}
예제 #6
0
oo\n\
";

int
main (int argc, char **argv)
{
  int i;
  char *p;
  mu_message_t msg;
  mu_stream_t stream = NULL;
  mu_header_t hdr;
  mu_body_t body;
  
  mu_set_program_name (argv[0]);

  mu_static_memory_stream_create (&stream, text, strlen (text));
  assert (mu_stream_to_message (stream, &msg) == 0);
  mu_stream_unref (stream);
  assert (mu_message_get_header (msg, &hdr) == 0);
  assert (mu_message_get_body (msg, &body) == 0);
  assert (mu_body_get_streamref (body, &stream) == 0);
  assert (mu_stream_seek (stream, 0, MU_SEEK_END, NULL) == 0);
  
  for (i = 1; i < argc; i++)
    {
      if (strcmp (argv[i], "-h") == 0)
	{
	  mu_printf ("usage: %s [-a HDR:VAL] [-t TEXT]\n", mu_program_name);
	  return 0;
	}
      
      if (strcmp (argv[i], "-a") == 0)
	{
	  i++;
	  assert (argv[i] != NULL);
	  p = strchr (argv[i], ':');
	  assert (p != NULL);
	  *p++ = 0;
	  while (*p && mu_isspace (*p))
	    p++;
	  assert (mu_header_set_value (hdr, argv[i], p, 1) == 0);
	}
      else if (strcmp (argv[i], "-l") == 0)
	{
	  mu_off_t off;
	  int whence = MU_SEEK_SET;
	  
	  i++;
	  assert (argv[i] != NULL);
	  off = strtol (argv[i], &p, 10);
	  assert (*p == 0);
	  if (off < 0)
	    whence = MU_SEEK_END;
	  assert (mu_stream_seek (stream, off, whence, NULL) == 0);
	}
      else if (strcmp (argv[i], "-t") == 0)
	{
	  mu_wordsplit_t ws;
	  i++;
	  assert (argv[i] != NULL);

	  if (mu_wordsplit (argv[i], &ws,
			    MU_WRDSF_NOSPLIT | MU_WRDSF_DEFFLAGS))
	    {
	      mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws));
	      exit (1);
	    }
	  else
	    assert (mu_stream_write (stream, ws.ws_wordv[0],
				     strlen (ws.ws_wordv[0]), NULL) == 0);
	  mu_wordsplit_free (&ws);
	}
      else
	mu_error ("ignoring unknown argument %s", argv[i]);
    }
  mu_stream_unref (stream);

  assert (mu_message_get_streamref (msg, &stream) == 0);
  assert (mu_stream_copy (mu_strout, stream, 0, NULL) == 0);
  mu_stream_unref (stream);

  return 0;
}
예제 #7
0
int
mu_message_create_attachment (const char *content_type, const char *encoding,
			      const char *filename, mu_message_t *newmsg)
{
  mu_header_t hdr;
  mu_body_t body;
  mu_stream_t fstream = NULL, tstream = NULL;
  char *header = NULL, *name = NULL, *fname = NULL;
  int ret;

  if (newmsg == NULL)
    return MU_ERR_OUT_PTR_NULL;
  if (filename == NULL)
    return EINVAL;

  if ((ret = mu_message_create (newmsg, NULL)) == 0)
    {
      if (content_type == NULL)
	content_type = "text/plain";
      if (encoding == NULL)
	encoding = "7bit";
      if ((fname = strdup (filename)) != NULL)
	{
	  name = strrchr (fname, '/');
	  if (name)
	    name++;
	  else
	    name = fname;
	  ret = mu_asprintf (&header,
			     "Content-Type: %s; name=%s\n"
			     "Content-Transfer-Encoding: %s\n"
			     "Content-Disposition: attachment; filename=%s\n\n",
			     content_type, name, encoding, name);
	  if (ret == 0)
	    {
	      if ((ret = mu_header_create (&hdr, header,
					   strlen (header))) == 0)
		{
		  mu_stream_t bstr;
		  mu_message_get_body (*newmsg, &body);
		  mu_body_get_streamref (body, &bstr);
		  
		  if ((ret = mu_file_stream_create (&fstream, filename,
						    MU_STREAM_READ)) == 0)
		    {
		      if ((ret = mu_filter_create (&tstream, fstream, encoding,
						   MU_FILTER_ENCODE,
						   MU_STREAM_READ)) == 0)
			{
			  mu_stream_copy (bstr, tstream, 0, NULL);
			  mu_stream_unref (tstream);
			  mu_message_set_header (*newmsg, hdr, NULL);
			}
		    }
		  mu_stream_unref (bstr);
		  free (header);
		}
	    }
	}
    }
  
  if (ret)
    {
      if (*newmsg)
	mu_message_destroy (newmsg, NULL);
      if (hdr)
	mu_header_destroy (&hdr);
      if (fstream)
	mu_stream_destroy (&fstream);
      if (fname)
	free (fname);
    }
  return ret;
}
예제 #8
0
int
main (int argc, char **argv)
{
  int index;
  int rc;
  mu_stream_t in, tmp;
  mu_message_t msg;
  mu_header_t hdr;
  mu_iterator_t itr;
  const char *file;
  char *newval;
  mu_off_t size;
  mu_body_t body;
  mu_stream_t bstr;
  
  MU_APP_INIT_NLS ();
  
  mh_argp_init ();
  mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc,
		 opt_handler, NULL, &index);

  if (index == argc)
    {
      mu_error (_("file name not given"));
      exit (1);
    }
  file = argv[index];

  prompter_init ();
  if (erase_seq)
    prompter_set_erase (erase_seq);
  if (kill_seq)
    prompter_set_erase (kill_seq);

  if ((rc = mu_stdio_stream_create (&strout, MU_STDOUT_FD, MU_STREAM_WRITE)))
    {
      mu_error (_("cannot open stdout: %s"), mu_strerror (rc));
      return 1;
    }
  
  if ((rc = mu_file_stream_create (&in, file, MU_STREAM_RDWR)))
    {
      mu_error (_("cannot open input file `%s': %s"),
		file, mu_strerror (rc));
      return 1;
    }
  rc = mu_stream_to_message (in, &msg);
  mu_stream_unref (in);
  if (rc)
    {
      mu_error (_("input stream %s is not a message (%s)"),
		file, mu_strerror (rc));
      return 1;
    }
  
  if ((rc = mu_temp_file_stream_create (&tmp, NULL, 0))) 
    {
      mu_error (_("Cannot open temporary file: %s"),
		mu_strerror (rc));
      return 1;
    }

  /* Copy headers */
  mu_message_get_header (msg, &hdr);
  mu_header_get_iterator (hdr, &itr);
  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      const char *name, *val;
      
      mu_iterator_current_kv (itr, (const void **)&name, (void**)&val);
      if (!is_empty_string (val))
	{
	  mu_stream_printf (tmp, "%s: %s\n", name, val);
	  mu_stream_printf (strout, "%s: %s\n", name, val);
	}
      else
	{
	  int cont = 0;
	  mu_opool_t opool;
	  const char *prompt = name;
	  
	  mu_opool_create (&opool, 1);
	  do
	    {
	      size_t len;
	      char *p;
	      p = prompter_get_value (prompt);
	      if (!p)
		return 1;
	      prompt = NULL;
	      if (cont)
		{
		  mu_opool_append_char (opool, '\n');
		  if (!mu_isspace (p[0]))
		    mu_opool_append_char (opool, '\t');
		}
	      len = strlen (p);
	      if (len > 0 && p[len-1] == '\\')
		{
		  len--;
		  cont = 1;
		}
	      else
		cont = 0;
	      mu_opool_append (opool, p, len);
	      free (p);
	    }
	  while (cont);

	  mu_opool_append_char (opool, 0);
	  newval = mu_opool_finish (opool, NULL);
	  if (!is_empty_string (newval))
	    mu_stream_printf (tmp, "%s: %s\n", name, newval);
	  mu_opool_destroy (&opool);
	}
    }
  mu_iterator_destroy (&itr);
  mu_stream_printf (strout, "--------\n");
  mu_stream_write (tmp, "\n", 1, NULL);

  /* Copy body */
  
  if (prepend_option)
    {
      mu_stream_printf (strout, "\n--------%s\n\n", _("Enter initial text"));
      while ((newval = prompter_get_line ()))
	{
	  mu_stream_write (tmp, newval, strlen (newval), NULL);
	  free (newval);
	  mu_stream_write (tmp, "\n", 1, NULL);
	}
    }

  mu_message_get_body (msg, &body);
  mu_body_get_streamref (body, &bstr);

  if (!prepend_option && !rapid_option)
    {
      mu_stream_copy (strout, bstr, 0, NULL);
      mu_stream_seek (bstr, 0, MU_SEEK_SET, NULL);
    }

  mu_stream_copy (tmp, bstr, 0, NULL);
  mu_stream_unref (bstr);

  if (!prepend_option && !rapid_option)
    {
      printf ("\n--------%s\n\n", _("Enter additional text"));
      while ((newval = prompter_get_line ()))
	{
	  mu_stream_write (tmp, newval, strlen (newval), NULL);
	  free (newval);
	  mu_stream_write (tmp, "\n", 1, NULL);
	}
    }

  /* Destroy the message */
  mu_message_destroy (&msg, mu_message_get_owner (msg));

  /* Rewind the streams and copy data back to in. */
  mu_stream_seek (in, 0, MU_SEEK_SET, NULL);
  mu_stream_seek (tmp, 0, MU_SEEK_SET, NULL);
  mu_stream_copy (in, tmp, 0, &size);
  mu_stream_truncate (in, size);

  mu_stream_destroy (&in);
  mu_stream_destroy (&tmp);
  mu_stream_destroy (&strout);

  prompter_done ();
  
  return 0;
}
예제 #9
0
void
message_display_parts (mu_message_t msg, int indent)
{
  int ret, j;
  size_t nparts;
  mu_message_t part;
  mu_header_t hdr;
  mu_stream_t str;
  mu_body_t body;
  int ismulti;
  size_t nbytes;

  /* How many parts does the message has? */
  if ((ret = mu_message_get_num_parts (msg, &nparts)) != 0)
    {
      fprintf (stderr, "mu_message_get_num_parts - %s\n", mu_strerror (ret));
      exit (2);
    }

  /* Iterate through all the parts.
     Treat type "message/rfc822" differently, since it is a message of
     its own that can have other subparts(recursive). */
  for (j = 1; j <= nparts; j++)
    {
      int status;
      const char *hvalue;
      char *type = NULL;
      const char *encoding = "";

      MU_ASSERT (mu_message_get_part (msg, j, &part));
      MU_ASSERT (mu_message_get_header (part, &hdr));
      status = mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE,
				     &hvalue);
      if (status == MU_ERR_NOENT)
	/* nothing */;
      else if (status != 0)
	mu_error ("Cannot get header value: %s", mu_strerror (status));
      else
	{
	  status = mu_mimehdr_aget_disp (hvalue, &type);
	  if (status)
	    mu_error ("Cannot extract content type field: %s",
		      mu_strerror (status));
	}
      printf ("%*.*sType of part %d = %s\n", indent, indent, "",
	      j, type ? type : "");
      print_message_part_sizes (part, indent);
      if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING,
				&encoding))
	encoding = "";
      ismulti = 0;
      if ((type
           && mu_c_strcasecmp (type, "message/rfc822") == 0)
          || (mu_message_is_multipart (part, &ismulti) == 0 && ismulti))
        {
          if (!ismulti)
	    MU_ASSERT (mu_message_unencapsulate (part, &part, NULL));
	  
          MU_ASSERT (mu_message_get_header (part, &hdr));
          if (mu_header_sget_value (hdr, MU_HEADER_FROM, &from))
	    from = "";
          if (mu_header_sget_value (hdr, MU_HEADER_SUBJECT, &subject))
	    subject = "";
          printf ("%*.*sEncapsulated message : %s\t%s\n",
                  indent, indent, "", from, subject);
          printf ("%*.*sBegin\n", indent, indent, "");
          message_display_parts (part, indent + indent_level);
          mu_message_destroy (&part, NULL);
        }
      else if (!type
               || (mu_c_strcasecmp (type, "text/plain") == 0)
               || (mu_c_strcasecmp (type, "text/html")) == 0)
	{
	  printf ("%*.*sText Message\n", indent, indent, "");
          printf ("%*.*sBegin\n", indent, indent, "");
          mu_message_get_body (part, &body);
          mu_body_get_streamref (body, &str);
          /* Make sure the original body stream is not closed when
             str gets destroyed */
          mu_filter_create (&str, str, encoding, MU_FILTER_DECODE,
			    MU_STREAM_READ);
	  
	  while (mu_stream_readline (str, buf, sizeof (buf), &nbytes) == 0
		 && nbytes)
            {
              printf ("%*.*s%s", indent, indent, "", buf);
            }
          mu_stream_destroy (&str);
        }
      else
        {
          /* Save the attachements.  */
          char *fname = NULL;

          mu_message_aget_decoded_attachment_name (part, charset,
						   &fname, NULL);
          if (fname == NULL)
            fname = mu_tempname (NULL);

          printf ("%*.*sAttachment - saving [%s]\n", indent, indent, "",
                  fname);
          printf ("%*.*sBegin\n", indent, indent, "");
          if (charset)
	    {
	      mu_mime_io_buffer_t info;
	      mu_mime_io_buffer_create (&info);
	      mu_mime_io_buffer_set_charset (info, charset);
	      MU_ASSERT (mu_message_save_attachment (part, NULL, info));
	      mu_mime_io_buffer_destroy (&info);
	    }
	  else
	    MU_ASSERT (mu_message_save_attachment (part, fname, NULL));
          if (print_attachments)
            print_file (fname, indent);
          free (fname);
        }
      printf ("\n%*.*sEnd\n", indent, indent, "");
      free (type);
    }
}
예제 #10
0
파일: mbox.c 프로젝트: ssvlab/esbmc-gpu
/* FIXME: Do we need to escape body line that begins with "From "? This
   will require reading the body line by line instead of by chunks,
   considerably hurting perfomance when expunging.  But should not this
   be the responsibility of the client ?  */
static int
mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
		      int is_expunging, int first)
{
  mbox_data_t mud = mailbox->data;
  int status = 0;
  size_t n = 0;
  char nl = '\n';
  size_t orig_size = *psize;
  char *s;
  
  switch (mud->state)
    {
    case MBOX_NO_STATE:
      mud->off = 0;
      mud->state = MBOX_STATE_APPEND_SENDER;

    case MBOX_STATE_APPEND_SENDER:
      /* Generate the sender for the "From " separator.  */
      {
	char *s;
	mu_envelope_t envelope = NULL;
	mu_message_get_envelope (msg, &envelope);
	status = mu_envelope_aget_sender (envelope, &mud->sender);
	switch (status) {
	case 0:
	  break;
	  
	case EAGAIN:
	  return status;

	case MU_ERR_NOENT: /* Envelope headers not found: try to guess */
	  free (mud->sender);
          mud->sender = NULL;
	  status = restore_sender (msg, mud);
	  if (status == 0)
            break;
	  
	default:
	  free (mud->sender);
	  free (mud->date);
	  mud->date = mud->sender = NULL;
	  mud->state = MBOX_NO_STATE;
	  return status;
	}

	/* Nuke trailing newline.  */
	s = strchr (mud->sender, nl);
	if (s)
	  *s = '\0';
	mud->state = MBOX_STATE_APPEND_DATE;
      }

    case MBOX_STATE_APPEND_DATE:
      /* Generate a date for the "From "  separator.  */
      {
	mu_envelope_t envelope = NULL;
	const char *envarr[5];
	
	mu_message_get_envelope (msg, &envelope);
	status = mu_envelope_aget_date (envelope, &mud->date);
	switch (status) {
	case 0:
	  break;
	  
	case EAGAIN:
	  return status;

	case MU_ERR_NOENT: /* Envelope headers not found: try to guess */
	  free (mud->date);
          mud->date = NULL;
	  status = restore_date (msg, mud);
	  if (status == 0)
	    break;
	  
	default:
	  free (mud->sender);
	  free (mud->date);
	  mud->date = mud->sender = NULL;
	  mud->state = MBOX_NO_STATE;
	  return status;
	}

	/* Nuke trailing newline.  */
	s = strchr (mud->date, nl);
	if (s)
	  *s = '\0';

	/* Write the separator to the mailbox.  */
	envarr[0] = "From ";
	envarr[1] = mud->sender;
	envarr[2] = " ";
	envarr[3] = mud->date;
	envarr[4] = "\n";
	
	status = write_array (mailbox->stream, psize, 5, envarr);
	if (status)
	  break;

	free (mud->sender);
	free (mud->date);
	mud->sender = mud->date = NULL;
	/* If we are not expunging get the message in one block via the stream
	   message instead of the header/body.  This is good for POP where
	   there is no separation between header and body(RETR).  */
	if (! is_expunging)
	  {
	    mud->state = MBOX_STATE_APPEND_MESSAGE;
	    break;
	  }
	mud->state = MBOX_STATE_APPEND_HEADER;
      }

    case MBOX_STATE_APPEND_HEADER:
      /* Append the Header.  */
      {
	char buffer[1024];
	size_t nread = 0;
	mu_stream_t is = NULL;
	mu_header_t header = NULL;
	mu_message_get_header (msg, &header);
	mu_header_get_stream (header, &is);
	do
	  {
	    status = mu_stream_readline (is, buffer, sizeof (buffer), mud->off,
					 &nread);
	    if (status != 0)
	      {
		if (status != EAGAIN)
		  {
		    mud->state = MBOX_NO_STATE;
		    mud->off = 0;
		  }
		mu_stream_truncate (mailbox->stream, orig_size);
		return status;
	      }
	    mud->off += nread;
	    if (*buffer == '\n')
	      break;

	    /* We do not copy the Status since it is rewritten by the
	       attribute code below. Ditto for X-UID and X-IMAPBase.
	       FIXME:
	       - We have a problem here the header may not fit the buffer.
	       - Should  we skip the IMAP "X-Status"? */
	    if ((mu_c_strncasecmp (buffer, "Status", 6) == 0)
		|| (mu_c_strncasecmp (buffer, "X-IMAPbase", 10) == 0)
		/* FIXME: isn't the length of "X-UID" 5, not 4? And
		 this will match X-UID and X-UIDL, is this intended? */
		|| (mu_c_strncasecmp (buffer, "X-UID", 4) == 0
		    && (buffer[5] == ':' || buffer[5] == ' '
			|| buffer[5] == '\t')))
	      continue;

	    status = mu_stream_write (mailbox->stream, buffer, nread,
				      *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	while (nread > 0);
	mud->off = 0;

	/* Rewrite the X-IMAPbase marker. */
	if (first && is_expunging)
	  {
	    n = sprintf (buffer, "X-IMAPbase: %lu %u\n",
			 (unsigned long) mud->uidvalidity,
			 (unsigned) mud->uidnext);
	    status = mu_stream_write (mailbox->stream, buffer, n, *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	mud->state = MBOX_STATE_APPEND_ATTRIBUTE;
      }

      case MBOX_STATE_APPEND_ATTRIBUTE:
      /* Put the new attributes.  */
      {
#define STATUS_PREFIX_LEN (sizeof(MU_HEADER_STATUS) - 1 + 2)
	char abuf[STATUS_PREFIX_LEN + MU_STATUS_BUF_SIZE + 1];
	size_t na = 0;
	mu_attribute_t attr = NULL;

	strcpy(abuf, MU_HEADER_STATUS);
	strcat(abuf, ": ");
	mu_message_get_attribute (msg, &attr);
	mu_attribute_to_string (attr, abuf + STATUS_PREFIX_LEN, 
	                        sizeof(abuf) - STATUS_PREFIX_LEN - 1, &na);
	strcat (abuf, "\n");
	na = strlen (abuf);
	mu_stream_write (mailbox->stream, abuf, na, *psize, &n);
	if (status != 0)
	  break;
	*psize += n;

	mud->state = MBOX_STATE_APPEND_UID;
      }

    case MBOX_STATE_APPEND_UID:
      /* The new X-UID. */
      {
	char suid[64];
	size_t uid = 0;
	if (is_expunging)
	  {
	    status = mu_message_get_uid (msg, &uid);
	    if (status == EAGAIN)
	      return status;
	  }
	else
	  uid = mud->uidnext++;

	if (status == 0 || uid != 0)
	  {
	    n = sprintf (suid, "X-UID: %u\n", (unsigned) uid);
	    /* Put the UID.  */
	    status = mu_stream_write (mailbox->stream, suid, n, *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }

	/* New line separator of the Header.  */
	status = mu_stream_write (mailbox->stream, &nl , 1, *psize, &n);
	if (status)
	  break;
	*psize += n;
	mud->state = MBOX_STATE_APPEND_BODY;
      }

    case MBOX_STATE_APPEND_BODY:
      /* Append the Body.  */
      {
	char buffer[1024];
	size_t nread = 0;
	mu_stream_t is = NULL;
	mu_body_t body = NULL;
	mu_message_get_body (msg, &body);
	mu_body_get_stream (body, &is);
	do
	  {
	    status = mu_stream_read (is, buffer, sizeof (buffer), mud->off,
				     &nread);
	    if (status != 0)
	      {
		if (status != EAGAIN)
		  {
		    mud->state = MBOX_NO_STATE;
		    mud->off = 0;
		  }
		return status;
	      }
	    mud->off += nread;
	    status = mu_stream_write (mailbox->stream, buffer, nread,
				      *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	while (nread > 0);
	mud->off = 0;
	n = 0;
	status = mu_stream_write (mailbox->stream, &nl, 1, *psize, &n);
	if (status)
	  break;
	*psize += n;
      }

    default:
      break;
    }

  /* If not expunging we are taking the stream message.  */
  if (!is_expunging)
    {
      switch (mud->state)
        {
	case MBOX_STATE_APPEND_MESSAGE:
	  {
	    /* Append the Message.  */
	    char buffer[1024];
	    size_t nread = 0;
	    mu_stream_t is = NULL;
	    mu_message_get_stream (msg, &is);
	    do
	      {
		status = mu_stream_read (is, buffer, sizeof (buffer), mud->off,
				      &nread);
		if (status != 0)
		  {
		    if (status != EAGAIN)
		      {
			mud->state = MBOX_NO_STATE;
			mud->off = 0;
		      }
		    mu_stream_truncate (mailbox->stream, orig_size);
		    return status;
		  }
		status = mu_stream_write (mailbox->stream, buffer, nread,
					  *psize, &n);
		if (status)
		  break;
		mud->off += nread;
		*psize += n;
	      }
	    while (nread > 0);
	    if (status)
	      break;
       	    status = mu_stream_write (mailbox->stream, &nl, 1, *psize, &n);
	    if (status == 0)
	      *psize += n;
	  }

	default:
	  break;
	}
    } /* is_expunging */
  mud->state = MBOX_NO_STATE;
  if (status)
    mu_stream_truncate (mailbox->stream, orig_size);
  else
    mu_stream_flush (mailbox->stream);
  return status;
}
예제 #11
0
int
mu_progmailer_send (struct _mu_progmailer *pm, mu_message_t msg)
{
  int status;
  mu_stream_t stream = NULL;
  char buffer[512];
  size_t len = 0;
  int rc;
  mu_header_t hdr;
  mu_body_t body;
  int found_nl = 0;
  int exit_status;
	
  if (!pm || !msg)
    return EINVAL;
  mu_message_get_header (msg, &hdr);
  status = mu_header_get_streamref (hdr, &stream);
  if (status)
    {
      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		("cannot get header stream: %s", mu_strerror (status)));
      return status;
    }
  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE, ("Sending headers..."));
  mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
  while ((status = mu_stream_readline (stream, buffer, sizeof (buffer),
				       &len)) == 0
	 && len != 0)
    {
      if (mu_c_strncasecmp (buffer, MU_HEADER_FCC, sizeof (MU_HEADER_FCC) - 1))
	{
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_PROT, ("Header: %s", buffer));
	  if (write (pm->fd, buffer, len) == -1)
	    {
	      status = errno;
	      
	      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
			("write failed: %s", strerror (status)));
	      break;
	    }
	}
      found_nl = (len == 1 && buffer[0] == '\n');
    }

  if (!found_nl)
    {
      if (write (pm->fd, "\n", 1) == -1)
	{
	  status = errno;
		
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		    ("write failed: %s", strerror (status)));
	}
    }
  mu_stream_destroy (&stream);
  
  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE, ("Sending body..."));
  mu_message_get_body (msg, &body);
  status = mu_body_get_streamref (body, &stream);
  if (status)
    {
      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		("cannot get body stream: %s\n", mu_strerror (status)));
      return status;
    }

  mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
  while ((status = mu_stream_read (stream, buffer, sizeof (buffer),
				   &len)) == 0
	 && len != 0)
    {
      if (write (pm->fd, buffer, len) == -1)
	{
	  status = errno;
	  
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
		    ("write failed: %s\n", strerror (status)));
	  break;
	}
    }
  mu_body_get_streamref (body, &stream);

  close (pm->fd);

  rc = waitpid (pm->pid, &exit_status, 0);
  if (status == 0)
    {
      if (rc < 0)
	{
	  if (errno == ECHILD)
	    status = 0;
	  else
	    { 
	      status = errno;
	      mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
			("waitpid(%lu) failed: %s\n",
			 (unsigned long) pm->pid, strerror (status)));
	    }
	}
      else if (WIFEXITED (exit_status))
	{
	  exit_status = WEXITSTATUS (exit_status);
	  mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE,
		    ("%s exited with: %d\n",
		     pm->command, exit_status));
	  status = (exit_status == 0) ? 0 : MU_ERR_PROCESS_EXITED;
	}
      else if (WIFSIGNALED (exit_status))
	status = MU_ERR_PROCESS_SIGNALED;
      else
	status = MU_ERR_PROCESS_UNKNOWN_FAILURE;
    }
  pm->pid = -1;
  return status;
}