test-smtp-submit.c revision db2fb7b8ba0e699cf807042550db801e0ae88e04
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *test_message1 =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Subject: Test message\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "To: rcpt@example.com\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "From: sender@example.com\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Test message\r\n";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *test_message2 =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Subject: Test message\r\n"
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen "To: rcpt@example.com\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "From: sender@example.com\r\n"
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen "Test message Test message Test message Test message Test message\r\n"
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen "Test message Test message Test message Test message Test message\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Test message Test message Test message Test message Test message\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Test message Test message Test message Test message Test message\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Test message Test message Test message Test message Test message\r\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Test message Test message Test message Test message Test message\r\n";
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainentypedef void (*test_server_init_t)(unsigned int index);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen (const struct smtp_submit_settings *submit_set);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic unsigned int server_pids_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct connection_list *server_conn_list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic unsigned int server_index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void (*test_server_input)(struct server_connection *conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void (*test_server_init)(struct server_connection *conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void (*test_server_deinit)(struct server_connection *conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Forward declarations
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainenstatic void test_server_run(unsigned int index);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainenserver_connection_deinit(struct server_connection **_conn);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainentest_client_defaults(struct smtp_submit_settings *smtp_set);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainenstatic void test_client_deinit(void);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainentest_client_smtp_send_simple(const struct smtp_submit_settings *smtp_set,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen unsigned int timeout_secs, const char **error_r);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainentest_client_smtp_send_simple_port(const struct smtp_submit_settings *smtp_set,
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen unsigned int timeout_secs, const char **error_r);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainenstatic const char *test_tmp_dir_get(void);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainentest_message_delivery(const char *message, const char *file);
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen const struct smtp_submit_settings *submit_set,
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen * Host lookup failed
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainentest_client_host_lookup_failed(const struct smtp_submit_settings *submit_set)
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen ret = test_client_smtp_send_simple(submit_set,
ed1f14af0d426b5550521a58fc414d130aa14172Timo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Connection refused
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainentest_server_connection_refused(unsigned int index ATTR_UNUSED)
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainentest_client_connection_refused(const struct smtp_submit_settings *submit_set)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ret = test_client_smtp_send_simple_port(submit_set,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Connection timed out
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainentest_connection_timed_out_input(struct server_connection *conn)
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenstatic void test_server_connection_timed_out(unsigned int index)
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen test_server_input = test_connection_timed_out_input;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainentest_client_connection_timed_out(const struct smtp_submit_settings *submit_set)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = test_client_smtp_send_simple_port(submit_set,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen test_out("timeout", (ioloop_time - time) < 5);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Bad greeting
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentest_bad_greeting_input(struct server_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentest_bad_greeting_init(struct server_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "554 No SMTP service here.\r\n");
a8012fea2a7315033bc467acbf46be8e7323318cTimo Sirainenstatic void test_server_bad_greeting(unsigned int index)
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainentest_client_bad_greeting(const struct smtp_submit_settings *submit_set)
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen ret = test_client_smtp_send_simple_port(submit_set,
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainen // FIXME: lmtp client handles this wrong, the greeting is not "bad"
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen //test_out_reason("run", ret == 0, error);
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
fadd878cd6098f5b873c21c121209a922679dae4Timo Sirainenstatic void test_bad_greeting(void)
f1e1d821d93e4a1dc6ed8f23febde868b5d64cd5Timo Sirainen * Denied HELO
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainentest_denied_helo_input(struct server_connection *conn)
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen line = i_stream_read_next_line(conn->conn.input);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "502 Command not implemented\r\n");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainentest_denied_helo_init(struct server_connection *conn)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "220 testserver ESMTP Testfix (Debian/GNU)\r\n");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void test_server_denied_helo(unsigned int index)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainentest_client_denied_helo(const struct smtp_submit_settings *submit_set)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = test_client_smtp_send_simple_port(submit_set,
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen // FIXME: lmtp client handles this wrong, the greeting is not "bad"
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen //test_out_reason("run", ret == 0, error);
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void test_denied_helo(void)
a9bbb619908c206d9cb319398d4aaad37a22cd67Timo Sirainen * Disconnect HELO
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainentest_disconnect_helo_input(struct server_connection *conn)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen line = i_stream_read_next_line(conn->conn.input);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainentest_disconnect_helo_init(struct server_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "220 testserver ESMTP Testfix (Debian/GNU)\r\n");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void test_server_disconnect_helo(unsigned int index)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen test_server_input = test_disconnect_helo_input;
834b90e1f426d1e3308670e09c050bcdea546eb8Timo Sirainentest_client_disconnect_helo(const struct smtp_submit_settings *submit_set)
6e354c4070b611471727692919d29440d73a73f7Timo Sirainen ret = test_client_smtp_send_simple_port(submit_set,
6e354c4070b611471727692919d29440d73a73f7Timo Sirainen // FIXME: lmtp client handles this wrong, the greeting is not "bad"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen //test_out_reason("run", ret == 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen test_out_reason("run (ret < 0)", ret < 0, error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen * Denied MAIL
struct _denied_mail_server {
const char *line;
case DENIED_MAIL_STATE_EHLO:
i_unreached();
int ret;
return FALSE;
static void test_denied_mail(void)
test_end();
enum _denied_rcpt_state {
struct _denied_rcpt_server {
const char *line;
case DENIED_RCPT_STATE_EHLO:
i_unreached();
int ret;
return FALSE;
static void test_denied_rcpt(void)
test_end();
enum _denied_second_rcpt_state {
struct _denied_second_rcpt_server {
const char *line;
i_unreached();
int ret;
return FALSE;
static void test_denied_second_rcpt(void)
test_end();
enum _denied_data_state {
struct _denied_data_server {
const char *line;
case DENIED_DATA_STATE_EHLO:
case DENIED_DATA_STATE_DATA:
i_unreached();
int ret;
return FALSE;
static void test_denied_data(void)
test_end();
enum _data_failure_state {
struct _data_failure_server {
const char *line;
case DATA_FAILURE_STATE_EHLO:
case DATA_FAILURE_STATE_DATA:
i_unreached();
int ret;
return FALSE;
static void test_data_failure(void)
test_end();
enum _data_disconnect_state {
struct _data_disconnect_server {
const char *line;
i_unreached();
int ret;
return FALSE;
static void test_data_disconnect(void)
test_end();
enum _data_timout_state {
struct _data_timout_server {
const char *line;
case DATA_TIMEOUT_STATE_EHLO:
case DATA_TIMEOUT_STATE_DATA:
i_unreached();
int ret;
return FALSE;
static void test_data_timeout(void)
test_end();
enum _successful_delivery_state {
struct _successful_delivery_server {
char *file_path;
const char *line;
int fd;
switch (res) {
i_unreached();
int ret;
return FALSE;
struct _parallel_delivery_client {
unsigned int count;
return FALSE;
static void test_successful_delivery(void)
test_end();
test_end();
int ret;
return FALSE;
static void test_failed_sendmail(void)
test_end();
int ret;
return FALSE;
static void test_successful_sendmail(void)
test_end();
struct _parallel_sendmail_client {
unsigned int count;
return FALSE;
static void test_parallel_sendmail(void)
test_end();
static void (*const test_functions[])(void) = {
static void test_client_deinit(void)
int ret;
return ret;
int fd;
if (debug)
return fd;
static void test_servers_kill_all(void)
if (server_pids_count > 0) {
for (i = 0; i < server_pids_count; i++) {
server_pids_count = 0;
static void test_tmp_dir_init(void)
("/tmp/dovecot-test-smtp-client.%s.%s",
static const char *test_tmp_dir_get(void)
tmp_dir);
return tmp_dir;
static void test_tmp_dir_deinit(void)
const char *error;
const unsigned char *data;
int ret;
const unsigned char *mdata;
if (test_has_failed())
if (test_has_failed())
static void test_run_client_server(
unsigned int server_tests_count)
server_pids_count = 0;
if (server_tests_count > 0) {
for (i = 0; i < server_tests_count; i++)
for (i = 0; i < server_tests_count; i++)
for (i = 0; i < server_tests_count; i++) {
if (server_pids[i] == 0) {
server_pids_count = 0;
hostpid_init();
if (debug)
server_test(i);
if (debug)
server_port = 0;
if (terminating != 0)
static void test_atexit(void)