imap-envelope.c revision 470d47a15c02471da1e3799fac5e263d0e377bf2
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina/* Copyright (C) 2002 Timo Sirainen */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "lib.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "ibuffer.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "temp-string.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "rfc822-address.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "imap-parser.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "imap-envelope.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina#include "imap-quote.h"
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastruct _MessagePartEnvelopeData {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina Pool pool;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina char *date, *subject;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina Rfc822Address *from, *sender, *reply_to;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina Rfc822Address *to, *cc, *bcc;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina char *in_reply_to, *message_id;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina};
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastatic Rfc822Address *parse_address(Pool pool, const char *value,
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina size_t value_len)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina Rfc822Address *ret;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_push();
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina ret = rfc822_address_parse(pool, t_strndup(value, value_len));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_pop();
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return ret;
488b455f6b7881ec108a127840b1c1f1523d937fMichal Židek}
488b455f6b7881ec108a127840b1c1f1523d937fMichal Židek
488b455f6b7881ec108a127840b1c1f1523d937fMichal Židekvoid imap_envelope_parse_header(Pool pool, MessagePartEnvelopeData **data,
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina const char *name,
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina const char *value, size_t value_len)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (*data == NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *data = p_new(pool, MessagePartEnvelopeData, 1);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->pool = pool;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (strcasecmp(name, "Date") == 0 && (*data)->date == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->date = imap_quote_value(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Subject") == 0 && (*data)->subject == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->subject = imap_quote_value(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "From") == 0 && (*data)->from == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->from = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Sender") == 0 && (*data)->sender == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->sender = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Reply-To") == 0 && (*data)->reply_to == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->reply_to = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "To") == 0 && (*data)->to == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->to = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Cc") == 0 && (*data)->cc == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->cc = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Bcc") == 0 && (*data)->bcc == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->bcc = parse_address(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "In-Reply-To") == 0 &&
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->in_reply_to == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->in_reply_to = imap_quote_value(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (strcasecmp(name, "Message-Id") == 0 &&
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->message_id == NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina (*data)->message_id = imap_quote_value(pool, value, value_len);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina}
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastatic void imap_write_address(TempString *str, Rfc822Address *addr)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (addr == NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, "NIL");
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '(');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina while (addr != NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '(');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, imap_quote_str_nil(addr->name));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, imap_quote_str_nil(addr->route));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, imap_quote_str_nil(addr->mailbox));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, imap_quote_str_nil(addr->domain));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ')');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina addr = addr->next;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ')');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina}
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinavoid imap_envelope_write_part_data(MessagePartEnvelopeData *data,
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina TempString *str)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, NVL(data->date, "NIL"));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, NVL(data->subject, "NIL"));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, data->from);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, NVL(data->sender, data->from));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, NVL(data->reply_to, data->from));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, data->to);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, data->cc);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_write_address(str, data->bcc);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, NVL(data->in_reply_to, "NIL"));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, NVL(data->message_id, "NIL"));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina}
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinaconst char *imap_envelope_get_part_data(MessagePartEnvelopeData *data)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina TempString *str;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina str = t_string_new(2048);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina imap_envelope_write_part_data(data, str);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return str->str;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina}
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastatic int imap_address_arg_append(ImapArg *arg, TempString *str, int *in_group)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina ImapArgList *list;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina const char *args[4];
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina int i;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (arg->type != IMAP_ARG_LIST)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return FALSE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina list = arg->data.list;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina /* we require 4 arguments, strings or NILs */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (list->size < 4)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return FALSE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina for (i = 0; i < 4; i++) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (list->args[i].type == IMAP_ARG_NIL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina args[i] = NULL;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else if (list->args[i].type == IMAP_ARG_STRING)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina args[i] = list->args[i].data.str;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina else
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return FALSE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (str->len > 0)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, ", ");
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (*in_group) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[0] == NULL && args[1] == NULL &&
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina args[2] == NULL && args[3] == NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina /* end of group */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ';');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *in_group = FALSE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return TRUE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina } else {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[0] == NULL && args[1] == NULL &&
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina args[2] != NULL && args[3] == NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina /* beginning of group */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, args[2]);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, ": ");
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *in_group = TRUE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return TRUE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina /* name <@route:mailbox@domain> */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[0] != NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, args[0]);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ' ');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '<');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[1] != NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '@');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, args[1]);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, ':');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[2] != NULL)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, args[2]);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (args[3] != NULL) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '@');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append(str, args[3]);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina t_string_append_c(str, '>');
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return TRUE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina}
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastatic const char *imap_envelope_parse_address(ImapArg *arg)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina{
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina ImapArgList *list;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina TempString *str;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina size_t i;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina int in_group;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (arg->type != IMAP_ARG_LIST)
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return NULL;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina in_group = FALSE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina str = t_string_new(128);
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina list = arg->data.list;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina for (i = 0; i < list->size; i++) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (!imap_address_arg_append(&list->args[i], str, &in_group))
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return NULL;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
return str->str;
}
static const char *
imap_envelope_parse_arg(ImapArg *arg, ImapEnvelopeField field,
const char *envelope)
{
const char *value;
if (arg->type == IMAP_ARG_NIL)
return "";
if (field >= IMAP_ENVELOPE_FROM && field <= IMAP_ENVELOPE_BCC)
value = imap_envelope_parse_address(arg);
else if (arg->type == IMAP_ARG_STRING || arg->type == IMAP_ARG_ATOM)
value = t_strdup(arg->data.str);
else
value = NULL;
if (value == NULL) {
i_error("Invalid field %u in IMAP envelope: %s",
field, envelope);
}
return value;
}
const char *imap_envelope_parse(const char *envelope, ImapEnvelopeField field)
{
IBuffer *inbuf;
ImapParser *parser;
ImapArg *args;
const char *value;
int ret;
i_assert(field < IMAP_ENVELOPE_FIELDS);
inbuf = i_buffer_create_from_data(data_stack_pool, envelope,
strlen(envelope));
parser = imap_parser_create(inbuf, NULL, 0);
(void)i_buffer_read(inbuf);
ret = imap_parser_read_args(parser, field+1, 0, &args);
if (ret > (int)field) {
value = imap_envelope_parse_arg(&args[field], field, envelope);
} else {
i_error("Error parsing IMAP envelope: %s", envelope);
value = NULL;
}
imap_parser_destroy(parser);
i_buffer_unref(inbuf);
return value;
}