NeoMutt  2025-12-11-435-g4ac674
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 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 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:1506
#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 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 86 of file recvcmd.c.

87{
88 if (b && !check_msg(b, err))
89 return false;
90 if (!b)
91 {
92 for (short i = 0; i < actx->idxlen; i++)
93 {
94 if (actx->idx[i]->body->tagged)
95 {
96 if (!check_msg(actx->idx[i]->body, err))
97 return false;
98 }
99 }
100 }
101 return true;
102}
static bool check_msg(struct Body *b, bool err)
Are we working with an RFC822 message.
Definition recvcmd.c:68
struct AttachPtr ** idx
Array of attachments.
Definition attach.h:67
short idxlen
Number of attachmentes.
Definition attach.h:68
struct Body * body
Attachment.
Definition attach.h:36
bool tagged
This attachment is tagged.
Definition body.h:90
+ 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 110 of file recvcmd.c.

111{
112 if (b)
113 return mutt_can_decode(b);
114
115 for (short i = 0; i < actx->idxlen; i++)
116 if (actx->idx[i]->body->tagged && !mutt_can_decode(actx->idx[i]->body))
117 return false;
118
119 return true;
120}
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition handler.c:1893
+ 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 127 of file recvcmd.c.

128{
129 short count = 0;
130 for (short i = 0; i < actx->idxlen; i++)
131 if (actx->idx[i]->body->tagged)
132 count++;
133
134 return count;
135}
+ 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 143 of file recvcmd.c.

144{
145 short level = actx->idx[i]->level;
146 short count = 0;
147
148 while ((++i < actx->idxlen) && (level < actx->idx[i]->level))
149 if (actx->idx[i]->body->tagged)
150 count++;
151
152 return count;
153}
int level
Nesting depth of attachment.
Definition attach.h:40
+ 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 162 of file recvcmd.c.

164{
165 if (!m || !fp || !actx)
166 return;
167
168 if (!check_all_msg(actx, b, true))
169 return;
170
171 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
172 struct Buffer *prompt = buf_pool_get();
173 struct Buffer *buf = buf_pool_get();
174
175 /* RFC5322 mandates a From: header, so warn before bouncing
176 * messages without one */
177 if (b)
178 {
179 if (TAILQ_EMPTY(&b->email->env->from))
180 {
181 mutt_error(_("Warning: message contains no From: header"));
183 }
184 }
185 else
186 {
187 for (short i = 0; i < actx->idxlen; i++)
188 {
189 if (actx->idx[i]->body->tagged)
190 {
191 if (TAILQ_EMPTY(&actx->idx[i]->body->email->env->from))
192 {
193 mutt_error(_("Warning: message contains no From: header"));
195 break;
196 }
197 }
198 }
199 }
200
201 /* one or more messages? */
202 int num_msg = b ? 1 : count_tagged(actx);
203 if (num_msg == 1)
204 buf_strcpy(prompt, _("Bounce message to: "));
205 else
206 buf_strcpy(prompt, _("Bounce tagged messages to: "));
207
209 &CompleteAliasOps, NULL) != 0) ||
210 buf_is_empty(buf))
211 {
212 goto done;
213 }
214
216 if (TAILQ_EMPTY(&al))
217 {
218 mutt_error(_("Error parsing address"));
219 goto done;
220 }
221
223
224 char *err = NULL;
225 if (mutt_addrlist_to_intl(&al, &err) < 0)
226 {
227 mutt_error(_("Bad IDN: '%s'"), err);
228 FREE(&err);
229 goto done;
230 }
231
232 buf_reset(buf);
233 buf_alloc(buf, 8192);
234 mutt_addrlist_write(&al, buf, true);
235
236 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", num_msg),
237 buf_string(buf));
238
239 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
240 {
241 msgwin_clear_text(NULL);
242 mutt_message(ngettext("Message not bounced", "Messages not bounced", num_msg));
243 goto done;
244 }
245
246 msgwin_clear_text(NULL);
247
248 int rc = 0;
249 if (b)
250 {
251 rc = mutt_bounce_message(fp, m, b->email, &al, NeoMutt->sub);
252 }
253 else
254 {
255 for (short i = 0; i < actx->idxlen; i++)
256 {
257 if (actx->idx[i]->body->tagged)
258 {
259 if (mutt_bounce_message(actx->idx[i]->fp, m, actx->idx[i]->body->email,
260 &al, NeoMutt->sub))
261 {
262 rc = 1;
263 }
264 }
265 }
266 }
267
268 if (rc == 0)
269 mutt_message(ngettext("Message bounced", "Messages bounced", num_msg));
270 else
271 mutt_error(ngettext("Error bouncing message", "Error bouncing messages", num_msg));
272
273done:
275 buf_pool_release(&buf);
276 buf_pool_release(&prompt);
277}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1464
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1210
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:1297
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
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
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
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:270
#define mutt_message(...)
Definition logging2.h:93
@ HC_ALIAS
Aliases.
Definition lib.h:56
#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:518
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:378
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition recvcmd.c:127
static bool check_all_msg(struct AttachCtx *actx, struct Body *b, bool err)
Are all the Attachments RFC822 messages?
Definition recvcmd.c:86
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:876
FILE * fp
Used in the recvattach menu.
Definition attach.h:37
struct Email * email
header information for message/rfc822
Definition body.h:74
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: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 ( 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 286 of file recvcmd.c.

287{
288 if (!check_all_msg(actx, b, true))
289 return;
290
291 if (b)
292 {
294 }
295 else
296 {
297 for (short i = 0; i < actx->idxlen; i++)
298 {
299 if (actx->idx[i]->body->tagged)
300 {
301 mutt_resend_message(actx->idx[i]->fp, m, actx->idx[i]->body->email,
302 NeoMutt->sub);
303 }
304 }
305 }
306}
int mutt_resend_message(FILE *fp, struct Mailbox *m, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition send.c:1552
+ 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 315 of file recvcmd.c.

316{
317 short i;
318 short nchildren;
319
320 for (i = 0; i < actx->idxlen; i++)
321 if (actx->idx[i]->body->tagged)
322 break;
323
324 while (--i >= 0)
325 {
326 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype))
327 {
328 nchildren = count_tagged_children(actx, i);
329 if (nchildren == nattach)
330 return actx->idx[i];
331 }
332 }
333
334 return NULL;
335}
static short count_tagged_children(struct AttachCtx *actx, short i)
Tagged children below a multipart/message attachment.
Definition recvcmd.c:143
+ 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 349 of file recvcmd.c.

350{
351 short level = actx->idx[i]->level;
352
353 while ((++i < actx->idxlen) && (actx->idx[i]->level > level))
354 {
355 if (actx->idx[i]->body == b)
356 return true;
357 }
358
359 return false;
360}
+ 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 370 of file recvcmd.c.

371{
372 struct AttachPtr *parent = NULL;
373
374 if (b)
375 {
376 for (short i = 0; i < actx->idxlen; i++)
377 {
378 if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype) &&
379 is_parent(i, actx, b))
380 {
381 parent = actx->idx[i];
382 }
383 if (actx->idx[i]->body == b)
384 break;
385 }
386 }
387 else if (nattach)
388 {
389 parent = find_common_parent(actx, nattach);
390 }
391
392 return parent;
393}
static struct AttachPtr * find_common_parent(struct AttachCtx *actx, short nattach)
Find a common parent message for the tagged attachments.
Definition recvcmd.c:315
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:349
An email to which things will be attached.
Definition attach.h:35
+ 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 403 of file recvcmd.c.

405{
406 CopyHeaderFlags chflags = CH_DECODE;
407 struct Buffer *prefix2 = buf_pool_get();
408
409 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
410 if (c_weed)
411 chflags |= CH_WEED | CH_REORDER;
412
413 if (quote)
414 {
415 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
416 if (prefix)
417 {
418 buf_strcpy(prefix2, prefix);
419 }
420 else if (!c_text_flowed)
421 {
422 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
423 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
424 setlocale(LC_TIME, NONULL(c_attribution_locale));
425 mutt_make_string(prefix2, -1, c_indent_string, NULL, -1, e, MUTT_FORMAT_NO_FLAGS, NULL);
426 setlocale(LC_TIME, "");
427 }
428 else
429 {
430 buf_strcpy(prefix2, ">");
431 }
432
433 chflags |= CH_PREFIX;
434 }
435
436 mutt_copy_header(fp_in, e, fp_out, chflags, quote ? buf_string(prefix2) : NULL, 0);
437 buf_pool_release(&prefix2);
438}
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
#define CH_DECODE
Do RFC2047 header decoding.
Definition copy_email.h:58
#define CH_PREFIX
Quote header using $indent_string string?
Definition copy_email.h:61
#define CH_WEED
Weed the headers?
Definition copy_email.h:57
#define CH_REORDER
Re-order output of headers (specified by 'header-order')
Definition copy_email.h:63
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition copy_email.h:54
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:802
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition render.h:33
#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 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 449 of file recvcmd.c.

451{
452 for (short i = 0; i < actx->idxlen; i++)
453 {
454 if (actx->idx[i]->body->tagged && (force || !mutt_can_decode(actx->idx[i]->body)))
455 {
456 if (mutt_body_copy(actx->idx[i]->fp, last, actx->idx[i]->body) == -1)
457 return NULL; /* XXXXX - may lead to crashes */
458 last = &((*last)->next);
459 }
460 }
461 return last;
462}
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 ( 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 474 of file recvcmd.c.

476{
477 bool mime_fwd_all = false;
478 bool mime_fwd_any = true;
479 struct Email *e_parent = NULL;
480 FILE *fp_parent = NULL;
481 enum QuadOption ans = MUTT_NO;
482 struct Buffer *tempfile = NULL;
483 struct Buffer *prefix = buf_pool_get();
484
485 /* First, find the parent message.
486 * Note: This could be made an option by just
487 * putting the following lines into an if block. */
488 struct AttachPtr *parent = find_parent(actx, b, nattach);
489 if (parent)
490 {
491 e_parent = parent->body->email;
492 fp_parent = parent->fp;
493 }
494 else
495 {
496 e_parent = e;
497 fp_parent = actx->fp_root;
498 }
499
500 struct Email *e_tmp = email_new();
501 e_tmp->env = mutt_env_new();
502 mutt_make_forward_subject(e_tmp->env, e_parent, NeoMutt->sub);
503
504 tempfile = buf_pool_get();
505 buf_mktemp(tempfile);
506 FILE *fp_tmp = mutt_file_fopen(buf_string(tempfile), "w");
507 if (!fp_tmp)
508 {
509 mutt_error(_("Can't open temporary file %s"), buf_string(tempfile));
510 email_free(&e_tmp);
511 goto bail;
512 }
513
514 mutt_forward_intro(e_parent, fp_tmp, NeoMutt->sub);
515
516 /* prepare the prefix here since we'll need it later. */
517
518 const bool c_forward_quote = cs_subset_bool(NeoMutt->sub, "forward_quote");
519 if (c_forward_quote)
520 {
521 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
522 if (c_text_flowed)
523 {
524 buf_strcpy(prefix, ">");
525 }
526 else
527 {
528 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
529 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
530 setlocale(LC_TIME, NONULL(c_attribution_locale));
531 mutt_make_string(prefix, -1, c_indent_string, NULL, -1, e_parent,
533 setlocale(LC_TIME, "");
534 }
535 }
536
537 include_header(c_forward_quote, fp_parent, e_parent, fp_tmp, buf_string(prefix));
538
539 /* Now, we have prepared the first part of the message body: The
540 * original message's header.
541 *
542 * The next part is more interesting: either include the message bodies,
543 * or attach them. */
544 if ((!b || mutt_can_decode(b)) &&
545 ((ans = query_quadoption(_("Forward as attachments?"), NeoMutt->sub, "mime_forward")) == MUTT_YES))
546 {
547 mime_fwd_all = true;
548 }
549 else if (ans == MUTT_ABORT)
550 {
551 goto bail;
552 }
553
554 /* shortcut MIMEFWDREST when there is only one attachment.
555 * Is this intuitive? */
556 if (!mime_fwd_all && !b && (nattach > 1) && !check_can_decode(actx, b))
557 {
558 ans = query_quadoption(_("Can't decode all tagged attachments. MIME-forward the others?"),
559 NeoMutt->sub, "mime_forward_rest");
560 if (ans == MUTT_ABORT)
561 goto bail;
562 else if (ans == MUTT_NO)
563 mime_fwd_any = false;
564 }
565
566 /* initialize a state structure */
567
568 struct State state = { 0 };
569 if (c_forward_quote)
570 state.prefix = buf_string(prefix);
571 state.flags = STATE_CHARCONV;
572 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
573 if (c_weed)
574 state.flags |= STATE_WEED;
575 state.fp_out = fp_tmp;
576
577 /* where do we append new MIME parts? */
578 struct Body **last = &e_tmp->body;
579
580 if (b)
581 {
582 /* single body case */
583
584 if (!mime_fwd_all && mutt_can_decode(b))
585 {
586 state.fp_in = fp;
587 mutt_body_handler(b, &state);
588 state_putc(&state, '\n');
589 }
590 else
591 {
592 if (mutt_body_copy(fp, last, b) == -1)
593 goto bail;
594 }
595 }
596 else
597 {
598 /* multiple body case */
599
600 if (!mime_fwd_all)
601 {
602 for (int i = 0; i < actx->idxlen; i++)
603 {
604 if (actx->idx[i]->body->tagged && mutt_can_decode(actx->idx[i]->body))
605 {
606 state.fp_in = actx->idx[i]->fp;
607 mutt_body_handler(actx->idx[i]->body, &state);
608 state_putc(&state, '\n');
609 }
610 }
611 }
612
613 if (mime_fwd_any && !copy_problematic_attachments(last, actx, mime_fwd_all))
614 goto bail;
615 }
616
617 mutt_forward_trailer(e_parent, fp_tmp, NeoMutt->sub);
618
619 mutt_file_fclose(&fp_tmp);
620 fp_tmp = NULL;
621
622 /* now that we have the template, send it. */
623 struct EmailArray ea = ARRAY_HEAD_INITIALIZER;
624 ARRAY_ADD(&ea, e_parent);
625 mutt_send_message(SEND_NO_FLAGS, e_tmp, buf_string(tempfile), NULL, &ea,
626 NeoMutt->sub);
627 ARRAY_FREE(&ea);
628 buf_pool_release(&tempfile);
629 buf_pool_release(&prefix);
630 return;
631
632bail:
633 if (fp_tmp)
634 {
635 mutt_file_fclose(&fp_tmp);
636 mutt_file_unlink(buf_string(tempfile));
637 }
638 buf_pool_release(&tempfile);
639 buf_pool_release(&prefix);
640
641 email_free(&e_tmp);
642}
#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:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1659
#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:449
static bool check_can_decode(struct AttachCtx *actx, struct Body *b)
Can we decode all tagged attachments?
Definition recvcmd.c:110
static struct AttachPtr * find_parent(struct AttachCtx *actx, struct Body *b, short nattach)
Find the parent of an Attachment.
Definition recvcmd.c:370
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:403
void mutt_forward_intro(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition send.c:456
void mutt_make_forward_subject(struct Envelope *env, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition send.c:987
void mutt_forward_trailer(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition send.c:480
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:2037
#define SEND_NO_FLAGS
No flags are set.
Definition send.h:41
FILE * fp_root
Used by recvattach for updating.
Definition attach.h:65
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 658 of file recvcmd.c.

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

791{
792 if (check_all_msg(actx, b, false))
793 {
794 attach_forward_msgs(fp, actx, b, flags);
795 }
796 else
797 {
798 const short nattach = count_tagged(actx);
799 attach_forward_bodies(fp, e, actx, b, nattach);
800 }
801}
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:474
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:658
+ 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 822 of file recvcmd.c.

824{
825 struct Envelope *curenv = NULL;
826 struct Email *e = NULL;
827
828 if (parent)
829 {
830 curenv = parent->env;
831 e = parent;
832 }
833 else
834 {
835 for (short i = 0; i < actx->idxlen; i++)
836 {
837 if (actx->idx[i]->body->tagged)
838 {
839 e = actx->idx[i]->body->email;
840 curenv = e->env;
841 break;
842 }
843 }
844 }
845
846 if (!curenv || !e)
847 {
848 mutt_error(_("Can't find any tagged messages"));
849 return -1;
850 }
851
852 if ((flags & SEND_NEWS))
853 {
854 /* in case followup set Newsgroups: with Followup-To: if it present */
855 if (!env->newsgroups && curenv && !mutt_istr_equal(curenv->followup_to, "poster"))
856 {
858 }
859 }
860 else
861 {
862 if (parent)
863 {
864 if (mutt_fetch_recips(env, curenv, flags, NeoMutt->sub) == -1)
865 return -1;
866 }
867 else
868 {
869 for (short i = 0; i < actx->idxlen; i++)
870 {
871 if (actx->idx[i]->body->tagged &&
872 (mutt_fetch_recips(env, actx->idx[i]->body->email->env, flags,
873 NeoMutt->sub) == -1))
874 {
875 return -1;
876 }
877 }
878 }
879
880 if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
881 {
882 mutt_error(_("No mailing lists found"));
883 return -1;
884 }
885
887 }
889
890 if (parent)
891 {
893 }
894 else
895 {
896 for (short i = 0; i < actx->idxlen; i++)
897 {
898 if (actx->idx[i]->body->tagged)
899 {
901 NeoMutt->sub);
902 }
903 }
904 }
905
906 return 0;
907}
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
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:1007
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
Definition send.c:957
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition send.c:874
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:1035
#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 915 of file recvcmd.c.

916{
918 CopyHeaderFlags chflags = CH_DECODE;
919
921
922 const bool c_header = cs_subset_bool(NeoMutt->sub, "header");
923 if (!c_header)
924 cmflags |= MUTT_CM_NOHEADER;
925 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
926 if (c_weed)
927 {
928 chflags |= CH_WEED;
929 cmflags |= MUTT_CM_WEED;
930 }
931
932 mutt_copy_message_fp(fp_tmp, fp, e, cmflags, chflags, 0);
934}
#define MUTT_CM_NOHEADER
Don't copy the message header.
Definition copy_email.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:664
void mutt_make_attribution_trailer(struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition send.c:675
+ 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 945 of file recvcmd.c.

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

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