1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ All sorts of `reply', `resend', `forward', and similar user commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #define n_FILE cmd_resend
38 #ifndef HAVE_AMALGAMATION
42 /* Modify subject we reply to to begin with Re: if it does not already */
43 static char *a_crese_reedit(char const *subj
);
45 /* Fetch these headers, as appropriate */
46 static struct name
*a_crese_reply_to(struct message
*mp
);
47 static struct name
*a_crese_mail_followup_to(struct message
*mp
);
49 /* We honoured Reply-To: and/or Mail-Followup-To:, but *recipients-in-cc* is
50 * set so try to keep "secondary" addressees in Cc:, if possible, */
51 static void a_crese_polite_rt_mft_move(struct message
*mp
, struct header
*hp
,
54 /* References and charset, as appropriate */
55 static void a_crese_make_ref_and_cs(struct message
*mp
, struct header
*head
);
57 /* `reply' and `Lreply' workhorse */
58 static int a_crese_list_reply(int *msgvec
, enum header_flags hf
);
60 /* Get PTF to implementation of command c (i.e., take care for *flipr*) */
61 static int (*a_crese_reply_or_Reply(char c
))(int *, bool_t
);
63 /* Reply to a single message. Extract each name from the message header and
64 * send them off to mail1() */
65 static int a_crese_reply(int *msgvec
, bool_t recipient_record
);
67 /* Reply to a series of messages by simply mailing to the senders and not
68 * messing around with the To: and Cc: lists as in normal reply */
69 static int a_crese_Reply(int *msgvec
, bool_t recipient_record
);
71 /* Forward a message to a new recipient, in the sense of RFC 2822 */
72 static int a_crese_fwd(char *str
, int recipient_record
);
74 /* Modify the subject we are replying to to begin with Fwd: */
75 static char *a_crese__fwdedit(char *subj
);
77 /* Do the real work of resending */
78 static int a_crese_resend1(void *v
, bool_t add_resent
);
81 a_crese_reedit(char const *subj
){
87 if(subj
!= NULL
&& *subj
!= '\0'){
92 in
.l
= strlen(in
.s
= n_UNCONST(subj
));
93 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
95 i
= strlen(cp
= subject_re_trim(out
.s
)) +1;
96 /* RFC mandates english "Re: " */
97 newsubj
= n_autorec_alloc(sizeof("Re: ") -1 + i
);
98 memcpy(newsubj
, "Re: ", sizeof("Re: ") -1);
99 memcpy(&newsubj
[sizeof("Re: ") -1], cp
, i
);
108 a_crese_reply_to(struct message
*mp
){
109 char const *cp
, *cp2
;
110 struct name
*rt
, *np
;
114 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
117 if((cp
= ok_vlook(reply_to_honour
)) != NULL
&&
118 (cp2
= hfield1("reply-to", mp
)) != NULL
&&
119 (rt
= checkaddrs(lextract(cp2
, GTO
| gf
), EACM_STRICT
, NULL
)) != NULL
){
124 if((n_psonce
& n_PSO_INTERACTIVE
) && !(n_pstate
& n_PS_ROBOT
)){
125 fprintf(n_stdout
, _("Reply-To: header contains:"));
126 for(np
= rt
; np
!= NULL
; np
= np
->n_flink
)
127 fprintf(n_stdout
, " %s", np
->n_name
);
128 putc('\n', n_stdout
);
131 tr
= _("Reply-To %s%s");
132 l
= strlen(tr
) + strlen(rt
->n_name
) + 3 +1;
133 sp
= n_lofi_alloc(l
);
135 snprintf(sp
, l
, tr
, rt
->n_name
, (rt
->n_flink
!= NULL
? "..." : n_empty
));
136 if(n_quadify(cp
, UIZ_MAX
, sp
, TRU1
) <= FAL0
)
146 a_crese_mail_followup_to(struct message
*mp
){
147 char const *cp
, *cp2
;
148 struct name
*mft
, *np
;
152 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
155 if((cp
= ok_vlook(followup_to_honour
)) != NULL
&&
156 (cp2
= hfield1("mail-followup-to", mp
)) != NULL
&&
157 (mft
= checkaddrs(lextract(cp2
, GTO
| gf
), EACM_STRICT
,NULL
)) != NULL
){
162 if((n_psonce
& n_PSO_INTERACTIVE
) && !(n_pstate
& n_PS_ROBOT
)){
163 fprintf(n_stdout
, _("Mail-Followup-To: header contains:"));
164 for(np
= mft
; np
!= NULL
; np
= np
->n_flink
)
165 fprintf(n_stdout
, " %s", np
->n_name
);
166 putc('\n', n_stdout
);
169 tr
= _("Followup-To %s%s");
170 l
= strlen(tr
) + strlen(mft
->n_name
) + 3 +1;
171 sp
= n_lofi_alloc(l
);
173 snprintf(sp
, l
, tr
, mft
->n_name
,
174 (mft
->n_flink
!= NULL
? "..." : n_empty
));
175 if(n_quadify(cp
, UIZ_MAX
, sp
, TRU1
) <= FAL0
)
185 a_crese_polite_rt_mft_move(struct message
*mp
, struct header
*hp
,
196 /* We may find that in the end To: is empty but Cc: is not, in which case we
197 * upgrade Cc: to To:, and jump back and redo the thing slightly different */
202 struct name
*nnp
, **xpp
, *xp
;
215 /* Try primary, then secondary */
216 for(xp
= hp
->h_mailx_orig_to
; xp
!= NULL
; xp
= xp
->n_flink
)
217 if(!asccasecmp(xp
->n_name
, nnp
->n_name
))
225 for(xp
= hp
->h_mailx_orig_cc
; xp
!= NULL
; xp
= xp
->n_flink
)
226 if(!asccasecmp(xp
->n_name
, nnp
->n_name
))
229 /* If this receiver came in only via R-T: or M-F-T:, place her/him/it in
230 * To: due to lack of a better place */
234 /* Link it at the end to not loose original sort order */
235 if((xp
= *xpp
) != NULL
)
236 while(xp
->n_flink
!= NULL
)
239 if((nnp
->n_blink
= xp
) != NULL
)
244 nnp
->n_type
= (nnp
->n_type
& ~GMASK
) | gf
;
247 /* If afterwards only Cc: data remains, upgrade all of it to To: */
248 if(hp
->h_to
== NULL
){
256 for(hp
->h_to
= np
; np
!= NULL
; np
= np
->n_flink
)
257 np
->n_type
= (np
->n_type
& ~GMASK
) | GTO
;
263 a_crese_make_ref_and_cs(struct message
*mp
, struct header
*head
) /* TODO ASAP */
266 char *oldref
, *oldmsgid
, *newref
;
267 size_t oldreflen
= 0, oldmsgidlen
= 0, reflen
;
272 oldref
= hfield1("references", mp
);
273 oldmsgid
= hfield1("message-id", mp
);
274 if (oldmsgid
== NULL
|| *oldmsgid
== '\0') {
281 oldreflen
= strlen(oldref
);
282 reflen
+= oldreflen
+ 2;
285 oldmsgidlen
= strlen(oldmsgid
);
286 reflen
+= oldmsgidlen
;
289 newref
= n_alloc(reflen
);
290 if (oldref
!= NULL
) {
291 memcpy(newref
, oldref
, oldreflen
+1);
292 if (oldmsgid
!= NULL
) {
293 newref
[oldreflen
++] = ',';
294 newref
[oldreflen
++] = ' ';
295 memcpy(newref
+ oldreflen
, oldmsgid
, oldmsgidlen
+1);
298 memcpy(newref
, oldmsgid
, oldmsgidlen
+1);
299 n
= extract(newref
, GREF
);
302 /* Limit number of references TODO better on parser side */
303 while (n
->n_flink
!= NULL
)
305 for (i
= 1; i
<= REFERENCES_MAX
; ++i
) {
306 if (n
->n_blink
!= NULL
)
313 if (ok_blook(reply_in_same_charset
) &&
314 (ccp
= hfield1("content-type", mp
)) != NULL
){
315 if((head
->h_charset
= ccp
= mime_param_get("charset", ccp
)) != NULL
){
316 if((ccp
= n_iconv_normalize_name(ccp
)) != NULL
)
317 ccp
= n_charsetalias_expand(ccp
);
318 head
->h_charset
= ccp
;
326 a_crese_list_reply(int *msgvec
, enum header_flags hf
){
329 char const *cp
, *cp2
;
331 struct name
*rt
, *mft
, *np
;
335 n_pstate_err_no
= n_ERR_NONE
;
337 /* TODO Since we may recur and do stuff with message lists we need to save
338 * TODO away the argument vector as long as that isn't done by machinery */
341 for(i
= 0; msgvec
[i
] != 0; ++i
)
344 save_msgvec
= n_lofi_alloc(sizeof(*save_msgvec
) * i
);
346 save_msgvec
[i
] = msgvec
[i
];
347 msgvec
= save_msgvec
;
350 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
353 n_autorec_relax_create();
354 mp
= &message
[*msgvec
- 1];
358 memset(&head
, 0, sizeof head
);
360 head
.h_subject
= a_crese_reedit(hfield1("subject", mp
));
361 head
.h_mailx_command
= (hf
& HF_LIST_REPLY
) ? "Lreply" : "reply";
362 head
.h_mailx_orig_from
= lextract(hfield1("from", mp
), GIDENT
| gf
);
363 head
.h_mailx_orig_to
= lextract(hfield1("to", mp
), GTO
| gf
);
364 head
.h_mailx_orig_cc
= lextract(hfield1("cc", mp
), GCC
| gf
);
365 head
.h_mailx_orig_bcc
= lextract(hfield1("bcc", mp
), GBCC
| gf
);
367 /* First of all check for Reply-To: then Mail-Followup-To:, because these,
368 * if honoured, take precedence over anything else. We will join the
369 * resulting list together if so desired.
370 * So if we shall honour R-T: or M-F-T:, then these are our receivers! */
371 rt
= a_crese_reply_to(mp
);
372 mft
= a_crese_mail_followup_to(mp
);
374 if(rt
!= NULL
|| mft
!= NULL
){
377 head
.h_mft
= namelist_dup(np
, GTO
| gf
); /* xxx GTO: no "clone"! */
379 /* Optionally do not propagate a receiver that originally was in
380 * secondary Cc: to the primary To: list */
381 if(ok_blook(recipients_in_cc
)){
382 a_crese_polite_rt_mft_move(mp
, &head
, np
);
384 head
.h_mailx_raw_cc
= namelist_dup(head
.h_cc
, GCC
| gf
);
385 head
.h_cc
= n_alternates_remove(head
.h_cc
, FAL0
);
389 head
.h_mailx_raw_to
= namelist_dup(head
.h_to
, GTO
| gf
);
390 head
.h_to
= n_alternates_remove(head
.h_to
, FAL0
);
392 for(np
= head
.h_to
; np
!= NULL
; np
= np
->n_flink
)
393 assert((np
->n_type
& GMASK
) == GTO
);
394 for(np
= head
.h_cc
; np
!= NULL
; np
= np
->n_flink
)
395 assert((np
->n_type
& GMASK
) == GCC
);
397 goto jrecipients_done
;
400 /* Otherwise do the normal From: / To: / Cc: dance */
402 cp2
= n_header_senderfield_of(mp
);
406 if(ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
)
407 np
= lextract(cp
, GCC
| gf
);
408 if((cp
= hfield1("cc", mp
)) != NULL
){
411 if((x
= lextract(cp
, GCC
| gf
)) != NULL
)
415 head
.h_mailx_raw_cc
= namelist_dup(np
, GCC
| gf
);
416 head
.h_cc
= n_alternates_remove(np
, FAL0
);
422 np
= lextract(cp2
, GTO
| gf
);
423 if(!ok_blook(recipients_in_cc
) && (cp
= hfield1("to", mp
)) != NULL
){
426 if((x
= lextract(cp
, GTO
| gf
)) != NULL
)
429 /* Delete my name from reply list, and with it, all my alternate names */
431 head
.h_mailx_raw_to
= namelist_dup(np
, GTO
| gf
);
432 np
= n_alternates_remove(np
, FAL0
);
433 /* The user may have send this to himself, don't ignore that */
435 np
= lextract(cp2
, GTO
| gf
);
436 head
.h_mailx_raw_to
= namelist_dup(np
, GTO
| gf
);
443 /* For list replies we want to automatically recognize the list address
444 * given in the List-Post: header, so that we will not throw away a possible
445 * corresponding receiver: temporarily "`mlist' the List-Post: address" */
446 if((hf
& HF_LIST_REPLY
) && (cp
= hfield1("list-post", mp
)) != NULL
){
449 if((x
= lextract(cp
, GEXTRA
| GSKIN
)) == NULL
|| x
->n_flink
!= NULL
||
450 (cp
= url_mailto_to_address(x
->n_name
)) == NULL
||
451 /* XXX terribly wasteful to create a new name, and can't we find
452 * XXX a way to mitigate that?? */
453 is_addr_invalid(x
= nalloc(cp
, GEXTRA
| GSKIN
), EACM_STRICT
)){
454 if(n_poption
& n_PO_D_V
)
455 n_err(_("Message contains invalid List-Post: header\n"));
457 /* A special case has been seen on e.g. ietf-announce@ietf.org:
458 * these usually post to multiple groups, with ietf-announce@
459 * in List-Post:, but with Reply-To: set to ietf@ietf.org (since
460 * -announce@ is only used for announcements, say).
461 * So our desire is to honour this request and actively overwrite
462 * List-Post: for our purpose; but only if its a single address.
463 * However, to avoid ambiguities with users that place themselve in
464 * Reply-To: and mailing lists which don't overwrite this (or only
465 * extend this, shall such exist), only do so if reply_to exists of
466 * a single address which points to the same domain as List-Post: */
467 if(rt
!= NULL
&& rt
->n_flink
== NULL
&&
468 name_is_same_domain(x
, rt
))
469 cp
= rt
->n_name
; /* rt is EACM_STRICT tested */
473 /* XXX is_mlist_mp()?? */
474 if(is_mlist(cp
, FAL0
) == MLIST_OTHER
)
475 head
.h_list_post
= cp
;
479 /* In case of list replies we actively sort out any non-list recipient */
480 if(hf
& HF_LIST_REPLY
){
481 struct name
**nhpp
, *nhp
, *tail
;
483 cp
= head
.h_list_post
;
485 nhp
= *(nhpp
= &head
.h_to
);
488 for(tail
= NULL
; nhp
!= NULL
;){
492 /* XXX is_mlist_mp()?? */
493 if((cp
!= NULL
&& !asccasecmp(cp
, np
->n_name
)) ||
494 is_mlist(np
->n_name
, FAL0
) != MLIST_OTHER
){
495 if((np
->n_blink
= tail
) != NULL
)
503 if(nhpp
== &head
.h_to
){
504 nhp
= *(nhpp
= &head
.h_cc
);
509 /* For `Lreply' only, fail immediately with DESTADDRREQ if there are no
510 * receivers at all! */
511 if(head
.h_to
== NULL
&& head
.h_cc
== NULL
){
512 n_err(_("No recipients specified for `Lreply'\n"));
514 n_pstate_err_no
= n_ERR_DESTADDRREQ
;
522 /* Move Cc: to To: as appropriate! */
523 if(head
.h_to
== NULL
&& (np
= head
.h_cc
) != NULL
){
525 for(head
.h_to
= np
; np
!= NULL
; np
= np
->n_flink
)
526 np
->n_type
= (np
->n_type
& ~GMASK
) | GTO
;
529 a_crese_make_ref_and_cs(mp
, &head
);
531 if(ok_blook(quote_as_attachment
)){
532 head
.h_attach
= n_autorec_calloc(1, sizeof *head
.h_attach
);
533 head
.h_attach
->a_msgno
= *msgvec
;
534 head
.h_attach
->a_content_description
= _("Original message content");
537 if(mail1(&head
, 1, mp
, NULL
, !!(hf
& HF_RECIPIENT_RECORD
), FAL0
) != OKAY
){
541 if(ok_blook(markanswered
) && !(mp
->m_flag
& MANSWERED
))
542 mp
->m_flag
|= MANSWER
| MANSWERED
;
543 n_autorec_relax_gut();
547 /* TODO message (error) ring.., less sleep */
548 if(n_psonce
& n_PSO_INTERACTIVE
){
550 _("Waiting a second before proceeding to the next message..\n"));
552 n_msleep(1000, FAL0
);
558 n_lofi_free(save_msgvec
);
560 return (msgvec
== NULL
);
564 (*a_crese_reply_or_Reply(char c
))(int *, bool_t
){
565 int (*rv
)(int*, bool_t
);
568 rv
= (ok_blook(flipr
) ^ (c
== 'R')) ? &a_crese_Reply
: &a_crese_reply
;
574 a_crese_reply(int *msgvec
, bool_t recipient_record
){
578 rv
= a_crese_list_reply(msgvec
,
579 (recipient_record
? HF_RECIPIENT_RECORD
: HF_NONE
));
585 a_crese_Reply(int *msgvec
, bool_t recipient_record
){
592 memset(&head
, 0, sizeof head
);
593 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
595 for(ap
= msgvec
; *ap
!= 0; ++ap
){
598 mp
= &message
[*ap
- 1];
602 if((np
= a_crese_reply_to(mp
)) == NULL
)
603 np
= lextract(n_header_senderfield_of(mp
), GTO
| gf
);
604 head
.h_to
= cat(head
.h_to
, np
);
607 mp
= &message
[msgvec
[0] - 1];
608 head
.h_subject
= hfield1("subject", mp
);
609 head
.h_subject
= a_crese_reedit(head
.h_subject
);
610 a_crese_make_ref_and_cs(mp
, &head
);
611 head
.h_mailx_command
= "Reply";
612 head
.h_mailx_orig_from
= lextract(hfield1("from", mp
), GIDENT
| gf
);
613 head
.h_mailx_orig_to
= lextract(hfield1("to", mp
), GTO
| gf
);
614 head
.h_mailx_orig_cc
= lextract(hfield1("cc", mp
), GCC
| gf
);
615 head
.h_mailx_orig_bcc
= lextract(hfield1("bcc", mp
), GBCC
| gf
);
617 if(ok_blook(recipients_in_cc
)){
618 a_crese_polite_rt_mft_move(mp
, &head
, head
.h_to
);
620 head
.h_mailx_raw_cc
= namelist_dup(head
.h_cc
, GCC
| gf
);
621 head
.h_cc
= n_alternates_remove(head
.h_cc
, FAL0
);
623 head
.h_mailx_raw_to
= namelist_dup(head
.h_to
, GTO
| gf
);
624 head
.h_to
= n_alternates_remove(head
.h_to
, FAL0
);
626 if(ok_blook(quote_as_attachment
)){
627 head
.h_attach
= n_autorec_calloc(1, sizeof *head
.h_attach
);
628 head
.h_attach
->a_msgno
= *msgvec
;
629 head
.h_attach
->a_content_description
= _("Original message content");
632 if(mail1(&head
, 1, mp
, NULL
, recipient_record
, FAL0
) != OKAY
){
637 if(ok_blook(markanswered
) && !(mp
->m_flag
& MANSWERED
))
638 mp
->m_flag
|= MANSWER
| MANSWERED
;
641 return (msgvec
== NULL
);
645 a_crese_fwd(char *str
, int recipient_record
){
649 bool_t f
, forward_as_attachment
;
656 if((recipient
= laststring(str
, &f
, TRU1
)) == NULL
){
657 n_err(_("No recipient specified.\n"));
658 n_pstate_err_no
= n_ERR_DESTADDRREQ
;
662 forward_as_attachment
= ok_blook(forward_as_attachment
);
663 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
664 msgvec
= n_autorec_alloc((msgCount
+ 2) * sizeof *msgvec
);
666 n_pstate_err_no
= n_ERR_NODATA
;
668 *msgvec
= first(0, MMNORM
);
671 }else if(getmsglist(str
, msgvec
, 0) < 0)
675 n_err(_("No applicable messages.\n"));
679 n_err(_("Cannot forward multiple messages at once\n"));
680 n_pstate_err_no
= n_ERR_NOTSUP
;
684 memset(&head
, 0, sizeof head
);
685 head
.h_to
= lextract(recipient
,
686 (GTO
| (ok_blook(fullnames
) ? GFULL
: GSKIN
)));
688 mp
= &message
[*msgvec
- 1];
691 head
.h_subject
= hfield1("subject", mp
);
692 head
.h_subject
= a_crese__fwdedit(head
.h_subject
);
693 head
.h_mailx_command
= "forward";
694 head
.h_mailx_raw_to
= namelist_dup(head
.h_to
, GTO
| gf
);
695 head
.h_mailx_orig_from
= lextract(hfield1("from", mp
), GIDENT
| gf
);
696 head
.h_mailx_orig_to
= lextract(hfield1("to", mp
), GTO
| gf
);
697 head
.h_mailx_orig_cc
= lextract(hfield1("cc", mp
), GCC
| gf
);
698 head
.h_mailx_orig_bcc
= lextract(hfield1("bcc", mp
), GBCC
| gf
);
700 if(forward_as_attachment
){
701 head
.h_attach
= n_autorec_calloc(1, sizeof *head
.h_attach
);
702 head
.h_attach
->a_msgno
= *msgvec
;
703 head
.h_attach
->a_content_description
= _("Forwarded message");
706 rv
= (mail1(&head
, 1, (forward_as_attachment
? NULL
: mp
), NULL
,
707 recipient_record
, TRU1
) != OKAY
); /* reverse! */
714 a_crese__fwdedit(char *subj
){
721 if(subj
== NULL
|| *subj
== '\0')
726 mime_fromhdr(&in
, &out
, TD_ISPR
| TD_ICONV
);
728 newsubj
= n_autorec_alloc(out
.l
+ 6);
729 if(!ascncasecmp(out
.s
, "Fwd: ", sizeof("Fwd: ") -1)) /* TODO EXTEND SUPP.. */
730 memcpy(newsubj
, out
.s
, out
.l
+1);
732 memcpy(newsubj
, "Fwd: ", 5); /* TODO ..a la subject_re_trim()! */
733 memcpy(&newsubj
[5], out
.s
, out
.l
+1);
743 a_crese_resend1(void *vp
, bool_t add_resent
){
745 struct name
*myto
, *myrawto
;
755 msgvec
= n_autorec_alloc((msgCount
+ 2) * sizeof *msgvec
);
756 name
= laststring(str
, &fail
, TRU1
);
758 n_err(_("No recipient specified.\n"));
759 n_pstate_err_no
= n_ERR_DESTADDRREQ
;
763 n_pstate_err_no
= n_ERR_NODATA
;
766 *msgvec
= first(0, MMNORM
);
769 }else if(getmsglist(str
, msgvec
, 0) < 0)
773 n_err(_("No applicable messages.\n"));
778 gf
= ok_blook(fullnames
) ? GFULL
| GSKIN
: GSKIN
;
780 myrawto
= nalloc(name
, GTO
| gf
);
781 myto
= usermap(namelist_dup(myrawto
, myrawto
->n_type
), FAL0
);
782 myto
= n_alternates_remove(myto
, TRU1
);
784 n_pstate_err_no
= n_ERR_DESTADDRREQ
;
788 n_autorec_relax_create();
789 for(ip
= msgvec
; *ip
!= 0 && UICMP(z
, PTR2SIZE(ip
- msgvec
), <, msgCount
);
793 mp
= &message
[*ip
- 1];
797 memset(&head
, 0, sizeof head
);
799 head
.h_mailx_command
= "resend";
800 head
.h_mailx_raw_to
= myrawto
;
801 head
.h_mailx_orig_from
= lextract(hfield1("from", mp
), GIDENT
| gf
);
802 head
.h_mailx_orig_to
= lextract(hfield1("to", mp
), GTO
| gf
);
803 head
.h_mailx_orig_cc
= lextract(hfield1("cc", mp
), GCC
| gf
);
804 head
.h_mailx_orig_bcc
= lextract(hfield1("bcc", mp
), GBCC
| gf
);
806 if(resend_msg(mp
, &head
, add_resent
) != OKAY
){
807 /* n_autorec_relax_gut(); XXX but is handled automatically? */
810 n_autorec_relax_unroll();
812 n_autorec_relax_gut();
815 n_pstate_err_no
= n_ERR_NONE
;
818 return (fail
!= FAL0
);
826 rv
= (*a_crese_reply_or_Reply('r'))(vp
, FAL0
);
832 c_replyall(void *vp
){
836 rv
= a_crese_reply(vp
, FAL0
);
842 c_replysender(void *vp
){
846 rv
= a_crese_Reply(vp
, FAL0
);
856 rv
= (*a_crese_reply_or_Reply('R'))(vp
, FAL0
);
866 rv
= a_crese_list_reply(vp
, HF_LIST_REPLY
);
872 c_followup(void *vp
){
876 rv
= (*a_crese_reply_or_Reply('r'))(vp
, TRU1
);
882 c_followupall(void *vp
){
886 rv
= a_crese_reply(vp
, TRU1
);
892 c_followupsender(void *vp
){
896 rv
= a_crese_Reply(vp
, TRU1
);
902 c_Followup(void *vp
){
906 rv
= (*a_crese_reply_or_Reply('R'))(vp
, TRU1
);
916 rv
= a_crese_fwd(vp
, 0);
926 rv
= a_crese_fwd(vp
, 1);
936 rv
= a_crese_resend1(vp
, TRU1
);
946 rv
= a_crese_resend1(vp
, FAL0
);