NeoMutt  2024-03-23-23-gec7045
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
email.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdio.h>
32#include <string.h>
33#include "mutt/lib.h"
34#include "address/lib.h"
35#include "email/lib.h"
36#include "lib.h"
37#include "attach/lib.h"
38#include "ncrypt/lib.h"
39
40void dump_addr_list(char *buf, size_t buflen, const struct AddressList *al, const char *name)
41{
42 if (!buf || !al)
43 return;
44 if (TAILQ_EMPTY(al))
45 return;
46
47 buf[0] = '\0';
48 struct Buffer *tmpbuf = buf_pool_get();
49 mutt_addrlist_write(al, tmpbuf, true);
50 mutt_str_copy(buf, buf_string(tmpbuf), buflen);
51 buf_pool_release(&tmpbuf);
52
53 mutt_debug(LL_DEBUG1, "\t%s: %s\n", name, buf);
54}
55
56void dump_list_head(const struct ListHead *list, const char *name)
57{
58 if (!list || !name)
59 return;
60 if (STAILQ_EMPTY(list))
61 return;
62
63 struct Buffer buf = buf_make(256);
64
65 struct ListNode *np = NULL;
66 STAILQ_FOREACH(np, list, entries)
67 {
68 if (!buf_is_empty(&buf))
69 buf_addch(&buf, ',');
70 buf_addstr(&buf, np->data);
71 }
72
73 mutt_debug(LL_DEBUG1, "\t%s: %s\n", name, buf_string(&buf));
74 buf_dealloc(&buf);
75}
76
77void dump_envelope(const struct Envelope *env)
78{
79 mutt_debug(LL_DEBUG1, "Envelope\n");
80
81 if (!env)
82 {
83 mutt_debug(LL_DEBUG1, "\tNULL pointer\n");
84 return;
85 }
86
87 struct Buffer buf = buf_make(256);
88 char arr[1024];
89
90#define ADD_FLAG(F) add_flag(&buf, (env->changed & F), #F)
95#undef ADD_FLAG
96 mutt_debug(LL_DEBUG1, "\tchanged: %s\n",
97 buf_is_empty(&buf) ? "[NONE]" : buf_string(&buf));
98
99#define ADDR_LIST(AL) dump_addr_list(arr, sizeof(arr), &env->AL, #AL)
100 ADDR_LIST(return_path);
101 ADDR_LIST(from);
102 ADDR_LIST(to);
103 ADDR_LIST(cc);
104 ADDR_LIST(bcc);
105 ADDR_LIST(sender);
106 ADDR_LIST(reply_to);
107 ADDR_LIST(mail_followup_to);
108 ADDR_LIST(x_original_to);
109#undef ADDR_LIST
110
111#define OPT_STRING(S) \
112 if (env->S) \
113 mutt_debug(LL_DEBUG1, "\t%s: %s\n", #S, env->S)
114 OPT_STRING(list_post);
115 OPT_STRING(list_subscribe);
116 OPT_STRING(list_unsubscribe);
117 OPT_STRING(subject);
118 OPT_STRING(real_subj);
119 OPT_STRING(disp_subj);
120 OPT_STRING(message_id);
121 OPT_STRING(supersedes);
122 OPT_STRING(date);
123 OPT_STRING(x_label);
124 OPT_STRING(organization);
125 OPT_STRING(newsgroups);
126 OPT_STRING(xref);
127 OPT_STRING(followup_to);
128 OPT_STRING(x_comment_to);
129#undef OPT_STRING
130
131 dump_list_head(&env->references, "references");
132 dump_list_head(&env->in_reply_to, "in_reply_to");
133 dump_list_head(&env->userhdrs, "userhdrs");
134
135 if (!buf_is_empty(&env->spam))
136 mutt_debug(LL_DEBUG1, "\tspam: %s\n", buf_string(&env->spam));
137
138#ifdef USE_AUTOCRYPT
139 if (env->autocrypt)
140 mutt_debug(LL_DEBUG1, "\tautocrypt: %p\n", (void *) env->autocrypt);
141 if (env->autocrypt_gossip)
142 mutt_debug(LL_DEBUG1, "\tautocrypt_gossip: %p\n", (void *) env->autocrypt_gossip);
143#endif
144
145 buf_dealloc(&buf);
146}
147
148void dump_email(const struct Email *e)
149{
150 mutt_debug(LL_DEBUG1, "Email\n");
151
152 if (!e)
153 {
154 mutt_debug(LL_DEBUG1, "\tNULL pointer\n");
155 return;
156 }
157
158 struct Buffer buf = buf_make(256);
159 char arr[256];
160
161 mutt_debug(LL_DEBUG1, "\tpath: %s\n", e->path);
162
163#define ADD_FLAG(F) add_flag(&buf, e->F, #F)
164 ADD_FLAG(active);
165 ADD_FLAG(attach_del);
166 ADD_FLAG(attach_valid);
167 ADD_FLAG(changed);
168 ADD_FLAG(collapsed);
169 ADD_FLAG(deleted);
170 ADD_FLAG(display_subject);
171 ADD_FLAG(expired);
172 ADD_FLAG(flagged);
173 ADD_FLAG(matched);
174 ADD_FLAG(mime);
175 ADD_FLAG(old);
176 ADD_FLAG(purge);
177 ADD_FLAG(quasi_deleted);
178 ADD_FLAG(read);
179 ADD_FLAG(recip_valid);
180 ADD_FLAG(replied);
181 ADD_FLAG(searched);
182 ADD_FLAG(subject_changed);
183 ADD_FLAG(superseded);
184 ADD_FLAG(tagged);
185 ADD_FLAG(threaded);
186 ADD_FLAG(trash);
187 ADD_FLAG(visible);
188#undef ADD_FLAG
189 mutt_debug(LL_DEBUG1, "\tFlags: %s\n", buf_is_empty(&buf) ? "[NONE]" : buf_string(&buf));
190
191#define ADD_FLAG(F) add_flag(&buf, (e->security & F), #F)
192 buf_reset(&buf);
207#undef ADD_FLAG
208 mutt_debug(LL_DEBUG1, "\tSecurity: %s\n",
209 buf_is_empty(&buf) ? "[NONE]" : buf_string(&buf));
210
211 mutt_date_make_tls(arr, sizeof(arr), e->date_sent);
212 mutt_debug(LL_DEBUG1, "\tSent: %s (%c%02u%02u)\n", arr,
213 e->zoccident ? '-' : '+', e->zhours, e->zminutes);
214
215 mutt_date_make_tls(arr, sizeof(arr), e->received);
216 mutt_debug(LL_DEBUG1, "\tRecv: %s\n", arr);
217
218 buf_dealloc(&buf);
219
220 mutt_debug(LL_DEBUG1, "\tnum_hidden: %ld\n", e->num_hidden);
221 mutt_debug(LL_DEBUG1, "\trecipient: %d\n", e->recipient);
222 mutt_debug(LL_DEBUG1, "\toffset: %ld\n", e->offset);
223 mutt_debug(LL_DEBUG1, "\tlines: %d\n", e->lines);
224 mutt_debug(LL_DEBUG1, "\tindex: %d\n", e->index);
225 mutt_debug(LL_DEBUG1, "\tmsgno: %d\n", e->msgno);
226 mutt_debug(LL_DEBUG1, "\tvnum: %d\n", e->vnum);
227 mutt_debug(LL_DEBUG1, "\tscore: %d\n", e->score);
228 mutt_debug(LL_DEBUG1, "\tattach_total: %d\n", e->attach_total);
229 // if (e->maildir_flags)
230 // mutt_debug(LL_DEBUG1, "\tmaildir_flags: %s\n", e->maildir_flags);
231
232 // struct MuttThread *thread
233 // struct Envelope *env
234 // struct Body *content
235 // struct TagList tags
236
237 // void *edata
238 buf_dealloc(&buf);
239}
240
241void dump_param_list(const struct ParameterList *pl)
242{
243 mutt_debug(LL_DEBUG1, "\tparameters\n");
244
245 if (!pl)
246 {
247 mutt_debug(LL_DEBUG1, "\tNULL pointer\n");
248 return;
249 }
250
251 if (TAILQ_EMPTY(pl))
252 {
253 mutt_debug(LL_DEBUG1, "\tempty\n");
254 return;
255 }
256
257 struct Parameter *np = NULL;
258 TAILQ_FOREACH(np, pl, entries)
259 {
260 mutt_debug(LL_DEBUG1, "\t\t%s = %s\n", NONULL(np->attribute), NONULL(np->value));
261 }
262}
263
264void dump_body(const struct Body *body)
265{
266 mutt_debug(LL_DEBUG1, "Body\n");
267
268 if (!body)
269 {
270 mutt_debug(LL_DEBUG1, "\tNULL pointer\n");
271 return;
272 }
273
274 struct Buffer buf = buf_make(256);
275 char arr[256];
276
277#define ADD_FLAG(F) add_flag(&buf, body->F, #F)
278 ADD_FLAG(attach_qualifies);
279 ADD_FLAG(badsig);
280 ADD_FLAG(deleted);
281 ADD_FLAG(force_charset);
282 ADD_FLAG(goodsig);
283#ifdef USE_AUTOCRYPT
284 ADD_FLAG(is_autocrypt);
285#endif
286 ADD_FLAG(noconv);
287 ADD_FLAG(tagged);
288 ADD_FLAG(unlink);
289 ADD_FLAG(use_disp);
290 ADD_FLAG(warnsig);
291#undef ADD_FLAG
292 mutt_debug(LL_DEBUG1, "\tFlags: %s\n", buf_is_empty(&buf) ? "[NONE]" : buf_string(&buf));
293
294#define OPT_STRING(S) \
295 if (body->S) \
296 mutt_debug(LL_DEBUG1, "\t%s: %s\n", #S, body->S)
297 OPT_STRING(charset);
298 OPT_STRING(description);
299 OPT_STRING(d_filename);
300 OPT_STRING(filename);
301 OPT_STRING(form_name);
302 OPT_STRING(language);
303 OPT_STRING(subtype);
304 OPT_STRING(xtype);
305#undef OPT_STRING
306
307 mutt_debug(LL_DEBUG1, "\thdr_offset: %ld\n", body->hdr_offset);
308 mutt_debug(LL_DEBUG1, "\toffset: %ld\n", body->offset);
309 mutt_debug(LL_DEBUG1, "\tlength: %ld\n", body->length);
310 mutt_debug(LL_DEBUG1, "\tattach_count: %d\n", body->attach_count);
311
312 mutt_debug(LL_DEBUG1, "\tcontent type: %s\n", name_content_type(body->type));
313 mutt_debug(LL_DEBUG1, "\tcontent encoding: %s\n", name_content_encoding(body->encoding));
314 mutt_debug(LL_DEBUG1, "\tcontent disposition: %s\n",
316
317 if (body->stamp != 0)
318 {
319 mutt_date_make_tls(arr, sizeof(arr), body->stamp);
320 mutt_debug(LL_DEBUG1, "\tstamp: %s\n", arr);
321 }
322
324
325 // struct Content *content; ///< Detailed info about the content of the attachment.
326 // struct Body *next; ///< next attachment in the list
327 // struct Body *parts; ///< parts of a multipart or message/rfc822
328 // struct Email *email; ///< header information for message/rfc822
329 // struct AttachPtr *aptr; ///< Menu information, used in recvattach.c
330 // struct Envelope *mime_headers; ///< Memory hole protected headers
331
332 if (body->next)
333 {
334 mutt_debug(LL_DEBUG1, "-NEXT-------------------------\n");
335 dump_body(body->next);
336 }
337 if (body->parts)
338 {
339 mutt_debug(LL_DEBUG1, "-PARTS-------------------------\n");
340 dump_body(body->parts);
341 }
342 if (body->next || body->parts)
343 mutt_debug(LL_DEBUG1, "--------------------------\n");
344 buf_dealloc(&buf);
345}
346
347void dump_attach(const struct AttachPtr *att)
348{
349 mutt_debug(LL_DEBUG1, "AttachPtr\n");
350
351 if (!att)
352 {
353 mutt_debug(LL_DEBUG1, "\tNULL pointer\n");
354 return;
355 }
356
357 struct Buffer buf = buf_make(256);
358
359#define ADD_FLAG(F) add_flag(&buf, att->F, #F)
360 ADD_FLAG(unowned);
361 ADD_FLAG(decrypted);
362 ADD_FLAG(collapsed);
363#undef ADD_FLAG
364
365 if (att->fp)
366 mutt_debug(LL_DEBUG1, "\tfp: %p (%d)\n", (void *) att->fp, fileno(att->fp));
367 mutt_debug(LL_DEBUG1, "\tparent_type: %d\n", att->parent_type);
368 mutt_debug(LL_DEBUG1, "\tlevel: %d\n", att->level);
369 mutt_debug(LL_DEBUG1, "\tnum: %d\n", att->num);
370
371 // struct Body *content; ///< Attachment
372 buf_dealloc(&buf);
373}
374
375char body_name(const struct Body *b)
376{
377 if (!b)
378 return '!';
379
380 if (b->type == TYPE_MULTIPART)
381 return '&';
382
383 if (b->description)
384 return b->description[0];
385
386 if (b->filename)
387 {
388 const char *base = basename(b->filename);
389 if (mutt_str_startswith(base, "neomutt-"))
390 return '0';
391
392 return base[0];
393 }
394
395 return '!';
396}
397
398void dump_body_next(struct Buffer *buf, const struct Body *b)
399{
400 if (!b)
401 return;
402
403 buf_addstr(buf, "<");
404 for (; b; b = b->next)
405 {
406 buf_add_printf(buf, "%c", body_name(b));
407 dump_body_next(buf, b->parts);
408 if (b->next)
409 buf_addch(buf, ',');
410 }
411 buf_addstr(buf, ">");
412}
413
414void dump_body_one_line(const struct Body *b)
415{
416 if (!b)
417 return;
418
419 struct Buffer *buf = buf_pool_get();
420 buf_addstr(buf, "Body layout: ");
421 dump_body_next(buf, b);
422
423 mutt_message("%s", buf_string(buf));
424 buf_pool_release(&buf);
425}
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1210
Email Address Handling.
GUI display the mailboxes in a side panel.
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:221
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:394
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:75
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:258
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
void dump_list_head(const struct ListHead *list, const char *name)
Definition: email.c:56
#define OPT_STRING(S)
void dump_email(const struct Email *e)
Definition: email.c:148
#define ADDR_LIST(AL)
void dump_body_next(struct Buffer *buf, const struct Body *b)
Definition: email.c:398
void dump_attach(const struct AttachPtr *att)
Definition: email.c:347
void dump_param_list(const struct ParameterList *pl)
Definition: email.c:241
void dump_envelope(const struct Envelope *env)
Definition: email.c:77
#define ADD_FLAG(F)
void dump_body_one_line(const struct Body *b)
Definition: email.c:414
char body_name(const struct Body *b)
Definition: email.c:375
void dump_body(const struct Body *body)
Definition: email.c:264
void dump_addr_list(char *buf, size_t buflen, const struct AddressList *al, const char *name)
Definition: email.c:40
const char * name_content_encoding(enum ContentEncoding enc)
Definition: names.c:65
const char * name_content_type(enum ContentType type)
Definition: names.c:47
const char * name_content_disposition(enum ContentDisposition disp)
Definition: names.c:80
Structs that make up an email.
#define MUTT_ENV_CHANGED_SUBJECT
Protected header update.
Definition: envelope.h:37
#define MUTT_ENV_CHANGED_XLABEL
X-Label edited.
Definition: envelope.h:36
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:34
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:35
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp)
Format date in TLS certificate verification style.
Definition: date.c:839
Convenience wrapper for the library headers.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
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:630
API for encryption/signing of emails.
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:85
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:87
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:92
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:80
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define SEC_SIGNOPAQUE
Email has an opaque signature (encrypted)
Definition: lib.h:83
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:81
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:82
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:88
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
#define SEC_KEYBLOCK
Email has a key attached.
Definition: lib.h:84
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#define TAILQ_EMPTY(head)
Definition: queue.h:721
Key value store.
#define NONULL(x)
Definition: string2.h:37
An email to which things will be attached.
Definition: attach.h:37
int num
Attachment index number.
Definition: attach.h:43
int level
Nesting depth of attachment.
Definition: attach.h:42
FILE * fp
Used in the recvattach menu.
Definition: attach.h:39
int parent_type
Type of parent attachment, e.g. TYPE_MULTIPART.
Definition: attach.h:40
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
signed short attach_count
Number of attachments.
Definition: body.h:90
time_t stamp
Time stamp of last encoding update.
Definition: body.h:76
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
char * description
content-description
Definition: body.h:55
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
struct Body * next
next attachment in the list
Definition: body.h:71
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:80
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:36
The envelope/body of an email.
Definition: email.h:39
unsigned int zminutes
Minutes away from UTC.
Definition: email.h:57
int lines
How many lines in the body of this message?
Definition: email.h:62
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:126
bool zoccident
True, if west of UTC, False if east.
Definition: email.h:58
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:71
short attach_total
Number of qualifying attachments in message, if attach_valid.
Definition: email.h:118
unsigned int zhours
Hours away from UTC.
Definition: email.h:56
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:60
int vnum
Virtual message number.
Definition: email.h:117
int score
Message score.
Definition: email.h:116
int msgno
Number displayed to the user.
Definition: email.h:114
char * path
Path of Email (for local Mailboxes)
Definition: email.h:70
int index
The absolute (unsorted) message number.
Definition: email.h:113
short recipient
User_is_recipient()'s return value, cached.
Definition: email.h:119
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:61
The header of an Email.
Definition: envelope.h:57
struct ListHead userhdrs
user defined headers
Definition: envelope.h:85
struct AutocryptHeader * autocrypt_gossip
Autocrypt Gossip header.
Definition: envelope.h:88
struct ListHead references
message references (in reverse order)
Definition: envelope.h:83
struct AutocryptHeader * autocrypt
Autocrypt header.
Definition: envelope.h:87
struct Buffer spam
Spam header.
Definition: envelope.h:82
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
Attribute associated with a MIME part.
Definition: parameter.h:33
char * attribute
Parameter name.
Definition: parameter.h:34
char * value
Parameter value.
Definition: parameter.h:35