NeoMutt  2023-05-17-16-g61469c
Teaching an old dog new tricks
DOXYGEN
config.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include <config/lib.h>
32#include <stdbool.h>
33#include <stdint.h>
34#include <string.h>
35#include "mutt/lib.h"
36#include "lib.h"
37#ifdef USE_SASL_CYRUS
38#include "conn/lib.h"
39#endif
40
44static int wrapheaders_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
45 intptr_t value, struct Buffer *err)
46{
47 const int min_length = 78; // Recommendations from RFC5233
48 const int max_length = 998;
49
50 if ((value >= min_length) && (value <= max_length))
51 return CSR_SUCCESS;
52
53 // L10N: This applies to the "$wrap_headers" config variable.
54 buf_printf(err, _("Option %s must be between %d and %d inclusive"),
55 cdef->name, min_length, max_length);
56 return CSR_ERR_INVALID;
57}
58
62static int smtp_auth_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
63 intptr_t value, struct Buffer *err)
64{
65 const struct Slist *smtp_auth_methods = (const struct Slist *) value;
66 if (!smtp_auth_methods || (smtp_auth_methods->count == 0))
67 return CSR_SUCCESS;
68
69 struct ListNode *np = NULL;
70 STAILQ_FOREACH(np, &smtp_auth_methods->head, entries)
71 {
72 if (smtp_auth_is_valid(np->data))
73 continue;
74#ifdef USE_SASL_CYRUS
76 continue;
77#endif
78 buf_printf(err, _("Option %s: %s is not a valid authenticator"), cdef->name, np->data);
79 return CSR_ERR_INVALID;
80 }
81
82 return CSR_SUCCESS;
83}
84
88static int simple_command_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef,
89 intptr_t value, struct Buffer *err)
90{
91 // Check for shell metacharacters that won't do what the user expects
92 const char *valstr = (const char *) value;
93 if (!valstr)
94 return CSR_SUCCESS;
95
96 const char c = valstr[strcspn(valstr, "|&;()<>[]{}$`'~\"\\*?")];
97 if (c == '\0')
98 return CSR_SUCCESS;
99
100 // L10N: This applies to the "$sendmail" and "$inews" config variables.
101 buf_printf(err, _("Option %s must not contain shell metacharacters: %c"), cdef->name, c);
102 return CSR_ERR_INVALID;
103}
104
108static struct ConfigDef SendVars[] = {
109 // clang-format off
110 { "abort_noattach", DT_QUAD, MUTT_NO, 0, NULL,
111 "Abort sending the email if attachments are missing"
112 },
113 { "abort_noattach_regex", DT_REGEX, IP "\\<(attach|attached|attachments?)\\>", 0, NULL,
114 "Regex to match text indicating attachments are expected"
115 },
116 { "abort_nosubject", DT_QUAD, MUTT_ASKYES, 0, NULL,
117 "Abort creating the email if subject is missing"
118 },
119 { "abort_unmodified", DT_QUAD, MUTT_YES, 0, NULL,
120 "Abort the sending if the message hasn't been edited"
121 },
122 { "allow_8bit", DT_BOOL, true, 0, NULL,
123 "Allow 8-bit messages, don't use quoted-printable or base64"
124 },
125 { "ask_bcc", DT_BOOL, false, 0, NULL,
126 "Ask the user for the blind-carbon-copy recipients"
127 },
128 { "ask_cc", DT_BOOL, false, 0, NULL,
129 "Ask the user for the carbon-copy recipients"
130 },
132 "When attaching files, use one of these character sets"
133 },
134 { "attribution_intro", DT_STRING, IP "On %d, %n wrote:", 0, NULL,
135 "Message to start a reply, 'On DATE, PERSON wrote:'"
136 },
137 { "attribution_locale", DT_STRING, 0, 0, NULL,
138 "Locale for dates in the attribution message"
139 },
140 { "attribution_trailer", DT_STRING, 0, 0, NULL,
141 "Suffix message to add after reply text"
142 },
143 { "bounce_delivered", DT_BOOL, true, 0, NULL,
144 "Add 'Delivered-To' to bounced messages"
145 },
146 { "content_type", DT_STRING, IP "text/plain", 0, NULL,
147 "Default 'Content-Type' for newly composed messages"
148 },
149 { "crypt_auto_encrypt", DT_BOOL, false, 0, NULL,
150 "Automatically PGP encrypt all outgoing mail"
151 },
152 { "crypt_auto_pgp", DT_BOOL, true, 0, NULL,
153 "Allow automatic PGP functions"
154 },
155 { "crypt_auto_sign", DT_BOOL, false, 0, NULL,
156 "Automatically PGP sign all outgoing mail"
157 },
158 { "crypt_auto_smime", DT_BOOL, true, 0, NULL,
159 "Allow automatic SMIME functions"
160 },
161 { "crypt_reply_encrypt", DT_BOOL, true, 0, NULL,
162 "Encrypt replies to encrypted messages"
163 },
164 { "crypt_reply_sign", DT_BOOL, false, 0, NULL,
165 "Sign replies to signed messages"
166 },
167 { "crypt_reply_sign_encrypted", DT_BOOL, false, 0, NULL,
168 "Sign replies to encrypted messages"
169 },
170 { "dsn_notify", DT_STRING, 0, 0, NULL,
171 "Request notification for message delivery or delay"
172 },
173 { "dsn_return", DT_STRING, 0, 0, NULL,
174 "What to send as a notification of message delivery or delay"
175 },
176 { "empty_subject", DT_STRING, IP "Re: your mail", 0, NULL,
177 "Subject to use when replying to an email with none"
178 },
179 { "encode_from", DT_BOOL, false, 0, NULL,
180 "Encode 'From ' as 'quote-printable' at the beginning of lines"
181 },
182 { "fast_reply", DT_BOOL, false, 0, NULL,
183 "Don't prompt for the recipients and subject when replying/forwarding"
184 },
185 { "fcc_attach", DT_QUAD, MUTT_YES, 0, NULL,
186 "Save sent message with all their attachments"
187 },
188 { "fcc_before_send", DT_BOOL, false, 0, NULL,
189 "Save FCCs before sending the message"
190 },
191 { "fcc_clear", DT_BOOL, false, 0, NULL,
192 "Save sent messages unencrypted and unsigned"
193 },
194 { "followup_to", DT_BOOL, true, 0, NULL,
195 "Add the 'Mail-Followup-To' header is generated when sending mail"
196 },
197 { "forward_attachments", DT_QUAD, MUTT_ASKYES, 0, NULL,
198 "Forward attachments when forwarding a message"
199 },
200 { "forward_attribution_intro", DT_STRING, IP "----- Forwarded message from %f -----", 0, NULL,
201 "Prefix message for forwarded messages"
202 },
203 { "forward_attribution_trailer", DT_STRING, IP "----- End forwarded message -----", 0, NULL,
204 "Suffix message for forwarded messages"
205 },
206 { "forward_decrypt", DT_BOOL, true, 0, NULL,
207 "Decrypt the message when forwarding it"
208 },
209 { "forward_edit", DT_QUAD, MUTT_YES, 0, NULL,
210 "Automatically start the editor when forwarding a message"
211 },
212 { "forward_format", DT_STRING|DT_NOT_EMPTY, IP "[%a: %s]", 0, NULL,
213 "printf-like format string to control the subject when forwarding a message"
214 },
215 { "forward_references", DT_BOOL, false, 0, NULL,
216 "Set the 'In-Reply-To' and 'References' headers when forwarding a message"
217 },
218 { "greeting", DT_STRING, 0, 0, NULL,
219 "Greeting string added to the top of all messages"
220 },
221 { "hdrs", DT_BOOL, true, 0, NULL,
222 "Add custom headers to outgoing mail"
223 },
224 { "hidden_host", DT_BOOL, false, 0, NULL,
225 "Don't use the hostname, just the domain, when generating the message id"
226 },
227 { "honor_followup_to", DT_QUAD, MUTT_YES, 0, NULL,
228 "Honour the 'Mail-Followup-To' header when group replying"
229 },
230 { "ignore_list_reply_to", DT_BOOL, false, 0, NULL,
231 "Ignore the 'Reply-To' header when using `<reply>` on a mailing list"
232 },
233 { "include", DT_QUAD, MUTT_ASKYES, 0, NULL,
234 "Include a copy of the email that's being replied to"
235 },
236 { "me_too", DT_BOOL, false, 0, NULL,
237 "Remove the user's address from the list of recipients"
238 },
239 { "mime_forward_decode", DT_BOOL, false, 0, NULL,
240 "Decode the forwarded message before attaching it"
241 },
242 { "mime_type_query_command", DT_STRING|DT_COMMAND, 0, 0, NULL,
243 "External command to determine the MIME type of an attachment"
244 },
245 { "mime_type_query_first", DT_BOOL, false, 0, NULL,
246 "Run the `$mime_type_query_command` before the mime.types lookup"
247 },
248 { "nm_record", DT_BOOL, false, 0, NULL,
249 "(notmuch) If the 'record' mailbox (sent mail) should be indexed"
250 },
251 { "pgp_reply_inline", DT_BOOL, false, 0, NULL,
252 "Reply using old-style inline PGP messages (not recommended)"
253 },
254 { "postpone_encrypt", DT_BOOL, false, 0, NULL,
255 "Self-encrypt postponed messages"
256 },
257 { "postpone_encrypt_as", DT_STRING, 0, 0, NULL,
258 "Fallback encryption key for postponed messages"
259 },
260 { "recall", DT_QUAD, MUTT_ASKYES, 0, NULL,
261 "Recall postponed mesaages when asked to compose a message"
262 },
263 { "reply_self", DT_BOOL, false, 0, NULL,
264 "Really reply to yourself, when replying to your own email"
265 },
266 { "reply_to", DT_QUAD, MUTT_ASKYES, 0, NULL,
267 "Address to use as a 'Reply-To' header"
268 },
269 { "reply_with_xorig", DT_BOOL, false, 0, NULL,
270 "Create 'From' header from 'X-Original-To' header"
271 },
272 { "resume_draft_files", DT_BOOL, false, 0, NULL,
273 "Process draft files like postponed messages"
274 },
275 { "reverse_name", DT_BOOL|R_INDEX, false, 0, NULL,
276 "Set the 'From' from the address the email was sent to"
277 },
278 { "reverse_real_name", DT_BOOL|R_INDEX, true, 0, NULL,
279 "Set the 'From' from the full 'To' address the email was sent to"
280 },
281 { "sendmail", DT_STRING|DT_COMMAND, IP SENDMAIL " -oem -oi", 0, simple_command_validator,
282 "External command to send email"
283 },
284 { "sendmail_wait", DT_NUMBER, 0, 0, NULL,
285 "Time to wait for sendmail to finish"
286 },
287 { "sig_dashes", DT_BOOL, true, 0, NULL,
288 "Insert '-- ' before the signature"
289 },
290 { "sig_on_top", DT_BOOL, false, 0, NULL,
291 "Insert the signature before the quoted text"
292 },
293 { "signature", DT_PATH|DT_PATH_FILE, IP "~/.signature", 0, NULL,
294 "File containing a signature to append to all mail"
295 },
296 { "use_8bit_mime", DT_BOOL, false, 0, NULL,
297 "Use 8-bit messages and ESMTP to send messages"
298 },
299 { "use_envelope_from", DT_BOOL, false, 0, NULL,
300 "Set the envelope sender of the message"
301 },
302 { "use_from", DT_BOOL, true, 0, NULL,
303 "Set the 'From' header for outgoing mail"
304 },
305 { "user_agent", DT_BOOL, false, 0, NULL,
306 "Add a 'User-Agent' header to outgoing mail"
307 },
308 { "wrap_headers", DT_NUMBER|DT_NOT_NEGATIVE, 78, 0, wrapheaders_validator,
309 "Width to wrap headers in outgoing messages"
310 },
311 { "write_bcc", DT_BOOL, false, 0, NULL,
312 "Write out the 'Bcc' field when preparing to send a mail"
313 },
314
315 { "abort_noattach_regexp", DT_SYNONYM, IP "abort_noattach_regex", IP "2021-03-21" },
316 { "askbcc", DT_SYNONYM, IP "ask_bcc", IP "2021-03-21" },
317 { "askcc", DT_SYNONYM, IP "ask_cc", IP "2021-03-21" },
318 { "attach_keyword", DT_SYNONYM, IP "abort_noattach_regex", IP "2021-03-21" },
319 { "attribution", DT_SYNONYM, IP "attribution_intro", IP "2023-02-20" },
320 { "crypt_autoencrypt", DT_SYNONYM, IP "crypt_auto_encrypt", IP "2021-03-21" },
321 { "crypt_autopgp", DT_SYNONYM, IP "crypt_auto_pgp", IP "2021-03-21" },
322 { "crypt_autosign", DT_SYNONYM, IP "crypt_auto_sign", IP "2021-03-21" },
323 { "crypt_autosmime", DT_SYNONYM, IP "crypt_auto_smime", IP "2021-03-21" },
324 { "crypt_replyencrypt", DT_SYNONYM, IP "crypt_reply_encrypt", IP "2021-03-21" },
325 { "crypt_replysign", DT_SYNONYM, IP "crypt_reply_sign", IP "2021-03-21" },
326 { "crypt_replysignencrypted", DT_SYNONYM, IP "crypt_reply_sign_encrypted", IP "2021-03-21" },
327 { "envelope_from", DT_SYNONYM, IP "use_envelope_from", IP "2021-03-21" },
328 { "forw_decrypt", DT_SYNONYM, IP "forward_decrypt", IP "2021-03-21" },
329 { "forw_format", DT_SYNONYM, IP "forward_format", IP "2021-03-21" },
330 { "metoo", DT_SYNONYM, IP "me_too", IP "2021-03-21" },
331 { "pgp_auto_traditional", DT_SYNONYM, IP "pgp_reply_inline", IP "2021-03-21" },
332 { "pgp_autoencrypt", DT_SYNONYM, IP "crypt_auto_encrypt", IP "2021-03-21" },
333 { "pgp_autosign", DT_SYNONYM, IP "crypt_auto_sign", IP "2021-03-21" },
334 { "pgp_replyencrypt", DT_SYNONYM, IP "crypt_reply_encrypt", IP "2021-03-21" },
335 { "pgp_replyinline", DT_SYNONYM, IP "pgp_reply_inline", IP "2021-03-21" },
336 { "pgp_replysign", DT_SYNONYM, IP "crypt_reply_sign", IP "2021-03-21" },
337 { "pgp_replysignencrypted", DT_SYNONYM, IP "crypt_reply_sign_encrypted", IP "2021-03-21" },
338 { "post_indent_str", DT_SYNONYM, IP "post_indent_string", IP "2021-03-21" },
339 { "post_indent_string", DT_SYNONYM, IP "attribution_trailer", IP "2023-02-20" },
340 { "reverse_realname", DT_SYNONYM, IP "reverse_real_name", IP "2021-03-21" },
341 { "use_8bitmime", DT_SYNONYM, IP "use_8bit_mime", IP "2021-03-21" },
342
343 { NULL },
344 // clang-format on
345};
346
347#if defined(USE_NNTP)
351static struct ConfigDef SendVarsNntp[] = {
352 // clang-format off
353 { "ask_followup_to", DT_BOOL, false, 0, NULL,
354 "(nntp) Ask the user for follow-up groups before editing"
355 },
356 { "ask_x_comment_to", DT_BOOL, false, 0, NULL,
357 "(nntp) Ask the user for the 'X-Comment-To' field before editing"
358 },
360 "(nntp) External command to post news articles"
361 },
362 { "mime_subject", DT_DEPRECATED|DT_BOOL, 0, IP "2021-03-24" },
363
364 { "ask_follow_up", DT_SYNONYM, IP "ask_followup_to", IP "2023-01-20" },
365 { NULL },
366 // clang-format on
367};
368#endif
369
370#if defined(USE_SMTP)
374static struct ConfigDef SendVarsSmtp[] = {
375 // clang-format off
376 { "smtp_authenticators", DT_SLIST|SLIST_SEP_COLON, 0, 0, smtp_auth_validator,
377 "(smtp) List of allowed authentication methods (colon-separated)"
378 },
379 { "smtp_oauth_refresh_command", DT_STRING|DT_COMMAND|DT_SENSITIVE, 0, 0, NULL,
380 "(smtp) External command to generate OAUTH refresh token"
381 },
382 { "smtp_pass", DT_STRING|DT_SENSITIVE, 0, 0, NULL,
383 "(smtp) Password for the SMTP server"
384 },
385 { "smtp_url", DT_STRING|DT_SENSITIVE, 0, 0, NULL,
386 "(smtp) Url of the SMTP server"
387 },
388 { "smtp_user", DT_STRING|DT_SENSITIVE, 0, 0, NULL,
389 "(smtp) Username for the SMTP server"
390 },
391 { NULL },
392 // clang-format on
393};
394#endif
395
400{
402
403#if defined(USE_NNTP)
405#endif
406
407#if defined(USE_SMTP)
409#endif
410
411 return rc;
412}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:171
Convenience wrapper for the config headers.
bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], uint32_t flags)
Register a set of config items.
Definition: set.c:279
#define CSR_ERR_INVALID
Value hasn't been set.
Definition: set.h:38
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define IP
Definition: set.h:54
Connection Library.
static int smtp_auth_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "smtp_authenticators" config variable - Implements ConfigDef::validator() -.
Definition: config.c:62
int charset_slist_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "charset" config variable - Implements ConfigDef::validator() - This is a version for ch...
Definition: charset.c:79
static int wrapheaders_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "wrap_headers" config variable - Implements ConfigDef::validator() -.
Definition: config.c:44
static int simple_command_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "sendmail" and "inews" config variables - Implements ConfigDef::validator() -.
Definition: config.c:88
bool config_init_send(struct ConfigSet *cs)
Register send config variables - Implements module_init_config_t -.
Definition: config.c:399
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_ASKYES
Ask the user, defaulting to 'Yes'.
Definition: quad.h:41
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
bool sasl_auth_validator(const char *authenticator)
Validate an auth method against Cyrus SASL methods.
Definition: sasl.c:133
static struct ConfigDef SendVarsSmtp[]
SMTP Config definitions for the send library.
Definition: config.c:374
static struct ConfigDef SendVars[]
Config definitions for the send library.
Definition: config.c:108
static struct ConfigDef SendVarsNntp[]
NNTP Config definitions for the send library.
Definition: config.c:351
#define SLIST_SEP_COLON
Definition: slist.h:35
#define SLIST_ALLOW_EMPTY
Definition: slist.h:40
bool smtp_auth_is_valid(const char *authenticator)
Check if string is a valid smtp authentication method.
Definition: smtp.c:931
Key value store.
String manipulation buffer.
Definition: buffer.h:34
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
Container for lots of config items.
Definition: set.h:252
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
String list.
Definition: slist.h:47
struct ListHead head
List containing values.
Definition: slist.h:48
size_t count
Number of values in list.
Definition: slist.h:49
#define DT_SLIST
a list of strings
Definition: types.h:39
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
#define DT_BOOL
boolean option
Definition: types.h:30
#define DT_DEPRECATED
Config item shouldn't be used any more.
Definition: types.h:77
#define DT_PATH_FILE
Path is a file.
Definition: types.h:57
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_NOT_EMPTY
Empty strings are not allowed.
Definition: types.h:49
#define DT_STRING
a string
Definition: types.h:41
#define DT_COMMAND
A command.
Definition: types.h:53
#define R_INDEX
Redraw the index menu (MENU_INDEX)
Definition: types.h:68
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
#define DT_NO_FLAGS
No flags are set.
Definition: types.h:47
#define DT_NOT_NEGATIVE
Negative numbers are not allowed.
Definition: types.h:50
#define DT_SENSITIVE
Contains sensitive value, e.g. password.
Definition: types.h:52
#define DT_REGEX
regular expressions
Definition: types.h:38
#define DT_NUMBER
a number
Definition: types.h:35