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