NeoMutt  2020-08-21-74-g346364
Teaching an old dog new tricks
DOXYGEN
recvcmd.c File Reference

Send/reply with an attachment. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.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 "send/lib.h"
#include "context.h"
#include "copy.h"
#include "handler.h"
#include "hdrline.h"
#include "init.h"
#include "mutt_body.h"
#include "mutt_globals.h"
#include "mutt_logging.h"
#include "muttlib.h"
#include "options.h"
#include "protos.h"
#include "state.h"
#include <libintl.h>
+ Include dependency graph for recvcmd.c:

Go to the source code of this file.

Macros

#define EXTRA_SPACE   (15 + 7 + 2)
 

Functions

static bool check_msg (struct Body *b, bool err)
 Are we working with an RFC822 message. More...
 
static bool check_all_msg (struct AttachCtx *actx, struct Body *cur, bool err)
 Are all the Attachments RFC822 messages? More...
 
static bool check_can_decode (struct AttachCtx *actx, struct Body *cur)
 Can we decode all tagged attachments? More...
 
static short count_tagged (struct AttachCtx *actx)
 Count the number of tagged attachments. More...
 
static short count_tagged_children (struct AttachCtx *actx, short i)
 tagged children below a multipart/message attachment More...
 
void mutt_attach_bounce (struct Mailbox *m, FILE *fp, struct AttachCtx *actx, struct Body *cur)
 Bounce function, from the attachment menu. More...
 
void mutt_attach_resend (FILE *fp, struct AttachCtx *actx, struct Body *cur)
 resend-message, from the attachment menu More...
 
static struct AttachPtrfind_common_parent (struct AttachCtx *actx, short nattach)
 find a common parent message for the tagged attachments More...
 
static int is_parent (short i, struct AttachCtx *actx, struct Body *cur)
 Check whether one attachment is the parent of another. More...
 
static struct AttachPtrfind_parent (struct AttachCtx *actx, struct Body *cur, short nattach)
 Find the parent of an Attachment. More...
 
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. More...
 
static struct Body ** copy_problematic_attachments (struct Body **last, struct AttachCtx *actx, bool force)
 Attach the body parts which can't be decoded. More...
 
static void attach_forward_bodies (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur, short nattach)
 forward one or several MIME bodies More...
 
static void attach_forward_msgs (FILE *fp, struct AttachCtx *actx, struct Body *cur, SendFlags flags)
 Forward one or several message-type attachments. More...
 
void mutt_attach_forward (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur, SendFlags flags)
 Forward an Attachment. More...
 
static int attach_reply_envelope_defaults (struct Envelope *env, struct AttachCtx *actx, struct Email *parent, SendFlags flags)
 Create the envelope defaults for a reply. More...
 
static void attach_include_reply (FILE *fp, FILE *fp_tmp, struct Email *e)
 This is very similar to send.c's include_reply() More...
 
void mutt_attach_reply (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *e_cur, SendFlags flags)
 Attach a reply. More...
 
void mutt_attach_mail_sender (FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur)
 Compose an email to the sender in the email attachment. More...
 

Variables

unsigned char C_MimeForwardRest
 Config: Forward all attachments, even if they can't be decoded. More...
 

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.

Macro Definition Documentation

◆ EXTRA_SPACE

#define EXTRA_SPACE   (15 + 7 + 2)

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

75 {
76  if (!mutt_is_message_type(b->type, b->subtype))
77  {
78  if (err)
79  mutt_error(_("You may only bounce message/rfc822 parts"));
80  return false;
81  }
82  return true;
83 }
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
#define _(a)
Definition: message.h:28
char * subtype
content-type subtype
Definition: body.h:37
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
#define mutt_error(...)
Definition: logging.h:84
+ 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 cur,
bool  err 
)
static

Are all the Attachments RFC822 messages?

Parameters
actxAttachment context
curCurrent message
errIf true, report errors
Return values
trueIf all parts are RFC822 messages

Definition at line 92 of file recvcmd.c.

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

◆ check_can_decode()

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

Can we decode all tagged attachments?

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

Definition at line 116 of file recvcmd.c.

117 {
118  if (cur)
119  return mutt_can_decode(cur);
120 
121  for (short i = 0; i < actx->idxlen; i++)
122  if (actx->idx[i]->body->tagged && !mutt_can_decode(actx->idx[i]->body))
123  return false;
124 
125  return true;
126 }
short idxlen
Number of attachmentes.
Definition: attach.h:55
bool tagged
This attachment is tagged.
Definition: body.h:70
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1803
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 133 of file recvcmd.c.

134 {
135  short count = 0;
136  for (short i = 0; i < actx->idxlen; i++)
137  if (actx->idx[i]->body->tagged)
138  count++;
139 
140  return count;
141 }
short idxlen
Number of attachmentes.
Definition: attach.h:55
bool tagged
This attachment is tagged.
Definition: body.h:70
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 149 of file recvcmd.c.

150 {
151  short level = actx->idx[i]->level;
152  short count = 0;
153 
154  while ((++i < actx->idxlen) && (level < actx->idx[i]->level))
155  if (actx->idx[i]->body->tagged)
156  count++;
157 
158  return count;
159 }
bool tagged
This attachment is tagged.
Definition: body.h:70
int level
Nesting depth of attachment.
Definition: attach.h:40
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the caller graph for this function:

◆ mutt_attach_bounce()

void mutt_attach_bounce ( struct Mailbox m,
FILE *  fp,
struct AttachCtx actx,
struct Body cur 
)

Bounce function, from the attachment menu.

Parameters
mMailbox
fpHandle of message
actxAttachment context
curBody of email

Definition at line 168 of file recvcmd.c.

169 {
170  if (!m || !fp || !actx)
171  return;
172 
173  char prompt[256];
174  char buf[8192];
175  char *err = NULL;
176  int ret = 0;
177  int p = 0;
178 
179  if (!check_all_msg(actx, cur, true))
180  return;
181 
182  /* one or more messages? */
183  p = cur ? 1 : count_tagged(actx);
184 
185  /* RFC5322 mandates a From: header, so warn before bouncing
186  * messages without one */
187  if (cur)
188  {
189  if (TAILQ_EMPTY(&cur->email->env->from))
190  {
191  mutt_error(_("Warning: message contains no From: header"));
193  }
194  }
195  else
196  {
197  for (short i = 0; i < actx->idxlen; i++)
198  {
199  if (actx->idx[i]->body->tagged)
200  {
201  if (TAILQ_EMPTY(&actx->idx[i]->body->email->env->from))
202  {
203  mutt_error(_("Warning: message contains no From: header"));
205  break;
206  }
207  }
208  }
209  }
210 
211  if (p)
212  mutt_str_copy(prompt, _("Bounce message to: "), sizeof(prompt));
213  else
214  mutt_str_copy(prompt, _("Bounce tagged messages to: "), sizeof(prompt));
215 
216  buf[0] = '\0';
217  if (mutt_get_field(prompt, buf, sizeof(buf), MUTT_ALIAS) || (buf[0] == '\0'))
218  return;
219 
220  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
221  mutt_addrlist_parse(&al, buf);
222  if (TAILQ_EMPTY(&al))
223  {
224  mutt_error(_("Error parsing address"));
225  return;
226  }
227 
228  mutt_expand_aliases(&al);
229 
230  if (mutt_addrlist_to_intl(&al, &err) < 0)
231  {
232  mutt_error(_("Bad IDN: '%s'"), err);
233  FREE(&err);
234  goto end;
235  }
236 
237  buf[0] = '\0';
238  mutt_addrlist_write(&al, buf, sizeof(buf), true);
239 
240 #define EXTRA_SPACE (15 + 7 + 2)
241  /* See commands.c. */
242  snprintf(prompt, sizeof(prompt) - 4,
243  ngettext("Bounce message to %s?", "Bounce messages to %s?", p), buf);
244 
246  {
247  mutt_simple_format(prompt, sizeof(prompt) - 4, 0, MessageWindow->state.cols - EXTRA_SPACE,
248  JUSTIFY_LEFT, 0, prompt, sizeof(prompt), false);
249  mutt_str_cat(prompt, sizeof(prompt), "...?");
250  }
251  else
252  mutt_str_cat(prompt, sizeof(prompt), "?");
253 
254  if (query_quadoption(C_Bounce, prompt) != MUTT_YES)
255  {
257  mutt_message(ngettext("Message not bounced", "Messages not bounced", p));
258  goto end;
259  }
260 
262 
263  if (cur)
264  ret = mutt_bounce_message(fp, cur->email, &al, NeoMutt->sub);
265  else
266  {
267  for (short i = 0; i < actx->idxlen; i++)
268  {
269  if (actx->idx[i]->body->tagged)
270  {
271  if (mutt_bounce_message(actx->idx[i]->fp, actx->idx[i]->body->email,
272  &al, NeoMutt->sub))
273  {
274  ret = 1;
275  }
276  }
277  }
278  }
279 
280  if (ret == 0)
281  mutt_message(ngettext("Message bounced", "Messages bounced", p));
282  else
283  mutt_error(ngettext("Error bouncing message", "Error bouncing messages", p));
284 
285 end:
286  mutt_addrlist_clear(&al);
287 }
int mutt_bounce_message(FILE *fp, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:1371
static bool check_all_msg(struct AttachCtx *actx, struct Body *cur, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:92
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
Left justify the text.
Definition: curs_lib.h:47
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:57
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
#define mutt_message(...)
Definition: logging.h:83
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:232
struct Envelope * env
Envelope information.
Definition: email.h:90
bool tagged
This attachment is tagged.
Definition: body.h:70
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
WHERE unsigned char C_Bounce
Config: Confirm before bouncing a message.
Definition: mutt_globals.h:124
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1359
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition: recvcmd.c:133
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
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:716
#define mutt_error(...)
Definition: logging.h:84
#define EXTRA_SPACE
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:1093
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 AttachCtx actx,
struct Body cur 
)

resend-message, from the attachment menu

Parameters
fpFile containing email
actxAttachment context
curAttachment

Definition at line 295 of file recvcmd.c.

296 {
297  if (!check_all_msg(actx, cur, true))
298  return;
299 
300  if (cur)
302  else
303  {
304  for (short i = 0; i < actx->idxlen; i++)
305  {
306  if (actx->idx[i]->body->tagged)
307  {
308  mutt_resend_message(actx->idx[i]->fp, Context,
309  actx->idx[i]->body->email, NeoMutt->sub);
310  }
311  }
312  }
313 }
The "current" mailbox.
Definition: context.h:38
static bool check_all_msg(struct AttachCtx *actx, struct Body *cur, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:92
short idxlen
Number of attachmentes.
Definition: attach.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
bool tagged
This attachment is tagged.
Definition: body.h:70
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
int mutt_resend_message(FILE *fp, struct Context *ctx, struct Email *e_cur, struct ConfigSubset *sub)
Resend an email.
Definition: send.c:1503
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 322 of file recvcmd.c.

323 {
324  short i;
325  short nchildren;
326 
327  for (i = 0; i < actx->idxlen; i++)
328  if (actx->idx[i]->body->tagged)
329  break;
330 
331  while (--i >= 0)
332  {
333  if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype))
334  {
335  nchildren = count_tagged_children(actx, i);
336  if (nchildren == nattach)
337  return actx->idx[i];
338  }
339  }
340 
341  return NULL;
342 }
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
short idxlen
Number of attachmentes.
Definition: attach.h:55
bool tagged
This attachment is tagged.
Definition: body.h:70
char * subtype
content-type subtype
Definition: body.h:37
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
static short count_tagged_children(struct AttachCtx *actx, short i)
tagged children below a multipart/message attachment
Definition: recvcmd.c:149
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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,
struct Body cur 
)
static

Check whether one attachment is the parent of another.

Parameters
iIndex of parent Attachment
actxAttachment context
curPotential child Attachemnt
Return values
trueAttachment

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

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

Definition at line 356 of file recvcmd.c.

357 {
358  short level = actx->idx[i]->level;
359 
360  while ((++i < actx->idxlen) && (actx->idx[i]->level > level))
361  {
362  if (actx->idx[i]->body == cur)
363  return true;
364  }
365 
366  return false;
367 }
int level
Nesting depth of attachment.
Definition: attach.h:40
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the caller graph for this function:

◆ find_parent()

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

Find the parent of an Attachment.

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

Definition at line 377 of file recvcmd.c.

378 {
379  struct AttachPtr *parent = NULL;
380 
381  if (cur)
382  {
383  for (short i = 0; i < actx->idxlen; i++)
384  {
385  if (mutt_is_message_type(actx->idx[i]->body->type, actx->idx[i]->body->subtype) &&
386  is_parent(i, actx, cur))
387  {
388  parent = actx->idx[i];
389  }
390  if (actx->idx[i]->body == cur)
391  break;
392  }
393  }
394  else if (nattach)
395  parent = find_common_parent(actx, nattach);
396 
397  return parent;
398 }
An email to which things will be attached.
Definition: attach.h:34
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
short idxlen
Number of attachmentes.
Definition: attach.h:55
char * subtype
content-type subtype
Definition: body.h:37
static int is_parent(short i, struct AttachCtx *actx, struct Body *cur)
Check whether one attachment is the parent of another.
Definition: recvcmd.c:356
static struct AttachPtr * find_common_parent(struct AttachCtx *actx, short nattach)
find a common parent message for the tagged attachments
Definition: recvcmd.c:322
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ include_header()

static void include_header ( bool  quote,
FILE *  fp_in,
struct Email e,
FILE *  fp_out,
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 408 of file recvcmd.c.

409 {
410  CopyHeaderFlags chflags = CH_DECODE;
411  char prefix2[128];
412 
413  if (C_Weed)
414  chflags |= CH_WEED | CH_REORDER;
415 
416  if (quote)
417  {
418  if (prefix)
419  mutt_str_copy(prefix2, prefix, sizeof(prefix2));
420  else if (!C_TextFlowed)
421  {
422  mutt_make_string(prefix2, sizeof(prefix2), 0, NONULL(C_IndentString),
424  }
425  else
426  mutt_str_copy(prefix2, ">", sizeof(prefix2));
427 
428  chflags |= CH_PREFIX;
429  }
430 
431  mutt_copy_header(fp_in, e, fp_out, chflags, quote ? prefix2 : NULL, 0);
432 }
The "current" mailbox.
Definition: context.h:38
#define NONULL(x)
Definition: string2.h:37
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
struct Mailbox * mailbox
Definition: context.h:50
#define CH_WEED
Weed the headers?
Definition: copy.h:52
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
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:716
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
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:398
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
#define CH_PREFIX
Quote header using C_IndentString string?
Definition: copy.h:56
#define mutt_make_string(BUF, BUFLEN, COLS, S, M, INPGR, E)
Definition: hdrline.h:58
WHERE char * C_IndentString
Config: String used to indent &#39;reply&#39; text.
Definition: mutt_globals.h:102
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: mutt_globals.h:165
+ 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 443 of file recvcmd.c.

445 {
446  for (short i = 0; i < actx->idxlen; i++)
447  {
448  if (actx->idx[i]->body->tagged && (force || !mutt_can_decode(actx->idx[i]->body)))
449  {
450  if (mutt_body_copy(actx->idx[i]->fp, last, actx->idx[i]->body) == -1)
451  return NULL; /* XXXXX - may lead to crashes */
452  last = &((*last)->next);
453  }
454  }
455  return last;
456 }
short idxlen
Number of attachmentes.
Definition: attach.h:55
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
bool tagged
This attachment is tagged.
Definition: body.h:70
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1803
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 cur,
short  nattach 
)
static

forward one or several MIME bodies

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

(non-message types)

Definition at line 468 of file recvcmd.c.

470 {
471  bool mime_fwd_all = false;
472  bool mime_fwd_any = true;
473  struct Email *e_parent = NULL;
474  FILE *fp_parent = NULL;
475  char prefix[256];
476  enum QuadOption ans = MUTT_NO;
477  struct Buffer *tmpbody = NULL;
478 
479  /* First, find the parent message.
480  * Note: This could be made an option by just
481  * putting the following lines into an if block. */
482  struct AttachPtr *parent = find_parent(actx, cur, nattach);
483  if (parent)
484  {
485  e_parent = parent->body->email;
486  fp_parent = parent->fp;
487  }
488  else
489  {
490  e_parent = e;
491  fp_parent = actx->fp_root;
492  }
493 
494  struct Email *e_tmp = email_new();
495  e_tmp->env = mutt_env_new();
496  mutt_make_forward_subject(e_tmp->env, Context->mailbox, e_parent, NeoMutt->sub);
497 
498  tmpbody = mutt_buffer_pool_get();
499  mutt_buffer_mktemp(tmpbody);
500  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tmpbody), "w");
501  if (!fp_tmp)
502  {
503  mutt_error(_("Can't open temporary file %s"), mutt_b2s(tmpbody));
504  email_free(&e_tmp);
505  goto bail;
506  }
507 
508  mutt_forward_intro(Context->mailbox, e_parent, fp_tmp, NeoMutt->sub);
509 
510  /* prepare the prefix here since we'll need it later. */
511 
512  if (C_ForwardQuote)
513  {
514  if (C_TextFlowed)
515  mutt_str_copy(prefix, ">", sizeof(prefix));
516  else
517  {
518  mutt_make_string(prefix, sizeof(prefix), 0, NONULL(C_IndentString),
519  Context->mailbox, Context->msg_in_pager, e_parent);
520  }
521  }
522 
523  include_header(C_ForwardQuote, fp_parent, e_parent, fp_tmp, prefix);
524 
525  /* Now, we have prepared the first part of the message body: The
526  * original message's header.
527  *
528  * The next part is more interesting: either include the message bodies,
529  * or attach them. */
530  if ((!cur || mutt_can_decode(cur)) &&
531  ((ans = query_quadoption(C_MimeForward, _("Forward as attachments?"))) == MUTT_YES))
532  {
533  mime_fwd_all = true;
534  }
535  else if (ans == MUTT_ABORT)
536  {
537  goto bail;
538  }
539 
540  /* shortcut MIMEFWDREST when there is only one attachment.
541  * Is this intuitive? */
542  if (!mime_fwd_all && !cur && (nattach > 1) && !check_can_decode(actx, cur))
543  {
544  ans = query_quadoption(
546  _("Can't decode all tagged attachments. MIME-forward the others?"));
547  if (ans == MUTT_ABORT)
548  goto bail;
549  else if (ans == MUTT_NO)
550  mime_fwd_any = false;
551  }
552 
553  /* initialize a state structure */
554 
555  struct State st = { 0 };
556  if (C_ForwardQuote)
557  st.prefix = prefix;
558  st.flags = MUTT_CHARCONV;
559  if (C_Weed)
560  st.flags |= MUTT_WEED;
561  st.fp_out = fp_tmp;
562 
563  /* where do we append new MIME parts? */
564  struct Body **last = &e_tmp->body;
565 
566  if (cur)
567  {
568  /* single body case */
569 
570  if (!mime_fwd_all && mutt_can_decode(cur))
571  {
572  st.fp_in = fp;
573  mutt_body_handler(cur, &st);
574  state_putc(&st, '\n');
575  }
576  else
577  {
578  if (mutt_body_copy(fp, last, cur) == -1)
579  goto bail;
580  }
581  }
582  else
583  {
584  /* multiple body case */
585 
586  if (!mime_fwd_all)
587  {
588  for (int i = 0; i < actx->idxlen; i++)
589  {
590  if (actx->idx[i]->body->tagged && mutt_can_decode(actx->idx[i]->body))
591  {
592  st.fp_in = actx->idx[i]->fp;
593  mutt_body_handler(actx->idx[i]->body, &st);
594  state_putc(&st, '\n');
595  }
596  }
597  }
598 
599  if (mime_fwd_any && !copy_problematic_attachments(last, actx, mime_fwd_all))
600  goto bail;
601  }
602 
603  mutt_forward_trailer(Context->mailbox, e_parent, fp_tmp, NeoMutt->sub);
604 
605  mutt_file_fclose(&fp_tmp);
606  fp_tmp = NULL;
607 
608  /* now that we have the template, send it. */
609  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
610  emaillist_add_email(&el, e_parent);
611  mutt_send_message(SEND_NO_FLAGS, e_tmp, mutt_b2s(tmpbody), NULL, &el, NeoMutt->sub);
612  emaillist_clear(&el);
613  mutt_buffer_pool_release(&tmpbody);
614  return;
615 
616 bail:
617  if (fp_tmp)
618  {
619  mutt_file_fclose(&fp_tmp);
620  mutt_file_unlink(mutt_b2s(tmpbody));
621  }
622  mutt_buffer_pool_release(&tmpbody);
623 
624  email_free(&e_tmp);
625 }
The "current" mailbox.
Definition: context.h:38
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
WHERE unsigned char C_MimeForward
Config: Forward a message as a &#39;message/RFC822&#39; MIME part.
Definition: mutt_globals.h:127
#define NONULL(x)
Definition: string2.h:37
An email to which things will be attached.
Definition: attach.h:34
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
The envelope/body of an email.
Definition: email.h:37
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:408
static bool check_can_decode(struct AttachCtx *actx, struct Body *cur)
Can we decode all tagged attachments?
Definition: recvcmd.c:116
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Body * body
List of MIME parts.
Definition: email.h:91
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:151
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
FILE * fp_out
File to write to.
Definition: state.h:47
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:40
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
struct Mailbox * mailbox
Definition: context.h:50
WHERE bool C_ForwardQuote
Config: Automatically quote a forwarded message using C_IndentString.
Definition: mutt_globals.h:147
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
bool tagged
This attachment is tagged.
Definition: body.h:70
User aborted the question (with Ctrl-G)
Definition: quad.h:38
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define mutt_b2s(buf)
Definition: buffer.h:41
static struct AttachPtr * find_parent(struct AttachCtx *actx, struct Body *cur, short nattach)
Find the parent of an Attachment.
Definition: recvcmd.c:377
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1803
void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition: send.c:400
#define MUTT_WEED
Weed headers even when not in display mode.
Definition: state.h:35
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
static struct Body ** copy_problematic_attachments(struct Body **last, struct AttachCtx *actx, bool force)
Attach the body parts which can&#39;t be decoded.
Definition: recvcmd.c:443
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:130
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:716
#define mutt_error(...)
Definition: logging.h:84
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1990
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
Keep track when processing files.
Definition: state.h:44
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
#define state_putc(STATE, STR)
Definition: state.h:56
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition: send.c:425
unsigned char C_MimeForwardRest
Config: Forward all attachments, even if they can&#39;t be decoded.
Definition: recvcmd.c:60
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition: send.c:903
#define mutt_make_string(BUF, BUFLEN, COLS, S, M, INPGR, E)
Definition: hdrline.h:58
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
WHERE char * C_IndentString
Config: String used to indent &#39;reply&#39; text.
Definition: mutt_globals.h:102
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: mutt_globals.h:165
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 cur,
SendFlags  flags 
)
static

Forward one or several message-type attachments.

Parameters
fpFile handle to attachment
actxAttachment Context
curAttachment 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 641 of file recvcmd.c.

643 {
644  struct Email *e_cur = NULL;
645  struct Email *e_tmp = NULL;
646  enum QuadOption ans;
647  struct Body **last = NULL;
648  struct Buffer *tmpbody = NULL;
649  FILE *fp_tmp = NULL;
650 
651  CopyHeaderFlags chflags = CH_XMIT;
652 
653  if (cur)
654  e_cur = cur->email;
655  else
656  {
657  for (short i = 0; i < actx->idxlen; i++)
658  {
659  if (actx->idx[i]->body->tagged)
660  {
661  e_cur = actx->idx[i]->body->email;
662  break;
663  }
664  }
665  }
666 
667  e_tmp = email_new();
668  e_tmp->env = mutt_env_new();
670 
671  tmpbody = mutt_buffer_pool_get();
672 
673  ans = query_quadoption(C_MimeForward, _("Forward MIME encapsulated?"));
674  if (ans == MUTT_NO)
675  {
676  /* no MIME encapsulation */
677 
678  mutt_buffer_mktemp(tmpbody);
679  fp_tmp = mutt_file_fopen(mutt_b2s(tmpbody), "w");
680  if (!fp_tmp)
681  {
682  mutt_error(_("Can't create %s"), mutt_b2s(tmpbody));
683  goto cleanup;
684  }
685 
687  if (C_ForwardQuote)
688  {
689  chflags |= CH_PREFIX;
690  cmflags |= MUTT_CM_PREFIX;
691  }
692 
693  if (C_ForwardDecode)
694  {
695  cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
696  if (C_Weed)
697  {
698  chflags |= CH_WEED | CH_REORDER;
699  cmflags |= MUTT_CM_WEED;
700  }
701  }
702 
703  if (cur)
704  {
706  mutt_copy_message_fp(fp_tmp, fp, cur->email, cmflags, chflags, 0);
708  }
709  else
710  {
711  for (short i = 0; i < actx->idxlen; i++)
712  {
713  if (actx->idx[i]->body->tagged)
714  {
716  fp_tmp, NeoMutt->sub);
717  mutt_copy_message_fp(fp_tmp, actx->idx[i]->fp,
718  actx->idx[i]->body->email, cmflags, chflags, 0);
720  fp_tmp, NeoMutt->sub);
721  }
722  }
723  }
724  mutt_file_fclose(&fp_tmp);
725  }
726  else if (ans == MUTT_YES) /* do MIME encapsulation - we don't need to do much here */
727  {
728  last = &e_tmp->body;
729  if (cur)
730  mutt_body_copy(fp, last, cur);
731  else
732  {
733  for (short i = 0; i < actx->idxlen; i++)
734  {
735  if (actx->idx[i]->body->tagged)
736  {
737  mutt_body_copy(actx->idx[i]->fp, last, actx->idx[i]->body);
738  last = &((*last)->next);
739  }
740  }
741  }
742  }
743  else
744  email_free(&e_tmp);
745 
746  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
747  emaillist_add_email(&el, e_cur);
748  mutt_send_message(flags, e_tmp, mutt_buffer_is_empty(tmpbody) ? NULL : mutt_b2s(tmpbody),
749  NULL, &el, NeoMutt->sub);
750  emaillist_clear(&el);
751  e_tmp = NULL; /* mutt_send_message frees this */
752 
753 cleanup:
754  email_free(&e_tmp);
755  mutt_buffer_pool_release(&tmpbody);
756 }
The "current" mailbox.
Definition: context.h:38
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
WHERE unsigned char C_MimeForward
Config: Forward a message as a &#39;message/RFC822&#39; MIME part.
Definition: mutt_globals.h:127
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
struct Body * body
List of MIME parts.
Definition: email.h:91
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:151
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:36
The body of an email.
Definition: body.h:34
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
struct Mailbox * mailbox
Definition: context.h:50
WHERE bool C_ForwardQuote
Config: Automatically quote a forwarded message using C_IndentString.
Definition: mutt_globals.h:147
#define CH_WEED
Weed the headers?
Definition: copy.h:52
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
bool tagged
This attachment is tagged.
Definition: body.h:70
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define mutt_b2s(buf)
Definition: buffer.h:41
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
WHERE bool C_ForwardDecode
Config: Decode the message when forwarding it.
Definition: mutt_globals.h:146
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add the "start of forwarded message" text.
Definition: send.c:400
#define CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition: copy.h:54
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:130
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
#define mutt_error(...)
Definition: logging.h:84
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1990
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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:609
void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp, struct ConfigSubset *sub)
Add a "end of forwarded message" text.
Definition: send.c:425
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
struct Email * email
header information for message/rfc822
Definition: body.h:55
#define CH_PREFIX
Quote header using C_IndentString string?
Definition: copy.h:56
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e, struct ConfigSubset *sub)
Create a subject for a forwarded email.
Definition: send.c:903
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct Body * body
Attachment.
Definition: attach.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 cur,
SendFlags  flags 
)

Forward an Attachment.

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

Definition at line 766 of file recvcmd.c.

768 {
769  if (check_all_msg(actx, cur, false))
770  attach_forward_msgs(fp, actx, cur, flags);
771  else
772  {
773  const short nattach = count_tagged(actx);
774  attach_forward_bodies(fp, e, actx, cur, nattach);
775  }
776 }
static bool check_all_msg(struct AttachCtx *actx, struct Body *cur, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:92
static void attach_forward_msgs(FILE *fp, struct AttachCtx *actx, struct Body *cur, SendFlags flags)
Forward one or several message-type attachments.
Definition: recvcmd.c:641
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition: recvcmd.c:133
static void attach_forward_bodies(FILE *fp, struct Email *e, struct AttachCtx *actx, struct Body *cur, short nattach)
forward one or several MIME bodies
Definition: recvcmd.c:468
+ 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 797 of file recvcmd.c.

799 {
800  struct Envelope *curenv = NULL;
801  struct Email *e = NULL;
802 
803  if (!parent)
804  {
805  for (short i = 0; i < actx->idxlen; i++)
806  {
807  if (actx->idx[i]->body->tagged)
808  {
809  e = actx->idx[i]->body->email;
810  curenv = e->env;
811  break;
812  }
813  }
814  }
815  else
816  {
817  curenv = parent->env;
818  e = parent;
819  }
820 
821  if (!curenv || !e)
822  {
823  mutt_error(_("Can't find any tagged messages"));
824  return -1;
825  }
826 
827 #ifdef USE_NNTP
828  if ((flags & SEND_NEWS))
829  {
830  /* in case followup set Newsgroups: with Followup-To: if it present */
831  if (!env->newsgroups && curenv && !mutt_istr_equal(curenv->followup_to, "poster"))
832  {
833  env->newsgroups = mutt_str_dup(curenv->followup_to);
834  }
835  }
836  else
837 #endif
838  {
839  if (parent)
840  {
841  if (mutt_fetch_recips(env, curenv, flags, NeoMutt->sub) == -1)
842  return -1;
843  }
844  else
845  {
846  for (short i = 0; i < actx->idxlen; i++)
847  {
848  if (actx->idx[i]->body->tagged &&
849  (mutt_fetch_recips(env, actx->idx[i]->body->email->env, flags,
850  NeoMutt->sub) == -1))
851  {
852  return -1;
853  }
854  }
855  }
856 
857  if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
858  {
859  mutt_error(_("No mailing lists found"));
860  return -1;
861  }
862 
864  }
866 
867  if (parent)
869  else
870  {
871  for (short i = 0; i < actx->idxlen; i++)
872  {
873  if (actx->idx[i]->body->tagged)
874  {
876  NeoMutt->sub);
877  }
878  }
879  }
880 
881  return 0;
882 }
The envelope/body of an email.
Definition: email.h:37
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
struct Envelope * env
Envelope information.
Definition: email.h:90
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:43
bool tagged
This attachment is tagged.
Definition: body.h:70
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
void mutt_fix_reply_recipients(struct Envelope *env, struct ConfigSubset *sub)
Remove duplicate recipients.
Definition: send.c:872
#define SEND_NEWS
Reply to a news article.
Definition: send.h:54
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition: send.c:785
char * newsgroups
List of newsgroups.
Definition: envelope.h:75
#define mutt_error(...)
Definition: logging.h:84
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:77
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
Set subject for a reply.
Definition: send.c:923
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:714
struct Email * email
header information for message/rfc822
Definition: body.h:55
void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *curenv, struct ConfigSubset *sub)
Generate references for a reply email.
Definition: send.c:950
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
The header of an Email.
Definition: envelope.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 890 of file recvcmd.c.

891 {
893  CopyHeaderFlags chflags = CH_DECODE;
894 
896 
897  if (!C_Header)
898  cmflags |= MUTT_CM_NOHEADER;
899  if (C_Weed)
900  {
901  chflags |= CH_WEED;
902  cmflags |= MUTT_CM_WEED;
903  }
904 
905  mutt_copy_message_fp(fp_tmp, fp, e, cmflags, chflags, 0);
907 }
void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add "on DATE, PERSON wrote" header.
Definition: send.c:580
The "current" mailbox.
Definition: context.h:38
WHERE bool C_Header
Config: Include the message headers in the reply email (Weed applies)
Definition: mutt_globals.h:148
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
Container for Accounts, Notifications.
Definition: neomutt.h:36
struct Mailbox * mailbox
Definition: context.h:50
#define CH_WEED
Weed the headers?
Definition: copy.h:52
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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:609
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition: send.c:605
+ 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 Email e,
struct AttachCtx actx,
struct Body e_cur,
SendFlags  flags 
)

Attach a reply.

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

Definition at line 917 of file recvcmd.c.

919 {
920  bool mime_reply_any = false;
921 
922  short nattach = 0;
923  struct AttachPtr *parent = NULL;
924  struct Email *e_parent = NULL;
925  FILE *fp_parent = NULL;
926  struct Email *e_tmp = NULL;
927  FILE *fp_tmp = NULL;
928  struct Buffer *tmpbody = NULL;
929 
930  char prefix[128];
931 
932 #ifdef USE_NNTP
933  if (flags & SEND_NEWS)
934  OptNewsSend = true;
935  else
936  OptNewsSend = false;
937 #endif
938 
939  if (!check_all_msg(actx, e_cur, false))
940  {
941  nattach = count_tagged(actx);
942  parent = find_parent(actx, e_cur, nattach);
943  if (parent)
944  {
945  e_parent = parent->body->email;
946  fp_parent = parent->fp;
947  }
948  else
949  {
950  e_parent = e;
951  fp_parent = actx->fp_root;
952  }
953  }
954 
955  if ((nattach > 1) && !check_can_decode(actx, e_cur))
956  {
957  const enum QuadOption ans = query_quadoption(
958  C_MimeForwardRest, _("Can't decode all tagged attachments. "
959  "MIME-encapsulate the others?"));
960  if (ans == MUTT_ABORT)
961  return;
962  if (ans == MUTT_YES)
963  mime_reply_any = true;
964  }
965  else if (nattach == 1)
966  mime_reply_any = true;
967 
968  e_tmp = email_new();
969  e_tmp->env = mutt_env_new();
970 
972  e_tmp->env, actx, e_parent ? e_parent : (e_cur ? e_cur->email : NULL), flags) == -1)
973  {
974  goto cleanup;
975  }
976 
977  tmpbody = mutt_buffer_pool_get();
978  mutt_buffer_mktemp(tmpbody);
979  fp_tmp = mutt_file_fopen(mutt_b2s(tmpbody), "w");
980  if (!fp_tmp)
981  {
982  mutt_error(_("Can't create %s"), mutt_b2s(tmpbody));
983  goto cleanup;
984  }
985 
986  if (!e_parent)
987  {
988  if (e_cur)
989  attach_include_reply(fp, fp_tmp, e_cur->email);
990  else
991  {
992  for (short i = 0; i < actx->idxlen; i++)
993  {
994  if (actx->idx[i]->body->tagged)
995  attach_include_reply(actx->idx[i]->fp, fp_tmp, actx->idx[i]->body->email);
996  }
997  }
998  }
999  else
1000  {
1001  mutt_make_attribution(Context->mailbox, e_parent, fp_tmp, NeoMutt->sub);
1002 
1003  struct State st;
1004  memset(&st, 0, sizeof(struct State));
1005  st.fp_out = fp_tmp;
1006 
1007  if (C_TextFlowed)
1008  {
1009  mutt_str_copy(prefix, ">", sizeof(prefix));
1010  }
1011  else
1012  {
1013  mutt_make_string(prefix, sizeof(prefix), 0, NONULL(C_IndentString),
1014  Context->mailbox, Context->msg_in_pager, e_parent);
1015  }
1016 
1017  st.prefix = prefix;
1018  st.flags = MUTT_CHARCONV;
1019 
1020  if (C_Weed)
1021  st.flags |= MUTT_WEED;
1022 
1023  if (C_Header)
1024  include_header(true, fp_parent, e_parent, fp_tmp, prefix);
1025 
1026  if (e_cur)
1027  {
1028  if (mutt_can_decode(e_cur))
1029  {
1030  st.fp_in = fp;
1031  mutt_body_handler(e_cur, &st);
1032  state_putc(&st, '\n');
1033  }
1034  else
1035  mutt_body_copy(fp, &e_tmp->body, e_cur);
1036  }
1037  else
1038  {
1039  for (short i = 0; i < actx->idxlen; i++)
1040  {
1041  if (actx->idx[i]->body->tagged && mutt_can_decode(actx->idx[i]->body))
1042  {
1043  st.fp_in = actx->idx[i]->fp;
1044  mutt_body_handler(actx->idx[i]->body, &st);
1045  state_putc(&st, '\n');
1046  }
1047  }
1048  }
1049 
1050  mutt_make_post_indent(Context->mailbox, e_parent, fp_tmp, NeoMutt->sub);
1051 
1052  if (mime_reply_any && !e_cur && !copy_problematic_attachments(&e_tmp->body, actx, false))
1053  {
1054  goto cleanup;
1055  }
1056  }
1057 
1058  mutt_file_fclose(&fp_tmp);
1059 
1060  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1061  emaillist_add_email(&el, e_parent ? e_parent : (e_cur ? e_cur->email : NULL));
1062  if (mutt_send_message(flags, e_tmp, mutt_b2s(tmpbody), NULL, &el, NeoMutt->sub) == 0)
1063  {
1065  }
1066  e_tmp = NULL; /* mutt_send_message frees this */
1067 
1068 cleanup:
1069  if (fp_tmp)
1070  {
1071  mutt_file_fclose(&fp_tmp);
1072  mutt_file_unlink(mutt_b2s(tmpbody));
1073  }
1074  mutt_buffer_pool_release(&tmpbody);
1075  email_free(&e_tmp);
1076  emaillist_clear(&el);
1077 }
void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add "on DATE, PERSON wrote" header.
Definition: send.c:580
The "current" mailbox.
Definition: context.h:38
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define NONULL(x)
Definition: string2.h:37
An email to which things will be attached.
Definition: attach.h:34
static bool check_all_msg(struct AttachCtx *actx, struct Body *cur, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:92
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
The envelope/body of an email.
Definition: email.h:37
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:408
static bool check_can_decode(struct AttachCtx *actx, struct Body *cur)
Can we decode all tagged attachments?
Definition: recvcmd.c:116
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static void attach_include_reply(FILE *fp, FILE *fp_tmp, struct Email *e)
This is very similar to send.c&#39;s include_reply()
Definition: recvcmd.c:890
struct Body * body
List of MIME parts.
Definition: email.h:91
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
int emaillist_add_email(struct EmailList *el, struct Email *e)
Add an Email to a list.
Definition: email.c:151
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
WHERE bool C_Header
Config: Include the message headers in the reply email (Weed applies)
Definition: mutt_globals.h:148
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
String manipulation buffer.
Definition: buffer.h:33
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
Messages that have been replied to.
Definition: mutt.h:95
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
struct Mailbox * mailbox
Definition: context.h:50
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
bool tagged
This attachment is tagged.
Definition: body.h:70
User aborted the question (with Ctrl-G)
Definition: quad.h:38
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
#define mutt_b2s(buf)
Definition: buffer.h:41
static struct AttachPtr * find_parent(struct AttachCtx *actx, struct Body *cur, short nattach)
Find the parent of an Attachment.
Definition: recvcmd.c:377
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1803
#define MUTT_WEED
Weed headers even when not in display mode.
Definition: state.h:35
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
static short count_tagged(struct AttachCtx *actx)
Count the number of tagged attachments.
Definition: recvcmd.c:133
#define SEND_NEWS
Reply to a news article.
Definition: send.h:54
static struct Body ** copy_problematic_attachments(struct Body **last, struct AttachCtx *actx, bool force)
Attach the body parts which can&#39;t be decoded.
Definition: recvcmd.c:443
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
void emaillist_clear(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:130
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:716
#define mutt_error(...)
Definition: logging.h:84
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1990
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
Keep track when processing files.
Definition: state.h:44
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1593
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
#define state_putc(STATE, STR)
Definition: state.h:56
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
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:797
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:46
unsigned char C_MimeForwardRest
Config: Forward all attachments, even if they can&#39;t be decoded.
Definition: recvcmd.c:60
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out, struct ConfigSubset *sub)
Add suffix to replied email text.
Definition: send.c:605
#define mutt_make_string(BUF, BUFLEN, COLS, S, M, INPGR, E)
Definition: hdrline.h:58
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
WHERE char * C_IndentString
Config: String used to indent &#39;reply&#39; text.
Definition: mutt_globals.h:102
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: mutt_globals.h:165
struct Body * body
Attachment.
Definition: attach.h:36
+ 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 ( FILE *  fp,
struct Email e,
struct AttachCtx actx,
struct Body cur 
)

Compose an email to the sender in the email attachment.

Parameters
fpFile containing attachment (UNUSED)
eEmail (UNUSED)
actxAttachment Context
curCurrent attachment

Definition at line 1086 of file recvcmd.c.

1088 {
1089  if (!check_all_msg(actx, cur, 0))
1090  {
1091  /* L10N: You will see this error message if you invoke <compose-to-sender>
1092  when you are on a normal attachment. */
1093  mutt_error(_("You may only compose to sender with message/rfc822 parts"));
1094  return;
1095  }
1096 
1097  struct Email *e_tmp = email_new();
1098  e_tmp->env = mutt_env_new();
1099 
1100  if (cur)
1101  {
1102  if (mutt_fetch_recips(e_tmp->env, cur->email->env, SEND_TO_SENDER, NeoMutt->sub) == -1)
1103  {
1104  email_free(&e_tmp);
1105  return;
1106  }
1107  }
1108  else
1109  {
1110  for (int i = 0; i < actx->idxlen; i++)
1111  {
1112  if (actx->idx[i]->body->tagged &&
1113  (mutt_fetch_recips(e_tmp->env, actx->idx[i]->body->email->env,
1114  SEND_TO_SENDER, NeoMutt->sub) == -1))
1115  {
1116  email_free(&e_tmp);
1117  return;
1118  }
1119  }
1120  }
1121 
1122  // This call will free e_tmp for us
1123  mutt_send_message(SEND_NO_FLAGS, e_tmp, NULL, NULL, NULL, NeoMutt->sub);
1124 }
static bool check_all_msg(struct AttachCtx *actx, struct Body *cur, bool err)
Are all the Attachments RFC822 messages?
Definition: recvcmd.c:92
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:52
The envelope/body of an email.
Definition: email.h:37
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:40
struct Envelope * env
Envelope information.
Definition: email.h:90
bool tagged
This attachment is tagged.
Definition: body.h:70
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags, struct ConfigSubset *sub)
Generate recpients for a reply email.
Definition: send.c:785
#define mutt_error(...)
Definition: logging.h:84
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el, struct ConfigSubset *sub)
Send an email.
Definition: send.c:1990
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
struct Email * email
header information for message/rfc822
Definition: body.h:55
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Body * body
Attachment.
Definition: attach.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_MimeForwardRest

unsigned char C_MimeForwardRest

Config: Forward all attachments, even if they can't be decoded.

Definition at line 60 of file recvcmd.c.