Coverage Report

Created: 2026-08-13 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}