NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
recvcmd.c File Reference

Send/reply with an attachment. More...

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

Go to the source code of this file.

Functions

static bool check_msg (struct Body *b, bool err)
 Are we working with an RFC822 message.
 
static bool check_all_msg (struct AttachCtx *actx, struct Body *b, bool err)
 Are all the Attachments RFC822 messages?
 
static bool check_can_decode (struct AttachCtx *actx, struct Body *b)
 Can we decode all tagged attachments?
 
static short count_tagged (struct AttachCtx *actx)
 Count the number of tagged attachments.
 
static short count_tagged_children (struct AttachCtx *actx, short i)
 Tagged children below a multipart/message attachment.
 
void attach_bounce_message (struct Mailbox *m, FILE *fp, struct AttachCtx *actx, struct Body *b)
 Bounce function, from the attachment menu.
 
void mutt_attach_resend (FILE *fp, struct Mailbox *m, struct AttachCtx *actx, struct Body *b)
 Resend-message, from the attachment menu.
 
static struct AttachPtrfind_common_parent (struct AttachCtx *actx, short nattach)
 Find a common parent message for the tagged attachments.
 
static int is_parent (short i, struct AttachCtx *actx, const struct Body *b)
 Check whether one attachment is the parent of another.
 
static struct AttachPtrfind_parent (struct AttachCtx *actx, struct Body *b, short nattach)
 Find the parent of an Attachment.
 
static void include_header (bool quote, FILE *fp_in, struct Email *e, FILE *fp_out, 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
  • Pietro Cerutti

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 69 of file recvcmd.c.

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

◆ check_all_msg()

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

Are all the Attachments RFC822 messages?

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

Definition at line 87 of file recvcmd.c.

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

◆ check_can_decode()

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

Can we decode all tagged attachments?

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

Definition at line 111 of file recvcmd.c.

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

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

145{
146 short level = actx->idx[i]->level;
147 short count = 0;
148
149 while ((++i < actx->idxlen) && (level < actx->idx[i]->level))
150 if (actx->idx[i]->body->tagged)
151 count++;
152
153 return count;
154}
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 163 of file recvcmd.c.

165{
166 if (!m || !fp || !actx)
167 return;
168
169 if (!check_all_msg(actx, b, true))
170 return;
171
172 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
173 struct Buffer *prompt = buf_pool_get();
174 struct Buffer *buf = buf_pool_get();
175
176 /* RFC5322 mandates a From: header, so warn before bouncing
177 * messages without one */
178 if (b)
179 {
180 if (TAILQ_EMPTY(&b->email->env->from))
181 {
182 mutt_error(_("Warning: message contains no From: header"));
184 }
185 }
186 else
187 {
188 for (short i = 0; i < actx->idxlen; i++)
189 {
190 if (actx->idx[i]->body->tagged)
191 {
192 if (TAILQ_EMPTY(&actx->idx[i]->body->email->env->from))
193 {
194 mutt_error(_("Warning: message contains no From: header"));
196 break;
197 }
198 }
199 }
200 }
201
202 /* one or more messages? */
203 int num_msg = b ? 1 : count_tagged(actx);
204 if (num_msg == 1)
205 buf_strcpy(prompt, _("Bounce message to: "));
206 else
207 buf_strcpy(prompt, _("Bounce tagged messages to: "));
208
210 &CompleteAliasOps, NULL) != 0) ||
211 buf_is_empty(buf))
212 {
213 goto done;
214 }
215
217 if (TAILQ_EMPTY(&al))
218 {
219 mutt_error(_("Error parsing address"));
220 goto done;
221 }
222
224
225 char *err = NULL;
226 if (mutt_addrlist_to_intl(&al, &err) < 0)
227 {
228 mutt_error(_("Bad IDN: '%s'"), err);
229 FREE(&err);
230 goto done;
231 }
232
233 buf_reset(buf);
234 buf_alloc(buf, 8192);
235 mutt_addrlist_write(&al, buf, true);
236
237 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", num_msg),
238 buf_string(buf));
239
240 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
241 {
242 msgwin_clear_text(NULL);
243 mutt_message(ngettext("Message not bounced", "Messages not bounced", num_msg));
244 goto done;
245 }
246
247 msgwin_clear_text(NULL);
248
249 int rc = 0;
250 if (b)
251 {
252 rc = mutt_bounce_message(fp, m, b->email, &al, NeoMutt->sub);
253 }
254 else
255 {
256 for (short i = 0; i < actx->idxlen; i++)
257 {
258 if (actx->idx[i]->body->tagged)
259 {
260 if (mutt_bounce_message(actx->idx[i]->fp, m, actx->idx[i]->body->email,
261 &al, NeoMutt->sub))
262 {
263 rc = 1;
264 }
265 }
266 }
267 }
268
269 if (rc == 0)
270 mutt_message(ngettext("Message bounced", "Messages bounced", num_msg));
271 else
272 mutt_error(ngettext("Error bouncing message", "Error bouncing messages", num_msg));
273
274done:
276 buf_pool_release(&buf);
277 buf_pool_release(&prompt);
278}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1207
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:478
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1294
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:298
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
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:275
#define mutt_message(...)
Definition: logging2.h:91
@ HC_ALIAS
Aliases.
Definition: lib.h:52
#define FREE(x)
Definition: memory.h:45
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:516
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:369
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition: recvcmd.c:128
static bool check_all_msg(struct AttachCtx *actx, struct Body *b, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:87
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:915
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
struct Email * email
header information for message/rfc822
Definition: body.h:73
String manipulation buffer.
Definition: buffer.h:34
struct Envelope * env
Envelope information.
Definition: email.h:66
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:45
+ 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 287 of file recvcmd.c.

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

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

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

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

405{
406 CopyHeaderFlags chflags = CH_DECODE;
407 char prefix2[128];
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 mutt_str_copy(prefix2, prefix, sizeof(prefix2));
419 }
420 else if (!c_text_flowed)
421 {
422 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
423 const char *const c_indent_string = cs_subset_string(NeoMutt->sub, "indent_string");
424 setlocale(LC_TIME, NONULL(c_attribution_locale));
425 mutt_make_string(prefix2, sizeof(prefix2), 0, NONULL(c_indent_string),
426 NULL, -1, e, MUTT_FORMAT_NO_FLAGS, NULL);
427 setlocale(LC_TIME, "");
428 }
429 else
430 {
431 mutt_str_copy(prefix2, ">", sizeof(prefix2));
432 }
433
434 chflags |= CH_PREFIX;
435 }
436
437 mutt_copy_header(fp_in, e, fp_out, chflags, quote ? prefix2 : NULL, 0);
438}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition: copy.c:423
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:54
#define CH_PREFIX
Quote header using $indent_string string?
Definition: copy.h:57
#define CH_WEED
Weed the headers?
Definition: copy.h:53
#define CH_REORDER
Re-order output of headers (specified by 'hdr_order')
Definition: copy.h:59
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
void mutt_make_string(char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1422
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
#define NONULL(x)
Definition: string2.h:37
+ 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: mutt_body.c:48
+ 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 char prefix[256] = { 0 };
482 enum QuadOption ans = MUTT_NO;
483 struct Buffer *tmpbody = NULL;
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 tmpbody = buf_pool_get();
505 buf_mktemp(tmpbody);
506 FILE *fp_tmp = mutt_file_fopen(buf_string(tmpbody), "w");
507 if (!fp_tmp)
508 {
509 mutt_error(_("Can't open temporary file %s"), buf_string(tmpbody));
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 mutt_str_copy(prefix, ">", sizeof(prefix));
525 }
526 else
527 {
528 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
529 const char *const c_indent_string = cs_subset_string(NeoMutt->sub, "indent_string");
530 setlocale(LC_TIME, NONULL(c_attribution_locale));
531 mutt_make_string(prefix, sizeof(prefix), 0, NONULL(c_indent_string), NULL,
532 -1, e_parent, MUTT_FORMAT_NO_FLAGS, NULL);
533 setlocale(LC_TIME, "");
534 }
535 }
536
537 include_header(c_forward_quote, fp_parent, e_parent, fp_tmp, 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 = 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(tmpbody), NULL, &ea,
626 NeoMutt->sub);
627 ARRAY_FREE(&ea);
628 buf_pool_release(&tmpbody);
629 return;
630
631bail:
632 if (fp_tmp)
633 {
634 mutt_file_fclose(&fp_tmp);
636 }
637 buf_pool_release(&tmpbody);
638
639 email_free(&e_tmp);
640}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:155
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:196
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1624
#define STATE_WEED
Weed headers even when not in display mode.
Definition: state.h:35
#define state_putc(STATE, STR)
Definition: state.h:58
#define STATE_CHARCONV
Do character set conversions.
Definition: state.h:36
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:111
static struct AttachPtr * find_parent(struct AttachCtx *actx, struct Body *b, short nattach)
Find the parent of an Attachment.
Definition: recvcmd.c:371
static void include_header(bool quote, FILE *fp_in, struct Email *e, FILE *fp_out, char *prefix)
Write an email header to a file, optionally quoting it.
Definition: recvcmd.c:404
void mutt_forward_intro(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition: send.c:440
void mutt_make_forward_subject(struct Envelope *env, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition: send.c:1037
void mutt_forward_trailer(struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition: send.c:463
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:2099
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:39
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:53
The body of an email.
Definition: body.h:36
The envelope/body of an email.
Definition: email.h:37
struct Body * body
List of MIME parts.
Definition: email.h:67
Keep track when processing files.
Definition: state.h:47
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:51
FILE * fp_out
File to write to.
Definition: state.h:49
char * prefix
String to add to the beginning of each output line.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:48
#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 656 of file recvcmd.c.

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

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

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

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

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

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