main.c revision b1c85a1f889a5e71f491e320bdac95df3c9fe550
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2017 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "lib.h"
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen#include "lib-signals.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "env-util.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "fd-set-nonblock.h"
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen#include "istream.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "istream-seekable.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "path-util.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "safe-mkstemp.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "eacces-error.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "ipwd.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "str.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "str-sanitize.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "strescape.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "unichar.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "rfc822-parser.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "message-address.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "settings-parser.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "master-service.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "master-service-settings.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "mail-storage-service.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "mail-namespace.h"
9999b049d4e02d7ea5d506a0ada68e519cfdbbbdTimo Sirainen#include "raw-storage.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "mail-deliver.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "mail-send.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "mbox-from.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include "lda-settings.h"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#include <stdio.h>
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen#include <sysexits.h>
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen/* After buffer grows larger than this, create a temporary file to /tmp
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen where to read the mail. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#define MAIL_MAX_MEMORY_BUFFER (1024*128)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic const char *wanted_headers[] = {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "From", "To", "Message-ID", "Subject", "Return-Path",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen NULL
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen};
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainenstatic const char *escape_local_part(const char *local_part)
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen{
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen const char *p;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen /* if local_part isn't dot-atom-text, we need to return quoted-string
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen dot-atom-text = 1*atext *("." 1*atext) */
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen for (p = local_part; *p != '\0'; p++) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen if (!IS_ATEXT(*p) && *p != '.')
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen break;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen }
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen if (*p != '\0' || *local_part == '.' ||
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen (p != local_part && p[-1] == '.'))
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen local_part = t_strdup_printf("\"%s\"", str_escape(local_part));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return local_part;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic const char *address_sanitize(const char *address)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct message_address *addr;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char *ret, *mailbox;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pool_t pool;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pool = pool_alloconly_create("address sanitizer", 256);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen addr = message_address_parse(pool, (const unsigned char *)address,
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen strlen(address), 1, FALSE);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (addr == NULL || addr->mailbox == NULL || addr->domain == NULL ||
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *addr->mailbox == '\0')
934f04e8a86c14a425f82ec7c74c169492093f98Timo Sirainen ret = DEFAULT_ENVELOPE_SENDER;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mailbox = escape_local_part(addr->mailbox);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (*addr->domain == '\0')
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = t_strdup(mailbox);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen else
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = t_strdup_printf("%s@%s", mailbox, addr->domain);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen pool_unref(&pool);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen return ret;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic int seekable_fd_callback(const char **path_r, void *context)
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen{
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen struct mail_deliver_context *ctx = context;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen string_t *path;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen int fd;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen path = t_str_new(128);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_user_set_get_temp_prefix(path, ctx->dest_user->set);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (fd == -1) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_error("safe_mkstemp(%s) failed: %m", str_c(path));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we just want the fd, unlink it */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (i_unlink(str_c(path)) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* shouldn't happen.. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_close_fd(&fd);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return -1;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *path_r = str_c(path);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return fd;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
378e1583e12eb10c265e8ab0cbd0c6250e8639b5Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic struct istream *
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainencreate_raw_stream(struct mail_deliver_context *ctx,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen int fd, time_t *mtime_r)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream *input, *input2, *input_list[2];
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const unsigned char *data;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen char *sender = NULL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen size_t i, size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen int ret, tz;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen *mtime_r = (time_t)-1;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fd_set_nonblock(fd, FALSE);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch input = i_stream_create_fd(fd, 4096);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen input->blocking = TRUE;
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen /* If input begins with a From-line, drop it */
7a727b88fdfccf74466041c17ebb34c1da663567Timo Sirainen ret = i_stream_read_bytes(input, &data, &size, 5);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ret > 0 && memcmp(data, "From ", 5) == 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* skip until the first LF */
ebcf7d6c9222f2c96053516e0c90994bff62dd55Timo Sirainen i_stream_skip(input, 5);
ebcf7d6c9222f2c96053516e0c90994bff62dd55Timo Sirainen while (i_stream_read_more(input, &data, &size) > 0) {
ebcf7d6c9222f2c96053516e0c90994bff62dd55Timo Sirainen for (i = 0; i < size; i++) {
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen if (data[i] == '\n')
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (i != size) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen (void)mbox_from_parse(data, i, mtime_r, &tz,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen &sender);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_skip(input, i + 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_skip(input, size);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (sender != NULL && ctx->src_envelope_sender == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* use the envelope sender from From_-line, but only if it
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen hasn't been specified with -f already. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->src_envelope_sender = p_strdup(ctx->pool, sender);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_free(sender);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (input->v_offset == 0) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen input2 = input;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen i_stream_ref(input2);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen } else {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen input2 = i_stream_create_limit(input, (uoff_t)-1);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen }
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen i_stream_unref(&input);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen input_list[0] = input2; input_list[1] = NULL;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER,
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen seekable_fd_callback, ctx);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen i_stream_unref(&input2);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen return input;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen}
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainenstatic struct mail *
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainenlda_raw_mail_open(struct mail_deliver_context *ctx, const char *path)
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen{
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct mail_user *raw_mail_user;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct mailbox *box;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct mailbox_transaction_context *t;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct mail *mail;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct mailbox_header_lookup_ctx *headers_ctx;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen struct istream *input;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen void **sets;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen const char *envelope_sender;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen time_t mtime;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen int ret;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen sets = master_service_settings_get_others(master_service);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen raw_mail_user =
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen raw_storage_create_from_set(ctx->dest_user->set_info, sets[0]);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen envelope_sender = ctx->src_envelope_sender != NULL ?
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen ctx->src_envelope_sender : DEFAULT_ENVELOPE_SENDER;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen if (path == NULL) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen input = create_raw_stream(ctx, 0, &mtime);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen i_stream_set_name(input, "stdin");
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen ret = raw_mailbox_alloc_stream(raw_mail_user, input, mtime,
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen envelope_sender, &box);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen i_stream_unref(&input);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen } else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ret = raw_mailbox_alloc_path(raw_mail_user, path, (time_t)-1,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen envelope_sender, &box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ret < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal("Can't open delivery mail as raw: %s",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mailbox_get_last_error(box, NULL));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen mail_user_unref(&raw_mail_user);
7d102c66eb1755e1894cf56e3594cd744e855238Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek t = mailbox_transaction_begin(box, 0);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek headers_ctx = mailbox_header_lookup_init(box, wanted_headers);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek mail = mail_alloc(t, 0, headers_ctx);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek mailbox_header_lookup_unref(&headers_ctx);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_set_seq(mail, 1);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return mail;
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek}
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainenstatic void
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenlda_set_dest_addr(struct mail_deliver_context *ctx, const char *user,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char *destaddr_source)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ctx->dest_addr == NULL &&
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen *ctx->set->lda_original_recipient_header != '\0') {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->dest_addr = mail_deliver_get_address(ctx->src_mail,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->set->lda_original_recipient_header);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen destaddr_source = t_strconcat(
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->set->lda_original_recipient_header, " header", NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
15d19d6e4daf460d8d2c82b981e23996dbdf7ba5Timo Sirainen if (ctx->dest_addr == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->dest_addr = strchr(user, '@') != NULL ? user :
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen t_strconcat(user, "@", ctx->set->hostname, NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen destaddr_source = "user@hostname";
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ctx->final_dest_addr == NULL)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->final_dest_addr = ctx->dest_addr;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ctx->dest_user->mail_debug) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_debug("Destination address: %s (source: %s)",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx->dest_addr, destaddr_source);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void failure_exit_callback(int *status)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen{
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we want all our exit codes to be sysexits.h compatible.
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if we failed because of a logging related error, we most likely
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen aren't writing to stderr, so try writing there to give some kind of
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen a clue what's wrong. FATAL_LOGOPEN failure already wrote to
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen stderr, so don't duplicate it. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen switch (*status) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_LOGWRITE:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fputs("Failed to write to log file", stderr);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_LOGERROR:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fputs("Internal logging error", stderr);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_LOGOPEN:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_OUTOFMEM:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_EXEC:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case FATAL_DEFAULT:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen default:
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen return;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen }
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen *status = EX_TEMPFAIL;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen}
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainenstatic void print_help(void)
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen{
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen printf(
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen"Usage: dovecot-lda [-c <config file>] [-a <address>] [-d <username>] [-p <path>]\n"
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen" [-f <envelope sender>] [-m <mailbox>] [-e] [-k]\n");
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen}
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainenint main(int argc, char *argv[])
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen{
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen const struct setting_parser_info *set_roots[] = {
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen &lda_setting_parser_info,
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen NULL
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen };
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen struct mail_deliver_context ctx;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen enum mail_storage_service_flags service_flags = 0;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen const char *user, *errstr, *path;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch struct lda_settings *lda_set;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen struct mail_storage_service_ctx *storage_service;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen struct mail_storage_service_user *service_user;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen struct mail_storage_service_input service_input;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen struct mail_storage *storage;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen const char *user_source = "", *destaddr_source = "";
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen uid_t process_euid;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen bool stderr_rejection = FALSE;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen int ret, c;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen enum mail_error error;
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen if (getuid() != geteuid() && geteuid() == 0) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen /* running setuid - don't allow this if the binary is
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen executable by anyone */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct stat st;
39a97e88db1d6626469f905085b787c268502153Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (stat(argv[0], &st) < 0) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen fprintf(stderr, "stat(%s) failed: %s\n",
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen argv[0], strerror(errno));
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen return EX_TEMPFAIL;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen } else if ((st.st_mode & 1) != 0 && (st.st_mode & 04000) != 0) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen fprintf(stderr, "%s must not be both world-executable "
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen "and setuid-root. This allows root exploits. "
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "See http://wiki2.dovecot.org/LDA#multipleuids\n",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen argv[0]);
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen return EX_TEMPFAIL;
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_set_failure_exit_callback(failure_exit_callback);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen master_service = master_service_init("lda",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MASTER_SERVICE_FLAG_STANDALONE |
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR |
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME,
39a97e88db1d6626469f905085b787c268502153Timo Sirainen &argc, &argv, "a:d:ef:m:p:r:");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_zero(&ctx);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.session = mail_deliver_session_init();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.pool = ctx.session->pool;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.dest_mailbox_name = "INBOX";
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.timeout_secs = LDA_SUBMISSION_TIMEOUT_SECS;
39a97e88db1d6626469f905085b787c268502153Timo Sirainen path = NULL;
39a97e88db1d6626469f905085b787c268502153Timo Sirainen
39a97e88db1d6626469f905085b787c268502153Timo Sirainen user = getenv("USER");
39a97e88db1d6626469f905085b787c268502153Timo Sirainen while ((c = master_getopt(master_service)) > 0) {
39a97e88db1d6626469f905085b787c268502153Timo Sirainen switch (c) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case 'a':
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* original recipient address */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.dest_addr = optarg;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen destaddr_source = "-a parameter";
35f3b7e05afecacd0332c210c6e253911c2813d8Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case 'd':
35f3b7e05afecacd0332c210c6e253911c2813d8Timo Sirainen /* destination user */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen user = optarg;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen case 'e':
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen stderr_rejection = TRUE;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen break;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen case 'f':
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen /* envelope sender address */
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen ctx.src_envelope_sender =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen p_strdup(ctx.pool, address_sanitize(optarg));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case 'm':
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* destination mailbox.
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen Ignore -m "". This allows doing -m ${extension}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen in Postfix to handle user+mailbox */
56b13d0e6ab03b6ea20c23cdf84577194db40af3Timo Sirainen if (*optarg != '\0') T_BEGIN {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (!uni_utf8_str_is_valid(optarg)) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal("Mailbox name not UTF-8: %s",
56b13d0e6ab03b6ea20c23cdf84577194db40af3Timo Sirainen optarg);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.dest_mailbox_name = optarg;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } T_END;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen case 'p':
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* input path */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (t_abspath(optarg, &path, &errstr) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal("t_abspath(%s) failed: %s",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen optarg, errstr);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen case 'r':
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* final recipient address */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.final_dest_addr = optarg;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen break;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen default:
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen print_help();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return EX_USAGE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (optind != argc) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen print_help();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen process_euid = geteuid();
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen else if (process_euid != 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we're non-root. get our username and possibly our home. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct passwd pw;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const char *home;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen home = getenv("HOME");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (user != NULL && home != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* no need for a pw lookup */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen user_source = "USER environment";
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else if ((ret = i_getpwuid(process_euid, &pw)) > 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen user = t_strdup(pw.pw_name);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (home == NULL)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen env_put(t_strconcat("HOME=", pw.pw_dir, NULL));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen user_source = "passwd lookup for process euid";
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen } else if (ret < 0) {
60d1fdf2c17fd0c7020234590dbd73da81c3ce8fTimo Sirainen /* temporary failure */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal("getpwuid() failed: %m");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else if (user == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal_status(EX_USAGE,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "Couldn't lookup our username (uid=%s)",
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen dec2str(process_euid));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_fatal_status(EX_USAGE,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen "destination user parameter (-d user) not given");
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen master_service_init_finish(master_service);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_zero(&service_input);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen service_input.module = "lda";
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen service_input.service = "lda";
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen service_input.username = user;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT |
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USE_SYSEXITS;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen storage_service = mail_storage_service_init(master_service, set_roots,
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen service_flags);
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen /* set before looking up the user (or ideally we'd do this between
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen _lookup() and _next(), but don't bother) */
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen ctx.delivery_time_started = ioloop_timeval;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen ret = mail_storage_service_lookup_next(storage_service, &service_input,
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen &service_user, &ctx.dest_user,
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen &errstr);
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen if (ret <= 0) {
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen if (ret < 0)
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen i_fatal("%s", errstr);
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen return EX_NOUSER;
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen }
aec1d6f3cdce8deed8b5d718fe4031ef7432cec1Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#ifdef SIGXFSZ
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen lib_signals_ignore(SIGXFSZ, TRUE);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen#endif
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen lda_set = mail_storage_service_user_get_set(service_user)[1];
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (settings_var_expand(&lda_setting_parser_info, lda_set,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.dest_user->pool,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_user_var_expand_table(ctx.dest_user),
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen &errstr) <= 0)
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen i_fatal("Failed to expand settings: %s", errstr);
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen ctx.set = lda_set;
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen if (ctx.dest_user->mail_debug && *user_source != '\0') {
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen i_debug("userdb lookup skipped, username taken from %s",
84cccc6b54d8f92fdee75fe96c63bb67b097eeb3Timo Sirainen user_source);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.src_mail = lda_raw_mail_open(&ctx, path);
934f04e8a86c14a425f82ec7c74c169492093f98Timo Sirainen lda_set_dest_addr(&ctx, user, destaddr_source);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (mail_deliver(&ctx, &storage) < 0) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (ctx.tempfail_error != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen errstr = ctx.tempfail_error;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen error = MAIL_ERROR_TEMP;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen } else if (storage != NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen errstr = mail_storage_get_last_error(storage, &error);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen } else {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* This shouldn't happen */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_error("BUG: Saving failed to unknown storage");
934f04e8a86c14a425f82ec7c74c169492093f98Timo Sirainen return EX_TEMPFAIL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (stderr_rejection) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* write to stderr also for tempfails so that MTA
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen can log the reason if it wants to. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen fprintf(stderr, "%s\n", errstr);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (error != MAIL_ERROR_NOQUOTA ||
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.set->quota_full_tempfail) {
934f04e8a86c14a425f82ec7c74c169492093f98Timo Sirainen /* Saving to INBOX should always work unless
934f04e8a86c14a425f82ec7c74c169492093f98Timo Sirainen we're over quota. If it didn't, it's probably a
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen configuration problem. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return EX_TEMPFAIL;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.mailbox_full = TRUE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen ctx.dsn = TRUE;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we'll have to reply with permanent failure */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_deliver_log(&ctx, "rejected: %s",
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen str_sanitize(errstr, 512));
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen if (stderr_rejection)
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen return EX_NOPERM;
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen ret = mail_send_rejection(&ctx, user, errstr);
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen if (ret != 0)
a67b39aac630b8d53c1afeec6abdc32ba91899c5Timo Sirainen return ret < 0 ? EX_TEMPFAIL : ret;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* ok, rejection sent */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
ec3eb53293a282b409fe128153038522c294dda3Aki Tuomi {
ec3eb53293a282b409fe128153038522c294dda3Aki Tuomi struct mailbox_transaction_context *t =
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen ctx.src_mail->transaction;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct mailbox *box = ctx.src_mail->box;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_free(&ctx.src_mail);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mailbox_transaction_rollback(&t);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mailbox_free(&box);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen }
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_user_unref(&ctx.dest_user);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_deliver_session_deinit(&ctx.session);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_storage_service_user_free(&service_user);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen mail_storage_service_deinit(&storage_service);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen master_service_deinit(&master_service);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return EX_OK;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen}
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen