diff options
Diffstat (limited to 'src/lib-smtp/smtp-reply.c')
-rw-r--r-- | src/lib-smtp/smtp-reply.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/lib-smtp/smtp-reply.c b/src/lib-smtp/smtp-reply.c new file mode 100644 index 0000000..3ee27da --- /dev/null +++ b/src/lib-smtp/smtp-reply.c @@ -0,0 +1,186 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "strfuncs.h" +#include "smtp-reply.h" + +void smtp_reply_init(struct smtp_reply *reply, unsigned int status, + const char *text) +{ + const char **text_lines = t_new(const char *, 2); + + text_lines[0] = text; + text_lines[1] = NULL; + + i_zero(reply); + reply->status = status; + reply->text_lines = text_lines; +} + +void smtp_reply_printf(struct smtp_reply *reply, unsigned int status, + const char *format, ...) +{ + va_list args; + + va_start(args, format); + smtp_reply_init(reply, status, t_strdup_vprintf(format, args)); + va_end(args); +} + +const char * +smtp_reply_get_enh_code(const struct smtp_reply *reply) +{ + if (reply->enhanced_code.x < 2) + return NULL; + if (reply->enhanced_code.x >= 6) + return NULL; + + return t_strdup_printf("%u.%u.%u", + reply->enhanced_code.x, reply->enhanced_code.y, reply->enhanced_code.z); +} + +const char *const * +smtp_reply_get_text_lines_omit_prefix(const struct smtp_reply *reply) +{ + unsigned int lines_count, i; + const char **lines; + const char *p; + + if ((p=strchr(reply->text_lines[0], ' ')) == NULL) + return reply->text_lines; + + lines_count = str_array_length(reply->text_lines); + lines = t_new(const char *, lines_count + 1); + + lines[0] = p + 1; + for (i = 1; i < lines_count; i++) + lines[i] = reply->text_lines[i]; + + return lines; +} + +void +smtp_reply_write(string_t *out, const struct smtp_reply *reply) +{ + const char *prefix, *enh_code; + const char *const *lines; + + i_assert(reply->status < 560); + i_assert(reply->enhanced_code.x < 6); + + prefix = t_strdup_printf("%03u", reply->status); + enh_code = smtp_reply_get_enh_code(reply); + + if (reply->text_lines == NULL || *reply->text_lines == NULL) { + str_append(out, prefix); + if (enh_code != NULL) { + str_append_c(out, ' '); + str_append(out, enh_code); + } + str_append(out, " \r\n"); + return; + } + + lines = reply->text_lines; + while (*lines != NULL) { + str_append(out, prefix); + if (*(lines+1) == NULL) + str_append_c(out, ' '); + else + str_append_c(out, '-'); + if (enh_code != NULL) { + str_append(out, enh_code); + str_append_c(out, ' '); + } + str_append(out, *lines); + str_append(out, "\r\n"); + lines++; + } +} + +static void +smtp_reply_write_message_one_line(string_t *out, const struct smtp_reply *reply) +{ + const char *const *lines; + + lines = reply->text_lines; + while (*lines != NULL) { + if (str_len(out) > 0) + str_append_c(out, ' '); + str_append(out, *lines); + lines++; + } +} + +void smtp_reply_write_one_line(string_t *out, const struct smtp_reply *reply) +{ + const char *enh_code = smtp_reply_get_enh_code(reply); + + i_assert(reply->status < 560); + i_assert(reply->enhanced_code.x < 6); + + str_printfa(out, "%03u", reply->status); + if (enh_code != NULL) { + str_append_c(out, ' '); + str_append(out, enh_code); + } + + smtp_reply_write_message_one_line(out, reply); +} + +const char *smtp_reply_log(const struct smtp_reply *reply) +{ + string_t *msg = t_str_new(256); + + if (smtp_reply_is_remote(reply)) { + const char *enh_code = smtp_reply_get_enh_code(reply); + + str_printfa(msg, "%03u", reply->status); + if (enh_code != NULL) { + str_append_c(msg, ' '); + str_append(msg, enh_code); + } + } + + smtp_reply_write_message_one_line(msg, reply); + return str_c(msg); +} + +const char *smtp_reply_get_message(const struct smtp_reply *reply) +{ + string_t *msg = t_str_new(256); + + smtp_reply_write_message_one_line(msg, reply); + return str_c(msg); +} + +void smtp_reply_copy(pool_t pool, struct smtp_reply *dst, + const struct smtp_reply *src) +{ + *dst = *src; + dst->text_lines = p_strarray_dup(pool, src->text_lines); +} + +struct smtp_reply *smtp_reply_clone(pool_t pool, + const struct smtp_reply *src) +{ + struct smtp_reply *dst; + + dst = p_new(pool, struct smtp_reply, 1); + smtp_reply_copy(pool, dst, src); + + return dst; +} + +void smtp_reply_add_to_event(const struct smtp_reply *reply, + struct event_passthrough *e) +{ + const char *enh_code = smtp_reply_get_enh_code(reply); + + e->add_int("status_code", reply->status); + e->add_str("enhanced_code", enh_code); + if (!smtp_reply_is_success(reply)) + e->add_str("error", smtp_reply_get_message(reply)); +} |