NeoMutt  2025-12-11-911-gd8d604
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 "editor/lib.h"
#include "expando/lib.h"
#include "history/lib.h"
#include "index/lib.h"
#include "question/lib.h"
#include "send/lib.h"
#include "attach.h"
#include "globals.h"
#include "mutt_logging.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 AttachPtrArray *aa, bool err)
 Are all the selected Attachments RFC822 messages?
 
static bool check_can_decode (struct AttachPtrArray *aa)
 Can we decode all selected attachments?
 
static bool aa_contains_body (struct AttachPtrArray *aa, const struct Body *b)
 Does the selection contain a Body?
 
static short count_selected_children (struct AttachCtx *actx, short i, struct AttachPtrArray *aa)
 Selected children below a multipart/message attachment.
 
void attach_bounce_message (struct AttachPtrArray *aa, struct Mailbox *m)
 Bounce function, from the attachment menu.
 
void mutt_attach_resend (struct AttachPtrArray *aa, struct Mailbox *m)
 Resend-message, from the attachment menu.
 
static struct AttachPtrfind_common_parent (struct AttachCtx *actx, struct AttachPtrArray *aa)
 Find a common parent message for the selected 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 AttachPtrArray *aa)
 Find the parent of a selected Attachment set.
 
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 AttachPtrArray *aa, bool force)
 Attach the body parts which can't be decoded.
 
static void attach_forward_bodies (struct Email *e, struct AttachCtx *actx, struct AttachPtrArray *aa)
 Forward one or several MIME bodies.
 
static void attach_forward_msgs (struct AttachPtrArray *aa, SendFlags flags)
 Forward one or several message-type attachments.
 
void mutt_attach_forward (struct AttachPtrArray *aa, struct Email *e, struct AttachCtx *actx, SendFlags flags)
 Forward selected attachments.
 
static int attach_reply_envelope_defaults (struct Envelope *env, struct AttachPtrArray *aa, 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 (struct AttachPtrArray *aa, struct Mailbox *m, struct Email *e, struct AttachCtx *actx, SendFlags flags)
 Attach a reply.
 
void mutt_attach_mail_sender (struct AttachPtrArray *aa)
 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 68 of file recvcmd.c.

69{
71 {
72 if (err)
73 mutt_error(_("You may only bounce message/rfc822 parts"));
74 return false;
75 }
76 return true;
77}
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1556
#define mutt_error(...)
Definition logging2.h:94
#define _(a)
Definition message.h:28
char * subtype
content-type subtype
Definition body.h:61
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 AttachPtrArray * aa,
bool err )
static

Are all the selected Attachments RFC822 messages?

Parameters
aaSelected attachments
errIf true, report errors
Return values
trueAll parts are RFC822 messages

Definition at line 85 of file recvcmd.c.

86{
87 struct AttachPtr **app = NULL;
88 ARRAY_FOREACH(app, aa)
89 {
90 if (!check_msg((*app)->body, err))
91 return false;
92 }
93 return true;
94}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
static bool check_msg(struct Body *b, bool err)
Are we working with an RFC822 message.
Definition recvcmd.c:68
An email to which things will be attached.
Definition attach.h:36
+ 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 AttachPtrArray * aa)
static

Can we decode all selected attachments?

Parameters
aaSelected attachments
Return values
trueAll selected attachments are decodable

Definition at line 101 of file recvcmd.c.

102{
103 struct AttachPtr **app = NULL;
104 ARRAY_FOREACH(app, aa)
105 {
106 if (!mutt_can_decode((*app)->body))
107 return false;
108 }
109
110 return true;
111}
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition handler.c:1898
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ aa_contains_body()

static bool aa_contains_body ( struct AttachPtrArray * aa,
const struct Body * b )
static

Does the selection contain a Body?

Parameters
aaSelected attachments
bCandidate Body
Return values
trueBody is selected

Definition at line 119 of file recvcmd.c.

120{
121 if (!b)
122 return false;
123
124 struct AttachPtr **app = NULL;
125 ARRAY_FOREACH(app, aa)
126 {
127 if ((*app)->body == b)
128 return true;
129 }
130
131 return false;
132}
+ Here is the caller graph for this function:

◆ count_selected_children()

static short count_selected_children ( struct AttachCtx * actx,
short i,
struct AttachPtrArray * aa )
static

Selected children below a multipart/message attachment.

Parameters
actxAttachment context
iIndex of first attachment
aaSelected attachments
Return values
numNumber of selected attachments

Definition at line 141 of file recvcmd.c.

142{
143 short level = actx->idx[i]->level;
144 short count = 0;
145
146 while ((++i < actx->idxlen) && (level < actx->idx[i]->level))
147 if (aa_contains_body(aa, actx->idx[i]->body))
148 count++;
149
150 return count;
151}
static bool aa_contains_body(struct AttachPtrArray *aa, const struct Body *b)
Does the selection contain a Body?
Definition recvcmd.c:119
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:69
struct Body * body
Attachment.
Definition attach.h:37
int level
Nesting depth of attachment.
Definition attach.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_bounce_message()

void attach_bounce_message ( struct AttachPtrArray * aa,
struct Mailbox * m )

Bounce function, from the attachment menu.

Parameters
aaSelected attachments
mMailbox

Definition at line 158 of file recvcmd.c.

159{
160 if (!m || ARRAY_EMPTY(aa))
161 return;
162
163 if (!check_all_msg(aa, true))
164 return;
165
166 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
167 struct Buffer *prompt = buf_pool_get();
168 struct Buffer *buf = buf_pool_get();
169
170 /* RFC5322 mandates a From: header, so warn before bouncing
171 * messages without one */
172 struct AttachPtr **app = NULL;
173 ARRAY_FOREACH(app, aa)
174 {
175 if (TAILQ_EMPTY(&(*app)->body->email->env->from))
176 {
177 mutt_error(_("Warning: message contains no From: header"));
179 break;
180 }
181 }
182
183 /* one or more messages? */
184 const int num_msg = ARRAY_SIZE(aa);
185 if (num_msg == 1)
186 buf_strcpy(prompt, _("Bounce message to: "));
187 else
188 buf_strcpy(prompt, _("Bounce messages to: "));
189
191 &CompleteAliasOps, NULL) != 0) ||
192 buf_is_empty(buf))
193 {
194 goto done;
195 }
196
198 if (TAILQ_EMPTY(&al))
199 {
200 mutt_error(_("Error parsing address"));
201 goto done;
202 }
203
205
206 char *err = NULL;
207 if (mutt_addrlist_to_intl(&al, &err) < 0)
208 {
209 mutt_error(_("Bad IDN: '%s'"), err);
210 FREE(&err);
211 goto done;
212 }
213
214 buf_reset(buf);
215 buf_alloc(buf, 8192);
216 mutt_addrlist_write(&al, buf, true);
217
218 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", num_msg),
219 buf_string(buf));
220
221 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
222 {
223 msgwin_clear_text(NULL);
224 mutt_message(ngettext("Message not bounced", "Messages not bounced", num_msg));
225 goto done;
226 }
227
228 msgwin_clear_text(NULL);
229
230 int rc = 0;
231 ARRAY_FOREACH(app, aa)
232 {
233 if (mutt_bounce_message((*app)->fp, m, (*app)->body->email, &al, NeoMutt->sub))
234 {
235 rc = 1;
236 }
237 }
238
239 if (rc == 0)
240 mutt_message(ngettext("Message bounced", "Messages bounced", num_msg));
241 else
242 mutt_error(ngettext("Error bouncing message", "Error bouncing messages", num_msg));
243
244done:
246 buf_pool_release(&buf);
247 buf_pool_release(&prompt);
248}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1469
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1215
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:1302
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:296
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
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
@ MUTT_COMP_NONE
No flags are set.
Definition wdata.h:46
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:502
#define mutt_message(...)
Definition logging2.h:93
@ HC_ALIAS
Aliases.
Definition lib.h:57
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:554
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
@ 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:384
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
static bool check_all_msg(struct AttachPtrArray *aa, bool err)
Are all the selected Attachments RFC822 messages?
Definition recvcmd.c:85
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:883
String manipulation buffer.
Definition buffer.h:36
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_resend()

void mutt_attach_resend ( struct AttachPtrArray * aa,
struct Mailbox * m )

Resend-message, from the attachment menu.

Parameters
aaSelected attachments
mCurrent mailbox

Definition at line 255 of file recvcmd.c.

256{
257 if (!check_all_msg(aa, true))
258 return;
259
260 struct AttachPtr **app = NULL;
261 ARRAY_FOREACH(app, aa)
262 {
263 mutt_resend_message((*app)->fp, m, (*app)->body->email, NeoMutt->sub);
264 }
265}
int mutt_resend_message(FILE *fp, struct Mailbox *m, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition send.c:1560
+ 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,
struct AttachPtrArray * aa )
static

Find a common parent message for the selected attachments.

Parameters
actxAttachment context
aaSelected attachments
Return values
ptrParent attachment
NULLFailure, no common parent

Definition at line 274 of file recvcmd.c.

275{
276 short i;
277 const short nattach = ARRAY_SIZE(aa);
278
279 for (i = 0; i < actx->idxlen; i++)
280 if (aa_contains_body(aa, actx->idx[i]->body))
281 break;
282
283 while (--i >= 0)
284 {
285 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype))
286 {
287 const short nchildren = count_selected_children(actx, i, aa);
288 if (nchildren == nattach)
289 return actx->idx[i];
290 }
291 }
292
293 return NULL;
294}
static short count_selected_children(struct AttachCtx *actx, short i, struct AttachPtrArray *aa)
Selected children below a multipart/message attachment.
Definition recvcmd.c:141
short idxlen
Number of attachmentes.
Definition attach.h:70
+ 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 308 of file recvcmd.c.

309{
310 short level = actx->idx[i]->level;
311
312 while ((++i < actx->idxlen) && (actx->idx[i]->level > level))
313 {
314 if (actx->idx[i]->body == b)
315 return true;
316 }
317
318 return false;
319}
+ Here is the caller graph for this function:

◆ find_parent()

static struct AttachPtr * find_parent ( struct AttachCtx * actx,
struct AttachPtrArray * aa )
static

Find the parent of a selected Attachment set.

Parameters
actxAttachment context
aaSelected attachments
Return values
ptrParent attachment
NULLNo parent exists

Definition at line 328 of file recvcmd.c.

329{
330 struct AttachPtr *parent = NULL;
331 const short nattach = ARRAY_SIZE(aa);
332
333 if (nattach == 1)
334 {
335 struct AttachPtr **app = ARRAY_GET(aa, 0);
336 struct Body *b = app ? (*app)->body : NULL;
337 for (short i = 0; i < actx->idxlen; i++)
338 {
339 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype) &&
340 is_parent(i, actx, b))
341 {
342 parent = actx->idx[i];
343 }
344 if (actx->idx[i]->body == b)
345 break;
346 }
347 }
348 else if (nattach)
349 {
350 parent = find_common_parent(actx, aa);
351 }
352
353 return parent;
354}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
static struct AttachPtr * find_common_parent(struct AttachCtx *actx, struct AttachPtrArray *aa)
Find a common parent message for the selected attachments.
Definition recvcmd.c:274
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:308
The body of an email.
Definition body.h:36
+ 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 364 of file recvcmd.c.

366{
367 CopyHeaderFlags chflags = CH_DECODE;
368 struct Buffer *prefix2 = buf_pool_get();
369
370 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
371 if (c_weed)
372 chflags |= CH_WEED | CH_REORDER;
373
374 if (quote)
375 {
376 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
377 if (prefix)
378 {
379 buf_strcpy(prefix2, prefix);
380 }
381 else if (!c_text_flowed)
382 {
383 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
384 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
385 setlocale(LC_TIME, NONULL(c_attribution_locale));
386 mutt_make_string(prefix2, -1, c_indent_string, NULL, -1, e, MUTT_FORMAT_NONE, NULL);
387 setlocale(LC_TIME, "");
388 }
389 else
390 {
391 buf_strcpy(prefix2, ">");
392 }
393
394 chflags |= CH_PREFIX;
395 }
396
397 mutt_copy_header(fp_in, e, fp_out, chflags, quote ? buf_string(prefix2) : NULL, 0);
398 buf_pool_release(&prefix2);
399}
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.
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_email.c:432
uint32_t CopyHeaderFlags
Definition copy_email.h:89
@ CH_WEED
Weed the headers?
Definition copy_email.h:67
@ CH_PREFIX
Quote header using $indent_string string?
Definition copy_email.h:71
@ CH_DECODE
Do RFC2047 header decoding.
Definition copy_email.h:68
@ CH_REORDER
Re-order output of headers (specified by 'header-order')
Definition copy_email.h:73
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 dlg_index.c:824
@ MUTT_FORMAT_NONE
No flags are set.
Definition render.h:37
#define NONULL(x)
Definition string2.h:44
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 AttachPtrArray * aa,
bool force )
static

Attach the body parts which can't be decoded.

Parameters
[out]lastBody pointer to update
[in]aaSelected attachments
[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 410 of file recvcmd.c.

412{
413 struct AttachPtr **app = NULL;
414 ARRAY_FOREACH(app, aa)
415 {
416 if (force || !mutt_can_decode((*app)->body))
417 {
418 if (mutt_body_copy((*app)->fp, last, (*app)->body) == -1)
419 return NULL; /* XXXXX - may lead to crashes */
420 last = &((*last)->next);
421 }
422 }
423 return last;
424}
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 copy_body.c:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_forward_bodies()

static void attach_forward_bodies ( struct Email * e,
struct AttachCtx * actx,
struct AttachPtrArray * aa )
static

Forward one or several MIME bodies.

Parameters
eEmail
actxAttachment Context
aaSelected attachments

(non-message types)

Definition at line 434 of file recvcmd.c.

436{
437 bool mime_fwd_all = false;
438 bool mime_fwd_any = true;
439 struct Email *e_parent = NULL;
440 FILE *fp_parent = NULL;
441 enum QuadOption ans = MUTT_NO;
442 struct Buffer *tempfile = NULL;
443 struct Buffer *prefix = buf_pool_get();
444 const short nattach = ARRAY_SIZE(aa);
445 struct AttachPtr **first = ARRAY_GET(aa, 0);
446 struct AttachPtr *current = first ? *first : NULL;
447 struct Body *b = current ? current->body : NULL;
448 FILE *fp = current ? current->fp : NULL;
449
450 /* First, find the parent message.
451 * Note: This could be made an option by just
452 * putting the following lines into an if block. */
453 struct AttachPtr *parent = find_parent(actx, aa);
454 if (parent)
455 {
456 e_parent = parent->body->email;
457 fp_parent = parent->fp;
458 }
459 else
460 {
461 e_parent = e;
462 fp_parent = actx->fp_root;
463 }
464
465 struct Email *e_tmp = email_new();
466 e_tmp->env = mutt_env_new();
467 mutt_make_forward_subject(e_tmp->env, e_parent, NeoMutt->sub);
468
469 tempfile = buf_pool_get();
470 buf_mktemp_draft(tempfile);
471 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
472 if (!fp_tmp)
473 {
474 mutt_error(_("Can't open temporary file %s"), buf_string(tempfile));
475 email_free(&e_tmp);
476 goto bail;
477 }
478
479 mutt_forward_intro(e_parent, fp_tmp, NeoMutt->sub);
480
481 /* prepare the prefix here since we'll need it later. */
482
483 const bool c_forward_quote = cs_subset_bool(NeoMutt->sub, "forward_quote");
484 if (c_forward_quote)
485 {
486 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
487 if (c_text_flowed)
488 {
489 buf_strcpy(prefix, ">");
490 }
491 else
492 {
493 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
494 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
495 setlocale(LC_TIME, NONULL(c_attribution_locale));
496 mutt_make_string(prefix, -1, c_indent_string, NULL, -1, e_parent,
497 MUTT_FORMAT_NONE, NULL);
498 setlocale(LC_TIME, "");
499 }
500 }
501
502 include_header(c_forward_quote, fp_parent, e_parent, fp_tmp, buf_string(prefix));
503
504 /* Now, we have prepared the first part of the message body: The
505 * original message's header.
506 *
507 * The next part is more interesting: either include the message bodies,
508 * or attach them. */
509 if ((!b || mutt_can_decode(b)) &&
510 ((ans = query_quadoption(_("Forward as attachments?"), NeoMutt->sub, "mime_forward")) == MUTT_YES))
511 {
512 mime_fwd_all = true;
513 }
514 else if (ans == MUTT_ABORT)
515 {
516 goto bail;
517 }
518
519 /* shortcut MIMEFWDREST when there is only one attachment.
520 * Is this intuitive? */
521 if (!mime_fwd_all && (nattach > 1) && !check_can_decode(aa))
522 {
523 ans = query_quadoption(_("Can't decode all selected attachments. MIME-forward the others?"),
524 NeoMutt->sub, "mime_forward_rest");
525 if (ans == MUTT_ABORT)
526 goto bail;
527 else if (ans == MUTT_NO)
528 mime_fwd_any = false;
529 }
530
531 /* initialize a state structure */
532
533 struct State state = { 0 };
534 if (c_forward_quote)
535 state.prefix = buf_string(prefix);
536 state.flags = STATE_CHARCONV;
537 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
538 if (c_weed)
539 state.flags |= STATE_WEED;
540 state.fp_out = fp_tmp;
541
542 /* where do we append new MIME parts? */
543 struct Body **last = &e_tmp->body;
544
545 if (nattach == 1)
546 {
547 /* single body case */
548
549 if (!mime_fwd_all && mutt_can_decode(b))
550 {
551 state.fp_in = fp;
552 mutt_body_handler(b, &state);
553 state_putc(&state, '\n');
554 }
555 else
556 {
557 if (mutt_body_copy(fp, last, b) == -1)
558 goto bail;
559 }
560 }
561 else
562 {
563 /* multiple body case */
564
565 if (!mime_fwd_all)
566 {
567 struct AttachPtr **app = NULL;
568 ARRAY_FOREACH(app, aa)
569 {
570 if (mutt_can_decode((*app)->body))
571 {
572 state.fp_in = (*app)->fp;
573 mutt_body_handler((*app)->body, &state);
574 state_putc(&state, '\n');
575 }
576 }
577 }
578
579 if (mime_fwd_any && !copy_problematic_attachments(last, aa, mime_fwd_all))
580 goto bail;
581 }
582
583 mutt_forward_trailer(e_parent, fp_tmp, NeoMutt->sub);
584
585 mutt_file_fclose(&fp_tmp);
586 fp_tmp = NULL;
587
588 /* now that we have the template, send it. */
589 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
590 ARRAY_ADD(&ea, e_parent);
591 mutt_send_message(SEND_NONE, e_tmp, buf_string(tempfile), NULL, &ea, NeoMutt->sub);
592 ARRAY_FREE(&ea);
593 buf_pool_release(&tempfile);
594 buf_pool_release(&prefix);
595 return;
596
597bail:
598 if (fp_tmp)
599 {
600 mutt_file_fclose(&fp_tmp);
601 mutt_file_unlink(buf_string(tempfile));
602 }
603 buf_pool_release(&tempfile);
604 buf_pool_release(&prefix);
605
606 email_free(&e_tmp);
607}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
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:45
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition file.c:156
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1664
#define state_putc(STATE, STR)
Definition state.h:65
@ STATE_CHARCONV
Do character set conversions.
Definition state.h:41
@ STATE_WEED
Weed headers even when not in display mode.
Definition state.h:40
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 AttachPtr * find_parent(struct AttachCtx *actx, struct AttachPtrArray *aa)
Find the parent of a selected Attachment set.
Definition recvcmd.c:328
static bool check_can_decode(struct AttachPtrArray *aa)
Can we decode all selected attachments?
Definition recvcmd.c:101
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:364
static struct Body ** copy_problematic_attachments(struct Body **last, struct AttachPtrArray *aa, bool force)
Attach the body parts which can't be decoded.
Definition recvcmd.c:410
void mutt_forward_intro(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition send.c:461
void mutt_make_forward_subject(struct Envelope *env, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition send.c:991
void mutt_forward_trailer(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition send.c:484
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:2030
@ SEND_NONE
No flags are set.
Definition send.h:45
FILE * fp_root
Used by recvattach for updating.
Definition attach.h:67
FILE * fp
Used in the recvattach menu.
Definition attach.h:38
struct Email * email
header information for message/rfc822
Definition body.h:74
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
struct Body * body
List of MIME parts.
Definition email.h:69
Keep track when processing files.
Definition state.h:54
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
const char * prefix
String to add to the beginning of each output line.
Definition state.h:57
#define buf_mktemp_draft(buf)
Definition tmp.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attach_forward_msgs()

static void attach_forward_msgs ( struct AttachPtrArray * aa,
SendFlags flags )
static

Forward one or several message-type attachments.

Parameters
aaSelected attachments
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 621 of file recvcmd.c.

622{
623 struct AttachPtr **first = ARRAY_GET(aa, 0);
624 if (!first)
625 return;
626
627 struct AttachPtr *current = *first;
628 FILE *fp = current->fp;
629 struct Body *b = current->body;
630 struct Email *e_cur = current->body->email;
631 struct Email *e_tmp = NULL;
632 enum QuadOption ans;
633 struct Body **last = NULL;
634 struct Buffer *tempfile = NULL;
635 FILE *fp_tmp = NULL;
636
637 CopyHeaderFlags chflags = CH_DECODE;
638
639 e_tmp = email_new();
640 e_tmp->env = mutt_env_new();
641 mutt_make_forward_subject(e_tmp->env, e_cur, NeoMutt->sub);
642
643 tempfile = buf_pool_get();
644
645 ans = query_quadoption(_("Forward MIME encapsulated?"), NeoMutt->sub, "mime_forward");
646 if (ans == MUTT_NO)
647 {
648 /* no MIME encapsulation */
649
650 buf_mktemp_draft(tempfile);
651 fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
652 if (!fp_tmp)
653 {
654 mutt_error(_("Can't create %s"), buf_string(tempfile));
655 goto cleanup;
656 }
657
659 const bool c_forward_quote = cs_subset_bool(NeoMutt->sub, "forward_quote");
660 if (c_forward_quote)
661 {
662 chflags |= CH_PREFIX;
663 cmflags |= MUTT_CM_PREFIX;
664 }
665
666 const bool c_forward_decode = cs_subset_bool(NeoMutt->sub, "forward_decode");
667 if (c_forward_decode)
668 {
669 cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
670 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
671 if (c_weed)
672 {
673 chflags |= CH_WEED | CH_REORDER;
674 cmflags |= MUTT_CM_WEED;
675 }
676 }
677
678 if (ARRAY_SIZE(aa) == 1)
679 {
680 mutt_forward_intro(b->email, fp_tmp, NeoMutt->sub);
681 mutt_copy_message_fp(fp_tmp, fp, b->email, cmflags, chflags, 0);
683 }
684 else
685 {
686 struct AttachPtr **app = NULL;
687 ARRAY_FOREACH(app, aa)
688 {
689 mutt_forward_intro((*app)->body->email, fp_tmp, NeoMutt->sub);
690 mutt_copy_message_fp(fp_tmp, (*app)->fp, (*app)->body->email, cmflags, chflags, 0);
691 mutt_forward_trailer((*app)->body->email, fp_tmp, NeoMutt->sub);
692 }
693 }
694 mutt_file_fclose(&fp_tmp);
695 }
696 else if (ans == MUTT_YES) /* do MIME encapsulation - we don't need to do much here */
697 {
698 last = &e_tmp->body;
699 if (ARRAY_SIZE(aa) == 1)
700 {
701 mutt_body_copy(fp, last, b);
702 }
703 else
704 {
705 struct AttachPtr **app = NULL;
706 ARRAY_FOREACH(app, aa)
707 {
708 mutt_body_copy((*app)->fp, last, (*app)->body);
709 last = &((*last)->next);
710 }
711 }
712 }
713 else
714 {
715 email_free(&e_tmp);
716 }
717
718 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
719 ARRAY_ADD(&ea, e_cur);
720 mutt_send_message(flags, e_tmp, buf_is_empty(tempfile) ? NULL : buf_string(tempfile),
721 NULL, &ea, NeoMutt->sub);
722 ARRAY_FREE(&ea);
723 e_tmp = NULL; /* mutt_send_message frees this */
724
725cleanup:
726 email_free(&e_tmp);
727 buf_pool_release(&tempfile);
728}
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_email.c:663
@ MUTT_CM_PREFIX
Quote the header and body.
Definition copy_email.h:43
@ MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy_email.h:44
@ MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy_email.h:48
@ MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition copy_email.h:47
@ MUTT_CM_NONE
No flags are set.
Definition copy_email.h:41
uint16_t CopyMessageFlags
Definition copy_email.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_forward()

void mutt_attach_forward ( struct AttachPtrArray * aa,
struct Email * e,
struct AttachCtx * actx,
SendFlags flags )

Forward selected attachments.

Parameters
aaSelected attachments
eEmail
actxAttachment Context
flagsSend mode, see SendFlags

Definition at line 737 of file recvcmd.c.

739{
740 if (check_all_msg(aa, false))
741 {
742 attach_forward_msgs(aa, flags);
743 }
744 else
745 {
746 attach_forward_bodies(e, actx, aa);
747 }
748}
static void attach_forward_bodies(struct Email *e, struct AttachCtx *actx, struct AttachPtrArray *aa)
Forward one or several MIME bodies.
Definition recvcmd.c:434
static void attach_forward_msgs(struct AttachPtrArray *aa, SendFlags flags)
Forward one or several message-type attachments.
Definition recvcmd.c:621
+ 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 AttachPtrArray * aa,
struct Email * parent,
SendFlags flags )
static

Create the envelope defaults for a reply.

Parameters
envEnvelope to fill in
aaSelected attachments
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 selected bodies are of a message type, and the header information is fetched from them.

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

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

Definition at line 769 of file recvcmd.c.

771{
772 struct Envelope *curenv = NULL;
773 struct Email *e = NULL;
774
775 if (parent)
776 {
777 curenv = parent->env;
778 e = parent;
779 }
780 else
781 {
782 struct AttachPtr **app = NULL;
783 ARRAY_FOREACH(app, aa)
784 {
785 e = (*app)->body->email;
786 curenv = e->env;
787 break;
788 }
789 }
790
791 if (!curenv || !e)
792 {
793 mutt_error(_("Can't find any selected messages"));
794 return -1;
795 }
796
797 if ((flags & SEND_NEWS))
798 {
799 /* in case followup set Newsgroups: with Followup-To: if it present */
800 if (!env->newsgroups && curenv && !mutt_istr_equal(curenv->followup_to, "poster"))
801 {
802 env->newsgroups = mutt_str_dup(curenv->followup_to);
803 }
804 }
805 else
806 {
807 if (parent)
808 {
809 if (mutt_fetch_recips(env, curenv, flags, NeoMutt->sub) == -1)
810 return -1;
811 }
812 else
813 {
814 struct AttachPtr **app = NULL;
815 ARRAY_FOREACH(app, aa)
816 {
817 if (mutt_fetch_recips(env, (*app)->body->email->env, flags, NeoMutt->sub) == -1)
818 {
819 return -1;
820 }
821 }
822 }
823
824 if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
825 {
826 mutt_error(_("No mailing lists found"));
827 return -1;
828 }
829
831 }
833
834 if (parent)
835 {
837 }
838 else
839 {
840 struct AttachPtr **app = NULL;
841 ARRAY_FOREACH(app, aa)
842 {
843 mutt_add_to_reference_headers(env, (*app)->body->email->env, NeoMutt->sub);
844 }
845 }
846
847 return 0;
848}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *env_cur, struct ConfigSubset *sub)
Set subject for a reply.
Definition send.c:1011
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
Definition send.c:961
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition send.c:878
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:1039
@ SEND_LIST_REPLY
Reply to mailing list.
Definition send.h:48
@ SEND_NEWS
Reply to a news article.
Definition send.h:59
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 856 of file recvcmd.c.

857{
859 CopyHeaderFlags chflags = CH_DECODE;
860
862
863 const bool c_header = cs_subset_bool(NeoMutt->sub, "header");
864 if (!c_header)
865 cmflags |= MUTT_CM_NOHEADER;
866 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
867 if (c_weed)
868 {
869 chflags |= CH_WEED;
870 cmflags |= MUTT_CM_WEED;
871 }
872
873 mutt_copy_message_fp(fp_tmp, fp, e, cmflags, chflags, 0);
875}
@ MUTT_CM_NOHEADER
Don't copy the message header.
Definition copy_email.h:42
void mutt_make_attribution_intro(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add "on DATE, PERSON wrote" header.
Definition send.c:668
void mutt_make_attribution_trailer(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition send.c:679
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_attach_reply()

void mutt_attach_reply ( struct AttachPtrArray * aa,
struct Mailbox * m,
struct Email * e,
struct AttachCtx * actx,
SendFlags flags )

Attach a reply.

Parameters
aaSelected attachments
mMailbox
eEmail
actxAttachment Context
flagsSend mode, see SendFlags

Definition at line 885 of file recvcmd.c.

887{
888 bool mime_reply_any = false;
889
890 const short nattach = ARRAY_SIZE(aa);
891 struct AttachPtr **first = ARRAY_GET(aa, 0);
892 if (!first)
893 return;
894
895 struct AttachPtr *current = *first;
896 FILE *fp = current->fp;
897 struct Body *b = current->body;
898 struct AttachPtr *parent = NULL;
899 struct Email *e_parent = NULL;
900 FILE *fp_parent = NULL;
901 struct Email *e_tmp = NULL;
902 FILE *fp_tmp = NULL;
903 struct Buffer *tempfile = NULL;
904 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
905
906 struct Buffer *prefix = buf_pool_get();
907
908 if (flags & SEND_NEWS)
909 OptNewsSend = true;
910 else
911 OptNewsSend = false;
912
913 /* Determine the parent message for the reply: either the selected
914 * attachment's parent or the top-level email if not nested */
915 if (!check_all_msg(aa, false))
916 {
917 parent = find_parent(actx, aa);
918 if (parent)
919 {
920 e_parent = parent->body->email;
921 fp_parent = parent->fp;
922 }
923 else
924 {
925 e_parent = e;
926 fp_parent = actx->fp_root;
927 }
928 }
929
930 /* Check if non-decodable attachments should be MIME-encapsulated */
931 if ((nattach > 1) && !check_can_decode(aa))
932 {
933 const enum QuadOption ans = query_quadoption(_("Can't decode all selected attachments. MIME-encapsulate the others?"),
934 NeoMutt->sub, "mime_forward_rest");
935 if (ans == MUTT_ABORT)
936 goto cleanup;
937 if (ans == MUTT_YES)
938 mime_reply_any = true;
939 }
940 else if (nattach == 1)
941 {
942 mime_reply_any = true;
943 }
944
945 e_tmp = email_new();
946 e_tmp->env = mutt_env_new();
947
948 if (attach_reply_envelope_defaults(e_tmp->env, aa,
949 e_parent ? e_parent : (b ? b->email : NULL),
950 flags) == -1)
951 {
952 goto cleanup;
953 }
954
955 /* Create a temporary file for the reply body and write the quoted
956 * content of the selected attachment(s) into it */
957 tempfile = buf_pool_get();
958 buf_mktemp_draft(tempfile);
959 fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
960 if (!fp_tmp)
961 {
962 mutt_error(_("Can't create %s"), buf_string(tempfile));
963 goto cleanup;
964 }
965
966 if (e_parent)
967 {
968 mutt_make_attribution_intro(e_parent, fp_tmp, NeoMutt->sub);
969
970 struct State state = { 0 };
971 state.fp_out = fp_tmp;
972
973 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
974 if (c_text_flowed)
975 {
976 buf_strcpy(prefix, ">");
977 }
978 else
979 {
980 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
981 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
982 setlocale(LC_TIME, NONULL(c_attribution_locale));
983 mutt_make_string(prefix, -1, c_indent_string, m, -1, e_parent, MUTT_FORMAT_NONE, NULL);
984 setlocale(LC_TIME, "");
985 }
986
987 state.prefix = buf_string(prefix);
988 state.flags = STATE_CHARCONV;
989
990 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
991 if (c_weed)
992 state.flags |= STATE_WEED;
993
994 const bool c_header = cs_subset_bool(NeoMutt->sub, "header");
995 if (c_header)
996 include_header(true, fp_parent, e_parent, fp_tmp, buf_string(prefix));
997
998 if (nattach == 1)
999 {
1000 if (mutt_can_decode(b))
1001 {
1002 state.fp_in = fp;
1003 mutt_body_handler(b, &state);
1004 state_putc(&state, '\n');
1005 }
1006 else
1007 {
1008 mutt_body_copy(fp, &e_tmp->body, b);
1009 }
1010 }
1011 else
1012 {
1013 struct AttachPtr **app = NULL;
1014 ARRAY_FOREACH(app, aa)
1015 {
1016 if (mutt_can_decode((*app)->body))
1017 {
1018 state.fp_in = (*app)->fp;
1019 mutt_body_handler((*app)->body, &state);
1020 state_putc(&state, '\n');
1021 }
1022 }
1023 }
1024
1025 mutt_make_attribution_trailer(e_parent, fp_tmp, NeoMutt->sub);
1026
1027 if (mime_reply_any && (nattach > 1) &&
1028 !copy_problematic_attachments(&e_tmp->body, aa, false))
1029 {
1030 goto cleanup;
1031 }
1032 }
1033 else
1034 {
1035 if (nattach == 1)
1036 {
1037 attach_include_reply(fp, fp_tmp, b->email);
1038 }
1039 else
1040 {
1041 struct AttachPtr **app = NULL;
1042 ARRAY_FOREACH(app, aa)
1043 {
1044 attach_include_reply((*app)->fp, fp_tmp, (*app)->body->email);
1045 }
1046 }
1047 }
1048
1049 mutt_file_fclose(&fp_tmp);
1050
1051 ARRAY_ADD(&ea, e_parent ? e_parent : b->email);
1052 if (mutt_send_message(flags, e_tmp, buf_string(tempfile), NULL, &ea, NeoMutt->sub) == 0)
1053 {
1054 mutt_set_flag(m, e, MUTT_REPLIED, true, true);
1055 }
1056 e_tmp = NULL; /* mutt_send_message frees this */
1057
1058cleanup:
1059 if (fp_tmp)
1060 {
1061 mutt_file_fclose(&fp_tmp);
1062 mutt_file_unlink(buf_string(tempfile));
1063 }
1064 buf_pool_release(&tempfile);
1065 buf_pool_release(&prefix);
1066 email_free(&e_tmp);
1067 ARRAY_FREE(&ea);
1068}
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:54
bool OptNewsSend
(pseudo) used to change behavior when posting
Definition globals.c:54
@ MUTT_REPLIED
Messages that have been replied to.
Definition mutt.h:91
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:856
static int attach_reply_envelope_defaults(struct Envelope *env, struct AttachPtrArray *aa, struct Email *parent, SendFlags flags)
Create the envelope defaults for a reply.
Definition recvcmd.c:769
+ 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 AttachPtrArray * aa)

Compose an email to the sender in the email attachment.

Parameters
aaSelected attachments

Definition at line 1074 of file recvcmd.c.

1075{
1076 if (!check_all_msg(aa, false))
1077 {
1078 /* L10N: You will see this error message if you invoke <compose-to-sender>
1079 when you are on a normal attachment. */
1080 mutt_error(_("You may only compose to sender with message/rfc822 parts"));
1081 return;
1082 }
1083
1084 struct Email *e_tmp = email_new();
1085 e_tmp->env = mutt_env_new();
1086
1087 struct AttachPtr **app = NULL;
1088 ARRAY_FOREACH(app, aa)
1089 {
1090 if (mutt_fetch_recips(e_tmp->env, (*app)->body->email->env, SEND_TO_SENDER,
1091 NeoMutt->sub) == -1)
1092 {
1093 email_free(&e_tmp);
1094 return;
1095 }
1096 }
1097
1098 // This call will free e_tmp for us
1099 mutt_send_message(SEND_NONE, e_tmp, NULL, NULL, NULL, NeoMutt->sub);
1100}
@ SEND_TO_SENDER
Compose new email to sender.
Definition send.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function: