/* * System library. */ #include #include #include /* * Utility library. */ #include #include #include /* * Global library. */ #include #include #include #include #include /* * Bounce service. */ #include #include /* * Testing library. */ #include #define TEST_ENCODING "7bit" #define NO_SMTPUTF8 (0) #define TEST_DSN_ENVID "TEST-ENVID" #define TEST_RECIPIENT "test-recipient" #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) /* test_driver - test driver */ static void test_driver(int argc, char **argv) { BOUNCE_TEMPLATES *bounce_templates; BOUNCE_INFO *bounce_info; VSTRING *message_buf; VSTREAM *message_stream; VSTRING *rec_buf; int rec_type; /* * Sanity checks. */ if (argc != 4) msg_fatal("usage: %s [options] service queue_name queue_id", argv[0]); if (chdir(var_queue_dir) < 0) msg_fatal("chdir %s: %m", var_queue_dir); bounce_hfrom_format = hfrom_format_parse(VAR_HFROM_FORMAT, var_hfrom_format); /* * Write one message to VSTRING. */ message_buf = vstring_alloc(100); if ((message_stream = vstream_memopen(message_buf, O_WRONLY)) == 0) msg_fatal("vstream_memopen O_WRONLY: %m"); bounce_templates = bounce_templates_create(); bounce_info = bounce_mail_init(argv[1], argv[2], argv[3], TEST_ENCODING, NO_SMTPUTF8, TEST_DSN_ENVID, bounce_templates->failure); if (bounce_header(message_stream, bounce_info, TEST_RECIPIENT, NO_POSTMASTER_COPY) < 0) msg_fatal("bounce_header: %m"); if (bounce_diagnostic_log(message_stream, bounce_info, DSN_NOTIFY_OVERRIDE) <= 0) msg_fatal("bounce_diagnostic_log: %m"); if (bounce_header_dsn(message_stream, bounce_info) != 0) msg_fatal("bounce_header_dsn: %m"); if (bounce_diagnostic_dsn(message_stream, bounce_info, DSN_NOTIFY_OVERRIDE) <= 0) msg_fatal("bounce_diagnostic_dsn: %m"); bounce_original(message_stream, bounce_info, DSN_RET_FULL); if (vstream_fclose(message_stream) != 0) msg_fatal("vstream_fclose: %m"); bounce_mail_free(bounce_info); /* * Render the bounce message in human-readable form. */ if ((message_stream = vstream_memopen(message_buf, O_RDONLY)) == 0) msg_fatal("vstream_memopen O_RDONLY: %m"); rec_buf = vstring_alloc(100); while ((rec_type = rec_get(message_stream, rec_buf, 0)) > 0) { switch (rec_type) { case REC_TYPE_CONT: vstream_printf("%.*s", (int) LEN(rec_buf), STR(rec_buf)); break; case REC_TYPE_NORM: vstream_printf("%.*s\n", (int) LEN(rec_buf), STR(rec_buf)); break; default: msg_panic("unexpected message record type %d", rec_type); } vstream_fflush(VSTREAM_OUT); } if (vstream_fclose(message_stream) != 0) msg_fatal("vstream_fclose: %m"); vstring_free(rec_buf); /* * Clean up. */ exit(0); } int var_bounce_limit; int var_max_queue_time; int var_delay_warn_time; char *var_notify_classes; char *var_bounce_rcpt; char *var_2bounce_rcpt; char *var_delay_rcpt; char *var_bounce_tmpl; bool var_threaded_bounce; char *var_hfrom_format; /* header_from_format */ int bounce_hfrom_format; int main(int argc, char **argv) { static const CONFIG_INT_TABLE int_table[] = { VAR_BOUNCE_LIMIT, DEF_BOUNCE_LIMIT, &var_bounce_limit, 1, 0, 0, }; static const CONFIG_TIME_TABLE time_table[] = { VAR_MAX_QUEUE_TIME, DEF_MAX_QUEUE_TIME, &var_max_queue_time, 0, 8640000, VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0, 0, }; static const CONFIG_STR_TABLE str_table[] = { VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, VAR_BOUNCE_RCPT, DEF_BOUNCE_RCPT, &var_bounce_rcpt, 1, 0, VAR_2BOUNCE_RCPT, DEF_2BOUNCE_RCPT, &var_2bounce_rcpt, 1, 0, VAR_DELAY_RCPT, DEF_DELAY_RCPT, &var_delay_rcpt, 1, 0, VAR_BOUNCE_TMPL, DEF_BOUNCE_TMPL, &var_bounce_tmpl, 0, 0, VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0, 0, }; static const CONFIG_NBOOL_TABLE nbool_table[] = { VAR_THREADED_BOUNCE, DEF_THREADED_BOUNCE, &var_threaded_bounce, 0, }; test_main(argc, argv, test_driver, CA_TEST_MAIN_INT_TABLE(int_table), CA_TEST_MAIN_STR_TABLE(str_table), CA_TEST_MAIN_TIME_TABLE(time_table), CA_TEST_MAIN_NBOOL_TABLE(nbool_table), 0); exit(0); }