deliver.c revision 355584df8bebece27e066a863eef81a765fb55b7
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2005-2006 Timo Sirainen */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "lib.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "lib-signals.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "ioloop.h"
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen#include "hostpid.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "home-expand.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "env-util.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "fd-set-nonblock.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "istream.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "istream-seekable.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "module-dir.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "str.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "var-expand.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "message-address.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "dict-client.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "mbox-from.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "auth-client.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "mail-send.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "duplicate.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include "deliver.h"
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <stdio.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <stdlib.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <unistd.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <fcntl.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <pwd.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#include <syslog.h>
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo 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
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen/* After buffer grows larger than this, create a temporary file to /tmp
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen where to read the mail. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define MAIL_MAX_MEMORY_BUFFER (1024*128)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstruct deliver_settings *deliver_set;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainendeliver_mail_func_t *deliver_mail = NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenvoid (*hook_mail_storage_created)(struct mail_storage *storage) = NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainenstatic struct module *modules;
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainenstatic struct ioloop *ioloop;
063254ba79239f1c0a78ea08d4aa22f8f11d984cTimo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void sig_die(int signo, void *context __attr_unused__)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e809db9220c804b16d4d74782433a1075da12274Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen which is too common at least while testing :) */
6ac48a4295edbeb6b962700be3c563ad015c0a4eTimo Sirainen if (signo != SIGINT)
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen i_warning("Killed with signal %d", signo);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen io_loop_stop(ioloop);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic int sync_quick(struct mailbox *box)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mailbox_sync_context *ctx;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mailbox_sync_rec sync_rec;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen struct mailbox_status status;
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ctx = mailbox_sync_init(box, 0);
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen while (mailbox_sync_next(ctx, &sync_rec) > 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return mailbox_sync_deinit(&ctx, &status);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic struct mailbox *
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenmailbox_open_or_create_synced(struct mail_storage *storage, const char *name)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mailbox *box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen bool syntax, temp;
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen MAILBOX_OPEN_KEEP_RECENT);
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen if (box != NULL)
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen return box;
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen (void)mail_storage_get_last_error(storage, &syntax, &temp);
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen if (syntax || temp)
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen return NULL;
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen /* probably the mailbox just doesn't exist. try creating it. */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen if (mail_storage_mailbox_create(storage, name, FALSE) < 0)
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen return NULL;
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* and try opening again */
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen box = mailbox_open(storage, name, NULL, MAILBOX_OPEN_FAST |
13f6c879a84b3edd2fcc8f9832812be1f8c5d3b6Timo Sirainen MAILBOX_OPEN_KEEP_RECENT);
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen if (box == NULL)
8ddc45fe2080010715c212ecbb2b12b6734f6d4bTimo Sirainen return NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (sync_quick(box) < 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mailbox_close(&box);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainenint deliver_save(struct mail_storage *storage, const char *mailbox,
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen struct mail *mail, enum mail_flags flags,
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen const char *const *keywords)
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen{
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen struct mailbox *box;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen struct mailbox_transaction_context *t;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mail_keywords *kw;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen int ret = 0;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen box = mailbox_open_or_create_synced(storage, mailbox);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (box == NULL)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return -1;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen t = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_EXTERNAL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen kw = strarray_length(keywords) == 0 ? NULL :
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mailbox_keywords_create(t, keywords);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (mailbox_copy(t, mail, flags, kw, NULL) < 0)
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen ret = -1;
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen mailbox_keywords_free(t, &kw);
f87844c400cf9741abad57d9815121d0738a738fTimo Sirainen
81d3c215bb1fdbda2cf7ccd9519f6b4fd03c3791Timo Sirainen if (ret < 0)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mailbox_transaction_rollback(&t);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen else
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ret = mailbox_transaction_commit(&t, 0);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen mailbox_close(&box);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen return ret;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen}
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenconst char *deliver_get_return_address(struct mail *mail)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen{
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen struct message_address *addr;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen const char *str;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen str = mail_get_first_header(mail, "Return-Path");
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen addr = str == NULL ? NULL :
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen message_address_parse(pool_datastack_create(),
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen (const unsigned char *)str,
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen strlen(str), 1);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen return addr == NULL || addr->mailbox == NULL || addr->domain == NULL ?
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen NULL : t_strconcat(addr->mailbox, "@", addr->domain, NULL);
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen}
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenconst char *deliver_get_new_message_id(void)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen{
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen static int count = 0;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen dec2str(ioloop_timeval.tv_sec),
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen dec2str(ioloop_timeval.tv_usec),
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen count++, deliver_set->hostname);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void config_file_init(const char *path)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen{
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen struct istream *input;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen const char *key, *value;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen char *line, *p, quote;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen int fd, sections = 0, lda_section = FALSE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen size_t len;
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen fd = open(path, O_RDONLY);
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen if (fd < 0)
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen i_fatal_status(EX_CONFIG, "open(%s) failed: %m", path);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen t_push();
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
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* skip whitespace */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen while (IS_WHITE(*line))
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen line++;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* ignore comments or empty lines */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (*line == '#' || *line == '\0')
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen continue;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* strip away comments. pretty kludgy way really.. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (p = line; *p != '\0'; p++) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (*p == '\'' || *p == '"') {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen quote = *p;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen for (p++; *p != quote && *p != '\0'; p++) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (*p == '\\' && p[1] != '\0')
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen p++;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen }
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (*p == '\0')
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen break;
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen } else if (*p == '#') {
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen *p = '\0';
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen break;
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen }
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen }
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* remove whitespace from end of line */
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen len = strlen(line);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen while (IS_WHITE(line[len-1]))
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen len--;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen line[len] = '\0';
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen value = p = strchr(line, '=');
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (value == NULL) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (strchr(line, '{') != NULL) {
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen if (strcmp(line, "protocol lda {") == 0 ||
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen strcmp(line, "plugin {") == 0)
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen lda_section = TRUE;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen sections++;
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (*line == '}') {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen sections--;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lda_section = FALSE;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen }
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen continue;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if (sections > 0 && !lda_section)
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen continue;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen while (p > line && p[-1] == ' ') p--;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen key = t_strdup_until(line, p);
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen do {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen value++;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } while (*value == ' ');
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_put(t_strconcat(t_str_ucase(key), "=", value, NULL));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&input);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen t_pop();
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen}
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainen
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenstatic const struct var_expand_table *
9ed77dd00248e88d731ec129116db5dddc0dd3b5Timo Sirainenget_var_expand_table(const char *user, const char *home)
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen static struct var_expand_table static_tab[] = {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'u', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'n', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'd', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 's', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'h', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'l', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'r', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { 'p', NULL },
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen { '\0', NULL }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen };
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct var_expand_table *tab;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab = t_malloc(sizeof(static_tab));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab[0].value = user;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab[1].value = t_strcut(user, '@');
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab[2].value = strchr(user, '@');
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab[3].value = "DELIVER";
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen tab[4].value = home;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen tab[5].value = NULL;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen tab[6].value = NULL;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen tab[7].value = my_pid;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen return tab;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen}
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainenstatic const char *
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainenexpand_mail_env(const char *env, const struct var_expand_table *table)
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen{
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen string_t *str;
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen const char *p;
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen str = t_str_new(256);
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen /* it's either type:data or just data */
00bf64c70c231f647c12c2fd49925ef73cb07f07Timo Sirainen p = strchr(env, ':');
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen if (p != NULL) {
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen while (env != p) {
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen str_append_c(str, *env);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen env++;
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen }
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen str_append_c(str, *env++);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen }
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen if (env[0] == '~' && env[1] == '/') {
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* expand home */
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen env = t_strconcat("%h", env+1, NULL);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen }
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen /* expand %vars */
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen var_expand(str, env, table);
2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66fTimo Sirainen return str_c(str);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen}
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainenstatic struct istream *create_mbox_stream(int fd)
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen{
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen const char *mbox_hdr;
2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66fTimo Sirainen struct istream *input_list[4], *input;
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen fd_set_nonblock(fd, FALSE);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen mbox_hdr = mbox_from_create("dovecot.deliver", ioloop_time);
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen input_list[0] = i_stream_create_from_data(default_pool, mbox_hdr,
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen strlen(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);
7c3f90095b4168d89a268ac1ec820c5925d48fd3Timo Sirainen input_list[3] = NULL;
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen
2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66fTimo Sirainen input = i_stream_create_seekable(input_list, default_pool,
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen MAIL_MAX_MEMORY_BUFFER,
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen "/tmp/dovecot.deliver.");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&input_list[0]);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&input_list[1]);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_stream_unref(&input_list[2]);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return input;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenstatic void open_logfile(const char *username)
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *prefix, *log_path;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen prefix = t_strdup_printf("deliver(%s)", username);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen log_path = getenv("LOG_PATH");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (log_path == NULL || *log_path == '\0') {
2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66fTimo Sirainen const char *env = getenv("SYSLOG_FACILITY");
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen i_set_failure_syslog(prefix, LOG_NDELAY,
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen env == NULL ? LOG_MAIL : atoi(env));
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen } else {
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen /* log to file or stderr */
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen i_set_failure_file(log_path, prefix);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen log_path = getenv("INFO_LOG_PATH");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (log_path != NULL && *log_path != '\0')
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_set_info_file(log_path);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_set_failure_timestamp_format(getenv("LOG_TIMESTAMP"));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainenstatic void print_help(void)
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen printf("Usage: deliver [-c <config file>] [-d <destination user>] [-m <mailbox>]\n");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainenint main(int argc, char *argv[])
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen{
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *config_path = DEFAULT_CONFIG_FILE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *mailbox = "INBOX";
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *auth_socket, *env_tz;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const char *home, *destination, *user, *mail_env;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen const struct var_expand_table *table;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen enum mail_storage_flags flags;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen enum mail_storage_lock_method lock_method;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mail_storage *storage, *mbox_storage;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mailbox *box;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct istream *input;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen struct mailbox_transaction_context *t;
b1a2d2042e8c7e99983175eb462b82cc7a8cb70bTimo Sirainen struct mail *mail;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen uid_t process_euid;
530f80fcbfa8be7378ff0d36ec7ecef41f198e2cTimo Sirainen int i, ret;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_init();
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ioloop = io_loop_create(default_pool);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_signals_init();
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_ignore(SIGPIPE);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen lib_signals_set_handler(SIGALRM, FALSE, NULL, NULL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#ifdef SIGXFSZ
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen lib_signals_set_handler(SIGXFSZ, FALSE, NULL, NULL);
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen#endif
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* Clean up environment. */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_tz = getenv("TZ");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen home = getenv("HOME");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_clean();
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (env_tz != NULL)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_put(t_strconcat("TZ=", env_tz, NULL));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (home != NULL)
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen env_put(t_strconcat("HOME=", home, NULL));
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen destination = NULL;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen for (i = 1; i < argc; i++) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (strcmp(argv[i], "-d") == 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* destination user */
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i++;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen if (i == argc) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_fatal_status(EX_USAGE,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen "Missing destination argument");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen destination = argv[i];
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen } else if (strcmp(argv[i], "-c") == 0) {
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen /* config file path */
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen i++;
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen if (i == argc) {
adcb46fe2c6d1139dfbd8ab08a8fbe96e53f8fd6Timo Sirainen i_fatal_status(EX_USAGE,
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen "Missing config file path argument");
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen }
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen config_path = argv[i];
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen } else if (strcmp(argv[i], "-m") == 0) {
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen /* destination mailbox */
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen i++;
df452e9628fe8d3356c42dd644b020ea9733c0c1Timo Sirainen if (i == argc) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_fatal_status(EX_USAGE,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen "Missing mailbox argument");
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen mailbox = argv[i];
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else {
8e1dbcb9b249c37d00b420705777b103ffa6145dTimo Sirainen print_help();
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen i_fatal_status(EX_USAGE,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen "Unknown argument: %s", argv[1]);
}
}
process_euid = geteuid();
if (destination != NULL)
user = destination;
else if (process_euid != 0) {
/* we're non-root. get our username. */
struct passwd *pw;
pw = getpwuid(process_euid);
if (pw != NULL)
user = t_strdup(pw->pw_name);
else {
i_fatal("Couldn't lookup our username (uid=%s)",
dec2str(process_euid));
}
} else {
i_fatal_status(EX_USAGE,
"destination user parameter (-d user) not given");
}
config_file_init(config_path);
open_logfile(user);
if (destination != NULL) {
auth_socket = getenv("AUTH_SOCKET_PATH");
if (auth_socket == NULL)
auth_socket = DEFAULT_AUTH_SOCKET_PATH;
ret = auth_client_put_user_env(ioloop, auth_socket,
destination, process_euid);
if (ret != 0)
return ret;
home = getenv("HOME");
if (home != NULL) {
/* If possible chdir to home directory so core file
could be written. If it fails, don't worry. */
(void)chdir(home);
}
} else {
destination = user;
}
deliver_set = i_new(struct deliver_settings, 1);
deliver_set->hostname = getenv("HOSTNAME");
if (deliver_set->hostname == NULL)
deliver_set->hostname = my_hostname;
deliver_set->postmaster_address = getenv("POSTMASTER_ADDRESS");
if (deliver_set->postmaster_address == NULL) {
i_fatal_status(EX_CONFIG,
"postmaster_address setting not given");
}
deliver_set->sendmail_path = getenv("SENDMAIL_PATH");
if (deliver_set->sendmail_path == NULL)
deliver_set->sendmail_path = DEFAULT_SENDMAIL_PATH;
dict_driver_register(&dict_driver_client);
duplicate_init();
mail_storage_init();
mail_storage_register_all();
/* MAIL comes from userdb, DEFAULT_MAIL_ENV from dovecot.conf */
mail_env = getenv("MAIL");
if (mail_env == NULL)
mail_env = getenv("DEFAULT_MAIL_ENV");
if (mail_env != NULL) {
table = get_var_expand_table(destination, getenv("HOME"));
mail_env = expand_mail_env(mail_env, table);
}
if (getenv("MAIL_PLUGINS") == NULL)
modules = NULL;
else {
const char *plugin_dir = getenv("MAIL_PLUGIN_DIR");
if (plugin_dir == NULL)
plugin_dir = MODULEDIR"/lda";
modules = module_dir_load(plugin_dir, getenv("MAIL_PLUGINS"),
TRUE);
}
/* FIXME: how should we handle namespaces? */
mail_storage_parse_env(&flags, &lock_method);
storage = mail_storage_create_with_data(mail_env, destination,
flags, lock_method);
if (storage == NULL) {
i_fatal_status(EX_CONFIG,
"Failed to create storage for '%s' with mail '%s'",
destination, mail_env == NULL ? "(null)" : mail_env);
}
if (hook_mail_storage_created != NULL)
hook_mail_storage_created(storage);
mbox_storage = mail_storage_create("mbox", "/tmp", destination, 0,
MAIL_STORAGE_LOCK_FCNTL);
input = create_mbox_stream(0);
box = mailbox_open(mbox_storage, "Dovecot Delivery Mail", input,
MAILBOX_OPEN_NO_INDEX_FILES |
MAILBOX_OPEN_MBOX_ONE_MSG_ONLY);
if (box == NULL)
i_fatal("Can't open delivery mail as mbox");
if (sync_quick(box) < 0)
i_fatal("Can't sync delivery mail");
t = mailbox_transaction_begin(box, 0);
mail = mail_alloc(t, 0, NULL);
if (mail_set_seq(mail, 1) < 0)
i_fatal("mail_set_seq() failed");
ret = deliver_mail == NULL ? 0 :
deliver_mail(storage, mail, destination, mailbox);
if (ret <= 0) {
/* plugins didn't handle this. save into INBOX. */
i_stream_seek(input, 0);
if (deliver_save(storage, mailbox, mail, 0, NULL) < 0) {
const char *error;
bool syntax, temporary_error;
int ret;
error = mail_storage_get_last_error(storage, &syntax,
&temporary_error);
if (temporary_error)
return EX_TEMPFAIL;
/* we'll have to reply with permanent failure */
ret = mail_send_rejection(mail, destination, error);
if (ret != 0)
return ret < 0 ? EX_TEMPFAIL : ret;
/* ok, rejection sent */
}
}
i_stream_unref(&input);
mail_free(&mail);
mailbox_transaction_rollback(&t);
mailbox_close(&box);
mail_storage_destroy(&mbox_storage);
mail_storage_destroy(&storage);
module_dir_unload(&modules);
mail_storage_deinit();
duplicate_deinit();
dict_driver_unregister(&dict_driver_client);
lib_signals_deinit();
io_loop_destroy(&ioloop);
lib_deinit();
return EX_OK;
}