-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathmail.c
124 lines (107 loc) · 4.07 KB
/
mail.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* FCRON - periodic command scheduler
*
* Copyright 2000-2025 Thibault Godouet <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The GNU General Public License can also be found in the file
* `LICENSE' that comes with the fcron source distribution.
*/
#include "fcron.h"
#include "mail.h"
char *
format_maildisplayname(char *displayname_conf)
/* Format the input string `conf_value` according to RFC5322 sec. 3.2.3.
* <https://datatracker.ietf.org/doc/html/rfc5322#section-3.2.3>.
* Returns: either the formatted displayname (possibly unchanged or empty)
* as a new dynamically allocated string (must be properly freed by the
* caller) or NULL on errors like buffer overflow. */
{
bool need_quotes = false;
char c = '\0';
char *ipos = NULL; /* Input position */
char *output = NULL, *quoted_output = NULL;
const uint buf_len = MAIL_FROM_VALUE_LEN_MAX;
uint cwritten = 0; /* how many chars we have written */
if (strlen(displayname_conf) == 0) {
return strdup2("");
}
output = (char *)alloc_safe(buf_len * sizeof(char), "output buffer");
/* walk the conf_value and rebuild it in buf1 */
for (ipos = displayname_conf; *ipos; ipos++) {
c = *ipos;
if (strchr(SPECIAL_MBOX_CHARS, c)) {
/* insert escape */
if (c == DQUOTE) {
output[cwritten] = BSLASH;
cwritten++;
}
need_quotes = true;
}
if (cwritten >= buf_len) {
error("Formatted 'displayname' exceeds %u chars", buf_len);
Free_safe(output);
return NULL;
}
output[cwritten] = c;
cwritten++;
}
if (need_quotes) {
quoted_output =
(char *)alloc_safe(buf_len * sizeof(char), "quoted output buffer");
int needed_len = snprintf(quoted_output, buf_len, "\"%s\"", output);
if (needed_len >= buf_len) {
error("Formatted 'displayname' too long: length:%u > max:%u chars",
needed_len, buf_len);
Free_safe(output);
Free_safe(quoted_output);
return NULL;
}
Free_safe(output);
return quoted_output;
}
return output;
}
char *
make_mailbox_addr(char *displayname_conf, char *mail_from, char *hostname)
/* Produce a "mailbox" header as per RFC5322 sec. 3.2.3
* <https://datatracker.ietf.org/doc/html/rfc5322#section-3.2.3>.
* Returns: either the formatted mailbox header as a new dynamically
* allocated string (must be properly freed by the caller) or NULL on
* errors like buffer overflow. */
{
char *buf = NULL;
uint written = 0;
bool need_anglebrackets = false;
const uint buf_len = MAIL_FROM_VALUE_LEN_MAX + 1;
buf = (char *)alloc_safe(buf_len * sizeof(char), "mailbox addr buffer");
if (displayname_conf[0] != '\0') {
/* displayname_conf isn't an empty string */
need_anglebrackets = true;
}
/* no @ here, it's handled upstream */
if (need_anglebrackets)
written = snprintf(buf, buf_len, "%s %c%s%s%c",
displayname_conf, '<', mail_from, hostname, '>');
else
written = snprintf(buf, buf_len, "%s%s", mail_from, hostname);
if (written >= buf_len) {
error("Mailbox addr exceeds %u chars", buf_len);
Free_safe(buf);
return NULL;
}
return buf;
}