Nico Golde:
[apps/madmutt.git] / recvcmd.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include "mutt.h"
15 #include "mutt_curses.h"
16 #include "mutt_menu.h"
17 #include "rfc1524.h"
18 #include "mime.h"
19 #include "mailbox.h"
20 #include "attach.h"
21 #include "mapping.h"
22 #include "mx.h"
23 #include "copy.h"
24 #include "mutt_idna.h"
25
26 #include "lib/mem.h"
27 #include "lib/intl.h"
28 #include "lib/str.h"
29
30 /* some helper functions to verify that we are exclusively operating
31  * on message/rfc822 attachments
32  */
33
34 static short check_msg (BODY * b, short err)
35 {
36   if (!mutt_is_message_type (b->type, b->subtype)) {
37     if (err)
38       mutt_error _("You may only bounce message/rfc822 parts.");
39
40     return -1;
41   }
42   return 0;
43 }
44
45 static short check_all_msg (ATTACHPTR ** idx, short idxlen,
46                             BODY * cur, short err)
47 {
48   short i;
49
50   if (cur && check_msg (cur, err) == -1)
51     return -1;
52   else if (!cur) {
53     for (i = 0; i < idxlen; i++) {
54       if (idx[i]->content->tagged) {
55         if (check_msg (idx[i]->content, err) == -1)
56           return -1;
57       }
58     }
59   }
60   return 0;
61 }
62
63
64 /* can we decode all tagged attachments? */
65
66 static short check_can_decode (ATTACHPTR ** idx, short idxlen, BODY * cur)
67 {
68   short i;
69
70   if (cur)
71     return mutt_can_decode (cur);
72
73   for (i = 0; i < idxlen; i++)
74     if (idx[i]->content->tagged && !mutt_can_decode (idx[i]->content))
75       return 0;
76
77   return 1;
78 }
79
80 static short count_tagged (ATTACHPTR ** idx, short idxlen)
81 {
82   short count = 0;
83   short i;
84
85   for (i = 0; i < idxlen; i++)
86     if (idx[i]->content->tagged)
87       count++;
88
89   return count;
90 }
91
92 /* count the number of tagged children below a multipart or message
93  * attachment.
94  */
95
96 static short count_tagged_children (ATTACHPTR ** idx, short idxlen, short i)
97 {
98   short level = idx[i]->level;
99   short count = 0;
100
101   while ((++i < idxlen) && (level < idx[i]->level))
102     if (idx[i]->content->tagged)
103       count++;
104
105   return count;
106 }
107 \f
108
109
110 /**
111  **
112  ** The bounce function, from the attachment menu
113  **
114  **/
115
116 void mutt_attach_bounce (FILE * fp, HEADER * hdr,
117                          ATTACHPTR ** idx, short idxlen, BODY * cur)
118 {
119   short i;
120   char prompt[STRING];
121   char buf[HUGE_STRING];
122   char *err = NULL;
123   ADDRESS *adr = NULL;
124   int ret = 0;
125   int p = 0;
126
127   if (check_all_msg (idx, idxlen, cur, 1) == -1)
128     return;
129
130   /* one or more messages? */
131   p = (cur || count_tagged (idx, idxlen) == 1);
132
133   if (p)
134     strfcpy (prompt, _("Bounce message to: "), sizeof (prompt));
135   else
136     strfcpy (prompt, _("Bounce tagged messages to: "), sizeof (prompt));
137
138   buf[0] = '\0';
139   if (mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS)
140       || buf[0] == '\0')
141     return;
142
143   if (!(adr = rfc822_parse_adrlist (adr, buf))) {
144     mutt_error _("Error parsing address!");
145
146     return;
147   }
148
149   adr = mutt_expand_aliases (adr);
150
151   if (mutt_addrlist_to_idna (adr, &err) < 0) {
152     mutt_error (_("Bad IDN: '%s'"), err);
153     FREE (&err);
154     rfc822_free_address (&adr);
155     return;
156   }
157
158   buf[0] = 0;
159   rfc822_write_address (buf, sizeof (buf), adr, 1);
160
161 #define extra_space (15+7+2)
162   /*
163    * See commands.c.
164    */
165   snprintf (prompt, sizeof (prompt) - 4,
166             (p ? _("Bounce message to %s") : _("Bounce messages to %s")),
167             buf);
168
169   if (mutt_strwidth (prompt) > COLS - extra_space) {
170     mutt_format_string (prompt, sizeof (prompt) - 4,
171                         0, COLS - extra_space, 0, 0,
172                         prompt, sizeof (prompt), 0);
173     safe_strcat (prompt, sizeof (prompt), "...?");
174   }
175   else
176     safe_strcat (prompt, sizeof (prompt), "?");
177
178   if (query_quadoption (OPT_BOUNCE, prompt) != M_YES) {
179     rfc822_free_address (&adr);
180     CLEARLINE (LINES - 1);
181     mutt_message (p ? _("Message not bounced.") : _("Messages not bounced."));
182     return;
183   }
184
185   CLEARLINE (LINES - 1);
186
187   if (cur)
188     ret = mutt_bounce_message (fp, cur->hdr, adr);
189   else {
190     for (i = 0; i < idxlen; i++) {
191       if (idx[i]->content->tagged)
192         if (mutt_bounce_message (fp, idx[i]->content->hdr, adr))
193           ret = 1;
194     }
195   }
196
197   if (!ret)
198     mutt_message (p ? _("Message bounced.") : _("Messages bounced."));
199   else
200     mutt_error (p ? _("Error bouncing message!") :
201                 _("Error bouncing messages!"));
202 }
203 \f
204
205
206 /**
207  **
208  ** resend-message, from the attachment menu 
209  **
210  **
211  **/
212
213 void mutt_attach_resend (FILE * fp, HEADER * hdr, ATTACHPTR ** idx,
214                          short idxlen, BODY * cur)
215 {
216   short i;
217
218   if (check_all_msg (idx, idxlen, cur, 1) == -1)
219     return;
220
221   if (cur)
222     mutt_resend_message (fp, Context, cur->hdr);
223   else {
224     for (i = 0; i < idxlen; i++)
225       if (idx[i]->content->tagged)
226         mutt_resend_message (fp, Context, idx[i]->content->hdr);
227   }
228 }
229 \f
230
231 /**
232  **
233  ** forward-message, from the attachment menu 
234  **
235  **/
236
237 /* try to find a common parent message for the tagged attachments. */
238
239 static HEADER *find_common_parent (ATTACHPTR ** idx, short idxlen,
240                                    short nattach)
241 {
242   short i;
243   short nchildren;
244
245   for (i = 0; i < idxlen; i++)
246     if (idx[i]->content->tagged)
247       break;
248
249   while (--i >= 0) {
250     if (mutt_is_message_type
251         (idx[i]->content->type, idx[i]->content->subtype)) {
252       nchildren = count_tagged_children (idx, idxlen, i);
253       if (nchildren == nattach)
254         return idx[i]->content->hdr;
255     }
256   }
257
258   return NULL;
259 }
260
261 /* 
262  * check whether attachment #i is a parent of the attachment
263  * pointed to by cur
264  * 
265  * Note: This and the calling procedure could be optimized quite a 
266  * bit.  For now, it's not worth the effort.
267  */
268
269 static int is_parent (short i, ATTACHPTR ** idx, short idxlen, BODY * cur)
270 {
271   short level = idx[i]->level;
272
273   while ((++i < idxlen) && idx[i]->level > level) {
274     if (idx[i]->content == cur)
275       return 1;
276   }
277
278   return 0;
279 }
280
281 static HEADER *find_parent (ATTACHPTR ** idx, short idxlen, BODY * cur,
282                             short nattach)
283 {
284   short i;
285   HEADER *parent = NULL;
286
287   if (cur) {
288     for (i = 0; i < idxlen; i++) {
289       if (mutt_is_message_type
290           (idx[i]->content->type, idx[i]->content->subtype)
291           && is_parent (i, idx, idxlen, cur))
292         parent = idx[i]->content->hdr;
293       if (idx[i]->content == cur)
294         break;
295     }
296   }
297   else if (nattach)
298     parent = find_common_parent (idx, idxlen, nattach);
299
300   return parent;
301 }
302
303 static void include_header (int quote, FILE * ifp,
304                             HEADER * hdr, FILE * ofp, char *_prefix)
305 {
306   int chflags = CH_DECODE;
307   char prefix[SHORT_STRING];
308
309   if (option (OPTWEED))
310     chflags |= CH_WEED | CH_REORDER;
311
312   if (quote) {
313     if (_prefix)
314       strfcpy (prefix, _prefix, sizeof (prefix));
315     else if (!option (OPTTEXTFLOWED))
316       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix),
317                          Context, hdr, 0);
318     else
319       strfcpy (prefix, ">", sizeof (prefix));
320
321     chflags |= CH_PREFIX;
322   }
323
324   mutt_copy_header (ifp, hdr, ofp, chflags, quote ? prefix : NULL);
325 }
326
327 /* Attach all the body parts which can't be decoded. 
328  * This code is shared by forwarding and replying. */
329
330 static BODY **copy_problematic_attachments (FILE * fp,
331                                             BODY ** last,
332                                             ATTACHPTR ** idx,
333                                             short idxlen, short force)
334 {
335   short i;
336
337   for (i = 0; i < idxlen; i++) {
338     if (idx[i]->content->tagged &&
339         (force || !mutt_can_decode (idx[i]->content))) {
340       if (mutt_copy_body (fp, last, idx[i]->content) == -1)
341         return NULL;            /* XXXXX - may lead to crashes */
342       last = &((*last)->next);
343     }
344   }
345   return last;
346 }
347
348 /* 
349  * forward one or several MIME bodies 
350  * (non-message types)
351  */
352
353 static void attach_forward_bodies (FILE * fp, HEADER * hdr,
354                                    ATTACHPTR ** idx, short idxlen,
355                                    BODY * cur, short nattach, int flags)
356 {
357   short i;
358   short mime_fwd_all = 0;
359   short mime_fwd_any = 1;
360   HEADER *parent = NULL;
361   HEADER *tmphdr = NULL;
362   BODY **last;
363   char tmpbody[_POSIX_PATH_MAX];
364   FILE *tmpfp = NULL;
365
366   char prefix[STRING];
367
368   int rc = 0;
369
370   STATE st;
371
372   /* 
373    * First, find the parent message.
374    * Note: This could be made an option by just
375    * putting the following lines into an if block.
376    */
377
378
379   parent = find_parent (idx, idxlen, cur, nattach);
380
381   if (parent == NULL)
382     parent = hdr;
383
384
385   tmphdr = mutt_new_header ();
386   tmphdr->env = mutt_new_envelope ();
387   mutt_make_forward_subject (tmphdr->env, Context, parent);
388
389   mutt_mktemp (tmpbody);
390   if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) {
391     mutt_error (_("Can't open temporary file %s."), tmpbody);
392     return;
393   }
394
395   mutt_forward_intro (tmpfp, parent);
396
397   /* prepare the prefix here since we'll need it later. */
398
399   if (option (OPTFORWQUOTE)) {
400     if (!option (OPTTEXTFLOWED))
401       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context,
402                          parent, 0);
403     else
404       strfcpy (prefix, ">", sizeof (prefix));
405   }
406
407   include_header (option (OPTFORWQUOTE), fp, parent, tmpfp, prefix);
408
409
410   /* 
411    * Now, we have prepared the first part of the message body: The
412    * original message's header. 
413    *
414    * The next part is more interesting: either include the message bodies,
415    * or attach them.
416    */
417
418   if ((!cur || mutt_can_decode (cur)) &&
419       (rc = query_quadoption (OPT_MIMEFWD,
420                               _("Forward as attachments?"))) == M_YES)
421     mime_fwd_all = 1;
422   else if (rc == -1)
423     goto bail;
424
425   /* 
426    * shortcut MIMEFWDREST when there is only one attachment.  Is 
427    * this intuitive?
428    */
429
430   if (!mime_fwd_all && !cur && (nattach > 1)
431       && !check_can_decode (idx, idxlen, cur)) {
432     if ((rc = query_quadoption (OPT_MIMEFWDREST,
433                                 _
434                                 ("Can't decode all tagged attachments.  MIME-forward the others?")))
435         == -1)
436       goto bail;
437     else if (rc == M_NO)
438       mime_fwd_any = 0;
439   }
440
441   /* initialize a state structure */
442
443   memset (&st, 0, sizeof (st));
444
445   if (option (OPTFORWQUOTE))
446     st.prefix = prefix;
447   st.flags = M_CHARCONV;
448   if (option (OPTWEED))
449     st.flags |= M_WEED;
450   st.fpin = fp;
451   st.fpout = tmpfp;
452
453   /* where do we append new MIME parts? */
454   last = &tmphdr->content;
455
456   if (cur) {
457     /* single body case */
458
459     if (!mime_fwd_all && mutt_can_decode (cur)) {
460       mutt_body_handler (cur, &st);
461       state_putc ('\n', &st);
462     }
463     else {
464       if (mutt_copy_body (fp, last, cur) == -1)
465         goto bail;
466       last = &((*last)->next);
467     }
468   }
469   else {
470     /* multiple body case */
471
472     if (!mime_fwd_all) {
473       for (i = 0; i < idxlen; i++) {
474         if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) {
475           mutt_body_handler (idx[i]->content, &st);
476           state_putc ('\n', &st);
477         }
478       }
479     }
480
481     if (mime_fwd_any &&
482         (last =
483          copy_problematic_attachments (fp, last, idx, idxlen,
484                                        mime_fwd_all)) == NULL)
485       goto bail;
486   }
487
488   mutt_forward_trailer (tmpfp);
489
490   fclose (tmpfp);
491   tmpfp = NULL;
492
493   /* now that we have the template, send it. */
494   ci_send_message (flags, tmphdr, tmpbody, NULL, parent);
495   return;
496
497 bail:
498
499   if (tmpfp) {
500     fclose (tmpfp);
501     mutt_unlink (tmpbody);
502   }
503
504   mutt_free_header (&tmphdr);
505 }
506
507
508 /* 
509  * Forward one or several message-type attachments. This 
510  * is different from the previous function
511  * since we want to mimic the index menu's behaviour.
512  *
513  * Code reuse from ci_send_message is not possible here -
514  * ci_send_message relies on a context structure to find messages,
515  * while, on the attachment menu, messages are referenced through
516  * the attachment index. 
517  */
518
519 static void attach_forward_msgs (FILE * fp, HEADER * hdr,
520                                  ATTACHPTR ** idx, short idxlen, BODY * cur,
521                                  int flags)
522 {
523   HEADER *curhdr = NULL;
524   HEADER *tmphdr;
525   short i;
526   int rc;
527
528   BODY **last;
529   char tmpbody[_POSIX_PATH_MAX];
530   FILE *tmpfp = NULL;
531
532   int cmflags = 0;
533   int chflags = CH_XMIT;
534
535   if (cur)
536     curhdr = cur->hdr;
537   else {
538     for (i = 0; i < idxlen; i++)
539       if (idx[i]->content->tagged) {
540         curhdr = idx[i]->content->hdr;
541         break;
542       }
543   }
544
545   tmphdr = mutt_new_header ();
546   tmphdr->env = mutt_new_envelope ();
547   mutt_make_forward_subject (tmphdr->env, Context, curhdr);
548
549
550   tmpbody[0] = '\0';
551
552   if ((rc = query_quadoption (OPT_MIMEFWD,
553                               _("Forward MIME encapsulated?"))) == M_NO) {
554
555     /* no MIME encapsulation */
556
557     mutt_mktemp (tmpbody);
558     if (!(tmpfp = safe_fopen (tmpbody, "w"))) {
559       mutt_error (_("Can't create %s."), tmpbody);
560       mutt_free_header (&tmphdr);
561       return;
562     }
563
564     if (option (OPTFORWQUOTE)) {
565       chflags |= CH_PREFIX;
566       cmflags |= M_CM_PREFIX;
567     }
568
569     if (option (OPTFORWDECODE)) {
570       cmflags |= M_CM_DECODE | M_CM_CHARCONV;
571       if (option (OPTWEED)) {
572         chflags |= CH_WEED | CH_REORDER;
573         cmflags |= M_CM_WEED;
574       }
575     }
576
577
578     if (cur) {
579       /* mutt_message_hook (cur->hdr, M_MESSAGEHOOK); */
580       mutt_forward_intro (tmpfp, cur->hdr);
581       _mutt_copy_message (tmpfp, fp, cur->hdr, cur->hdr->content, cmflags,
582                           chflags);
583       mutt_forward_trailer (tmpfp);
584     }
585     else {
586       for (i = 0; i < idxlen; i++) {
587         if (idx[i]->content->tagged) {
588           /* mutt_message_hook (idx[i]->content->hdr, M_MESSAGEHOOK); */
589           mutt_forward_intro (tmpfp, idx[i]->content->hdr);
590           _mutt_copy_message (tmpfp, fp, idx[i]->content->hdr,
591                               idx[i]->content->hdr->content, cmflags,
592                               chflags);
593           mutt_forward_trailer (tmpfp);
594         }
595       }
596     }
597     fclose (tmpfp);
598   }
599   else if (rc == M_YES) {       /* do MIME encapsulation - we don't need to do much here */
600     last = &tmphdr->content;
601     if (cur)
602       mutt_copy_body (fp, last, cur);
603     else {
604       for (i = 0; i < idxlen; i++)
605         if (idx[i]->content->tagged) {
606           mutt_copy_body (fp, last, idx[i]->content);
607           last = &((*last)->next);
608         }
609     }
610   }
611   else
612     mutt_free_header (&tmphdr);
613
614   ci_send_message (flags, tmphdr, *tmpbody ? tmpbody : NULL, NULL, curhdr);
615
616 }
617
618 void mutt_attach_forward (FILE * fp, HEADER * hdr,
619                           ATTACHPTR ** idx, short idxlen, BODY * cur,
620                           int flags)
621 {
622   short nattach;
623
624
625   if (check_all_msg (idx, idxlen, cur, 0) == 0)
626     attach_forward_msgs (fp, hdr, idx, idxlen, cur, flags);
627   else {
628     nattach = count_tagged (idx, idxlen);
629     attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach, flags);
630   }
631 }
632 \f
633
634
635 /**
636  ** 
637  ** the various reply functions, from the attachment menu
638  **
639  **
640  **/
641
642 /* Create the envelope defaults for a reply.
643  *
644  * This function can be invoked in two ways.
645  * 
646  * Either, parent is NULL.  In this case, all tagged bodies are of a message type,
647  * and the header information is fetched from them.
648  * 
649  * Or, parent is non-NULL.  In this case, cur is the common parent of all the
650  * tagged attachments.
651  * 
652  * Note that this code is horribly similar to envelope_defaults () from send.c.
653  */
654
655 static int
656 attach_reply_envelope_defaults (ENVELOPE * env, ATTACHPTR ** idx,
657                                 short idxlen, HEADER * parent, int flags)
658 {
659   ENVELOPE *curenv = NULL;
660   HEADER *curhdr = NULL;
661   short i;
662
663   if (!parent) {
664     for (i = 0; i < idxlen; i++) {
665       if (idx[i]->content->tagged) {
666         curhdr = idx[i]->content->hdr;
667         curenv = curhdr->env;
668         break;
669       }
670     }
671   }
672   else {
673     curenv = parent->env;
674     curhdr = parent;
675   }
676
677   if (curenv == NULL || curhdr == NULL) {
678     mutt_error _("Can't find any tagged messages.");
679
680     return -1;
681   }
682
683 #ifdef USE_NNTP
684   if ((flags & SENDNEWS)) {
685     /* in case followup set Newsgroups: with Followup-To: if it present */
686     if (!env->newsgroups && curenv &&
687         mutt_strcasecmp (curenv->followup_to, "poster"))
688       env->newsgroups = safe_strdup (curenv->followup_to);
689   }
690   else
691 #endif
692   {
693     if (parent) {
694       if (mutt_fetch_recips (env, curenv, flags) == -1)
695         return -1;
696     }
697     else {
698       for (i = 0; i < idxlen; i++) {
699         if (idx[i]->content->tagged
700             && mutt_fetch_recips (env, idx[i]->content->hdr->env,
701                                   flags) == -1)
702           return -1;
703       }
704     }
705
706     if ((flags & SENDLISTREPLY) && !env->to) {
707       mutt_error _("No mailing lists found!");
708
709       return (-1);
710     }
711
712     mutt_fix_reply_recipients (env);
713   }
714   mutt_make_misc_reply_headers (env, Context, curhdr, curenv);
715
716   if (parent)
717     mutt_add_to_reference_headers (env, curenv, NULL, NULL);
718   else {
719     LIST **p = NULL, **q = NULL;
720
721     for (i = 0; i < idxlen; i++) {
722       if (idx[i]->content->tagged)
723         mutt_add_to_reference_headers (env, idx[i]->content->hdr->env, &p,
724                                        &q);
725     }
726   }
727
728   return 0;
729 }
730
731
732 /*  This is _very_ similar to send.c's include_reply(). */
733
734 static void attach_include_reply (FILE * fp, FILE * tmpfp, HEADER * cur,
735                                   int flags)
736 {
737   int cmflags = M_CM_PREFIX | M_CM_DECODE | M_CM_CHARCONV;
738   int chflags = CH_DECODE;
739
740   /* mutt_message_hook (cur, M_MESSAGEHOOK); */
741
742   mutt_make_attribution (Context, cur, tmpfp);
743
744   if (!option (OPTHEADER))
745     cmflags |= M_CM_NOHEADER;
746   if (option (OPTWEED)) {
747     chflags |= CH_WEED;
748     cmflags |= M_CM_WEED;
749   }
750
751   _mutt_copy_message (tmpfp, fp, cur, cur->content, cmflags, chflags);
752   mutt_make_post_indent (Context, cur, tmpfp);
753 }
754
755 void mutt_attach_reply (FILE * fp, HEADER * hdr,
756                         ATTACHPTR ** idx, short idxlen, BODY * cur, int flags)
757 {
758   short mime_reply_any = 0;
759
760   short nattach = 0;
761   HEADER *parent = NULL;
762   HEADER *tmphdr = NULL;
763   short i;
764
765   STATE st;
766   char tmpbody[_POSIX_PATH_MAX];
767   FILE *tmpfp;
768
769   char prefix[SHORT_STRING];
770   int rc;
771
772 #ifdef USE_NNTP
773   if (flags & SENDNEWS)
774     set_option (OPTNEWSSEND);
775   else
776     unset_option (OPTNEWSSEND);
777 #endif
778
779   if (check_all_msg (idx, idxlen, cur, 0) == -1) {
780     nattach = count_tagged (idx, idxlen);
781     if ((parent = find_parent (idx, idxlen, cur, nattach)) == NULL)
782       parent = hdr;
783   }
784
785   if (nattach > 1 && !check_can_decode (idx, idxlen, cur)) {
786     if ((rc = query_quadoption (OPT_MIMEFWDREST,
787                                 _
788                                 ("Can't decode all tagged attachments.  MIME-encapsulate the others?")))
789         == -1)
790       return;
791     else if (rc == M_YES)
792       mime_reply_any = 1;
793   }
794   else if (nattach == 1)
795     mime_reply_any = 1;
796
797   tmphdr = mutt_new_header ();
798   tmphdr->env = mutt_new_envelope ();
799
800   if (attach_reply_envelope_defaults (tmphdr->env, idx, idxlen,
801                                       parent ? parent : (cur ? cur->
802                                                          hdr : NULL),
803                                       flags) == -1) {
804     mutt_free_header (&tmphdr);
805     return;
806   }
807
808   mutt_mktemp (tmpbody);
809   if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) {
810     mutt_error (_("Can't create %s."), tmpbody);
811     mutt_free_header (&tmphdr);
812     return;
813   }
814
815   if (!parent) {
816     if (cur)
817       attach_include_reply (fp, tmpfp, cur->hdr, flags);
818     else {
819       for (i = 0; i < idxlen; i++) {
820         if (idx[i]->content->tagged)
821           attach_include_reply (fp, tmpfp, idx[i]->content->hdr, flags);
822       }
823     }
824   }
825   else {
826     mutt_make_attribution (Context, parent, tmpfp);
827
828     memset (&st, 0, sizeof (STATE));
829     st.fpin = fp;
830     st.fpout = tmpfp;
831
832     if (!option (OPTTEXTFLOWED))
833       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix),
834                          Context, parent, 0);
835     else
836       strfcpy (prefix, ">", sizeof (prefix));
837
838     st.prefix = prefix;
839     st.flags = M_CHARCONV;
840
841     if (option (OPTWEED))
842       st.flags |= M_WEED;
843
844     if (option (OPTHEADER))
845       include_header (1, fp, parent, tmpfp, prefix);
846
847     if (cur) {
848       if (mutt_can_decode (cur)) {
849         mutt_body_handler (cur, &st);
850         state_putc ('\n', &st);
851       }
852       else
853         mutt_copy_body (fp, &tmphdr->content, cur);
854     }
855     else {
856       for (i = 0; i < idxlen; i++) {
857         if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) {
858           mutt_body_handler (idx[i]->content, &st);
859           state_putc ('\n', &st);
860         }
861       }
862     }
863
864     mutt_make_post_indent (Context, parent, tmpfp);
865
866     if (mime_reply_any && !cur &&
867         copy_problematic_attachments (fp, &tmphdr->content, idx, idxlen,
868                                       0) == NULL) {
869       mutt_free_header (&tmphdr);
870       fclose (tmpfp);
871       return;
872     }
873   }
874
875   fclose (tmpfp);
876
877   if (ci_send_message (flags, tmphdr, tmpbody, NULL, parent) == 0)
878     mutt_set_flag (Context, hdr, M_REPLIED, 1);
879 }