Пример #1
0
/* Check whether an alias from ADDRESSES is part of To: or Cc: headers
   of the originating mail. Return non-zero if so and store a pointer
   to the matching address to *MY_ADDRESS. */
static int
match_addresses (mu_header_t hdr, mu_sieve_value_t *addresses,
		 char **my_address)
{
  int match = 0;
  const char *str;
  struct addr_data ad;

  ad.my_address = NULL;
  if (mu_header_sget_value (hdr, MU_HEADER_TO, &str) == 0)
    {
      if (!mu_address_create (&ad.addr, str))
	{
	  match += mu_sieve_vlist_do (addresses, _compare, &ad);
	  mu_address_destroy (&ad.addr);
	}
    }

  if (!match && mu_header_sget_value (hdr, MU_HEADER_CC, &str) == 0)
    {
      if (!mu_address_create (&ad.addr, str))
	{
	  match += mu_sieve_vlist_do (addresses, _compare, &ad);
	  mu_address_destroy (&ad.addr);
	}
    }
  *my_address = ad.my_address;
  return match;
}
Пример #2
0
static int
message_envelope_sender (mu_envelope_t envelope, char *buf, size_t len,
			 size_t *pnwrite)
{
  mu_message_t msg = mu_envelope_get_owner (envelope);
  mu_header_t header;
  int status;
  const char *sender;
  struct mu_auth_data *auth = NULL;
  static char *hdrnames[] = {
    "X-Envelope-Sender",
    "X-Envelope-From",
    "X-Original-Sender",
    "From",
    NULL
  };
  mu_address_t address = NULL;

  if (msg == NULL)
    return EINVAL;

  /* First, try the header  */
  status = mu_message_get_header (msg, &header);
  if (status)
    return status;
  status = mu_header_sget_firstof (header, hdrnames, &sender, NULL);
  if (status)
    {
      auth = mu_get_auth_by_uid (getuid ());
      if (!auth)
	return MU_ERR_NOENT;
      sender = auth->name;
    }

  status = mu_address_create (&address, sender);
  if (status == 0)
    {
      status = mu_address_sget_email (address, 1, &sender);
      if (status == 0)
	{
	  size_t n = strlen (sender);
	  if (buf && len > 0)
	    {
	      len--; /* One for the null.  */
	      n = (n < len) ? n : len;
	      memcpy (buf, sender, n);
	      buf[n] = '\0';
	    }
	  if (pnwrite)
	    *pnwrite = n;
	}
      mu_address_destroy (&address);
    }
  
  if (auth)
    mu_auth_data_free (auth);

  return status;
}
Пример #3
0
int
add_recipient (const char *name)
{
  mu_address_t addr;
  int status;
    
  status = mu_address_create (&addr, name);
  if (status == 0)
    status = mu_address_union (&recipients, addr);
  mu_address_destroy (&addr);
  return status;
}
Пример #4
0
static void
annotate (struct mh_whatnow_env *wh)
{
  mu_message_t msg;
  mu_address_t addr = NULL;
  size_t i, count;
  
  if (!wh->anno_field || !wh->anno_list)
    return;
  
  msg = mh_file_to_message (NULL, wh->file);
  if (!msg)
    return;
  
  mh_expand_aliases (msg, &addr, NULL, NULL);
  mu_address_get_count (addr, &count);
  for (i = 1; i <= count; i++)
    {
      mu_address_t subaddr;

      if (mu_address_get_nth (addr, i, &subaddr) == 0)
	{
	  size_t size;
	  struct anno_data d;

	  mu_address_to_string (subaddr, NULL, 0, &size);
	  d.value = xmalloc (size + 1);
	  d.field = wh->anno_field;
	  d.date = i == 1;
	  mu_address_to_string (subaddr, d.value, size + 1, NULL);
	  mu_list_do (wh->anno_list, anno, &d);
	  free (d.value);
	  mu_address_destroy (&subaddr);
	}
    }
  mu_address_destroy (&addr);
  mu_message_destroy (&msg, NULL);
}
Пример #5
0
static void
send_address_add (mu_address_t *paddr, const char *value)
{
  mu_address_t addr = NULL;
  int rc;

  rc = mu_address_create (&addr, value);
  if (rc)
    {
      mu_error (_("%s: %s"), value, mu_strerror (rc));
      exit (1);
    }
  MU_ASSERT (mu_address_union (paddr, addr));
  mu_address_destroy (&addr);
}
Пример #6
0
int
mu_set_user_email (const char *candidate)
{
  int err = 0;
  mu_address_t addr = NULL;
  size_t emailno = 0;
  char *email = NULL;
  const char *domain = NULL;

  if (!candidate)
    {
      free (mu_user_email);
      mu_user_email = NULL;
      return 0;
    }
  
  if ((err = mu_address_create (&addr, candidate)) != 0)
    return err;

  if ((err = mu_address_get_email_count (addr, &emailno)) != 0)
    goto cleanup;

  if (emailno != 1)
    {
      errno = EINVAL;
      goto cleanup;
    }

  if ((err = mu_address_aget_email (addr, 1, &email)) != 0)
    goto cleanup;

  free (mu_user_email);

  mu_user_email = email;

  if ((err = mu_address_sget_domain (addr, 1, &domain)) == 0)
    mu_set_user_email_domain (domain);
  
cleanup:
  mu_address_destroy (&addr);

  return err;
}
Пример #7
0
static int
_count_items (void *item, void *data)
{
  char *name = item;
  struct val_ctr *vp = data;
  char *val;
  mu_address_t addr;
  size_t count = 0;
  
  if (mu_header_aget_value (vp->hdr, name, &val))
    return 0;
  if (mu_address_create (&addr, val) == 0)
    {
      mu_address_get_count (addr, &count);
      mu_address_destroy (&addr);
      vp->count += count;
    }
  free (val);
  return vp->count >= vp->limit;
}
Пример #8
0
int
restore_sender (mu_message_t msg, mbox_data_t mud)
{
  mu_header_t hdr;
  char *from = NULL;
  int rc = 0;
  
  if (mu_message_get_header (msg, &hdr) == 0)
    mu_header_aget_value (hdr, MU_HEADER_FROM, &from);

  if (from)
    {
      int status;
      mu_address_t addr;
      
      status = mu_address_create (&addr, from);
      free (from);
      from = NULL;
      if (status == 0)
	mu_address_aget_email (addr, 1, &from);
      mu_address_destroy (&addr);
    }

  if (!from)
    {
      from = strdup (PACKAGE);
      if (!from) 
	return ENOMEM;
    }

  mud->sender = strdup (from);
  if (!mud->sender)
    rc = ENOMEM;
  free (from);
  return rc;
}
Пример #9
0
/* Generate and send the reply message */
static int
vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
		char *text, char *to, char *from)
{
  mu_mime_t mime = NULL;
  mu_message_t newmsg;
  mu_header_t newhdr;
  mu_address_t to_addr = NULL, from_addr = NULL;
  char *value;
  mu_mailer_t mailer;
  int rc;

  if (mu_sieve_tag_lookup (tags, "file", NULL))
    {
      mu_stream_t instr;
      
      rc = mu_mapfile_stream_create (&instr, text, MU_STREAM_READ);
      if (rc)
	{
	  mu_sieve_error (mach,
			  _("%lu: cannot open message file %s: %s"),
			  (unsigned long) mu_sieve_get_message_num (mach),
			  text,
			  mu_strerror (rc));
	  return -1;
	}
      rc = mu_stream_to_message (instr, &newmsg);
      mu_stream_unref (instr);
      if (rc)
	{
	  mu_sieve_error (mach,
			  _("%lu: cannot read message from file %s: %s"),
			  (unsigned long) mu_sieve_get_message_num (mach),
			  text,
			  mu_strerror (rc));
	  return -1;
	} 
    }
  else
    {
      if (build_mime (mach, tags, &mime, msg, text))
	return -1;
      mu_mime_get_message (mime, &newmsg);
      mu_message_unref (newmsg);
      mu_message_get_header (newmsg, &newhdr);
    }
  
  rc = mu_address_create (&to_addr, to);
  if (rc)
    {
      mu_sieve_error (mach,
		      _("%lu: cannot create recipient address <%s>: %s"),
		      (unsigned long) mu_sieve_get_message_num (mach),
		      from, mu_strerror (rc));
    }
  else
    {
      mu_header_set_value (newhdr, MU_HEADER_TO, to, 0);
      
      vacation_subject (mach, tags, msg, newhdr);
      
      if (from)
        {
          if (mu_address_create (&from_addr, from))
	    from_addr = NULL;
        }
      else
        {
          from_addr = NULL;
        }
      
      if (mu_rfc2822_in_reply_to (msg, &value) == 0)
        {
          mu_header_set_value (newhdr, MU_HEADER_IN_REPLY_TO, value, 1);
          free (value);
        }
      
      if (mu_rfc2822_references (msg, &value) == 0)
        {
          mu_header_set_value (newhdr, MU_HEADER_REFERENCES, value, 1);
          free (value);
        }
      
      mailer = mu_sieve_get_mailer (mach);
      if (mailer)
	{
	  rc = mu_mailer_send_message (mailer, newmsg, from_addr, to_addr);
	}
      else
	rc = MU_ERR_FAILURE;
    }
  mu_address_destroy (&to_addr);
  mu_address_destroy (&from_addr);
  mu_mime_destroy (&mime);
  return rc;
}
Пример #10
0
int
reply0 (msgset_t *mspec, mu_message_t msg, void *data)
{
  mu_header_t hdr;
  compose_env_t env;
  int status;
  char *str;

  set_cursor (mspec->msg_part[0]);
  
  compose_init (&env);

  mu_message_get_header (msg, &hdr);

  compose_header_set (&env, MU_HEADER_TO,
		      util_get_sender (mspec->msg_part[0], 0),
		      COMPOSE_SINGLE_LINE);

  if (*(int*) data) /* reply starts with a lowercase */
    {
      /* Add all recepients of the originate letter */

      mu_address_t addr = NULL;
      size_t i, count = 0;

      if (mu_header_aget_value (hdr, MU_HEADER_TO, &str) == 0)
	{
	  mu_address_create (&addr, str);
	  free (str);
	  mu_address_get_count (addr, &count);
	}

      /* Make sure we do not include our alternate names */
      for (i = 1; i <= count; i++)
	{
	  const char *email;
	  if (mu_address_sget_email (addr, i, &email) || email == NULL)
	    continue;
	  if ((mailvar_get (NULL, "metoo", mailvar_type_boolean, 0) == 0)
	      || !mail_is_my_name (email))
	    compose_header_set (&env, MU_HEADER_TO,
				email,
				COMPOSE_SINGLE_LINE);
	}
      
      mu_address_destroy (&addr);

      /* Finally, add any Ccs */
      if (mu_header_aget_value (hdr, MU_HEADER_CC, &str) == 0)
	compose_header_set (&env, MU_HEADER_TO, str, COMPOSE_SINGLE_LINE);
    }

  if (mu_header_aget_value (hdr, MU_HEADER_SUBJECT, &str) == 0)
    {
      char *p = NULL;
      
      if (mu_unre_subject (str, NULL))
	util_strcat (&p, util_reply_prefix ());
      util_strcat (&p, str);
      free (str);
      compose_header_set (&env, MU_HEADER_SUBJECT, p, COMPOSE_REPLACE);
      free (p);
    }
  else
    compose_header_set (&env, MU_HEADER_SUBJECT, "", COMPOSE_REPLACE);

  mu_printf ("To: %s\n",
	   compose_header_get (&env, MU_HEADER_TO, ""));
  str = compose_header_get (&env, MU_HEADER_CC, NULL);
  if (str)
    mu_printf ("Cc: %s\n", str);
  mu_printf ("Subject: %s\n\n",
		    compose_header_get (&env, MU_HEADER_SUBJECT, ""));
  
  make_in_reply_to (&env, msg);
  make_references (&env, msg);
  status = mail_send0 (&env,
		       mailvar_get (NULL, "byname", mailvar_type_boolean, 0)
		                     == 0);
  compose_destroy (&env);

  return status;
}
Пример #11
0
void
smtp (int fd)
{
  int state, c;
  char *buf = NULL;
  size_t size = 0;
  mu_mailbox_t mbox;
  mu_message_t msg;
  char *tempfile;
  char *rcpt_addr;
  
  in = fdopen (fd, "r");
  out = fdopen (fd, "w");
  SETVBUF (in, NULL, _IOLBF, 0);
  SETVBUF (out, NULL, _IOLBF, 0);

  smtp_reply (220, "Ready");
  for (state = STATE_INIT; state != STATE_QUIT; )
    {
      int argc;
      char **argv;
      int kw, len;
      
      if (getline (&buf, &size, in) == -1)
	exit (1);
      len = strlen (buf);
      while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r'))
	len --;
      buf[len] = 0;
      
      if (mu_argcv_get (buf, "", NULL, &argc, &argv))
	exit (1);

      kw = smtp_kw (argv[0]);
      if (kw == KW_QUIT)
	{
	  smtp_reply (221, "Done");
	  state = STATE_QUIT;
	  mu_argcv_free (argc, argv);
	  continue;
	}
      
      switch (state)
	{
	case STATE_INIT:
	  switch (kw)
	    {
	    case KW_EHLO:
	    case KW_HELO:
	      if (argc == 2)
		{
		  smtp_reply (250, "pleased to meet you");
		  state = STATE_EHLO;
		}
	      else
		smtp_reply (501, "%s requires domain address", argv[0]);
	      break;

	    default:
	      smtp_reply (503, "Polite people say HELO first");
	      break;
	    }
	  break;
	  
	case STATE_EHLO:
	  switch (kw)
	    {
	    case KW_MAIL:
	      if (argc == 2)
		from_person = check_prefix (argv[1], "from:");
	      else if (argc == 3 && mu_c_strcasecmp (argv[1], "from:") == 0)
		from_person = argv[2];
	      else
		from_person = NULL;

	      if (from_person)
		{
		  from_person = strdup (from_person);
		  smtp_reply (250, "Sender OK");
		  state = STATE_MAIL;
		}
	      else
		smtp_reply (501, "Syntax error");
	      break;

	    default:
	      smtp_reply (503, "Need MAIL command");
	    }
	  break;
	  
	case STATE_MAIL:
	  switch (kw)
	    {
	    case KW_RCPT:
	      if (argc == 2)
		rcpt_addr = check_prefix (argv[1], "to:");
	      else if (argc == 3 && mu_c_strcasecmp (argv[1], "to:") == 0)
		rcpt_addr = argv[2];
	      else
		rcpt_addr = NULL;
	      
	      if (rcpt_addr)
		{
		  if (add_recipient (rcpt_addr))
		    smtp_reply (451, "Recipient not accepted");
		  else
		    {
		      smtp_reply (250, "Recipient OK");
		      state = STATE_RCPT;
		    }
		}
	      else
		smtp_reply (501, "Syntax error");
	      break;
	      
	    default:
	      smtp_reply (503, "Need RCPT command");
	    }
	  break;
	  
	case STATE_RCPT:
	  switch (kw)
	    {
	    case KW_RCPT:
	      if (argc == 2)
		rcpt_addr = check_prefix (argv[1], "to:");
	      else if (argc == 3 && mu_c_strcasecmp (argv[1], "to:") == 0)
		rcpt_addr = argv[2];
	      else
		rcpt_addr = NULL;
	      
	      if (rcpt_addr)
		{
		  if (add_recipient (rcpt_addr))
		    smtp_reply (451, "Recipient not accepted");
		  else
		    {
		      smtp_reply (250, "Recipient OK");
		      state = STATE_RCPT;
		    }
		}
	      else
		smtp_reply (501, "Syntax error");
	      break;

	    case KW_DATA:
	      smtp_reply (354,
			  "Enter mail, end with \".\" on a line by itself");
	      make_tmp (in, from_person, &tempfile);
	      if ((c = mu_mailbox_create_default (&mbox, tempfile)) != 0)
		{
		  mu_error ("%s: can't create mailbox %s: %s",
			    progname,
			    tempfile, mu_strerror (c));
		  unlink (tempfile);
		  exit (1);
		}

	      if ((c = mu_mailbox_open (mbox, MU_STREAM_RDWR)) != 0)
		{
		  mu_error ("%s: can't open mailbox %s: %s",
			    progname, 
			    tempfile, mu_strerror (c));
		  unlink (tempfile);
		  exit (1);
		}

	      mu_mailbox_get_message (mbox, 1, &msg);
	      if (message_finalize (msg, 0) == 0)
		mta_send (msg);
	      else
		smtp_reply (501, "can't send message"); /*FIXME: code?*/
	      unlink (tempfile);

	      mu_address_destroy (&recipients);
	      from_person = NULL;
	      
	      smtp_reply (250, "Message accepted for delivery");
	      state = STATE_EHLO;
	      break;

	    default:
	      smtp_reply (503, "Invalid command");
	      break;
	    }
	  break;

	}
      mu_argcv_free (argc, argv);
    }
    
  close (fd);
}
Пример #12
0
/* %f */
static char *
hdr_from (struct header_call_args *args, void *data)
{
  char *from = NULL;
  
  if (mailvar_get (NULL, "fromfield", mailvar_type_boolean, 0) == 0)
    {  
      mu_header_t hdr;
      
      mu_message_get_header (args->msg, &hdr);
      if (mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
	{
	  mu_address_t address = NULL;
	  if (mu_address_create (&address, from) == 0)
	    {
	      char *name;
	      const char *email;
	  
	      if (mu_address_sget_email (address, 1, &email) == 0)
		{
		  if (mailvar_get (NULL, "showto",
				   mailvar_type_boolean, 0) == 0
		      && mail_is_my_name (email))
		    {
		      char *tmp;

		      if (mu_header_aget_value_unfold (hdr, MU_HEADER_TO, 
						       &tmp) == 0)
			{
			  mu_address_t addr_to;
			  if (mu_address_create (&addr_to, tmp) == 0)
			    {
			      mu_address_destroy (&address);
			      address = addr_to;
			    }
			  free (tmp);
			}
		    }
		}
	      
	      if ((mu_address_aget_personal (address, 1, &name) == 0
		   && name)
		  || (mu_address_aget_email (address, 1, &name) == 0
		      && name))
		{
		  free (from);
		  from = name;
		}
	      mu_address_destroy (&address);
	    }
	}
      util_rfc2047_decode (&from);
    }
  else
    {
      mu_envelope_t env = NULL;
      const char *sender = "";
      
      if (mu_message_get_envelope (args->msg, &env) == 0)
	mu_envelope_sget_sender (env, &sender);
      from = strdup (sender);
    }

  header_buf_string (args, from);
  free (from);
  return args->buf;
}