Beispiel #1
0
int mutt_resend_message (FILE *fp, CONTEXT *ctx, HEADER *cur)
{
  HEADER *msg = mutt_new_header ();
  
  if (mutt_prepare_template (fp, ctx, msg, cur, 1) < 0)
    return -1;
  
  return ci_send_message (SENDRESEND, msg, NULL, ctx, cur);
}
Beispiel #2
0
static void query_menu(char *buf, size_t buflen, QUERY *results, int retbuf)
{
    MUTTMENU *menu;
    HEADER *msg = NULL;
    ENTRY *QueryTable = NULL;
    QUERY *queryp = NULL;
    int i, done = 0;
    int op;
    char helpstr[LONG_STRING];
    char title[STRING];

    snprintf(title, sizeof(title), _("Query")); /* FIXME */

    menu = mutt_new_menu(MENU_QUERY);
    menu->make_entry = query_entry;
    menu->search = query_search;
    menu->tag = query_tag;
    menu->title = title;
    menu->help = mutt_compile_help(helpstr,
                                   sizeof(helpstr),
                                   MENU_QUERY,
                                   QueryHelp);

    if (results == NULL) {
        /* Prompt for Query */
        if ((mutt_get_field(_("Query: "), buf, buflen, 0) == 0)
            && buf[0]) {
            results = run_query(buf, 0);
        }
    }

    if (results) {
        snprintf(title, sizeof(title), _("Query '%s'"), buf);

        /* count the number of results */
        for (queryp = results; queryp; queryp = queryp->next)
            menu->max++;

        menu->data = QueryTable =
                         (ENTRY *)safe_calloc(menu->max, sizeof(ENTRY));

        for (i = 0, queryp = results; queryp; queryp = queryp->next, i++)
            QueryTable[i].data = queryp;

        while (!done) {
            switch ((op = mutt_menuLoop(menu))) {
            case OP_QUERY_APPEND:
            case OP_QUERY:

                if ((mutt_get_field(_("Query: "), buf, buflen, 0) == 0)
                    && buf[0]) {
                    QUERY *newresults = NULL;

                    newresults = run_query(buf, 0);

                    menu->redraw = REDRAW_FULL;

                    if (newresults) {
                        snprintf(title, sizeof(title), _("Query '%s'"), buf);

                        if (op == OP_QUERY) {
                            free_query(&results);
                            results = newresults;
                            safe_free(&QueryTable);
                        } else {
                            /* append */
                            for (queryp = results; queryp->next;
                                 queryp = queryp->next) ;

                            queryp->next = newresults;
                        }


                        menu->current = 0;
                        mutt_menuDestroy(&menu);
                        menu = mutt_new_menu(MENU_QUERY);
                        menu->make_entry = query_entry;
                        menu->search = query_search;
                        menu->tag = query_tag;
                        menu->title = title;
                        menu->help = mutt_compile_help(helpstr,
                                                       sizeof(helpstr),
                                                       MENU_QUERY,
                                                       QueryHelp);

                        /* count the number of results */
                        for (queryp = results; queryp; queryp = queryp->next)
                            menu->max++;

                        if (op == OP_QUERY) {
                            menu->data = QueryTable =
                                             (ENTRY *)safe_calloc(menu->max,
                                                                  sizeof(ENTRY));

                            for (i = 0, queryp = results; queryp;
                                 queryp = queryp->next, i++)
                                QueryTable[i].data = queryp;
                        } else {
                            int clear = 0;

                            /* append */
                            safe_realloc(&QueryTable,
                                         menu->max * sizeof(ENTRY));

                            menu->data = QueryTable;

                            for (i = 0, queryp = results; queryp;
                                 queryp = queryp->next, i++) {
                                /* once we hit new entries, clear/init the tag
                                   */
                                if (queryp == newresults)
                                    clear = 1;

                                QueryTable[i].data = queryp;

                                if (clear)
                                    QueryTable[i].tagged = 0;
                            }
                        }
                    }
                }
                break;

            case OP_CREATE_ALIAS:

                if (menu->tagprefix) {
                    ADDRESS *naddr = NULL;

                    for (i = 0; i < menu->max; i++)
                        if (QueryTable[i].tagged) {
                            ADDRESS *a = result_to_addr(QueryTable[i].data);
                            rfc822_append(&naddr, a, 0);
                            rfc822_free_address(&a);
                        }

                    mutt_create_alias(NULL, naddr);
                } else {
                    ADDRESS *a = result_to_addr(QueryTable[menu->current].data);
                    mutt_create_alias(NULL, a);
                    rfc822_free_address(&a);
                }
                break;

            case OP_GENERIC_SELECT_ENTRY:

                if (retbuf) {
                    done = 2;
                    break;
                }

            /* fall through to OP_MAIL */

            case OP_MAIL:
                msg = mutt_new_header();
                msg->env = mutt_new_envelope();

                if (!menu->tagprefix) {
                    msg->env->to =
                        result_to_addr(QueryTable[menu->current].data);
                } else {
                    for (i = 0; i < menu->max; i++)
                        if (QueryTable[i].tagged) {
                            ADDRESS *a = result_to_addr(QueryTable[i].data);
                            rfc822_append(&msg->env->to, a, 0);
                            rfc822_free_address(&a);
                        }
                }
                ci_send_message(0, msg, NULL, Context, NULL);
                menu->redraw = REDRAW_FULL;
                break;

            case OP_EXIT:
                done = 1;
                break;
            }
        }

        /* if we need to return the selected entries */
        if (retbuf
            && (done == 2)) {
            int tagged = 0;
            size_t curpos = 0;

            memset(buf, 0, buflen);

            /* check for tagged entries */
            for (i = 0; i < menu->max; i++) {
                if (QueryTable[i].tagged) {
                    if (curpos == 0) {
                        ADDRESS *tmpa = result_to_addr(QueryTable[i].data);
                        mutt_addrlist_to_local(tmpa);
                        tagged = 1;
                        rfc822_write_address(buf, buflen, tmpa, 0);
                        curpos = mutt_strlen(buf);
                        rfc822_free_address(&tmpa);
                    } else if (curpos + 2 < buflen) {
                        ADDRESS *tmpa = result_to_addr(QueryTable[i].data);
                        mutt_addrlist_to_local(tmpa);
                        strcat(buf, ", "); /* __STRCAT_CHECKED__ */
                        rfc822_write_address((char *)buf + curpos + 1,
                                             buflen - curpos - 1,
                                             tmpa,
                                             0);
                        curpos = mutt_strlen(buf);
                        rfc822_free_address(&tmpa);
                    }
                }
            }

            /* then enter current message */
            if (!tagged) {
                ADDRESS *tmpa = result_to_addr(QueryTable[menu->current].data);
                mutt_addrlist_to_local(tmpa);
                rfc822_write_address(buf, buflen, tmpa, 0);
                rfc822_free_address(&tmpa);
            }
        }

        free_query(&results);
        safe_free(&QueryTable);

        /* tell whoever called me to redraw the screen when I return */
        globals.set_option(OPTNEEDREDRAW);
    }

    mutt_menuDestroy(&menu);
}
Beispiel #3
0
Datei: main.c Projekt: 0xAX/muttx
int main(int argc, char **argv)
{
	char folder[_POSIX_PATH_MAX] = "";
	int flags = 0;

	/* set default locale */
	setlocale(LC_ALL, "");
	/* initialization of main output routines with default values */
	mutt_error = mutt_message = mutt_nocurses_error;

	/* parse command line options */
        parse_argv(argc, argv);

        if (arg_version == 1)
        {
                show_version();
		exit(RETURN_SUCCESS);
        } else if (arg_version == 2)
        {
                show_version_verbose();
                exit(RETURN_SUCCESS);
        }

        if (arg_execute)
        {
                init(commands);
                is_mutt_init = true;
        }

        if (arg_expand_alias)
        {
                struct list_t *alias;

                if (!is_mutt_init)
                        init(commands);

                for(alias = aliases; alias; alias = alias->next)
                {
                        struct address *a = mutt_lookup_alias(alias->data);

                        if (a)
                        {
                                printf("alias->data %s\n", alias->data);
                                mutt_write_address_list(a, stdout, 0, 0);
                        }
                }
                exit(RETURN_SUCCESS);
        }

        if (arg_query_conf)
        {
                if (!is_mutt_init)
                        init(commands);

                if (queries)
                        return mutt_query_variables(queries);

                exit(RETURN_SUCCESS);
        }

        if (arg_emulate_mailx) {
                sendflags |= SENDMAILX;
        }

        if (arg_mailbox)
                strfcpy(folder, arg_mailbox, sizeof(folder));

        if (arg_mailbox_type)
                mx_set_magic(arg_mailbox_type);

        if (arg_resume_postponed)
                sendflags |= SENDPOSTPONED;

        /* no-curses for non-terminal session */
	if (!isatty(STDIN_FILENO))
	{
		set_bit(options, OPTNOCURSES);
		sendflags = SENDBATCH;
	}
	else
	{
		/*
		 * This must come before mutt_init() because curses needs to be started
		 * before calling the init_pair() function to set the color scheme.
		 */
		start_curses();
		/* check whether terminal status is supported */
		term_status = mutt_ts_capability();
	}

	/* Initialize crypto backends. */
	crypt_init();

	if (!is_mutt_init)
		init(commands);

	if (!bit_val(options, OPTNOCURSES))
	{
		SETCOLOR(MT_COLOR_NORMAL);
		clear();
		mutt_error = mutt_curses_error;
		mutt_message = mutt_curses_message;
	}

	/* Create the Maildir directory if it doesn't exist */
	if (!bit_val(options, OPTNOCURSES) && Maildir)
	{
		struct stat sb;
		char fpath[_POSIX_PATH_MAX];
		char msg[STRING];

		strfcpy(fpath, Maildir, sizeof(fpath));
		mutt_expand_path(fpath, sizeof(fpath));
#if USE_IMAP
		/* we're not connected yet - skip mail folder creation */
		if (!mx_is_imap(fpath))
#endif
			if (stat(fpath, &sb) == -1 && errno == ENOENT)
			{
				snprintf(msg, sizeof(msg), ("%s does not exist. Create it?"), Maildir);
				if (mutt_yesorno(msg, M_YES) == M_YES)
					if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
						mutt_error( ("Can't create %s: %s."), Maildir, strerror(errno));
			}
	}

	if (sendflags & SENDPOSTPONED)
	{
		if (!bit_val(options, OPTNOCURSES))
			mutt_flushinp();
		ci_send_message(SENDPOSTPONED, NULL, NULL, NULL, NULL);
		mutt_endwin(NULL);
	}
	else if (arg_subject || msg || sendflags || arg_include || attach)
	{
		FILE *fin = NULL;
		char buf[LONG_STRING];
		char *tempfile = NULL, *infile = NULL;
		char *bodytext = NULL;
		int rv = 0;

		if (!bit_val(options, OPTNOCURSES))
			mutt_flushinp();

		if (!msg)
			msg = mutt_new_header();
		if (!msg->env)
			msg->env = mutt_new_envelope();

		for(; addr_to; addr_to = addr_to->next)
		{
			if (url_check_scheme(addr_to->data) == U_MAILTO)
			{
				if (url_parse_mailto(msg->env, &bodytext, addr_to->data) < 0)
				{
					if (!bit_val(options, OPTNOCURSES))
						mutt_endwin(NULL);
					fputs(("Failed to parse mailto: link\n"), stderr);
					exit(RETURN_WRONG_ADDR);
				}
			}
			else
				msg->env->to = rfc822_parse_adrlist(msg->env->to, addr_to->data);
		}

		if (bit_val(options, OPTAUTOEDIT) && !msg->env->to && !msg->env->cc)
		{
			if (!bit_val(options, OPTNOCURSES))
				mutt_endwin(NULL);
			fputs(("No recipients specified.\n"), stderr);
			exit(RETURN_ERR_ARG);
		}

		if (arg_subject)
			msg->env->subject = safe_strdup(arg_subject);

                if (arg_include)
                        infile = arg_include;

		if (infile || bodytext)
		{
			if (infile)
			{
				if (mutt_strcmp("-", infile) == 0)
					fin = stdin;
				else
				{
					char path[_POSIX_PATH_MAX];

					strfcpy(path, infile, sizeof(path));
					mutt_expand_path(path, sizeof(path));
					if ((fin = fopen(path, "r")) == NULL)
					{
						if (!bit_val(options, OPTNOCURSES))
							mutt_endwin(NULL);
						perror(path);
						exit(RETURN_ERR_ARG);
					}
				}
			}

			mutt_mktemp(buf, sizeof(buf));
			tempfile = safe_strdup(buf);

			/* TODO: is the following if still needed? */
			if (tempfile)
			{
				FILE *fout;

				if ((fout = safe_fopen(tempfile, "w")) == NULL)
				{
					if (!bit_val(options, OPTNOCURSES))
						mutt_endwin(NULL);
					perror(tempfile);
					safe_fclose(&fin);
					safe_free(&tempfile);
					exit(RETURN_ERR_ARG);
				}
				if (fin)
					mutt_copy_stream(fin, fout);
				else if (bodytext)
					fputs(bodytext, fout);
				safe_fclose(&fout);
			}

			if (fin && fin != stdin)
				safe_fclose(&fin);
		}

		safe_free(&bodytext);

		if (attach)
		{
			struct list_t *t = attach;
			struct body *a = NULL;

			while(t)
			{
				if (a)
				{
					a->next = mutt_make_file_attach(t->data);
					a = a->next;
				}
				else
					msg->content = a = mutt_make_file_attach(t->data);
				if (!a)
				{
					if (!bit_val(options, OPTNOCURSES))
						mutt_endwin(NULL);
					fprintf(stderr, ("%s: unable to attach file.\n"), t->data);
					mutt_free_list(&attach);
					exit(RETURN_ERR_ARG);
				}
				t = t->next;
			}
			mutt_free_list(&attach);
		}

		rv = ci_send_message(sendflags, msg, tempfile, NULL, NULL);

		if (!bit_val(options, OPTNOCURSES))
			mutt_endwin(NULL);

		if (rv)
			exit(RETURN_ERR_ARG);
	}
	else
	{

		if (!folder[0])
			strfcpy(folder, NONULL(Spoolfile), sizeof(folder));
		mutt_expand_path(folder, sizeof(folder));

		mutt_str_replace(&CurrentFolder, folder);
		mutt_str_replace(&LastFolder, folder);
		mutt_folder_hook(folder);

		if ((Context = mx_open_mailbox(folder, flags, NULL)) || !arg_mailbox)
		{
			mutt_index_menu();
			if (Context)
				safe_free(&Context);
		}
#if USE_IMAP
		imap_logout_all();
#endif

#if USE_SASL
		mutt_sasl_done();
#endif
		mutt_free_opts();
		mutt_endwin(Errorbuf);
	}
	exit(RETURN_SUCCESS);
}
Beispiel #4
0
void mutt_attach_reply (FILE * fp, struct header *hdr,
			ATTACHPTR ** idx, short idxlen, struct body * cur,
			int flags)
{
	short mime_reply_any = 0;

	short nattach = 0;
	struct header *parent = NULL;
	struct header *tmphdr = NULL;
	short i;

	STATE st;
	char tmpbody[_POSIX_PATH_MAX];
	FILE *tmpfp;

	char prefix[SHORT_STRING];
	int rc;

	if (check_all_msg (idx, idxlen, cur, 0) == -1)
	{
		nattach = count_tagged (idx, idxlen);
		if ((parent = find_parent (idx, idxlen, cur, nattach)) == NULL)
			parent = hdr;
	}

	if (nattach > 1 && !check_can_decode (idx, idxlen, cur))
	{
		if ((rc = query_quadoption (OPT_MIMEFWDREST,
					    ("Can't decode all tagged attachments.  MIME-encapsulate the others?"))) == -1)
			return;
		else if (rc == M_YES)
			mime_reply_any = 1;
	}
	else if (nattach == 1)
		mime_reply_any = 1;

	tmphdr = mutt_new_header ();
	tmphdr->env = mutt_new_envelope ();

	if (attach_reply_envelope_defaults (tmphdr->env, idx, idxlen,
					    parent ? parent : (cur ? cur->hdr : NULL), flags) == -1)
	{
		mutt_free_header (&tmphdr);
		return;
	}

	mutt_mktemp (tmpbody, sizeof (tmpbody));
	if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL)
	{
		mutt_error (("Can't create %s."), tmpbody);
		mutt_free_header (&tmphdr);
		return;
	}

	if (!parent)
	{
		if (cur)
			attach_include_reply (fp, tmpfp, cur->hdr, flags);
		else
		{
			for (i = 0; i < idxlen; i++)
			{
				if (idx[i]->content->tagged)
					attach_include_reply (fp, tmpfp, idx[i]->content->hdr, flags);
			}
		}
	}
	else
	{
		mutt_make_attribution (Context, parent, tmpfp);

		memset (&st, 0, sizeof (STATE));
		st.fpin = fp;
		st.fpout = tmpfp;

		if (!bit_val(options, OPTTEXTFLOWED))
			_mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix),
					   Context, parent, 0);
		else
			strfcpy (prefix, ">", sizeof (prefix));

		st.prefix = prefix;
		st.flags  = M_CHARCONV;

		if (bit_val(options, OPTWEED))
			st.flags |= M_WEED;

		if (bit_val(options, OPTHEADER))
			include_header (1, fp, parent, tmpfp, prefix);

		if (cur)
		{
			if (mutt_can_decode (cur))
			{
				mutt_body_handler (cur, &st);
				state_putc ('\n', &st);
			}
			else
				mutt_copy_body (fp, &tmphdr->content, cur);
		}
		else
		{
			for (i = 0; i < idxlen; i++)
			{
				if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content))
				{
					mutt_body_handler (idx[i]->content, &st);
					state_putc ('\n', &st);
				}
			}
		}

		mutt_make_post_indent (Context, parent, tmpfp);

		if (mime_reply_any && !cur &&
		    copy_problematic_attachments (fp, &tmphdr->content, idx, idxlen, 0) == NULL)
		{
			mutt_free_header (&tmphdr);
			safe_fclose (&tmpfp);
			return;
		}
	}

	safe_fclose (&tmpfp);

	if (ci_send_message (flags, tmphdr, tmpbody, NULL,
			     parent ? parent : (cur ? cur->hdr : NULL)) == 0)
		mutt_set_flag (Context, hdr, M_REPLIED, 1);
}
Beispiel #5
0
static void attach_forward_msgs (FILE * fp, struct header *hdr,
				 ATTACHPTR ** idx, short idxlen, struct body * cur)
{
	struct header *curhdr = NULL;
	struct header *tmphdr;
	short i;
	int rc;

	struct body **last;
	char tmpbody[_POSIX_PATH_MAX];
	FILE *tmpfp = NULL;

	int cmflags = 0;
	int chflags = CH_XMIT;

	if (cur)
		curhdr = cur->hdr;
	else
	{
		for (i = 0; i < idxlen; i++)
			if (idx[i]->content->tagged)
			{
				curhdr = idx[i]->content->hdr;
				break;
			}
	}

	tmphdr = mutt_new_header ();
	tmphdr->env = mutt_new_envelope ();
	mutt_make_forward_subject (tmphdr->env, Context, curhdr);


	tmpbody[0] = '\0';

	if ((rc = query_quadoption (OPT_MIMEFWD,
				    ("Forward MIME encapsulated?"))) == M_NO)
	{

		/* no MIME encapsulation */

		mutt_mktemp (tmpbody, sizeof (tmpbody));
		if (!(tmpfp = safe_fopen (tmpbody, "w")))
		{
			mutt_error (("Can't create %s."), tmpbody);
			mutt_free_header (&tmphdr);
			return;
		}

		if (bit_val(options, OPTFORWQUOTE))
		{
			chflags |= CH_PREFIX;
			cmflags |= M_CM_PREFIX;
		}

		if (bit_val(options, OPTFORWDECODE))
		{
			cmflags |= M_CM_DECODE | M_CM_CHARCONV;
			if (bit_val(options, OPTWEED))
			{
				chflags |= CH_WEED | CH_REORDER;
				cmflags |= M_CM_WEED;
			}
		}


		if (cur)
		{
			/* mutt_message_hook (cur->hdr, M_MESSAGEHOOK); */
			mutt_forward_intro (tmpfp, cur->hdr);
			_mutt_copy_message (tmpfp, fp, cur->hdr, cur->hdr->content, cmflags, chflags);
			mutt_forward_trailer (tmpfp);
		}
		else
		{
			for (i = 0; i < idxlen; i++)
			{
				if (idx[i]->content->tagged)
				{
					/* mutt_message_hook (idx[i]->content->hdr, M_MESSAGEHOOK); */
					mutt_forward_intro (tmpfp, idx[i]->content->hdr);
					_mutt_copy_message (tmpfp, fp, idx[i]->content->hdr,
							    idx[i]->content->hdr->content, cmflags, chflags);
					mutt_forward_trailer (tmpfp);
				}
			}
		}
		safe_fclose (&tmpfp);
	}
	else if (rc == M_YES)	/* do MIME encapsulation - we don't need to do much here */
	{
		last = &tmphdr->content;
		if (cur)
			mutt_copy_body (fp, last, cur);
		else
		{
			for (i = 0; i < idxlen; i++)
				if (idx[i]->content->tagged)
				{
					mutt_copy_body (fp, last, idx[i]->content);
					last = &((*last)->next);
				}
		}
	}
	else
		mutt_free_header (&tmphdr);

	ci_send_message (0, tmphdr, *tmpbody ? tmpbody : NULL,
			 NULL, curhdr);

}
Beispiel #6
0
static void attach_forward_bodies (FILE * fp, struct header * hdr,
				   ATTACHPTR ** idx, short idxlen,
				   struct body * cur,
				   short nattach)
{
	short i;
	short mime_fwd_all = 0;
	short mime_fwd_any = 1;
	struct header *parent = NULL;
	struct header *tmphdr = NULL;
	struct body **last;
	char tmpbody[_POSIX_PATH_MAX];
	FILE *tmpfp = NULL;

	char prefix[STRING];

	int rc = 0;

	STATE st;

	/*
	 * First, find the parent message.
	 * Note: This could be made an option by just
	 * putting the following lines into an if block.
	 */


	parent = find_parent (idx, idxlen, cur, nattach);

	if (parent == NULL)
		parent = hdr;


	tmphdr = mutt_new_header ();
	tmphdr->env = mutt_new_envelope ();
	mutt_make_forward_subject (tmphdr->env, Context, parent);

	mutt_mktemp (tmpbody, sizeof (tmpbody));
	if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL)
	{
		mutt_error (("Can't open temporary file %s."), tmpbody);
		return;
	}

	mutt_forward_intro (tmpfp, parent);

	/* prepare the prefix here since we'll need it later. */

	if (bit_val(options, OPTFORWQUOTE))
	{
		if (!bit_val(options, OPTTEXTFLOWED))
			_mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context,
					   parent, 0);
		else
			strfcpy (prefix, ">", sizeof (prefix));
	}

	include_header (bit_val(options, OPTFORWQUOTE), fp, parent,
			tmpfp, prefix);


	/*
	 * Now, we have prepared the first part of the message body: The
	 * original message's header.
	 *
	 * The next part is more interesting: either include the message bodies,
	 * or attach them.
	 */

	if ((!cur || mutt_can_decode (cur)) &&
	    (rc = query_quadoption (OPT_MIMEFWD,
				    ("Forward as attachments?"))) == M_YES)
		mime_fwd_all = 1;
	else if (rc == -1)
		goto bail;

	/*
	 * shortcut MIMEFWDREST when there is only one attachment.  Is
	 * this intuitive?
	 */

	if (!mime_fwd_all && !cur && (nattach > 1)
	    && !check_can_decode (idx, idxlen, cur))
	{
		if ((rc = query_quadoption (OPT_MIMEFWDREST,
					    ("Can't decode all tagged attachments.  MIME-forward the others?"))) == -1)
			goto bail;
		else if (rc == M_NO)
			mime_fwd_any = 0;
	}

	/* initialize a state structure */

	memset (&st, 0, sizeof (st));

	if (bit_val(options, OPTFORWQUOTE))
		st.prefix = prefix;
	st.flags = M_CHARCONV;
	if (bit_val(options, OPTWEED))
		st.flags |= M_WEED;
	st.fpin = fp;
	st.fpout = tmpfp;

	/* where do we append new MIME parts? */
	last = &tmphdr->content;

	if (cur)
	{
		/* single body case */

		if (!mime_fwd_all && mutt_can_decode (cur))
		{
			mutt_body_handler (cur, &st);
			state_putc ('\n', &st);
		}
		else
		{
			if (mutt_copy_body (fp, last, cur) == -1)
				goto bail;
			last = &((*last)->next);
		}
	}
	else
	{
		/* multiple body case */

		if (!mime_fwd_all)
		{
			for (i = 0; i < idxlen; i++)
			{
				if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content))
				{
					mutt_body_handler (idx[i]->content, &st);
					state_putc ('\n', &st);
				}
			}
		}

		if (mime_fwd_any &&
		    copy_problematic_attachments (fp, last, idx, idxlen, mime_fwd_all) == NULL)
			goto bail;
	}

	mutt_forward_trailer (tmpfp);

	safe_fclose (&tmpfp);
	tmpfp = NULL;

	/* now that we have the template, send it. */
	ci_send_message (0, tmphdr, tmpbody, NULL, parent);
	return;

bail:

	if (tmpfp)
	{
		safe_fclose (&tmpfp);
		mutt_unlink (tmpbody);
	}

	mutt_free_header (&tmphdr);
}