NeoMutt  2024-04-25-89-g194907
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
recvcmd.c File Reference

Send/reply with an attachment. More...

#include "config.h"
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "recvcmd.h"
#include "attach/lib.h"
#include "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "copy.h"
#include "globals.h"
#include "handler.h"
#include "hdrline.h"
#include "mutt_body.h"
#include "mutt_logging.h"
#include "protos.h"
#include <libintl.h>
+ Include dependency graph for recvcmd.c:

Go to the source code of this file.

Functions

static bool check_msg (struct Body *b, bool err)
 Are we working with an RFC822 message.
 
static bool check_all_msg (struct AttachCtx *actx, struct Body *b, bool err)
 Are all the Attachments RFC822 messages?
 
static bool check_can_decode (struct AttachCtx *actx, struct Body *b)
 Can we decode all tagged attachments?
 
static short count_tagged (struct AttachCtx *actx)
 Count the number of tagged attachments.
 
static short count_tagged_children (struct AttachCtx *actx, short i)
 Tagged children below a multipart/message attachment.
 
void attach_bounce_message (struct Mailbox *m, FILE *fp, struct AttachCtx *actx, struct Body *b)
 Bounce function, from the attachment menu.
 
void mutt_attach_resend (FILE *fp, struct Mailbox *m, struct AttachCtx *actx, struct Body *b)
 Resend-message, from the attachment menu.
 
static struct AttachPtrfind_common_parent (struct AttachCtx *actx, short nattach)
 Find a common parent message for the tagged attachments.
 
static int is_parent (short i, struct AttachCtx *actx, const struct Body *b)
 Check whether one attachment is the parent of another.
 
static struct AttachPtrfind_parent (struct AttachCtx *actx, struct Body *b, short nattach)
 Find the parent of an Attachment.
 
static void include_header (bool quote, FILE *fp_in, struct Email *e, FILE *fp_out, const char *prefix)
 Write an email header to a file, optionally quoting it.
 
static struct Body ** copy_problematic_attachments (struct Body **last, struct AttachCtx *actx, bool force)
 Attach the body parts which can't be decoded.
 
static void attach_forward_bodies (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *b, short nattach)
 Forward one or several MIME bodies.
 
static void attach_forward_msgs (FILE *fp, struct AttachCtx *actx, struct Body *b, SendFlags flags)
 Forward one or several message-type attachments.
 
void mutt_attach_forward (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *b, SendFlags flags)
 Forward an Attachment.
 
static int attach_reply_envelope_defaults (struct Envelope *env, struct AttachCtx *actx, struct Email *parent, SendFlags flags)
 Create the envelope defaults for a reply.
 
static void attach_include_reply (FILE *fp, FILE *fp_tmp, struct Email *e)
 This is very similar to send.c's include_reply()
 
void mutt_attach_reply (FILE *fp, struct Mailbox *m, struct Email *e, struct AttachCtx *actx, struct Body *b, SendFlags flags)
 Attach a reply.
 
void mutt_attach_mail_sender (struct AttachCtx *actx, struct Body *b)
 Compose an email to the sender in the email attachment.
 

Detailed Description

Send/reply with an attachment.

Authors
  • Thomas Roessler
  • Richard Russon
  • Pietro Cerutti
  • Leon Philman
  • Tóth János

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file recvcmd.c.

Function Documentation

◆ check_msg()

static bool check_msg ( struct Body b,
bool  err 
)
static

Are we working with an RFC822 message.

Parameters
bBody of email
errIf true, display a message if this isn't an RFC822 message
Return values
trueThis is an RFC822 message

some helper functions to verify that we are exclusively operating on message/rfc822 attachments

Definition at line 72 of file recvcmd.c.

73{
75 {
76 if (err)
77 mutt_error(_("You may only bounce message/rfc822 parts"));
78 return false;
79 }
80 return true;
81}
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1493
#define mutt_error(...)
Definition: logging2.h:92
#define _(a)
Definition: message.h:28
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_all_msg()

static bool check_all_msg ( struct AttachCtx actx,
struct Body b,
bool  err 
)
static

Are all the Attachments RFC822 messages?

Parameters
actxAttachment context
bCurrent message
errIf true, report errors
Return values
trueAll parts are RFC822 messages

Definition at line 90 of file recvcmd.c.

91{
92 if (b && !check_msg(b, err))
93 return false;
94 if (!b)
95 {
96 for (short i = 0; i < actx->idxlen; i++)
97 {
98 if (actx->idx[i]->body->tagged)
99 {
100 if (!check_msg(actx->idx[i]->body, err))
101 return false;
102 }
103 }
104 }
105 return true;
106}
static bool check_msg(struct Body *b, bool err)
Are we working with an RFC822 message.
Definition: recvcmd.c:72
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:69
short idxlen
Number of attachmentes.
Definition: attach.h:70
struct Body * body
Attachment.
Definition: attach.h:38
bool tagged
This attachment is tagged.
Definition: body.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_can_decode()

static bool check_can_decode ( struct AttachCtx actx,
struct Body b 
)
static

Can we decode all tagged attachments?

Parameters
actxAttachment context
bBody of email
Return values
trueAll tagged attachments are decodable

Definition at line 114 of file recvcmd.c.

115{
116 if (b)
117 return mutt_can_decode(b);
118
119 for (short i = 0; i < actx->idxlen; i++)
120 if (actx->idx[i]->body->tagged && !mutt_can_decode(actx->idx[i]->body))
121 return false;
122
123 return true;
124}
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition: handler.c:1865
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ count_tagged()

static short count_tagged ( struct AttachCtx actx)
static

Count the number of tagged attachments.

Parameters
actxAttachment context
Return values
numNumber of tagged attachments

Definition at line 131 of file recvcmd.c.

132{
133 short count = 0;
134 for (short i = 0; i < actx->idxlen; i++)
135 if (actx->idx[i]->body->tagged)
136 count++;
137
138 return count;
139}
+ Here is the caller graph for this function:

◆ count_tagged_children()

static short count_tagged_children ( struct AttachCtx actx,
short  i 
)
static

Tagged children below a multipart/message attachment.

Parameters
actxAttachment context
iIndex of first attachment
Return values
numNumber of tagged attachments

Definition at line 147 of file recvcmd.c.

148{
149 short level = actx->idx[i]->level;
150 short count = 0;
151
152 while ((++i < actx->idxlen) && (level < actx->idx[i]->level))
153 if (actx->idx[i]->body->tagged)
154 count++;
155
156 return count;
157}
int level
Nesting depth of attachment.
Definition: attach.h:42
+ Here is the caller graph for this function:

◆ attach_bounce_message()

void attach_bounce_message ( struct Mailbox m,
FILE *  fp,
struct AttachCtx actx,
struct Body b 
)

Bounce function, from the attachment menu.

Parameters
mMailbox
fpHandle of message
actxAttachment context
bBody of email

Definition at line 166 of file recvcmd.c.

168{
169 if (!m || !fp || !actx)
170 return;
171
172 if (!check_all_msg(actx, b, true))
173 return;
174
175 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
176 struct Buffer *prompt = buf_pool_get();
177 struct Buffer *buf = buf_pool_get();
178
179 /* RFC5322 mandates a From: header, so warn before bouncing
180 * messages without one */
181 if (b)
182 {
183 if (TAILQ_EMPTY(&b->email->env->from))
184 {
185 mutt_error(_("Warning: message contains no From: header"));
187 }
188 }
189 else
190 {
191 for (short i = 0; i < actx->idxlen; i++)
192 {
193 if (actx->idx[i]->body->tagged)
194 {
195 if (TAILQ_EMPTY(&actx->idx[i]->body->email->env->from))
196 {
197 mutt_error(_("Warning: message contains no From: header"));
199 break;
200 }
201 }
202 }
203 }
204
205 /* one or more messages? */
206 int num_msg = b ? 1 : count_tagged(actx);
207 if (num_msg == 1)
208 buf_strcpy(prompt, _("Bounce message to: "));
209 else
210 buf_strcpy(prompt, _("Bounce tagged messages to: "));
211
213 &CompleteAliasOps, NULL) != 0) ||
214 buf_is_empty(buf))
215 {
216 goto done;
217 }
218
220 if (TAILQ_EMPTY(&al))
221 {
222 mutt_error(_("Error parsing address"));
223 goto done;
224 }
225
227
228 char *err = NULL;
229 if (mutt_addrlist_to_intl(&al, &err) < 0)
230 {
231 mutt_error(_("Bad IDN: '%s'"), err);
232 FREE(&err);
233 goto done;
234 }
235
236 buf_reset(buf);
237 buf_alloc(buf, 8192);
238 mutt_addrlist_write(&al, buf, true);
239
240 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", num_msg),
241 buf_string(buf));
242
243 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
244 {
245 msgwin_clear_text(NULL);
246 mutt_message(ngettext("Message not bounced", "Messages not bounced", num_msg));
247 goto done;
248 }
249
250 msgwin_clear_text(NULL);
251
252 int rc = 0;
253 if (b)
254 {
255 rc = mutt_bounce_message(fp, m, b->email, &al, NeoMutt->sub);
256 }
257 else
258 {
259 for (short i = 0; i < actx->idxlen; i++)
260 {
261 if (actx->idx[i]->body->tagged)
262 {
263 if (mutt_bounce_message(actx->idx[i]->fp, m, actx->idx[i]->body->email,
264 &al, NeoMutt->sub))
265 {
266 rc = 1;
267 }
268 }
269 }
270 }
271
272 if (rc == 0)
273 mutt_message(ngettext("Message bounced", "Messages bounced", num_msg));
274 else
275 mutt_error(ngettext("Error bouncing message", "Error bouncing messages", num_msg));
276
277done:
279 buf_pool_release(&buf);
280 buf_pool_release(&prompt);
281}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1460
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1206
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1293
const struct CompleteOps CompleteAliasOps
Auto-Completion of Aliases.
Definition: complete.c:108
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:274
#define mutt_message(...)
Definition: logging2.h:91
@ HC_ALIAS
Aliases.
Definition: lib.h:52
#define FREE(x)
Definition: memory.h:45
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:519
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:365
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition: recvcmd.c:131
static bool check_all_msg(struct AttachCtx *actx, struct Body *b, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:90
int mutt_bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:917
FILE * fp
Used in the recvattach menu.
Definition: attach.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:36
struct Envelope * env
Envelope information.
Definition: email.h:68
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_resend()

void mutt_attach_resend ( FILE *  fp,
struct Mailbox m,
struct AttachCtx actx,
struct Body b 
)

Resend-message, from the attachment menu.

Parameters
fpFile containing email
mCurrent mailbox
actxAttachment context
bAttachment

Definition at line 290 of file recvcmd.c.

291{
292 if (!check_all_msg(actx, b, true))
293 return;
294
295 if (b)
296 {
298 }
299 else
300 {
301 for (short i = 0; i < actx->idxlen; i++)
302 {
303 if (actx->idx[i]->body->tagged)
304 {
305 mutt_resend_message(actx->idx[i]->fp, m, actx->idx[i]->body->email,
306 NeoMutt->sub);
307 }
308 }
309 }
310}
int mutt_resend_message(FILE *fp, struct Mailbox *m, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1631
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_common_parent()

static struct AttachPtr * find_common_parent ( struct AttachCtx actx,
short  nattach 
)
static

Find a common parent message for the tagged attachments.

Parameters
actxAttachment context
nattachNumber of tagged attachments
Return values
ptrParent attachment
NULLFailure, no common parent

Definition at line 319 of file recvcmd.c.

320{
321 short i;
322 short nchildren;
323
324 for (i = 0; i < actx->idxlen; i++)
325 if (actx->idx[i]->body->tagged)
326 break;
327
328 while (--i >= 0)
329 {
330 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype))
331 {
332 nchildren = count_tagged_children(actx, i);
333 if (nchildren == nattach)
334 return actx->idx[i];
335 }
336 }
337
338 return NULL;
339}
static short count_tagged_children(struct AttachCtx *actx, short i)
Tagged children below a multipart/message attachment.
Definition: recvcmd.c:147
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_parent()

static int is_parent ( short  i,
struct AttachCtx actx,
const struct Body b 
)
static

Check whether one attachment is the parent of another.

Parameters
iIndex of parent Attachment
actxAttachment context
bPotential child Attachment
Return values
trueAttachment

check whether attachment i is a parent of the attachment pointed to by b

Note
This and the calling procedure could be optimized quite a bit. For now, it's not worth the effort.

Definition at line 353 of file recvcmd.c.

354{
355 short level = actx->idx[i]->level;
356
357 while ((++i < actx->idxlen) && (actx->idx[i]->level > level))
358 {
359 if (actx->idx[i]->body == b)
360 return true;
361 }
362
363 return false;
364}
+ Here is the caller graph for this function:

◆ find_parent()

static struct AttachPtr * find_parent ( struct AttachCtx actx,
struct Body b,
short  nattach 
)
static

Find the parent of an Attachment.

Parameters
actxAttachment context
bAttachment (OPTIONAL)
nattachUse the nth attachment
Return values
ptrParent attachment
NULLNo parent exists

Definition at line 374 of file recvcmd.c.

375{
376 struct AttachPtr *parent = NULL;
377
378 if (b)
379 {
380 for (short i = 0; i < actx->idxlen; i++)
381 {
382 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype) &&
383 is_parent(i, actx, b))
384 {
385 parent = actx->idx[i];
386 }
387 if (actx->idx[i]->body == b)
388 break;
389 }
390 }
391 else if (nattach)
392 {
393 parent = find_common_parent(actx, nattach);
394 }
395
396 return parent;
397}
static struct AttachPtr * find_common_parent(struct AttachCtx *actx, short nattach)
Find a common parent message for the tagged attachments.
Definition: recvcmd.c:319
static int is_parent(short i, struct AttachCtx *actx, const struct Body *b)
Check whether one attachment is the parent of another.
Definition: recvcmd.c:353
An email to which things will be attached.
Definition: attach.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ include_header()

static void include_header ( bool  quote,
FILE *  fp_in,
struct Email e,
FILE *  fp_out,
const char *  prefix 
)
static

Write an email header to a file, optionally quoting it.

Parameters
quoteIf true, prefix the lines
fp_inFile to read from
eEmail
fp_outFile to write to
prefixPrefix for each line (OPTIONAL)

Definition at line 407 of file recvcmd.c.

409{
410 CopyHeaderFlags chflags = CH_DECODE;
411 struct Buffer *prefix2 = buf_pool_get();
412
413 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
414 if (c_weed)
415 chflags |= CH_WEED | CH_REORDER;
416
417 if (quote)
418 {
419 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
420 if (prefix)
421 {
422 buf_strcpy(prefix2, prefix);
423 }
424 else if (!c_text_flowed)
425 {
426 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
427 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
428 setlocale(LC_TIME, NONULL(c_attribution_locale));
429 mutt_make_string(prefix2, -1, c_indent_string, NULL, -1, e, MUTT_FORMAT_NO_FLAGS, NULL);
430 setlocale(LC_TIME, "");
431 }
432 else
433 {
434 buf_strcpy(prefix2, ">");
435 }
436
437 chflags |= CH_PREFIX;
438 }
439
440 mutt_copy_header(fp_in, e, fp_out, chflags, quote ? buf_string(prefix2) : NULL, 0);
441 buf_pool_release(&prefix2);
442}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
Definition: config_type.c:357
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c:425
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:56
#define CH_PREFIX
Quote header using $indent_string string?
Definition: copy.h:59
#define CH_WEED
Weed the headers?
Definition: copy.h:55
#define CH_REORDER
Re-order output of headers (specified by 'hdr_order')
Definition: copy.h:61
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:52
int mutt_make_string(struct Buffer *buf, size_t max_cols, const struct Expando *exp, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1796
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
#define NONULL(x)
Definition: string2.h:37
Parsed Expando trees.
Definition: expando.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ copy_problematic_attachments()

static struct Body ** copy_problematic_attachments ( struct Body **  last,
struct AttachCtx actx,
bool  force 
)
static

Attach the body parts which can't be decoded.

Parameters
[out]lastBody pointer to update
[in]actxAttachment context
[in]forceIf true, attach parts that can't be decoded
Return values
ptrPointer to last Body part

This code is shared by forwarding and replying.

Definition at line 453 of file recvcmd.c.

455{
456 for (short i = 0; i < actx->idxlen; i++)
457 {
458 if (actx->idx[i]->body->tagged && (force || !mutt_can_decode(actx->idx[i]->body)))
459 {
460 if (mutt_body_copy(actx->idx[i]->fp, last, actx->idx[i]->body) == -1)
461 return NULL; /* XXXXX - may lead to crashes */
462 last = &((*last)->next);
463 }
464 }
465 return last;
466}
int mutt_body_copy(FILE *fp, struct Body **b_dst, struct Body *b_src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_forward_bodies()

static void attach_forward_bodies ( FILE *  fp,
struct Email e,
struct AttachCtx actx,
struct Body b,
short  nattach 
)
static

Forward one or several MIME bodies.

Parameters
fpFile to read from
eEmail
actxAttachment Context
bBody of email
nattachNumber of tagged attachments

(non-message types)

Definition at line 478 of file recvcmd.c.

480{
481 bool mime_fwd_all = false;
482 bool mime_fwd_any = true;
483 struct Email *e_parent = NULL;
484 FILE *fp_parent = NULL;
485 enum QuadOption ans = MUTT_NO;
486 struct Buffer *tmpbody = NULL;
487 struct Buffer *prefix = buf_pool_get();
488
489 /* First, find the parent message.
490 * Note: This could be made an option by just
491 * putting the following lines into an if block. */
492 struct AttachPtr *parent = find_parent(actx, b, nattach);
493 if (parent)
494 {
495 e_parent = parent->body->email;
496 fp_parent = parent->fp;
497 }
498 else
499 {
500 e_parent = e;
501 fp_parent = actx->fp_root;
502 }
503
504 struct Email *e_tmp = email_new();
505 e_tmp->env = mutt_env_new();
506 mutt_make_forward_subject(e_tmp->env, e_parent, NeoMutt->sub);
507
508 tmpbody = buf_pool_get();
509 buf_mktemp(tmpbody);
510 FILE *fp_tmp = mutt_file_fopen(buf_string(tmpbody), "w");
511 if (!fp_tmp)
512 {
513 mutt_error(_("Can't open temporary file %s"), buf_string(tmpbody));
514 email_free(&e_tmp);
515 goto bail;
516 }
517
518 mutt_forward_intro(e_parent, fp_tmp, NeoMutt->sub);
519
520 /* prepare the prefix here since we'll need it later. */
521
522 const bool c_forward_quote = cs_subset_bool(NeoMutt->sub, "forward_quote");
523 if (c_forward_quote)
524 {
525 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
526 if (c_text_flowed)
527 {
528 buf_strcpy(prefix, ">");
529 }
530 else
531 {
532 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
533 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
534 setlocale(LC_TIME, NONULL(c_attribution_locale));
535 mutt_make_string(prefix, -1, c_indent_string, NULL, -1, e_parent,
537 setlocale(LC_TIME, "");
538 }
539 }
540
541 include_header(c_forward_quote, fp_parent, e_parent, fp_tmp, buf_string(prefix));
542
543 /* Now, we have prepared the first part of the message body: The
544 * original message's header.
545 *
546 * The next part is more interesting: either include the message bodies,
547 * or attach them. */
548 if ((!b || mutt_can_decode(b)) &&
549 ((ans = query_quadoption(_("Forward as attachments?"), NeoMutt->sub, "mime_forward")) == MUTT_YES))
550 {
551 mime_fwd_all = true;
552 }
553 else if (ans == MUTT_ABORT)
554 {
555 goto bail;
556 }
557
558 /* shortcut MIMEFWDREST when there is only one attachment.
559 * Is this intuitive? */
560 if (!mime_fwd_all && !b && (nattach > 1) && !check_can_decode(actx, b))
561 {
562 ans = query_quadoption(_("Can't decode all tagged attachments. MIME-forward the others?"),
563 NeoMutt->sub, "mime_forward_rest");
564 if (ans == MUTT_ABORT)
565 goto bail;
566 else if (ans == MUTT_NO)
567 mime_fwd_any = false;
568 }
569
570 /* initialize a state structure */
571
572 struct State state = { 0 };
573 if (c_forward_quote)
574 state.prefix = buf_string(prefix);
575 state.flags = STATE_CHARCONV;
576 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
577 if (c_weed)
578 state.flags |= STATE_WEED;
579 state.fp_out = fp_tmp;
580
581 /* where do we append new MIME parts? */
582 struct Body **last = &e_tmp->body;
583
584 if (b)
585 {
586 /* single body case */
587
588 if (!mime_fwd_all && mutt_can_decode(b))
589 {
590 state.fp_in = fp;
591 mutt_body_handler(b, &state);
592 state_putc(&state, '\n');
593 }
594 else
595 {
596 if (mutt_body_copy(fp, last, b) == -1)
597 goto bail;
598 }
599 }
600 else
601 {
602 /* multiple body case */
603
604 if (!mime_fwd_all)
605 {
606 for (int i = 0; i < actx->idxlen; i++)
607 {
608 if (actx->idx[i]->body->tagged && mutt_can_decode(actx->idx[i]->body))
609 {
610 state.fp_in = actx->idx[i]->fp;
611 mutt_body_handler(actx->idx[i]->body, &state);
612 state_putc(&state, '\n');
613 }
614 }
615 }
616
617 if (mime_fwd_any && !copy_problematic_attachments(last, actx, mime_fwd_all))
618 goto bail;
619 }
620
621 mutt_forward_trailer(e_parent, fp_tmp, NeoMutt->sub);
622
623 mutt_file_fclose(&fp_tmp);
624 fp_tmp = NULL;
625
626 /* now that we have the template, send it. */
627 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
628 ARRAY_ADD(&ea, e_parent);
629 mutt_send_message(SEND_NO_FLAGS, e_tmp, buf_string(tmpbody), NULL, &ea,
630 NeoMutt->sub);
631 ARRAY_FREE(&ea);
632 buf_pool_release(&tmpbody);
633 buf_pool_release(&prefix);
634 return;
635
636bail:
637 if (fp_tmp)
638 {
639 mutt_file_fclose(&fp_tmp);
641 }
642 buf_pool_release(&tmpbody);
643 buf_pool_release(&prefix);
644
645 email_free(&e_tmp);
646}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:156
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:58
struct Email * email_new(void)
Create a new Email.
Definition: email.c:80
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:46
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:221
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1631
#define STATE_WEED
Weed headers even when not in display mode.
Definition: state.h:36
#define state_putc(STATE, STR)
Definition: state.h:59
#define STATE_CHARCONV
Do character set conversions.
Definition: state.h:37
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
static struct Body ** copy_problematic_attachments(struct Body **last, struct AttachCtx *actx, bool force)
Attach the body parts which can't be decoded.
Definition: recvcmd.c:453
static bool check_can_decode(struct AttachCtx *actx, struct Body *b)
Can we decode all tagged attachments?
Definition: recvcmd.c:114
static struct AttachPtr * find_parent(struct AttachCtx *actx, struct Body *b, short nattach)
Find the parent of an Attachment.
Definition: recvcmd.c:374
static void include_header(bool quote, FILE *fp_in, struct Email *e, FILE *fp_out, const char *prefix)
Write an email header to a file, optionally quoting it.
Definition: recvcmd.c:407
void mutt_forward_intro(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition: send.c:455
void mutt_make_forward_subject(struct Envelope *env, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition: send.c:1052
void mutt_forward_trailer(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition: send.c:479
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2116
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:41
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:67
The body of an email.
Definition: body.h:36
The envelope/body of an email.
Definition: email.h:39
struct Body * body
List of MIME parts.
Definition: email.h:69
Keep track when processing files.
Definition: state.h:48
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:52
FILE * fp_out
File to write to.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:49
const char * prefix
String to add to the beginning of each output line.
Definition: state.h:51
#define buf_mktemp(buf)
Definition: tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_forward_msgs()

static void attach_forward_msgs ( FILE *  fp,
struct AttachCtx actx,
struct Body b,
SendFlags  flags 
)
static

Forward one or several message-type attachments.

Parameters
fpFile handle to attachment
actxAttachment Context
bAttachment to forward (OPTIONAL)
flagsSend mode, see SendFlags

This is different from the previous function since we want to mimic the index menu's behavior.

Code reuse from mutt_send_message() is not possible here. It relies on a context structure to find messages, while, on the attachment menu, messages are referenced through the attachment index.

Definition at line 662 of file recvcmd.c.

663{
664 struct Email *e_cur = NULL;
665 struct Email *e_tmp = NULL;
666 enum QuadOption ans;
667 struct Body **last = NULL;
668 struct Buffer *tmpbody = NULL;
669 FILE *fp_tmp = NULL;
670
671 CopyHeaderFlags chflags = CH_DECODE;
672
673 if (b)
674 {
675 e_cur = b->email;
676 }
677 else
678 {
679 for (short i = 0; i < actx->idxlen; i++)
680 {
681 if (actx->idx[i]->body->tagged)
682 {
683 e_cur = actx->idx[i]->body->email;
684 break;
685 }
686 }
687 }
688
689 e_tmp = email_new();
690 e_tmp->env = mutt_env_new();
691 mutt_make_forward_subject(e_tmp->env, e_cur, NeoMutt->sub);
692
693 tmpbody = buf_pool_get();
694
695 ans = query_quadoption(_("Forward MIME encapsulated?"), NeoMutt->sub, "mime_forward");
696 if (ans == MUTT_NO)
697 {
698 /* no MIME encapsulation */
699
700 buf_mktemp(tmpbody);
701 fp_tmp = mutt_file_fopen(buf_string(tmpbody), "w");
702 if (!fp_tmp)
703 {
704 mutt_error(_("Can't create %s"), buf_string(tmpbody));
705 goto cleanup;
706 }
707
709 const bool c_forward_quote = cs_subset_bool(NeoMutt->sub, "forward_quote");
710 if (c_forward_quote)
711 {
712 chflags |= CH_PREFIX;
713 cmflags |= MUTT_CM_PREFIX;
714 }
715
716 const bool c_forward_decode = cs_subset_bool(NeoMutt->sub, "forward_decode");
717 if (c_forward_decode)
718 {
719 cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
720 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
721 if (c_weed)
722 {
723 chflags |= CH_WEED | CH_REORDER;
724 cmflags |= MUTT_CM_WEED;
725 }
726 }
727
728 if (b)
729 {
730 mutt_forward_intro(b->email, fp_tmp, NeoMutt->sub);
731 mutt_copy_message_fp(fp_tmp, fp, b->email, cmflags, chflags, 0);
733 }
734 else
735 {
736 for (short i = 0; i < actx->idxlen; i++)
737 {
738 if (actx->idx[i]->body->tagged)
739 {
740 mutt_forward_intro(actx->idx[i]->body->email, fp_tmp, NeoMutt->sub);
741 mutt_copy_message_fp(fp_tmp, actx->idx[i]->fp,
742 actx->idx[i]->body->email, cmflags, chflags, 0);
743 mutt_forward_trailer(actx->idx[i]->body->email, fp_tmp, NeoMutt->sub);
744 }
745 }
746 }
747 mutt_file_fclose(&fp_tmp);
748 }
749 else if (ans == MUTT_YES) /* do MIME encapsulation - we don't need to do much here */
750 {
751 last = &e_tmp->body;
752 if (b)
753 {
754 mutt_body_copy(fp, last, b);
755 }
756 else
757 {
758 for (short i = 0; i < actx->idxlen; i++)
759 {
760 if (actx->idx[i]->body->tagged)
761 {
762 mutt_body_copy(actx->idx[i]->fp, last, actx->idx[i]->body);
763 last = &((*last)->next);
764 }
765 }
766 }
767 }
768 else
769 {
770 email_free(&e_tmp);
771 }
772
773 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
774 ARRAY_ADD(&ea, e_cur);
775 mutt_send_message(flags, e_tmp, buf_is_empty(tmpbody) ? NULL : buf_string(tmpbody),
776 NULL, &ea, NeoMutt->sub);
777 ARRAY_FREE(&ea);
778 e_tmp = NULL; /* mutt_send_message frees this */
779
780cleanup:
781 email_free(&e_tmp);
782 buf_pool_release(&tmpbody);
783}
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Make a copy of a message from a FILE pointer.
Definition: copy.c:653
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:43
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:39
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:40
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:44
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:37
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_forward()

void mutt_attach_forward ( FILE *  fp,
struct Email e,
struct AttachCtx actx,
struct Body b,
SendFlags  flags 
)

Forward an Attachment.

Parameters
fpHandle to the attachment
eEmail
actxAttachment Context
bCurrent message
flagsSend mode, see SendFlags

Definition at line 793 of file recvcmd.c.

795{
796 if (check_all_msg(actx, b, false))
797 {
798 attach_forward_msgs(fp, actx, b, flags);
799 }
800 else
801 {
802 const short nattach = count_tagged(actx);
803 attach_forward_bodies(fp, e, actx, b, nattach);
804 }
805}
static void attach_forward_bodies(FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *b, short nattach)
Forward one or several MIME bodies.
Definition: recvcmd.c:478
static void attach_forward_msgs(FILE *fp, struct AttachCtx *actx, struct Body *b, SendFlags flags)
Forward one or several message-type attachments.
Definition: recvcmd.c:662
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_reply_envelope_defaults()

static int attach_reply_envelope_defaults ( struct Envelope env,
struct AttachCtx actx,
struct Email parent,
SendFlags  flags 
)
static

Create the envelope defaults for a reply.

Parameters
envEnvelope to fill in
actxAttachment Context
parentParent Email
flagsFlags, see SendFlags
Return values
0Success
-1Error

This function can be invoked in two ways.

Either, parent is NULL. In this case, all tagged bodies are of a message type, and the header information is fetched from them.

Or, parent is non-NULL. In this case, cur is the common parent of all the tagged attachments.

Note that this code is horribly similar to envelope_defaults() from send.c.

Definition at line 826 of file recvcmd.c.

828{
829 struct Envelope *curenv = NULL;
830 struct Email *e = NULL;
831
832 if (parent)
833 {
834 curenv = parent->env;
835 e = parent;
836 }
837 else
838 {
839 for (short i = 0; i < actx->idxlen; i++)
840 {
841 if (actx->idx[i]->body->tagged)
842 {
843 e = actx->idx[i]->body->email;
844 curenv = e->env;
845 break;
846 }
847 }
848 }
849
850 if (!curenv || !e)
851 {
852 mutt_error(_("Can't find any tagged messages"));
853 return -1;
854 }
855
856 if ((flags & SEND_NEWS))
857 {
858 /* in case followup set Newsgroups: with Followup-To: if it present */
859 if (!env->newsgroups && curenv && !mutt_istr_equal(curenv->followup_to, "poster"))
860 {
862 }
863 }
864 else
865 {
866 if (parent)
867 {
868 if (mutt_fetch_recips(env, curenv, flags, NeoMutt->sub) == -1)
869 return -1;
870 }
871 else
872 {
873 for (short i = 0; i < actx->idxlen; i++)
874 {
875 if (actx->idx[i]->body->tagged &&
876 (mutt_fetch_recips(env, actx->idx[i]->body->email->env, flags,
877 NeoMutt->sub) == -1))
878 {
879 return -1;
880 }
881 }
882 }
883
884 if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
885 {
886 mutt_error(_("No mailing lists found"));
887 return -1;
888 }
889
891 }
893
894 if (parent)
895 {
897 }
898 else
899 {
900 for (short i = 0; i < actx->idxlen; i++)
901 {
902 if (actx->idx[i]->body->tagged)
903 {
905 NeoMutt->sub);
906 }
907 }
908 }
909
910 return 0;
911}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *env_cur, struct ConfigSubset *sub)
Set subject for a reply.
Definition: send.c:1072
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
Definition: send.c:1022
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition: send.c:939
void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *env_cur, struct ConfigSubset *sub)
Generate references for a reply email.
Definition: send.c:1100
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:44
#define SEND_NEWS
Reply to a news article.
Definition: send.h:55
The header of an Email.
Definition: envelope.h:57
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
char * followup_to
List of 'followup-to' fields.
Definition: envelope.h:80
char * newsgroups
List of newsgroups.
Definition: envelope.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_include_reply()

static void attach_include_reply ( FILE *  fp,
FILE *  fp_tmp,
struct Email e 
)
static

This is very similar to send.c's include_reply()

Parameters
fpFile handle to attachment
fp_tmpFile handle to temporary file
eEmail

Definition at line 919 of file recvcmd.c.

920{
922 CopyHeaderFlags chflags = CH_DECODE;
923
925
926 const bool c_header = cs_subset_bool(NeoMutt->sub, "header");
927 if (!c_header)
928 cmflags |= MUTT_CM_NOHEADER;
929 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
930 if (c_weed)
931 {
932 chflags |= CH_WEED;
933 cmflags |= MUTT_CM_WEED;
934 }
935
936 mutt_copy_message_fp(fp_tmp, fp, e, cmflags, chflags, 0);
938}
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition: copy.h:38
void mutt_make_attribution_intro(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add "on DATE, PERSON wrote" header.
Definition: send.c:663
void mutt_make_attribution_trailer(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition: send.c:674
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_reply()

void mutt_attach_reply ( FILE *  fp,
struct Mailbox m,
struct Email e,
struct AttachCtx actx,
struct Body b,
SendFlags  flags 
)

Attach a reply.

Parameters
fpFile handle to reply
mMailbox
eEmail
actxAttachment Context
bCurrent message
flagsSend mode, see SendFlags

Definition at line 949 of file recvcmd.c.

951{
952 bool mime_reply_any = false;
953
954 short nattach = 0;
955 struct AttachPtr *parent = NULL;
956 struct Email *e_parent = NULL;
957 FILE *fp_parent = NULL;
958 struct Email *e_tmp = NULL;
959 FILE *fp_tmp = NULL;
960 struct Buffer *tmpbody = NULL;
961 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
962
963 struct Buffer *prefix = buf_pool_get();
964
965 if (flags & SEND_NEWS)
966 OptNewsSend = true;
967 else
968 OptNewsSend = false;
969
970 if (!check_all_msg(actx, b, false))
971 {
972 nattach = count_tagged(actx);
973 parent = find_parent(actx, b, nattach);
974 if (parent)
975 {
976 e_parent = parent->body->email;
977 fp_parent = parent->fp;
978 }
979 else
980 {
981 e_parent = e;
982 fp_parent = actx->fp_root;
983 }
984 }
985
986 if ((nattach > 1) && !check_can_decode(actx, b))
987 {
988 const enum QuadOption ans = query_quadoption(_("Can't decode all tagged attachments. MIME-encapsulate the others?"),
989 NeoMutt->sub, "mime_forward_rest");
990 if (ans == MUTT_ABORT)
991 goto cleanup;
992 if (ans == MUTT_YES)
993 mime_reply_any = true;
994 }
995 else if (nattach == 1)
996 {
997 mime_reply_any = true;
998 }
999
1000 e_tmp = email_new();
1001 e_tmp->env = mutt_env_new();
1002
1003 if (attach_reply_envelope_defaults(e_tmp->env, actx,
1004 e_parent ? e_parent : (b ? b->email : NULL),
1005 flags) == -1)
1006 {
1007 goto cleanup;
1008 }
1009
1010 tmpbody = buf_pool_get();
1011 buf_mktemp(tmpbody);
1012 fp_tmp = mutt_file_fopen(buf_string(tmpbody), "w");
1013 if (!fp_tmp)
1014 {
1015 mutt_error(_("Can't create %s"), buf_string(tmpbody));
1016 goto cleanup;
1017 }
1018
1019 if (e_parent)
1020 {
1021 mutt_make_attribution_intro(e_parent, fp_tmp, NeoMutt->sub);
1022
1023 struct State state = { 0 };
1024 state.fp_out = fp_tmp;
1025
1026 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
1027 if (c_text_flowed)
1028 {
1029 buf_strcpy(prefix, ">");
1030 }
1031 else
1032 {
1033 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
1034 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
1035 setlocale(LC_TIME, NONULL(c_attribution_locale));
1036 mutt_make_string(prefix, -1, c_indent_string, m, -1, e_parent,
1037 MUTT_FORMAT_NO_FLAGS, NULL);
1038 setlocale(LC_TIME, "");
1039 }
1040
1041 state.prefix = buf_string(prefix);
1042 state.flags = STATE_CHARCONV;
1043
1044 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
1045 if (c_weed)
1046 state.flags |= STATE_WEED;
1047
1048 const bool c_header = cs_subset_bool(NeoMutt->sub, "header");
1049 if (c_header)
1050 include_header(true, fp_parent, e_parent, fp_tmp, buf_string(prefix));
1051
1052 if (b)
1053 {
1054 if (mutt_can_decode(b))
1055 {
1056 state.fp_in = fp;
1057 mutt_body_handler(b, &state);
1058 state_putc(&state, '\n');
1059 }
1060 else
1061 {
1062 mutt_body_copy(fp, &e_tmp->body, b);
1063 }
1064 }
1065 else
1066 {
1067 for (short i = 0; i < actx->idxlen; i++)
1068 {
1069 if (actx->idx[i]->body->tagged && mutt_can_decode(actx->idx[i]->body))
1070 {
1071 state.fp_in = actx->idx[i]->fp;
1072 mutt_body_handler(actx->idx[i]->body, &state);
1073 state_putc(&state, '\n');
1074 }
1075 }
1076 }
1077
1078 mutt_make_attribution_trailer(e_parent, fp_tmp, NeoMutt->sub);
1079
1080 if (mime_reply_any && !b && !copy_problematic_attachments(&e_tmp->body, actx, false))
1081 {
1082 goto cleanup;
1083 }
1084 }
1085 else
1086 {
1087 if (b)
1088 {
1089 attach_include_reply(fp, fp_tmp, b->email);
1090 }
1091 else
1092 {
1093 for (short i = 0; i < actx->idxlen; i++)
1094 {
1095 if (actx->idx[i]->body->tagged)
1096 attach_include_reply(actx->idx[i]->fp, fp_tmp, actx->idx[i]->body->email);
1097 }
1098 }
1099 }
1100
1101 mutt_file_fclose(&fp_tmp);
1102
1103 ARRAY_ADD(&ea, e_parent ? e_parent : (b ? b->email : NULL));
1104 if (mutt_send_message(flags, e_tmp, buf_string(tmpbody), NULL, &ea, NeoMutt->sub) == 0)
1105 {
1106 mutt_set_flag(m, e, MUTT_REPLIED, true, true);
1107 }
1108 e_tmp = NULL; /* mutt_send_message frees this */
1109
1110cleanup:
1111 if (fp_tmp)
1112 {
1113 mutt_file_fclose(&fp_tmp);
1114 mutt_file_unlink(buf_string(tmpbody));
1115 }
1116 buf_pool_release(&tmpbody);
1117 buf_pool_release(&prefix);
1118 email_free(&e_tmp);
1119 ARRAY_FREE(&ea);
1120}
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:57
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: globals.c:71
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:72
static void attach_include_reply(FILE *fp, FILE *fp_tmp, struct Email *e)
This is very similar to send.c's include_reply()
Definition: recvcmd.c:919
static int attach_reply_envelope_defaults(struct Envelope *env, struct AttachCtx *actx, struct Email *parent, SendFlags flags)
Create the envelope defaults for a reply.
Definition: recvcmd.c:826
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_mail_sender()

void mutt_attach_mail_sender ( struct AttachCtx actx,
struct Body b 
)

Compose an email to the sender in the email attachment.

Parameters
actxAttachment Context
bCurrent attachment

Definition at line 1127 of file recvcmd.c.

1128{
1129 if (!check_all_msg(actx, b, 0))
1130 {
1131 /* L10N: You will see this error message if you invoke <compose-to-sender>
1132 when you are on a normal attachment. */
1133 mutt_error(_("You may only compose to sender with message/rfc822 parts"));
1134 return;
1135 }
1136
1137 struct Email *e_tmp = email_new();
1138 e_tmp->env = mutt_env_new();
1139
1140 if (b)
1141 {
1142 if (mutt_fetch_recips(e_tmp->env, b->email->env, SEND_TO_SENDER, NeoMutt->sub) == -1)
1143 {
1144 email_free(&e_tmp);
1145 return;
1146 }
1147 }
1148 else
1149 {
1150 for (int i = 0; i < actx->idxlen; i++)
1151 {
1152 if (actx->idx[i]->body->tagged &&
1153 (mutt_fetch_recips(e_tmp->env, actx->idx[i]->body->email->env,
1154 SEND_TO_SENDER, NeoMutt->sub) == -1))
1155 {
1156 email_free(&e_tmp);
1157 return;
1158 }
1159 }
1160 }
1161
1162 // This call will free e_tmp for us
1163 mutt_send_message(SEND_NO_FLAGS, e_tmp, NULL, NULL, NULL, NeoMutt->sub);
1164}
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function: