smtp-server-transaction.c revision 499ca6dc5d746fd7a7efc6d497deede89553669f
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "lib.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "array.h"
5dd05e966ffd69181ab3067f6939b03ced68ebc3Timo Sirainen#include "str.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "strfuncs.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "guid.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "base64.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen#include "message-date.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "smtp-address.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen#include "smtp-server-private.h"
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenstruct smtp_server_transaction *
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainensmtp_server_transaction_create(struct smtp_server_connection *conn,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const struct smtp_address *mail_from,
cd466fe7b84b0223735a6469c7f7bc225f65996dTimo Sirainen const struct smtp_params_mail *params,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const struct timeval *timestamp)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct smtp_server_transaction *trans;
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen pool_t pool;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen guid_128_t guid;
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen string_t *id;
d56384d5226c8860079d0d0b08b83404e8c42986Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen /* create new transaction */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen pool = pool_alloconly_create("smtp server transaction", 512);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen trans = p_new(pool, struct smtp_server_transaction, 1);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen trans->pool = pool;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen trans->conn = conn;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* generate transaction ID */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen id = t_str_new(30);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen guid_128_generate(guid);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen base64_encode(guid, sizeof(guid), id);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_assert(str_c(id)[str_len(id)-2] == '=');
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen str_truncate(id, str_len(id)-2); /* drop trailing "==" */
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen trans->id = p_strdup(pool, str_c(id));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen trans->mail_from = smtp_address_clone(trans->pool, mail_from);
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen smtp_params_mail_copy(pool, &trans->params, params);
6a9f9a5101b665fd2ef80c9e048a5eace78e01efTimo Sirainen trans->timestamp = *timestamp;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return trans;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen}
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenvoid smtp_server_transaction_free(struct smtp_server_transaction **_trans)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct smtp_server_transaction *trans = *_trans;
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen pool_unref(&trans->pool);
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen *_trans = NULL;
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenstruct smtp_server_recipient *
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainensmtp_server_transaction_find_rcpt_duplicate(
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen struct smtp_server_transaction *trans,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct smtp_server_recipient *rcpt)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct smtp_server_recipient *const *rcptp;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen i_assert(array_is_created(&trans->rcpt_to));
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen array_foreach(&trans->rcpt_to, rcptp) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct smtp_server_recipient *drcpt = *rcptp;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen if (drcpt == rcpt)
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen continue;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen if (smtp_address_equals(drcpt->path, rcpt->path) &&
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen smtp_params_rcpt_equals(&drcpt->params, &rcpt->params))
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen return drcpt;
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen }
1f57716285d4c5bc9bf2fd5569e3c85fd496afd9Timo Sirainen return NULL;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenstruct smtp_server_recipient *
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainensmtp_server_transaction_add_rcpt(struct smtp_server_transaction *trans,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const struct smtp_address *rcpt_to,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const struct smtp_params_rcpt *params)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct smtp_server_recipient *rcpt;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen rcpt = p_new(trans->pool, struct smtp_server_recipient, 1);
a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023Timo Sirainen rcpt->path = smtp_address_clone(trans->pool, rcpt_to);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen smtp_params_rcpt_copy(trans->pool, &rcpt->params, params);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen if (!array_is_created(&trans->rcpt_to))
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen p_array_init(&trans->rcpt_to, trans->pool, 8);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
a29a5b7520f7b8d6cdaf97e66d184b6a9e4f4ecfTimo Sirainen array_append(&trans->rcpt_to, &rcpt, 1);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return rcpt;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen}
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenbool smtp_server_transaction_has_rcpt(struct smtp_server_transaction *trans)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return (array_is_created(&trans->rcpt_to) &&
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen array_count(&trans->rcpt_to) > 0);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen}
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenunsigned int
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainensmtp_server_transaction_rcpt_count(struct smtp_server_transaction *trans)
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (!array_is_created(&trans->rcpt_to))
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return 0;
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen return array_count(&trans->rcpt_to);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen}
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainenvoid smtp_server_transaction_fail_data(struct smtp_server_transaction *trans,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct smtp_server_cmd_ctx *data_cmd,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen unsigned int status, const char *enh_code,
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen const char *fmt, va_list args)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen{
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen struct smtp_server_recipient *const *rcpts;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen const char *msg;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen unsigned int count, i;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen msg = t_strdup_vprintf(fmt, args);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen rcpts = array_get(&trans->rcpt_to, &count);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen for (i = 0; i < count; i++) {
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen smtp_server_reply_index(data_cmd, i,
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen status, enh_code, "<%s> %s",
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen smtp_address_encode(rcpts[i]->path), msg);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen }
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen}
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainenvoid smtp_server_transaction_write_trace_record(string_t *str,
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen struct smtp_server_transaction *trans)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen{
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen struct smtp_server_connection *conn = trans->conn;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen const struct smtp_server_helo_data *helo_data = &conn->helo;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen const char *host, *secstr, *rcpt_to = NULL;
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen if (array_count(&trans->rcpt_to) == 1) {
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen struct smtp_server_recipient *const *rcpts =
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen array_idx(&trans->rcpt_to, 0);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen rcpt_to = smtp_address_encode(rcpts[0]->path);
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen }
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen
5dd05e966ffd69181ab3067f6939b03ced68ebc3Timo Sirainen /* from */
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen str_append(str, "Received: from ");
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen if (helo_data->domain_valid)
b09be485e9373be4288f5615bbce6ebed65a425aTimo Sirainen str_append(str, helo_data->domain);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen else
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen str_append(str, "unknown");
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen host = "";
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen if (conn->remote_ip.family != 0)
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen host = net_ip2addr(&conn->remote_ip);
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen if (host[0] != '\0') {
9453e8d75cfd8fab2232cf772e9b120f308fb3eeTimo Sirainen str_append(str, " ([");
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen str_append(str, host);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen str_append(str, "])");
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen }
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen /* (using) */
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen secstr = smtp_server_connection_get_security_string(conn);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (secstr != NULL) {
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen str_append(str, "\r\n\t(using ");
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen str_append(str, secstr);
33ca6b017b6ebbd048651b5e3d16915001dbc291Timo Sirainen str_append(str, ")");
}
/* by, with */
str_append(str, "\r\n\tby ");
str_append(str, conn->set.hostname);
str_append(str, " with ");
str_append(str, smtp_server_connection_get_protocol_name(conn));
/* id */
str_append(str, "\r\n\tid ");
str_append(str, trans->id);
/* (envelope-from) */
str_append(str, "\r\n\t(envelope-from <");
smtp_address_write(str, trans->mail_from);
str_append(str, ">)");
/* for */
if (rcpt_to != NULL) {
str_append(str, "\r\n\tfor <");
str_append(str, rcpt_to);
str_append(str, ">");
}
str_append(str, "; ");
/* date */
str_append(str, message_date_create(trans->timestamp.tv_sec));
str_printfa(str, "\r\n");
}