/src/dovecot/src/lib-smtp/smtp-reply.c
Line | Count | Source |
1 | | /* Copyright (c) Dovecot authors, see top-level COPYING file */ |
2 | | |
3 | | #include "lib.h" |
4 | | #include "array.h" |
5 | | #include "str.h" |
6 | | #include "strfuncs.h" |
7 | | #include "smtp-reply.h" |
8 | | |
9 | | void smtp_reply_init(struct smtp_reply *reply, unsigned int status, |
10 | | const char *text) |
11 | 0 | { |
12 | 0 | const char **text_lines = t_new(const char *, 2); |
13 | |
|
14 | 0 | text_lines[0] = text; |
15 | 0 | text_lines[1] = NULL; |
16 | |
|
17 | 0 | i_zero(reply); |
18 | 0 | reply->status = status; |
19 | 0 | reply->text_lines = text_lines; |
20 | 0 | } |
21 | | |
22 | | void smtp_reply_printf(struct smtp_reply *reply, unsigned int status, |
23 | | const char *format, ...) |
24 | 0 | { |
25 | 0 | va_list args; |
26 | |
|
27 | 0 | va_start(args, format); |
28 | 0 | smtp_reply_init(reply, status, t_strdup_vprintf(format, args)); |
29 | 0 | va_end(args); |
30 | 0 | } |
31 | | |
32 | | const char * |
33 | | smtp_reply_get_enh_code(const struct smtp_reply *reply) |
34 | 222 | { |
35 | 222 | if (reply->enhanced_code.x < 2) |
36 | 0 | return NULL; |
37 | 222 | if (reply->enhanced_code.x >= 6) |
38 | 0 | return NULL; |
39 | | |
40 | 222 | return t_strdup_printf("%u.%u.%u", |
41 | 222 | reply->enhanced_code.x, reply->enhanced_code.y, reply->enhanced_code.z); |
42 | 222 | } |
43 | | |
44 | | const char *const * |
45 | | smtp_reply_get_text_lines_omit_prefix(const struct smtp_reply *reply) |
46 | 0 | { |
47 | 0 | unsigned int lines_count, i; |
48 | 0 | const char **lines; |
49 | 0 | const char *p; |
50 | |
|
51 | 0 | if ((p=strchr(reply->text_lines[0], ' ')) == NULL) |
52 | 0 | return reply->text_lines; |
53 | | |
54 | 0 | lines_count = str_array_length(reply->text_lines); |
55 | 0 | lines = t_new(const char *, lines_count + 1); |
56 | |
|
57 | 0 | lines[0] = p + 1; |
58 | 0 | for (i = 1; i < lines_count; i++) |
59 | 0 | lines[i] = reply->text_lines[i]; |
60 | |
|
61 | 0 | return lines; |
62 | 0 | } |
63 | | |
64 | | void |
65 | | smtp_reply_write(string_t *out, const struct smtp_reply *reply) |
66 | 222 | { |
67 | 222 | const char *prefix, *enh_code; |
68 | 222 | const char *const *lines; |
69 | | |
70 | 222 | i_assert(reply->status < 560); |
71 | 222 | i_assert(reply->enhanced_code.x < 6); |
72 | | |
73 | 222 | prefix = t_strdup_printf("%03u", reply->status); |
74 | 222 | enh_code = smtp_reply_get_enh_code(reply); |
75 | | |
76 | 222 | if (reply->text_lines == NULL || *reply->text_lines == NULL) { |
77 | 0 | str_append(out, prefix); |
78 | 0 | if (enh_code != NULL) { |
79 | 0 | str_append_c(out, ' '); |
80 | 0 | str_append(out, enh_code); |
81 | 0 | } |
82 | 0 | str_append(out, " \r\n"); |
83 | 0 | return; |
84 | 0 | } |
85 | | |
86 | 222 | lines = reply->text_lines; |
87 | 444 | while (*lines != NULL) { |
88 | 222 | str_append(out, prefix); |
89 | 222 | if (*(lines+1) == NULL) |
90 | 222 | str_append_c(out, ' '); |
91 | 0 | else |
92 | 0 | str_append_c(out, '-'); |
93 | 222 | if (enh_code != NULL) { |
94 | 222 | str_append(out, enh_code); |
95 | 222 | str_append_c(out, ' '); |
96 | 222 | } |
97 | 222 | str_append(out, *lines); |
98 | 222 | str_append(out, "\r\n"); |
99 | 222 | lines++; |
100 | 222 | } |
101 | 222 | } |
102 | | |
103 | | static void |
104 | | smtp_reply_write_message_one_line(string_t *out, const struct smtp_reply *reply) |
105 | 0 | { |
106 | 0 | const char *const *lines; |
107 | |
|
108 | 0 | lines = reply->text_lines; |
109 | 0 | while (*lines != NULL) { |
110 | 0 | if (str_len(out) > 0) |
111 | 0 | str_append_c(out, ' '); |
112 | 0 | str_append(out, *lines); |
113 | 0 | lines++; |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | | void smtp_reply_write_one_line(string_t *out, const struct smtp_reply *reply) |
118 | 0 | { |
119 | 0 | const char *enh_code = smtp_reply_get_enh_code(reply); |
120 | |
|
121 | 0 | i_assert(reply->status < 560); |
122 | 0 | i_assert(reply->enhanced_code.x < 6); |
123 | | |
124 | 0 | str_printfa(out, "%03u", reply->status); |
125 | 0 | if (enh_code != NULL) { |
126 | 0 | str_append_c(out, ' '); |
127 | 0 | str_append(out, enh_code); |
128 | 0 | } |
129 | |
|
130 | 0 | smtp_reply_write_message_one_line(out, reply); |
131 | 0 | } |
132 | | |
133 | | const char *smtp_reply_log(const struct smtp_reply *reply) |
134 | 0 | { |
135 | 0 | string_t *msg = t_str_new(256); |
136 | |
|
137 | 0 | if (smtp_reply_is_remote(reply)) { |
138 | 0 | const char *enh_code = smtp_reply_get_enh_code(reply); |
139 | |
|
140 | 0 | str_printfa(msg, "%03u", reply->status); |
141 | 0 | if (enh_code != NULL) { |
142 | 0 | str_append_c(msg, ' '); |
143 | 0 | str_append(msg, enh_code); |
144 | 0 | } |
145 | 0 | } |
146 | |
|
147 | 0 | smtp_reply_write_message_one_line(msg, reply); |
148 | 0 | return str_c(msg); |
149 | 0 | } |
150 | | |
151 | | const char *smtp_reply_get_message(const struct smtp_reply *reply) |
152 | 0 | { |
153 | 0 | string_t *msg = t_str_new(256); |
154 | |
|
155 | 0 | smtp_reply_write_message_one_line(msg, reply); |
156 | 0 | return str_c(msg); |
157 | 0 | } |
158 | | |
159 | | void smtp_reply_copy(pool_t pool, struct smtp_reply *dst, |
160 | | const struct smtp_reply *src) |
161 | 0 | { |
162 | 0 | *dst = *src; |
163 | 0 | dst->text_lines = p_strarray_dup(pool, src->text_lines); |
164 | 0 | } |
165 | | |
166 | | struct smtp_reply *smtp_reply_clone(pool_t pool, |
167 | | const struct smtp_reply *src) |
168 | 0 | { |
169 | 0 | struct smtp_reply *dst; |
170 | |
|
171 | 0 | dst = p_new(pool, struct smtp_reply, 1); |
172 | 0 | smtp_reply_copy(pool, dst, src); |
173 | |
|
174 | 0 | return dst; |
175 | 0 | } |
176 | | |
177 | | void smtp_reply_add_to_event(const struct smtp_reply *reply, |
178 | | struct event_passthrough *e) |
179 | 0 | { |
180 | 0 | const char *enh_code = smtp_reply_get_enh_code(reply); |
181 | |
|
182 | 0 | e->add_int("status_code", reply->status); |
183 | 0 | e->add_str("enhanced_code", enh_code); |
184 | 0 | if (!smtp_reply_is_success(reply)) |
185 | 0 | e->add_str("error", smtp_reply_get_message(reply)); |
186 | 0 | } |