NeoMutt  2025-12-11-58-g09398d
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
expando_msgid.c
Go to the documentation of this file.
1
22
28
29#include <stdbool.h>
30#include <string.h>
31#include <unistd.h>
32#include "mutt/lib.h"
33#include "address/lib.h"
34#include "email/lib.h"
35#include "expando_msgid.h"
36#include "expando/lib.h"
37#include "globals.h"
38#include "sendlib.h"
39
43static void msgid_counter(const struct ExpandoNode *node, void *data,
44 MuttFormatFlags flags, struct Buffer *buf)
45{
46 static char Counter = 'A';
47
48 buf_addch(buf, Counter);
49 Counter = (Counter == 'Z') ? 'A' : Counter + 1;
50}
51
55static long msgid_day_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
56{
57 struct MsgIdData *mid = data;
58
59 return mid->tm.tm_mday;
60}
61
65static void msgid_hostname(const struct ExpandoNode *node, void *data,
66 MuttFormatFlags flags, struct Buffer *buf)
67{
68 struct MsgIdData *mid = data;
69
70 buf_strcpy(buf, mid->fqdn);
71}
72
76static long msgid_hour_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
77{
78 struct MsgIdData *mid = data;
79
80 return mid->tm.tm_hour;
81}
82
86static long msgid_minute_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
87{
88 struct MsgIdData *mid = data;
89
90 return mid->tm.tm_min;
91}
92
96static long msgid_month_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
97{
98 struct MsgIdData *mid = data;
99
100 return mid->tm.tm_mon + 1;
101}
102
106static long msgid_pid_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
107{
108 return getpid();
109}
110
114static void msgid_random_1(const struct ExpandoNode *node, void *data,
115 MuttFormatFlags flags, struct Buffer *buf)
116{
117 char raw[2] = { 0 };
118
119 // hex encoded random byte
120 mutt_randbuf(raw, 1);
121 buf_printf(buf, "%02x", (unsigned char) raw[0]);
122}
123
127static void msgid_random_3(const struct ExpandoNode *node, void *data,
128 MuttFormatFlags flags, struct Buffer *buf)
129{
130 char raw[3] = { 0 };
131 char enc[6] = { 0 };
132
133 mutt_randbuf(raw, sizeof(raw));
134 mutt_b64_encode_urlsafe(raw, sizeof(raw), enc, sizeof(enc));
135
136 buf_strcpy(buf, enc);
137}
138
142static void msgid_random_12(const struct ExpandoNode *node, void *data,
143 MuttFormatFlags flags, struct Buffer *buf)
144{
145 char raw[12] = { 0 };
146 char enc[20] = { 0 };
147
148 struct MsgIdData *mid = data;
149
150 // Convert the four least significant bytes of our timestamp and put it in
151 // raw, with proper endianness (for humans) taken into account
152 for (int i = 0; i < 4; i++)
153 raw[i] = (uint8_t) (mid->now >> (3 - i) * 8u);
154
155 mutt_randbuf(raw + 4, sizeof(raw) - 4);
156 mutt_b64_encode_urlsafe(raw, sizeof(raw), enc, sizeof(enc));
157
158 buf_strcpy(buf, enc);
159}
160
164static long msgid_second_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
165{
166 struct MsgIdData *mid = data;
167
168 return mid->tm.tm_sec;
169}
170
174static long msgid_year_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
175{
176 struct MsgIdData *mid = data;
177
178 return mid->tm.tm_year + 1900;
179}
180
187 // clang-format off
200 { -1, -1, NULL, NULL },
201 // clang-format on
202};
203
227static char *msgid_gen_random(void)
228{
229 const int ID_LEFT_LEN = 50;
230 const int ID_RIGHT_LEN = 12;
231 char rnd_id_left[ID_LEFT_LEN + 1];
232 char rnd_id_right[ID_RIGHT_LEN + 1];
233 char buf[128] = { 0 };
234
235 mutt_rand_base32(rnd_id_left, sizeof(rnd_id_left) - 1);
236 mutt_rand_base32(rnd_id_right, sizeof(rnd_id_right) - 1);
237 rnd_id_left[ID_LEFT_LEN] = 0;
238 rnd_id_right[ID_RIGHT_LEN] = 0;
239
240 snprintf(buf, sizeof(buf), "<%s@%s>", rnd_id_left, rnd_id_right);
241 return mutt_str_dup(buf);
242}
243
250char *msgid_generate(void)
251{
252 const struct Expando *c_message_id_format = cs_subset_expando(NeoMutt->sub, "message_id_format");
253 if (!c_message_id_format)
254 return msgid_gen_random();
255
256 struct MsgIdData mid = { 0 };
257
258 mid.now = time(NULL);
259 mid.tm = mutt_date_gmtime(mid.now);
260
261 mid.fqdn = mutt_fqdn(false, NeoMutt->sub);
262 if (!mid.fqdn)
264
265 struct Buffer *buf = buf_pool_get();
266
267 expando_filter(c_message_id_format, MsgIdRenderCallbacks, &mid,
269 if (buf_is_empty(buf))
270 {
271 buf_pool_release(&buf);
272 return msgid_gen_random();
273 }
274
275 if (buf_at(buf, 0) != '<')
276 buf_insert(buf, 0, "<");
277
278 const int last = buf_len(buf) - 1;
279 if (buf_at(buf, last) != '>')
280 buf_addch(buf, '>');
281
282 char *msgid = buf_strdup(buf);
283 buf_pool_release(&buf);
284
285 return msgid;
286}
Email Address Handling.
size_t mutt_b64_encode_urlsafe(const char *in, size_t inlen, char *out, size_t outlen)
Convert raw bytes to a URL-safe base64 string.
Definition base64.c:163
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t buf_insert(struct Buffer *buf, size_t offset, const char *s)
Add a string in the middle of a buffer.
Definition buffer.c:256
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
const struct Expando * cs_subset_expando(const struct ConfigSubset *sub, const char *name)
Get an Expando config item by name.
@ ED_MSG_ID
Message Id ED_MSG_ ExpandoDataMsgId.
Definition domain.h:49
Structs that make up an email.
int expando_filter(const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, char **env_list, struct Buffer *buf)
Render an Expando and run the result through a filter.
Definition filter.c:138
Parse Expando string.
static char * msgid_gen_random(void)
Generate a random Message ID.
const struct ExpandoRenderCallback MsgIdRenderCallbacks[]
Callbacks for Message Id Expandos.
char * msgid_generate(void)
Generate a Message-Id.
Message Id Expando definitions.
@ ED_MSG_COUNTER
Step counter looping from 'A' to 'Z'.
@ ED_MSG_SECOND
Current year using 4 digits (GMT)
@ ED_MSG_YEAR
4 byte timestamp + 8 bytes of pseudo-random data encoded in Base64
@ ED_MSG_HOUR
Current hour using a 24-hour clock (GMT)
@ ED_MSG_PID
PID of the running mutt process.
@ ED_MSG_RANDOM_1
3 bytes of pseudo-random data encoded in Base64
@ ED_MSG_MINUTE
Current month number (GMT)
@ ED_MSG_RANDOM_3
Current second of the minute (GMT)
@ ED_MSG_DAY
Current day of the month (GMT)
@ ED_MSG_HOSTNAME
$hostname
@ ED_MSG_MONTH
Current minute of the hour (GMT)
@ ED_MSG_RANDOM_12
1 byte of pseudo-random data hex encoded (example: '1b')
char * ShortHostname
Short version of the hostname.
Definition globals.c:37
static long msgid_minute_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Minute - Implements get_number_t -.
static long msgid_second_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Second - Implements get_number_t -.
static long msgid_year_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Year (4 digit) - Implements get_number_t -.
static long msgid_day_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Day - Implements get_number_t -.
static long msgid_pid_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Process Id - Implements get_number_t -.
static long msgid_hour_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Hour - Implements get_number_t -.
static long msgid_month_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Message Id: Month - Implements get_number_t -.
static void msgid_random_3(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Message Id: 3 Random Bytes of Base64 - Implements get_string_t -.
static void msgid_hostname(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Message Id: Hostname - Implements get_string_t -.
static void msgid_random_1(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Message Id: 1 Random Hex Byte - Implements get_string_t -.
static void msgid_counter(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Message Id: Step Counter - Implements get_string_t -.
static void msgid_random_12(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Message Id: Timestamp + 8 Random Bytes of Base64 - Implements get_string_t -.
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
Definition date.c:926
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition random.c:58
void mutt_rand_base32(char *buf, size_t buflen)
Fill a buffer with a base32-encoded random string.
Definition random.c:106
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition render.h:33
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition render.h:32
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:707
Miscellaneous functions for sending an email.
#define NONULL(x)
Definition string2.h:43
String manipulation buffer.
Definition buffer.h:36
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
Basic Expando Node.
Definition node.h:67
Parsed Expando trees.
Definition expando.h:41
Data to generate a Message-Id.
struct tm tm
Time Now (tm)
time_t now
Time Now (seconds)
const char * fqdn
Fully-qualified Domain Name.
Container for Accounts, Notifications.
Definition neomutt.h:43
char ** env
Private copy of the environment variables.
Definition neomutt.h:56
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47