mail-deliver.c revision 9562831b85e433ae92edd3ea42294578239eff98
/* Copyright (c) 2005-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "str-sanitize.h"
#include "time-util.h"
#include "unichar.h"
#include "var-expand.h"
#include "message-address.h"
#include "lda-settings.h"
#include "mail-storage.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "duplicate.h"
#include "mail-deliver.h"
#define MAIL_DELIVER_USER_CONTEXT(obj) \
#define MAIL_DELIVER_STORAGE_CONTEXT(obj) \
struct mail_deliver_user {
struct mail_deliver_context *deliver_ctx;
bool want_storage_id;
};
struct mail_deliver_cache {
bool filled;
const char *message_id;
const char *subject;
const char *from;
const char *from_envelope;
const char *storage_id;
};
struct mail_deliver_mailbox {
union mailbox_module_context module_ctx;
bool delivery_box;
};
struct mail_deliver_transaction {
struct mail_deliver_cache cache;
};
static const char *lda_log_wanted_headers[] = {
"From", "Message-ID", "Subject",
};
static enum mail_fetch_field lda_log_wanted_fetch_fields =
{
struct message_address *addr;
const char *str;
return NULL;
(const unsigned char *)str,
}
{
}
static void
{
const char *from;
return;
}
const struct var_expand_table *
const char *message)
{
unsigned int delivery_time_msecs;
following call is ignored. Otherwise, only the source mail exists. */
/* This call finishes a mail delivery. With Sieve there may be multiple
mail deliveries. */
const struct var_expand_table stack_tab[] = {
};
}
{
const struct var_expand_table *tab;
return;
i_error("Failed to expand deliver_log_format=%s: %s",
}
}
struct mail_deliver_session *mail_deliver_session_init(void)
{
struct mail_deliver_session *session;
return session;
}
{
}
{
struct mail_namespace *ns;
enum mailbox_flags flags =
*error_str_r = NULL;
if (!uni_utf8_str_is_valid(name)) {
*error_str_r = "Mailbox name not valid UTF-8";
return -1;
}
/* delivering to a namespace prefix means we actually want to
deliver to the INBOX instead */
name = "INBOX";
}
/* deliveries to INBOX must always succeed,
regardless of ACLs */
}
/* flag that this mailbox is used for delivering the mail.
the context isn't set in pigeonhole testuite. */
if (mailbox_open(box) == 0)
return 0;
return -1;
/* try creating it. */
if (*error_r != MAIL_ERROR_EXISTS)
return -1;
/* someone else just created it */
}
if (ctx->lda_mailbox_autosubscribe) {
/* (try to) subscribe to it */
}
/* and try opening again */
if (mailbox_open(box) < 0) {
return -1;
}
return 0;
}
{
struct mailbox_metadata metadata;
const guid_128_t *guid;
/* just play it safe and assume a duplicate */
return TRUE;
}
/* there shouldn't be all that many recipients,
so just do a linear search */
return TRUE;
}
return FALSE;
}
struct mail_save_context *save_ctx)
{
struct mailbox_transaction_context *trans =
return;
/* avoid storing duplicate GUIDs to delivered mails to INBOX. this
happens if mail is delivered to same user multiple times within a
session. the problem with this is that if GUIDs are used as POP3
UIDLs, some clients can't handle the duplicates well. */
}
}
static struct mail *
struct mailbox_transaction_context **trans_r)
{
struct mailbox_transaction_context *t;
return NULL;
t = mailbox_transaction_begin(box, 0);
}
*trans_r = t;
return mail;
}
struct mail_storage **storage_r)
{
struct mailbox_transaction_context *t;
struct mail_save_context *save_ctx;
struct mailbox_header_lookup_ctx *headers_ctx;
struct mail_keywords *kw;
enum mail_error error;
bool default_save;
int ret = 0;
if (default_save)
mailbox_free(&box);
}
return -1;
}
if (ctx->save_dest_mail)
save_ctx = mailbox_save_alloc(t);
ret = -1;
if (ret < 0)
else
if (ret == 0) {
if (ctx->save_dest_mail) {
/* copying needs the message body. with maildir we also
need to get the GUID in case the message gets
expunged. get these early so the copying won't fail
later on. */
}
}
} else {
}
mailbox_free(&box);
return ret;
}
{
return ctx->src_envelope_sender;
}
{
static int count = 0;
return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
}
struct mail_storage *storage)
{
enum mail_error error;
return TRUE;
return error == MAIL_ERROR_TEMP;
}
return FALSE;
}
struct mail_storage **storage_r)
{
struct mail_deliver_user *muser =
int ret;
if (deliver_mail == NULL)
ret = -1;
else {
/* if message was saved, don't bounce it even though
the script failed later. */
} else {
/* success. message may or may not have been saved. */
ret = 0;
}
return -1;
}
}
/* plugins didn't handle this. save into the default mailbox. */
return -1;
}
}
/* still didn't work. try once more to save it
to INBOX. */
}
return ret;
}
{
return old_hook;
}
{
struct mail_deliver_user *muser =
struct mail_deliver_transaction *dt =
return -1;
/* initialize most of the fields from dest_mail */
return 0;
}
{
struct mail_deliver_user *muser =
struct mail_deliver_transaction *dt =
return -1;
/* initialize most of the fields from dest_mail */
return 0;
}
static void
{
struct mail_deliver_user *muser =
struct mailbox_transaction_context *t;
const char *storage_id;
if (!muser->want_storage_id)
return;
/* getting storage_id requires a whole new mailbox view that is
synced, so it'll contain the newly written mail. this is racy, so
it's possible another process has already deleted the mail. */
storage_id[0] == '\0')
storage_id = NULL;
(void)mailbox_transaction_commit(&t);
} else {
}
mailbox_free(&box);
}
static struct mailbox_transaction_context *
{
struct mail_deliver_user *muser =
struct mailbox_transaction_context *t;
struct mail_deliver_transaction *dt;
return t;
}
static int
struct mail_transaction_commit_changes *changes_r)
{
struct mail_deliver_user *muser =
/* sieve creates multiple transactions, saves the mails and
then commits all of them at the end. we'll need to keep
switching the deliver_ctx->cache for each commit.
we also want to do this only for commits generated by sieve.
other plugins or storage backends may be creating transactions as
well, which we need to ignore. */
if (mbox->delivery_box)
return -1;
}
return 0;
}
{
struct mail_deliver_user *muser;
}
{
struct mail_deliver_mailbox *mbox;
struct mail_deliver_user *muser =
and should not be involved */
return;
v->copy = mail_deliver_copy;
}
static struct mail_storage_hooks mail_deliver_hooks = {
};
void mail_deliver_hooks_init(void)
{
}