deliver.c revision 355584df8bebece27e066a863eef81a765fb55b7
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2005-2006 Timo Sirainen */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define DEFAULT_CONFIG_FILE SYSCONFDIR"/dovecot.conf"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define DEFAULT_AUTH_SOCKET_PATH PKG_RUNDIR"/auth-master"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen/* After buffer grows larger than this, create a temporary file to /tmp
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen where to read the mail. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenvoid (*hook_mail_storage_created)(struct mail_storage *storage) = NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void sig_die(int signo, void *context __attr_unused__)
e809db9220c804b16d4d74782433a1075da12274Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen which is too common at least while testing :) */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic struct mailbox *
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenmailbox_open_or_create_synced(struct mail_storage *storage, const char *name)
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen (void)mail_storage_get_last_error(storage, &syntax, &temp);
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen /* probably the mailbox just doesn't exist. try creating it. */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen if (mail_storage_mailbox_create(storage, name, FALSE) < 0)
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* and try opening again */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainenint deliver_save(struct mail_storage *storage, const char *mailbox,
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen const char *const *keywords)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen box = mailbox_open_or_create_synced(storage, mailbox);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (mailbox_copy(t, mail, flags, kw, NULL) < 0)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenconst char *deliver_get_return_address(struct mail *mail)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen const char *str;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen str = mail_get_first_header(mail, "Return-Path");
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen message_address_parse(pool_datastack_create(),
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen (const unsigned char *)str,
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen return addr == NULL || addr->mailbox == NULL || addr->domain == NULL ?
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen NULL : t_strconcat(addr->mailbox, "@", addr->domain, NULL);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen static int count = 0;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen i_fatal_status(EX_CONFIG, "open(%s) failed: %m", path);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen input = i_stream_create_file(fd, default_pool, 1024, TRUE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* @UNSAFE: line is modified */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* skip whitespace */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* ignore comments or empty lines */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* strip away comments. pretty kludgy way really.. */
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (*p == '\0')
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen } else if (*p == '#') {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* remove whitespace from end of line */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_put(t_strconcat(t_str_ucase(key), "=", value, NULL));
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenstatic const struct var_expand_table *
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenget_var_expand_table(const char *user, const char *home)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen static struct var_expand_table static_tab[] = {
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainenstatic const char *
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainenexpand_mail_env(const char *env, const struct var_expand_table *table)
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen const char *p;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen /* it's either type:data or just data */
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen while (env != p) {
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* expand home */
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* expand %vars */
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainenstatic struct istream *create_mbox_stream(int fd)
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen mbox_hdr = mbox_from_create("dovecot.deliver", ioloop_time);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen input_list[0] = i_stream_create_from_data(default_pool, mbox_hdr,
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen input_list[1] = i_stream_create_file(fd, default_pool, 4096, FALSE);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen input_list[2] = i_stream_create_from_data(default_pool, "\n", 1);
2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66fTimo Sirainen input = i_stream_create_seekable(input_list, default_pool,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen prefix = t_strdup_printf("deliver(%s)", username);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen /* log to file or stderr */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_set_failure_timestamp_format(getenv("LOG_TIMESTAMP"));
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenstatic void print_help(void)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen printf("Usage: deliver [-c <config file>] [-d <destination user>] [-m <mailbox>]\n");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *config_path = DEFAULT_CONFIG_FILE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *home, *destination, *user, *mail_env;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_signals_set_handler(SIGALRM, FALSE, NULL, NULL);
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen lib_signals_set_handler(SIGXFSZ, FALSE, NULL, NULL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* Clean up environment. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* destination user */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen "Missing destination argument");
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen /* config file path */
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen "Missing config file path argument");
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* destination mailbox */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen "Missing mailbox argument");
else if (process_euid != 0) {
if (ret != 0)
return ret;
/* MAIL comes from userdb, DEFAULT_MAIL_ENV from dovecot.conf */
TRUE);
if (ret <= 0) {
const char *error;
int ret;
if (temporary_error)
return EX_TEMPFAIL;
if (ret != 0)
lib_deinit();
return EX_OK;