deliver.c revision 59650fcf68bd83e1b2d56e6ca7e60121babc9e3f
/* Copyright (C) 2005-2006 Timo Sirainen */
#include "lib.h"
#include "lib-signals.h"
#include "ioloop.h"
#include "hostpid.h"
#include "home-expand.h"
#include "env-util.h"
#include "fd-set-nonblock.h"
#include "istream.h"
#include "istream-seekable.h"
#include "module-dir.h"
#include "str.h"
#include "str-sanitize.h"
#include "var-expand.h"
#include "message-address.h"
#include "dict-client.h"
#include "mbox-from.h"
#include "auth-client.h"
#include "mail-send.h"
#include "duplicate.h"
#include "deliver.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <syslog.h>
#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
#define DEFAULT_ENVELOPE_SENDER "dovecot.deliver"
/* After buffer grows larger than this, create a temporary file to /tmp
where to read the mail. */
struct deliver_settings *deliver_set;
{
/* warn about being killed because of some signal, except SIGINT (^C)
which is too common at least while testing :) */
}
{
struct mailbox_sync_context *ctx;
struct mailbox_sync_rec sync_rec;
struct mailbox_status status;
;
}
static struct mailbox *
{
return box;
return NULL;
/* probably the mailbox just doesn't exist. try creating it. */
return NULL;
/* and try opening again */
return NULL;
if (sync_quick(box) < 0) {
mailbox_close(&box);
return NULL;
}
return box;
}
const char *const *keywords)
{
struct mailbox_transaction_context *t;
struct mail_keywords *kw;
const char *msgid;
int ret = 0;
return -1;
ret = -1;
mailbox_keywords_free(t, &kw);
if (ret < 0)
else
ret = mailbox_transaction_commit(&t, 0);
"msgid=%s: saved mail to %s",
mailbox_close(&box);
return ret;
}
{
struct message_address *addr;
const char *str;
(const unsigned char *)str,
}
const char *deliver_get_new_message_id(void)
{
static int count = 0;
return t_strdup_printf("<dovecot-%s-%s-%d@%s>",
}
static void config_file_init(const char *path)
{
if (fd < 0)
t_push();
/* @UNSAFE: line is modified */
/* skip whitespace */
line++;
/* ignore comments or empty lines */
continue;
/* strip away comments. pretty kludgy way really.. */
for (p = line; *p != '\0'; p++) {
if (*p == '\'' || *p == '"') {
quote = *p;
for (p++; *p != quote && *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0')
p++;
}
if (*p == '\0')
break;
} else if (*p == '#') {
*p = '\0';
break;
}
}
/* remove whitespace from end of line */
len--;
lda_section = TRUE;
sections++;
}
if (*line == '}') {
sections--;
lda_section = FALSE;
}
continue;
}
if (sections > 0 && !lda_section)
continue;
do {
value++;
} while (*value == ' ');
}
t_pop();
}
static const struct var_expand_table *
{
static struct var_expand_table static_tab[] = {
{ 'u', NULL },
{ 'n', NULL },
{ 'd', NULL },
{ 's', NULL },
{ 'h', NULL },
{ 'l', NULL },
{ 'r', NULL },
{ 'p', NULL },
{ 'i', NULL },
{ '\0', NULL }
};
struct var_expand_table *tab;
"/HOME_DIRECTORY_USED_BUT_NOT_GIVEN_BY_USERDB";
return tab;
}
static const char *
{
const char *p;
/* it's either type:data or just data */
if (p != NULL) {
while (env != p) {
env++;
}
}
/* expand home */
}
/* expand %vars */
}
static const char *address_sanitize(const char *address)
{
struct message_address *addr;
const char *ret;
else
return ret;
}
{
const char *mbox_hdr;
"/tmp/dovecot.deliver.");
i_stream_unref(&input_list[0]);
return input;
}
static void open_logfile(const char *username)
{
} else {
/* log to file or stderr */
}
}
static void print_help(void)
{
printf("Usage: deliver [-c <config file>] [-d <destination user>] [-m <mailbox>]\n");
}
{
const char *config_path = DEFAULT_CONFIG_FILE;
const char *envelope_sender = DEFAULT_ENVELOPE_SENDER;
const char *mailbox = "INBOX";
const char *auth_socket, *env_tz;
const struct var_expand_table *table;
enum mail_storage_flags flags;
struct mailbox_transaction_context *t;
int i, ret;
lib_init();
#ifdef SIGXFSZ
#endif
/* Clean up environment. */
env_clean();
destination = NULL;
for (i = 1; i < argc; i++) {
/* destination user */
i++;
if (i == argc) {
"Missing destination argument");
}
destination = argv[i];
/* config file path */
i++;
if (i == argc) {
"Missing config file path argument");
}
config_path = argv[i];
/* destination mailbox */
i++;
if (i == argc) {
"Missing mailbox argument");
}
/* envelope sender address */
i++;
if (i == argc) {
"Missing envleope argument");
}
envelope_sender = argv[i];
} else {
print_help();
}
}
process_euid = geteuid();
if (destination != NULL)
user = destination;
else if (process_euid != 0) {
/* we're non-root. get our username. */
else {
i_fatal("Couldn't lookup our username (uid=%s)",
}
} else {
"destination user parameter (-d user) not given");
}
if (destination != NULL) {
if (auth_socket == NULL)
if (ret != 0)
return ret;
/* If possible chdir to home directory so core file
could be written. If it fails, don't worry. */
}
} else {
destination = user;
}
i = 0077;
(void)umask(i);
"postmaster_address setting not given");
}
/* MAIL comes from userdb, MAIL_LOCATION from dovecot.conf */
/* Keep this for backwards compatibility */
}
}
else {
if (plugin_dir == NULL)
TRUE);
}
/* FIXME: how should we handle namespaces? */
flags, lock_method);
"Failed to create storage for '%s' with mail '%s'",
}
if (hook_mail_storage_created != 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);
i_fatal("mail_set_seq() failed");
if (ret <= 0) {
/* plugins didn't handle this. save into INBOX. */
i_stream_seek(input, 0);
const char *error;
bool syntax, temporary_error;
int ret;
if (temporary_error)
return EX_TEMPFAIL;
/* we'll have to reply with permanent failure */
if (ret != 0)
/* ok, rejection sent */
}
}
mailbox_close(&box);
lib_deinit();
return EX_OK;
}