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