NeoMutt  2025-12-11-911-gd8d604
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
copy_email.h File Reference

Duplicate the structure of an entire email. More...

#include "config.h"
#include <stdint.h>
#include <stdio.h>
+ Include dependency graph for copy_email.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_CM_DECODE_CRYPT   (MUTT_CM_DECODE_PGP | MUTT_CM_DECODE_SMIME)
 Combination flag for decoding any kind of cryptography (PGP or S/MIME)
 

Typedefs

typedef uint16_t CopyMessageFlags
 
typedef uint32_t CopyHeaderFlags
 

Enumerations

enum  CopyMessageFlag {
  MUTT_CM_NONE = 0 , MUTT_CM_NOHEADER = 1U << 0 , MUTT_CM_PREFIX = 1U << 1 , MUTT_CM_DECODE = 1U << 2 ,
  MUTT_CM_DISPLAY = 1U << 3 , MUTT_CM_UPDATE = 1U << 4 , MUTT_CM_WEED = 1U << 5 , MUTT_CM_CHARCONV = 1U << 6 ,
  MUTT_CM_PRINTING = 1U << 7 , MUTT_CM_REPLYING = 1U << 8 , MUTT_CM_DECODE_PGP = 1U << 9 , MUTT_CM_DECODE_SMIME = 1U << 10 ,
  MUTT_CM_VERIFY = 1U << 11
}
 Flags for mutt_copy_message(), e.g. More...
 
enum  CopyHeaderFlag {
  CH_NONE = 0 , CH_UPDATE = 1U << 0 , CH_WEED = 1U << 1 , CH_DECODE = 1U << 2 ,
  CH_XMIT = 1U << 3 , CH_FROM = 1U << 4 , CH_PREFIX = 1U << 5 , CH_NOSTATUS = 1U << 6 ,
  CH_REORDER = 1U << 7 , CH_NONEWLINE = 1U << 8 , CH_MIME = 1U << 9 , CH_UPDATE_LEN = 1U << 10 ,
  CH_TXTPLAIN = 1U << 11 , CH_NOLEN = 1U << 12 , CH_WEED_DELIVERED = 1U << 13 , CH_FORCE_FROM = 1U << 14 ,
  CH_NOQFROM = 1U << 15 , CH_UPDATE_IRT = 1U << 16 , CH_UPDATE_REFS = 1U << 17 , CH_DISPLAY = 1U << 18 ,
  CH_UPDATE_LABEL = 1U << 19 , CH_UPDATE_SUBJECT = 1U << 20 , CH_VIRTUAL = 1U << 21
}
 Flags for mutt_copy_header(), e.g. More...
 

Functions

int mutt_copy_hdr (FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
 Copy header from one file to another.
 
int mutt_copy_header (FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
 Copy Email header.
 
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.
 
int mutt_copy_message (FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
 Copy a message from a Mailbox.
 
int mutt_append_message (struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
 Append a message.
 

Detailed Description

Duplicate the structure of an entire email.

Authors
  • Michael R. Elkins
  • Richard Russon
  • 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 copy_email.h.

Macro Definition Documentation

◆ MUTT_CM_DECODE_CRYPT

#define MUTT_CM_DECODE_CRYPT   (MUTT_CM_DECODE_PGP | MUTT_CM_DECODE_SMIME)

Combination flag for decoding any kind of cryptography (PGP or S/MIME)

Definition at line 58 of file copy_email.h.

Typedef Documentation

◆ CopyMessageFlags

typedef uint16_t CopyMessageFlags

Definition at line 55 of file copy_email.h.

◆ CopyHeaderFlags

typedef uint32_t CopyHeaderFlags

Definition at line 89 of file copy_email.h.

Enumeration Type Documentation

◆ CopyMessageFlag

Flags for mutt_copy_message(), e.g.

MUTT_CM_NOHEADER

Enumerator
MUTT_CM_NONE 

No flags are set.

MUTT_CM_NOHEADER 

Don't copy the message header.

MUTT_CM_PREFIX 

Quote the header and body.

MUTT_CM_DECODE 

Decode the message body into text/plain.

MUTT_CM_DISPLAY 

Output is displayed to the user.

MUTT_CM_UPDATE 

Update structs on sync.

MUTT_CM_WEED 

Weed message/rfc822 attachment headers.

MUTT_CM_CHARCONV 

Perform character set conversions.

MUTT_CM_PRINTING 

Printing the message - display light.

MUTT_CM_REPLYING 

Replying the message.

MUTT_CM_DECODE_PGP 

Used for decoding PGP messages.

MUTT_CM_DECODE_SMIME 

Used for decoding S/MIME messages.

MUTT_CM_VERIFY 

Do signature verification.

Definition at line 39 of file copy_email.h.

40{
41 MUTT_CM_NONE = 0,
42 MUTT_CM_NOHEADER = 1U << 0,
43 MUTT_CM_PREFIX = 1U << 1,
44 MUTT_CM_DECODE = 1U << 2,
45 MUTT_CM_DISPLAY = 1U << 3,
46 MUTT_CM_UPDATE = 1U << 4,
47 MUTT_CM_WEED = 1U << 5,
48 MUTT_CM_CHARCONV = 1U << 6,
49 MUTT_CM_PRINTING = 1U << 7,
50 MUTT_CM_REPLYING = 1U << 8,
51 MUTT_CM_DECODE_PGP = 1U << 9,
52 MUTT_CM_DECODE_SMIME = 1U << 10,
53 MUTT_CM_VERIFY = 1U << 11,
54};
@ MUTT_CM_PREFIX
Quote the header and body.
Definition copy_email.h:43
@ MUTT_CM_REPLYING
Replying the message.
Definition copy_email.h:50
@ MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition copy_email.h:52
@ MUTT_CM_DECODE_PGP
Used for decoding PGP messages.
Definition copy_email.h:51
@ MUTT_CM_DECODE
Decode the message body into text/plain.
Definition copy_email.h:44
@ MUTT_CM_NOHEADER
Don't copy the message header.
Definition copy_email.h:42
@ MUTT_CM_PRINTING
Printing the message - display light.
Definition copy_email.h:49
@ MUTT_CM_CHARCONV
Perform character set conversions.
Definition copy_email.h:48
@ MUTT_CM_UPDATE
Update structs on sync.
Definition copy_email.h:46
@ MUTT_CM_DISPLAY
Output is displayed to the user.
Definition copy_email.h:45
@ MUTT_CM_VERIFY
Do signature verification.
Definition copy_email.h:53
@ MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition copy_email.h:47
@ MUTT_CM_NONE
No flags are set.
Definition copy_email.h:41

◆ CopyHeaderFlag

Flags for mutt_copy_header(), e.g.

CH_UPDATE

Enumerator
CH_NONE 

No flags are set.

CH_UPDATE 

Update the status and x-status fields?

CH_WEED 

Weed the headers?

CH_DECODE 

Do RFC2047 header decoding.

CH_XMIT 

Transmitting this message? (Ignore Lines: and Content-Length:)

CH_FROM 

Retain the "From " message separator?

CH_PREFIX 

Quote header using $indent_string string?

CH_NOSTATUS 

Suppress the status and x-status fields.

CH_REORDER 

Re-order output of headers (specified by 'header-order')

CH_NONEWLINE 

Don't output terminating newline after the header.

CH_MIME 

Ignore MIME fields.

CH_UPDATE_LEN 

Update Lines: and Content-Length:

CH_TXTPLAIN 

Generate text/plain MIME headers.

CH_NOLEN 

Don't write Content-Length: and Lines:

CH_WEED_DELIVERED 

Weed eventual Delivered-To headers.

CH_FORCE_FROM 

Give CH_FROM precedence over CH_WEED?

CH_NOQFROM 

Ignore ">From " line.

CH_UPDATE_IRT 

Update In-Reply-To:

CH_UPDATE_REFS 

Update References:

CH_DISPLAY 

Display result to user.

CH_UPDATE_LABEL 

Update X-Label: from email->env->x_label?

CH_UPDATE_SUBJECT 

Update Subject: protected header update.

CH_VIRTUAL 

Write virtual header lines too.

Definition at line 63 of file copy_email.h.

64{
65 CH_NONE = 0,
66 CH_UPDATE = 1U << 0,
67 CH_WEED = 1U << 1,
68 CH_DECODE = 1U << 2,
69 CH_XMIT = 1U << 3,
70 CH_FROM = 1U << 4,
71 CH_PREFIX = 1U << 5,
72 CH_NOSTATUS = 1U << 6,
73 CH_REORDER = 1U << 7,
74 CH_NONEWLINE = 1U << 8,
75 CH_MIME = 1U << 9,
76 CH_UPDATE_LEN = 1U << 10,
77 CH_TXTPLAIN = 1U << 11,
78 CH_NOLEN = 1U << 12,
79 CH_WEED_DELIVERED = 1U << 13,
80 CH_FORCE_FROM = 1U << 14,
81 CH_NOQFROM = 1U << 15,
82 CH_UPDATE_IRT = 1U << 16,
83 CH_UPDATE_REFS = 1U << 17,
84 CH_DISPLAY = 1U << 18,
85 CH_UPDATE_LABEL = 1U << 19,
86 CH_UPDATE_SUBJECT = 1U << 20,
87 CH_VIRTUAL = 1U << 21,
88};
@ CH_UPDATE
Update the status and x-status fields?
Definition copy_email.h:66
@ CH_XMIT
Transmitting this message? (Ignore Lines: and Content-Length:)
Definition copy_email.h:69
@ CH_WEED_DELIVERED
Weed eventual Delivered-To headers.
Definition copy_email.h:79
@ CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition copy_email.h:76
@ CH_WEED
Weed the headers?
Definition copy_email.h:67
@ CH_FROM
Retain the "From " message separator?
Definition copy_email.h:70
@ CH_UPDATE_LABEL
Update X-Label: from email->env->x_label?
Definition copy_email.h:85
@ CH_UPDATE_IRT
Update In-Reply-To:
Definition copy_email.h:82
@ CH_NOSTATUS
Suppress the status and x-status fields.
Definition copy_email.h:72
@ CH_DISPLAY
Display result to user.
Definition copy_email.h:84
@ CH_UPDATE_REFS
Update References:
Definition copy_email.h:83
@ CH_MIME
Ignore MIME fields.
Definition copy_email.h:75
@ CH_PREFIX
Quote header using $indent_string string?
Definition copy_email.h:71
@ CH_NOLEN
Don't write Content-Length: and Lines:
Definition copy_email.h:78
@ CH_VIRTUAL
Write virtual header lines too.
Definition copy_email.h:87
@ CH_NONE
No flags are set.
Definition copy_email.h:65
@ CH_UPDATE_SUBJECT
Update Subject: protected header update.
Definition copy_email.h:86
@ CH_TXTPLAIN
Generate text/plain MIME headers.
Definition copy_email.h:77
@ CH_DECODE
Do RFC2047 header decoding.
Definition copy_email.h:68
@ CH_NONEWLINE
Don't output terminating newline after the header.
Definition copy_email.h:74
@ CH_NOQFROM
Ignore ">From " line.
Definition copy_email.h:81
@ CH_FORCE_FROM
Give CH_FROM precedence over CH_WEED?
Definition copy_email.h:80
@ CH_REORDER
Re-order output of headers (specified by 'header-order')
Definition copy_email.h:73

Function Documentation

◆ mutt_copy_hdr()

int mutt_copy_hdr ( FILE * fp_in,
FILE * fp_out,
LOFF_T off_start,
LOFF_T off_end,
CopyHeaderFlags chflags,
const char * prefix,
int wraplen )

Copy header from one file to another.

Parameters
fp_inFILE pointer to read from
fp_outFILE pointer to write to
off_startOffset to start from
off_endOffset to finish at
chflagsFlags, see CopyHeaderFlags
prefixPrefix for quoting headers
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Ok, the only reason for not merging this with mutt_copy_header() below is to avoid creating a Email structure in message_handler(). Also, this one will wrap headers much more aggressively than the other one.

Definition at line 112 of file copy_email.c.

114{
115 bool from = false;
116 bool this_is_from = false;
117 bool ignore = false;
118 char buf[1024] = { 0 }; /* should be long enough to get most fields in one pass */
119 char *nl = NULL;
120 struct StringArray headers = ARRAY_HEAD_INITIALIZER;
121 int hdr_count;
122 int x;
123 char *this_one = NULL;
124 size_t this_one_len = 0;
125
126 if (off_start < 0)
127 return -1;
128
129 if (ftello(fp_in) != off_start)
130 if (!mutt_file_seek(fp_in, off_start, SEEK_SET))
131 return -1;
132
133 buf[0] = '\n';
134 buf[1] = '\0';
135
136 if ((chflags & (CH_REORDER | CH_WEED | CH_MIME | CH_DECODE | CH_PREFIX | CH_WEED_DELIVERED)) == 0)
137 {
138 /* Without these flags to complicate things
139 * we can do a more efficient line to line copying */
140 while (ftello(fp_in) < off_end)
141 {
142 nl = strchr(buf, '\n');
143
144 if (!fgets(buf, sizeof(buf), fp_in))
145 break;
146
147 /* Convert CRLF line endings to LF */
148 const size_t line_len = strlen(buf);
149 if ((line_len > 2) && (buf[line_len - 2] == '\r') && (buf[line_len - 1] == '\n'))
150 {
151 buf[line_len - 2] = '\n';
152 buf[line_len - 1] = '\0';
153 }
154
155 /* Is it the beginning of a header? */
156 if (nl && (buf[0] != ' ') && (buf[0] != '\t'))
157 {
158 ignore = true;
159 if (!from && mutt_str_startswith(buf, "From "))
160 {
161 if ((chflags & CH_FROM) == 0)
162 continue;
163 from = true;
164 }
165 else if ((chflags & CH_NOQFROM) && mutt_istr_startswith(buf, ">From "))
166 {
167 continue;
168 }
169 else if ((buf[0] == '\n') || ((buf[0] == '\r') && (buf[1] == '\n')))
170 {
171 break; /* end of header */
172 }
173
174 if ((chflags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
175 (mutt_istr_startswith(buf, "Status:") || mutt_istr_startswith(buf, "X-Status:")))
176 {
177 continue;
178 }
179 if ((chflags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
180 (mutt_istr_startswith(buf, "Content-Length:") ||
181 mutt_istr_startswith(buf, "Lines:")))
182 {
183 continue;
184 }
185 if ((chflags & CH_UPDATE_REFS) && mutt_istr_startswith(buf, "References:"))
186 {
187 continue;
188 }
189 if ((chflags & CH_UPDATE_IRT) && mutt_istr_startswith(buf, "In-Reply-To:"))
190 {
191 continue;
192 }
193 if (chflags & CH_UPDATE_LABEL && mutt_istr_startswith(buf, "X-Label:"))
194 continue;
195 if ((chflags & CH_UPDATE_SUBJECT) && mutt_istr_startswith(buf, "Subject:"))
196 {
197 continue;
198 }
199
200 ignore = false;
201 }
202
203 if (!ignore && (fputs(buf, fp_out) == EOF))
204 return -1;
205 }
206 return 0;
207 }
208
209 hdr_count = 1;
210 x = 0;
211
213 ASSERT(mod_data);
214
215 /* We are going to read and collect the headers in an array
216 * so we are able to do re-ordering.
217 * First count the number of entries in the array */
218 if (chflags & CH_REORDER)
219 {
220 struct ListNode *np = NULL;
221 STAILQ_FOREACH(np, &mod_data->header_order, entries)
222 {
223 mutt_debug(LL_DEBUG3, "Reorder list: %s\n", np->data);
224 hdr_count++;
225 }
226 }
227
228 mutt_debug(LL_DEBUG1, "WEED is %sset\n", (chflags & CH_WEED) ? "" : "not ");
229
230 ARRAY_RESERVE(&headers, hdr_count);
231
232 /* Read all the headers into the array */
233 while (ftello(fp_in) < off_end)
234 {
235 nl = strchr(buf, '\n');
236
237 /* Read a line */
238 if (!fgets(buf, sizeof(buf), fp_in))
239 break;
240
241 /* Is it the beginning of a header? */
242 if (nl && (buf[0] != ' ') && (buf[0] != '\t'))
243 {
244 /* Do we have anything pending? */
245 if (this_one)
246 {
247 if (chflags & CH_DECODE)
248 {
249 if (address_header_decode(&this_one) == 0)
250 rfc2047_decode(&this_one);
251 this_one_len = mutt_str_len(this_one);
252 }
253
254 add_one_header(&headers, x, this_one);
255 this_one = NULL;
256 }
257
258 ignore = true;
259 this_is_from = false;
260 if (!from && mutt_str_startswith(buf, "From "))
261 {
262 if ((chflags & CH_FROM) == 0)
263 continue;
264 this_is_from = true;
265 from = true;
266 }
267 else if ((buf[0] == '\n') || ((buf[0] == '\r') && (buf[1] == '\n')))
268 {
269 break; /* end of header */
270 }
271
272 /* note: CH_FROM takes precedence over header weeding. */
273 if (!((chflags & CH_FROM) && (chflags & CH_FORCE_FROM) && this_is_from) &&
274 (chflags & CH_WEED) && mutt_matches_ignore(buf))
275 {
276 continue;
277 }
278 if ((chflags & CH_WEED_DELIVERED) && mutt_istr_startswith(buf, "Delivered-To:"))
279 {
280 continue;
281 }
282 if ((chflags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
283 (mutt_istr_startswith(buf, "Status:") || mutt_istr_startswith(buf, "X-Status:")))
284 {
285 continue;
286 }
287 if ((chflags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
288 (mutt_istr_startswith(buf, "Content-Length:") || mutt_istr_startswith(buf, "Lines:")))
289 {
290 continue;
291 }
292 if ((chflags & CH_MIME))
293 {
294 if (mutt_istr_startswith(buf, "mime-version:"))
295 {
296 continue;
297 }
298 size_t plen = mutt_istr_startswith(buf, "content-");
299 if ((plen != 0) && (mutt_istr_startswith(buf + plen, "transfer-encoding:") ||
300 mutt_istr_startswith(buf + plen, "type:")))
301 {
302 continue;
303 }
304 }
305 if ((chflags & CH_UPDATE_REFS) && mutt_istr_startswith(buf, "References:"))
306 {
307 continue;
308 }
309 if ((chflags & CH_UPDATE_IRT) && mutt_istr_startswith(buf, "In-Reply-To:"))
310 {
311 continue;
312 }
313 if ((chflags & CH_UPDATE_LABEL) && mutt_istr_startswith(buf, "X-Label:"))
314 continue;
315 if ((chflags & CH_UPDATE_SUBJECT) && mutt_istr_startswith(buf, "Subject:"))
316 {
317 continue;
318 }
319
320 /* Find x -- the array entry where this header is to be saved */
321 if (chflags & CH_REORDER)
322 {
323 struct ListNode *np = NULL;
324 x = 0;
325 int match = -1;
326 size_t match_len = 0;
327
328 STAILQ_FOREACH(np, &mod_data->header_order, entries)
329 {
330 size_t hdr_order_len = mutt_str_len(np->data);
331 if (mutt_istrn_equal(buf, np->data, hdr_order_len))
332 {
333 if ((match == -1) || (hdr_order_len > match_len))
334 {
335 match = x;
336 match_len = hdr_order_len;
337 }
338 mutt_debug(LL_DEBUG2, "Reorder: %s matches %s\n", np->data, buf);
339 }
340 x++;
341 }
342 if (match != -1)
343 x = match;
344 }
345
346 ignore = false;
347 } /* If beginning of header */
348
349 if (!ignore)
350 {
351 mutt_debug(LL_DEBUG2, "Reorder: x = %d; hdr_count = %d\n", x, hdr_count);
352 if (this_one)
353 {
354 size_t blen = mutt_str_len(buf);
355
356 MUTT_MEM_REALLOC(&this_one, this_one_len + blen + 1, char);
357 mutt_strn_copy(this_one + this_one_len, buf, blen, blen + 1);
358 this_one_len += blen;
359 }
360 else
361 {
362 this_one = mutt_str_dup(buf);
363 this_one_len = mutt_str_len(this_one);
364 }
365 }
366 } /* while (ftello (fp_in) < off_end) */
367
368 /* Do we have anything pending? -- XXX, same code as in above in the loop. */
369 if (this_one)
370 {
371 if (chflags & CH_DECODE)
372 {
373 if (address_header_decode(&this_one) == 0)
374 rfc2047_decode(&this_one);
375 this_one_len = mutt_str_len(this_one);
376 }
377
378 add_one_header(&headers, x, this_one);
379 this_one = NULL;
380 }
381
382 /* Now output the headers in order */
383 bool error = false;
384 const char **hp = NULL;
385 const short c_wrap = cs_subset_number(NeoMutt->sub, "wrap");
386
387 ARRAY_FOREACH(hp, &headers)
388 {
389 if (!error && hp && *hp)
390 {
391 /* We couldn't do the prefixing when reading because RFC2047
392 * decoding may have concatenated lines. */
393 if (chflags & (CH_DECODE | CH_PREFIX))
394 {
395 const char *pre = (chflags & CH_PREFIX) ? prefix : NULL;
396 wraplen = mutt_window_wrap_cols(wraplen, c_wrap);
397
398 if (mutt_write_one_header(fp_out, 0, *hp, pre, wraplen, chflags, NeoMutt->sub) == -1)
399 {
400 error = true;
401 }
402 }
403 else
404 {
405 if (fputs(*hp, fp_out) == EOF)
406 {
407 error = true;
408 }
409 }
410 }
411
412 FREE(hp);
413 }
414 ARRAY_FREE(&headers);
415
416 if (error)
417 return -1;
418 return 0;
419}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_RESERVE(head, n)
Reserve memory for the array.
Definition array.h:191
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
static int address_header_decode(char **h)
Parse an email's headers.
static void add_one_header(struct StringArray *headers, int pos, char *value)
Add a header to a Headers array.
Definition copy_email.c:82
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition parse.c:320
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_REALLOC(pptr, n, type)
Definition memory.h:55
@ MODULE_ID_EMAIL
ModuleEmail, Email code
Definition module_api.h:64
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition string.c:364
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition string.c:457
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition rfc2047.c:669
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags, struct ConfigSubset *sub)
Write one header line to a file.
Definition header.c:424
#define ASSERT(COND)
Definition signal2.h:59
Email private Module data.
Definition module_data.h:32
struct ListHead header_order
List of header fields in the order they should be displayed.
Definition module_data.h:36
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_copy_header()

int mutt_copy_header ( FILE * fp_in,
struct Email * e,
FILE * fp_out,
CopyHeaderFlags chflags,
const char * prefix,
int wraplen )

Copy Email header.

Parameters
fp_inFILE pointer to read from
eEmail
fp_outFILE pointer to write to
chflagsSee CopyHeaderFlags
prefixPrefix for quoting headers (if CH_PREFIX is set)
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Definition at line 432 of file copy_email.c.

434{
435 char *temp_hdr = NULL;
436 const bool c_weed = (chflags & CH_UPDATE) ? false : cs_subset_bool(NeoMutt->sub, "weed");
437
438 if (e->env)
439 {
440 chflags |= ((e->env->changed & MUTT_ENV_CHANGED_IRT) ? CH_UPDATE_IRT : 0) |
441 ((e->env->changed & MUTT_ENV_CHANGED_REFS) ? CH_UPDATE_REFS : 0) |
442 ((e->env->changed & MUTT_ENV_CHANGED_XLABEL) ? CH_UPDATE_LABEL : 0) |
443 ((e->env->changed & MUTT_ENV_CHANGED_SUBJECT) ? CH_UPDATE_SUBJECT : 0);
444 }
445
446 if (mutt_copy_hdr(fp_in, fp_out, e->offset, e->body->offset, chflags, prefix, wraplen) == -1)
447 return -1;
448
449 if (chflags & CH_TXTPLAIN)
450 {
451 char chsbuf[128] = { 0 };
452 char buf[128] = { 0 };
453 fputs("MIME-Version: 1.0\n", fp_out);
454 fputs("Content-Transfer-Encoding: 8bit\n", fp_out);
455 fputs("Content-Type: text/plain; charset=", fp_out);
456 const char *const c_charset = cc_charset();
457 mutt_ch_canonical_charset(chsbuf, sizeof(chsbuf), c_charset ? c_charset : "us-ascii");
458 mutt_addr_cat(buf, sizeof(buf), chsbuf, MimeSpecials);
459 fputs(buf, fp_out);
460 fputc('\n', fp_out);
461 }
462
463 if ((chflags & CH_UPDATE_IRT) && !STAILQ_EMPTY(&e->env->in_reply_to) &&
464 !(c_weed && mutt_matches_ignore("In-Reply-To")))
465 {
466 fputs("In-Reply-To:", fp_out);
467 struct ListNode *np = NULL;
468 STAILQ_FOREACH(np, &e->env->in_reply_to, entries)
469 {
470 fputc(' ', fp_out);
471 fputs(np->data, fp_out);
472 }
473 fputc('\n', fp_out);
474 }
475
476 if ((chflags & CH_UPDATE_REFS) && !STAILQ_EMPTY(&e->env->references) &&
477 !(c_weed && mutt_matches_ignore("References")))
478 {
479 fputs("References:", fp_out);
480 mutt_write_references(&e->env->references, fp_out, 0);
481 fputc('\n', fp_out);
482 }
483
484 if ((chflags & CH_UPDATE) && ((chflags & CH_NOSTATUS) == 0))
485 {
486 if ((e->old || e->read))
487 {
488 fputs("Status: ", fp_out);
489 if (e->read)
490 fputs("RO", fp_out);
491 else if (e->old)
492 fputc('O', fp_out);
493 fputc('\n', fp_out);
494 }
495
496 if ((e->flagged || e->replied))
497 {
498 fputs("X-Status: ", fp_out);
499 if (e->replied)
500 fputc('A', fp_out);
501 if (e->flagged)
502 fputc('F', fp_out);
503 fputc('\n', fp_out);
504 }
505 }
506
507 if (chflags & CH_UPDATE_LEN && ((chflags & CH_NOLEN) == 0) &&
508 !(c_weed && mutt_matches_ignore("Content-Length")))
509 {
510 fprintf(fp_out, "Content-Length: " OFF_T_FMT "\n", e->body->length);
511 if ((e->lines != 0) || (e->body->length == 0))
512 fprintf(fp_out, "Lines: %d\n", e->lines);
513 }
514
515#ifdef USE_NOTMUCH
516 if (chflags & CH_VIRTUAL)
517 {
518 /* Add some fake headers based on notmuch data */
519 char *folder = nm_email_get_folder(e);
520 if (folder && !(c_weed && mutt_matches_ignore("Folder")))
521 {
522 struct Buffer *buf = buf_pool_get();
523 buf_strcpy(buf, folder);
524 pretty_mailbox(buf);
525 fprintf(fp_out, "Folder: %s\n", buf->data);
526 buf_pool_release(&buf);
527 }
528 }
529#endif
530
531 struct Buffer *tags = buf_pool_get();
532 driver_tags_get(&e->tags, tags);
533 if (!buf_is_empty(tags) && !(c_weed && mutt_matches_ignore("Tags")))
534 {
535 fputs("Tags: ", fp_out);
536 fputs(buf_string(tags), fp_out);
537 fputc('\n', fp_out);
538 }
539 buf_pool_release(&tags);
540
541 const struct Slist *const c_send_charset = cs_subset_slist(NeoMutt->sub, "send_charset");
542 const short c_wrap = cs_subset_number(NeoMutt->sub, "wrap");
543 if ((chflags & CH_UPDATE_LABEL) && e->env->x_label &&
544 !(c_weed && mutt_matches_ignore("X-Label")))
545 {
546 temp_hdr = e->env->x_label;
547 /* env->x_label isn't currently stored with direct references elsewhere.
548 * Mailbox->label_hash strdups the keys. But to be safe, encode a copy */
549 if (!(chflags & CH_DECODE))
550 {
551 temp_hdr = mutt_str_dup(temp_hdr);
552 rfc2047_encode(&temp_hdr, NULL, sizeof("X-Label:"), c_send_charset);
553 }
554 if (mutt_write_one_header(fp_out, "X-Label", temp_hdr, (chflags & CH_PREFIX) ? prefix : 0,
555 mutt_window_wrap_cols(wraplen, c_wrap), chflags,
556 NeoMutt->sub) == -1)
557 {
558 return -1;
559 }
560 if (!(chflags & CH_DECODE))
561 FREE(&temp_hdr);
562 }
563
564 if ((chflags & CH_UPDATE_SUBJECT) && e->env->subject &&
565 !(c_weed && mutt_matches_ignore("Subject")))
566 {
567 temp_hdr = e->env->subject;
568 /* env->subject is directly referenced in Mailbox->subj_hash, so we
569 * have to be careful not to encode (and thus free) that memory. */
570 if (!(chflags & CH_DECODE))
571 {
572 temp_hdr = mutt_str_dup(temp_hdr);
573 rfc2047_encode(&temp_hdr, NULL, sizeof("Subject:"), c_send_charset);
574 }
575 if (mutt_write_one_header(fp_out, "Subject", temp_hdr, (chflags & CH_PREFIX) ? prefix : 0,
576 mutt_window_wrap_cols(wraplen, c_wrap), chflags,
577 NeoMutt->sub) == -1)
578 {
579 return -1;
580 }
581 if (!(chflags & CH_DECODE))
582 FREE(&temp_hdr);
583 }
584
585 if ((chflags & CH_NONEWLINE) == 0)
586 {
587 if (chflags & CH_PREFIX)
588 fputs(prefix, fp_out);
589 fputc('\n', fp_out); /* add header terminator */
590 }
591
592 if (ferror(fp_out) || feof(fp_out))
593 return -1;
594
595 return 0;
596}
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition address.c:713
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition helpers.c:242
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
const char * cc_charset(void)
Get the cached value of $charset.
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition copy_email.c:112
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition mime.c:69
void mutt_ch_canonical_charset(char *buf, size_t buflen, const char *name)
Canonicalise the charset of a string.
Definition charset.c:360
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition notmuch.c:1505
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define STAILQ_EMPTY(head)
Definition queue.h:382
void rfc2047_encode(char **pd, const char *specials, int col, const struct Slist *charsets)
RFC-2047-encode a string.
Definition rfc2047.c:636
void mutt_write_references(const struct ListHead *r, FILE *fp, size_t trim)
Add the message references to a list.
Definition header.c:520
LOFF_T offset
offset where the actual data begins
Definition body.h:52
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
bool read
Email is read.
Definition email.h:50
struct Envelope * env
Envelope information.
Definition email.h:68
int lines
How many lines in the body of this message?
Definition email.h:62
struct Body * body
List of MIME parts.
Definition email.h:69
bool old
Email is seen, but unread.
Definition email.h:49
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
struct TagList tags
For drivers that support server tagging.
Definition email.h:72
char *const subject
Email's subject.
Definition envelope.h:70
struct ListHead references
message references (in reverse order)
Definition envelope.h:83
struct ListHead in_reply_to
in-reply-to header content
Definition envelope.h:84
char * x_label
X-Label.
Definition envelope.h:76
String list.
Definition slist.h:37
void driver_tags_get(struct TagList *tl, struct Buffer *tags)
Get tags all tags separated by space.
Definition tags.c:165
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_copy_message_fp()

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.

Parameters
fp_outWhere to write output
fp_inWhere to get input
eEmail being copied
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

Definition at line 663 of file copy_email.c.

665{
666 struct Body *body = e->body;
667 struct Buffer *prefix = buf_pool_get();
668 LOFF_T new_offset = -1;
669 int rc = 0;
670
671 if (cmflags & MUTT_CM_PREFIX)
672 {
673 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
674 if (c_text_flowed)
675 {
676 buf_strcpy(prefix, ">");
677 }
678 else
679 {
680 const char *const c_attribution_locale = cs_subset_string(NeoMutt->sub, "attribution_locale");
681 const struct Expando *c_indent_string = cs_subset_expando(NeoMutt->sub, "indent_string");
682 struct Mailbox *m_cur = get_current_mailbox();
683 setlocale(LC_TIME, NONULL(c_attribution_locale));
684 mutt_make_string(prefix, -1, c_indent_string, m_cur, -1, e, MUTT_FORMAT_NONE, NULL);
685 setlocale(LC_TIME, "");
686 }
687 }
688
689 if ((cmflags & MUTT_CM_NOHEADER) == 0)
690 {
691 if (cmflags & MUTT_CM_PREFIX)
692 {
693 chflags |= CH_PREFIX;
694 }
695 else if (e->attach_del && (chflags & CH_UPDATE_LEN))
696 {
697 int new_lines;
698 int rc_attach_del = -1;
699 LOFF_T new_length = body->length;
700 struct Buffer *quoted_date = NULL;
701
702 quoted_date = buf_pool_get();
703 buf_addch(quoted_date, '"');
704 mutt_date_make_date(quoted_date, cs_subset_bool(NeoMutt->sub, "local_date_header"));
705 buf_addch(quoted_date, '"');
706
707 /* Count the number of lines and bytes to be deleted */
708 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
709 {
710 goto attach_del_cleanup;
711 }
712 const int del = count_delete_lines(fp_in, body, &new_length, buf_len(quoted_date));
713 if (del == -1)
714 {
715 goto attach_del_cleanup;
716 }
717 new_lines = e->lines - del;
718
719 /* Copy the headers */
720 if (mutt_copy_header(fp_in, e, fp_out, chflags | CH_NOLEN | CH_NONEWLINE,
721 NULL, wraplen) != 0)
722 {
723 goto attach_del_cleanup;
724 }
725 fprintf(fp_out, "Content-Length: " OFF_T_FMT "\n", new_length);
726 if (new_lines <= 0)
727 new_lines = 0;
728 else
729 fprintf(fp_out, "Lines: %d\n", new_lines);
730
731 putc('\n', fp_out);
732 if (ferror(fp_out) || feof(fp_out))
733 goto attach_del_cleanup;
734 new_offset = ftello(fp_out);
735
736 /* Copy the body */
737 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
738 goto attach_del_cleanup;
739 if (copy_delete_attach(body, fp_in, fp_out, buf_string(quoted_date)))
740 goto attach_del_cleanup;
741
742 buf_pool_release(&quoted_date);
743
744 LOFF_T fail = ((ftello(fp_out) - new_offset) - new_length);
745 if (fail)
746 {
747 mutt_error(ngettext("The length calculation was wrong by %ld byte",
748 "The length calculation was wrong by %ld bytes", fail),
749 (long) fail);
750 new_length += fail;
751 }
752
753 /* Update original message if we are sync'ing a mailfolder */
754 if (cmflags & MUTT_CM_UPDATE)
755 {
756 e->attach_del = false;
757 e->lines = new_lines;
758 body->offset = new_offset;
759
760 body->length = new_length;
761 mutt_body_free(&body->parts);
762 }
763
764 rc_attach_del = 0;
765
766 attach_del_cleanup:
767 buf_pool_release(&quoted_date);
768 rc = rc_attach_del;
769 goto done;
770 }
771
772 if (mutt_copy_header(fp_in, e, fp_out, chflags,
773 (chflags & CH_PREFIX) ? buf_string(prefix) : NULL, wraplen) == -1)
774 {
775 rc = -1;
776 goto done;
777 }
778
779 new_offset = ftello(fp_out);
780 }
781
782 if (cmflags & MUTT_CM_DECODE)
783 {
784 /* now make a text/plain version of the message */
785 struct State state = { 0 };
786 state.fp_in = fp_in;
787 state.fp_out = fp_out;
788 if (cmflags & MUTT_CM_PREFIX)
789 state.prefix = buf_string(prefix);
790 if (cmflags & MUTT_CM_DISPLAY)
791 {
792 state.flags |= STATE_DISPLAY;
793 state.wraplen = wraplen;
794 const char *const c_pager = pager_get_pager(NeoMutt->sub);
795 if (!c_pager)
796 state.flags |= STATE_PAGER;
797 }
798 if (cmflags & MUTT_CM_PRINTING)
799 state.flags |= STATE_PRINTING;
800 if (cmflags & MUTT_CM_WEED)
801 state.flags |= STATE_WEED;
802 if (cmflags & MUTT_CM_CHARCONV)
803 state.flags |= STATE_CHARCONV;
804 if (cmflags & MUTT_CM_REPLYING)
805 state.flags |= STATE_REPLYING;
806
807 if ((WithCrypto != 0) && cmflags & MUTT_CM_VERIFY)
808 state.flags |= STATE_VERIFY;
809
810 rc = mutt_body_handler(body, &state);
811 }
812 else if ((WithCrypto != 0) && (cmflags & MUTT_CM_DECODE_CRYPT) && (e->security & SEC_ENCRYPT))
813 {
814 struct Body *cur = NULL;
815 FILE *fp = NULL;
816
817 if (((WithCrypto & APPLICATION_PGP) != 0) && (cmflags & MUTT_CM_DECODE_PGP) &&
819 {
820 if (crypt_pgp_decrypt_mime(fp_in, &fp, e->body, &cur))
821 {
822 rc = 1;
823 goto done;
824 }
825 fputs("MIME-Version: 1.0\n", fp_out);
826 }
827
828 if (((WithCrypto & APPLICATION_SMIME) != 0) && (cmflags & MUTT_CM_DECODE_SMIME) &&
830 {
831 if (crypt_smime_decrypt_mime(fp_in, &fp, e->body, &cur))
832 {
833 rc = 1;
834 goto done;
835 }
836 }
837
838 if (!cur)
839 {
840 mutt_error(_("No decryption engine available for message"));
841 rc = 1;
842 goto done;
843 }
844
845 mutt_write_mime_header(cur, fp_out, NeoMutt->sub);
846 fputc('\n', fp_out);
847
848 if (!mutt_file_seek(fp, cur->offset, SEEK_SET))
849 {
850 rc = 1;
851 goto done;
852 }
853
854 if (mutt_file_copy_bytes(fp, fp_out, cur->length) == -1)
855 {
856 mutt_file_fclose(&fp);
857 mutt_body_free(&cur);
858 rc = 1;
859 goto done;
860 }
861 mutt_body_free(&cur);
862 mutt_file_fclose(&fp);
863 }
864 else
865 {
866 if (!mutt_file_seek(fp_in, body->offset, SEEK_SET))
867 {
868 rc = 1;
869 goto done;
870 }
871 if (cmflags & MUTT_CM_PREFIX)
872 {
873 int c;
874 size_t bytes = body->length;
875
876 fputs(buf_string(prefix), fp_out);
877
878 while (((c = fgetc(fp_in)) != EOF) && bytes--)
879 {
880 fputc(c, fp_out);
881 if (c == '\n')
882 {
883 fputs(buf_string(prefix), fp_out);
884 }
885 }
886 }
887 else if (mutt_file_copy_bytes(fp_in, fp_out, body->length) == -1)
888 {
889 rc = 1;
890 goto done;
891 }
892 }
893
894 if ((cmflags & MUTT_CM_UPDATE) && ((cmflags & MUTT_CM_NOHEADER) == 0) &&
895 (new_offset != -1))
896 {
897 body->offset = new_offset;
898 mutt_body_free(&body->parts);
899 }
900
901done:
902 buf_pool_release(&prefix);
903 return rc;
904}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy Email header.
Definition copy_email.c:432
static int count_delete_lines(FILE *fp, struct Body *b, LOFF_T *length, size_t datelen)
Count lines to be deleted in this email body.
Definition copy_email.c:609
static int copy_delete_attach(struct Body *b, FILE *fp_in, FILE *fp_out, const char *quoted_date)
Copy a message, deleting marked attachments.
#define MUTT_CM_DECODE_CRYPT
Combination flag for decoding any kind of cryptography (PGP or S/MIME)
Definition copy_email.h:58
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:237
int crypt_smime_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:510
int mutt_make_string(struct Buffer *buf, size_t max_cols, const struct Expando *exp, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition dlg_index.c:824
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition file.c:192
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_error(...)
Definition logging2.h:94
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1664
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition index.c:726
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition mime.h:33
void mutt_date_make_date(struct Buffer *buf, bool local)
Write a date in RFC822 format to a buffer.
Definition date.c:398
#define _(a)
Definition message.h:28
@ STATE_CHARCONV
Do character set conversions.
Definition state.h:41
@ STATE_PRINTING
Are we printing? - STATE_DISPLAY "light".
Definition state.h:42
@ STATE_REPLYING
Are we replying?
Definition state.h:43
@ STATE_PAGER
Output will be displayed in the Pager.
Definition state.h:46
@ STATE_VERIFY
Perform signature verification.
Definition state.h:38
@ STATE_WEED
Weed headers even when not in display mode.
Definition state.h:40
@ STATE_DISPLAY
Output is displayed to the user.
Definition state.h:37
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
#define WithCrypto
Definition lib.h:132
const char * pager_get_pager(struct ConfigSubset *sub)
Get the value of $pager.
Definition config.c:111
@ MUTT_FORMAT_NONE
No flags are set.
Definition render.h:37
int mutt_write_mime_header(struct Body *b, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition header.c:757
#define NONULL(x)
Definition string2.h:44
The body of an email.
Definition body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
unsigned int type
content-type primary type, ContentType
Definition body.h:40
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
bool attach_del
Has an attachment marked for deletion.
Definition email.h:99
Parsed Expando trees.
Definition expando.h:41
A mailbox.
Definition mailbox.h:81
Keep track when processing files.
Definition state.h:54
int wraplen
Width to wrap lines to (when flags & STATE_DISPLAY)
Definition state.h:59
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
const char * prefix
String to add to the beginning of each output line.
Definition state.h:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_copy_message()

int mutt_copy_message ( FILE * fp_out,
struct Email * e,
struct Message * msg,
CopyMessageFlags cmflags,
CopyHeaderFlags chflags,
int wraplen )

Copy a message from a Mailbox.

Parameters
fp_outFILE pointer to write to
eEmail
msgMessage
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
wraplenWidth to wrap at (when chflags & CH_DISPLAY)
Return values
0Success
-1Failure

should be made to return -1 on fatal errors, and 1 on non-fatal errors like partial decode, where it is worth displaying as much as possible

Definition at line 920 of file copy_email.c.

922{
923 if (!msg || !e->body)
924 {
925 return -1;
926 }
927 if (fp_out == msg->fp)
928 {
929 mutt_debug(LL_DEBUG1, "trying to read/write from/to the same FILE*!\n");
930 return -1;
931 }
932
933 int rc = mutt_copy_message_fp(fp_out, msg->fp, e, cmflags, chflags, wraplen);
934 if ((rc == 0) && (ferror(fp_out) || feof(fp_out)))
935 {
936 mutt_debug(LL_DEBUG1, "failed to detect EOF!\n");
937 rc = -1;
938 }
939 return rc;
940}
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Make a copy of a message from a FILE pointer.
Definition copy_email.c:663
FILE * fp
pointer to the message data
Definition message.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_append_message()

int mutt_append_message ( struct Mailbox * m_dst,
struct Mailbox * m_src,
struct Email * e,
struct Message * msg,
CopyMessageFlags cmflags,
CopyHeaderFlags chflags )

Append a message.

Parameters
m_dstDestination Mailbox
m_srcSource Mailbox
eEmail
msgMessage
cmflagsFlags, see CopyMessageFlags
chflagsFlags, see CopyHeaderFlags
Return values
0Success
-1Failure

Definition at line 995 of file copy_email.c.

998{
999 if (!e)
1000 return -1;
1001
1002 const bool own_msg = !msg;
1003 if (own_msg && !(msg = mx_msg_open(m_src, e)))
1004 {
1005 return -1;
1006 }
1007
1008 int rc = append_message(m_dst, msg->fp, m_src, e, cmflags, chflags);
1009 if (own_msg)
1010 {
1011 mx_msg_close(m_src, &msg);
1012 }
1013 return rc;
1014}
static int append_message(struct Mailbox *dest, FILE *fp_in, struct Mailbox *src, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Appends a copy of the given message to a mailbox.
Definition copy_email.c:953
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
+ Here is the call graph for this function:
+ Here is the caller graph for this function: