diff options
Diffstat (limited to 'src/lib-lda')
-rw-r--r-- | src/lib-lda/Makefile.am | 35 | ||||
-rw-r--r-- | src/lib-lda/Makefile.in | 878 | ||||
-rw-r--r-- | src/lib-lda/lda-settings.c | 80 | ||||
-rw-r--r-- | src/lib-lda/lda-settings.h | 21 | ||||
-rw-r--r-- | src/lib-lda/mail-deliver.c | 810 | ||||
-rw-r--r-- | src/lib-lda/mail-deliver.h | 185 | ||||
-rw-r--r-- | src/lib-lda/mail-send.c | 216 | ||||
-rw-r--r-- | src/lib-lda/mail-send.h | 11 |
8 files changed, 2236 insertions, 0 deletions
diff --git a/src/lib-lda/Makefile.am b/src/lib-lda/Makefile.am new file mode 100644 index 0000000..3ea04f3 --- /dev/null +++ b/src/lib-lda/Makefile.am @@ -0,0 +1,35 @@ +noinst_LTLIBRARIES = liblda.la + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-settings \ + -I$(top_srcdir)/src/lib-smtp \ + -I$(top_srcdir)/src/lib-index \ + -I$(top_srcdir)/src/lib-imap \ + -I$(top_srcdir)/src/lib-smtp \ + -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-storage \ + -I$(top_srcdir)/src/lib-ssl-iostream + +liblda_la_SOURCES = \ + lda-settings.c \ + mail-deliver.c \ + mail-send.c + +headers = \ + lda-settings.h \ + mail-deliver.h \ + mail-send.h + +pkginc_libdir=$(pkgincludedir) +pkginc_lib_HEADERS = $(headers) + +deps=../lib-storage/libdovecot-storage.la ../lib-dovecot/libdovecot.la + +pkglib_LTLIBRARIES = libdovecot-lda.la +libdovecot_lda_la_SOURCES = +libdovecot_lda_la_LIBADD = liblda.la $(deps) +libdovecot_lda_la_DEPENDENCIES = liblda.la $(deps) +libdovecot_lda_la_LDFLAGS = -export-dynamic + + diff --git a/src/lib-lda/Makefile.in b/src/lib-lda/Makefile.in new file mode 100644 index 0000000..9d2713a --- /dev/null +++ b/src/lib-lda/Makefile.in @@ -0,0 +1,878 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/lib-lda +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_checktype2.m4 \ + $(top_srcdir)/m4/ac_typeof.m4 $(top_srcdir)/m4/arc4random.m4 \ + $(top_srcdir)/m4/blockdev.m4 $(top_srcdir)/m4/c99_vsnprintf.m4 \ + $(top_srcdir)/m4/clock_gettime.m4 $(top_srcdir)/m4/crypt.m4 \ + $(top_srcdir)/m4/crypt_xpg6.m4 $(top_srcdir)/m4/dbqlk.m4 \ + $(top_srcdir)/m4/dirent_dtype.m4 $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/fd_passing.m4 $(top_srcdir)/m4/fdatasync.m4 \ + $(top_srcdir)/m4/flexible_array_member.m4 \ + $(top_srcdir)/m4/glibc.m4 $(top_srcdir)/m4/gmtime_max.m4 \ + $(top_srcdir)/m4/gmtime_tm_gmtoff.m4 \ + $(top_srcdir)/m4/ioloop.m4 $(top_srcdir)/m4/iovec.m4 \ + $(top_srcdir)/m4/ipv6.m4 $(top_srcdir)/m4/libcap.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libwrap.m4 \ + $(top_srcdir)/m4/linux_mremap.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mmap_write.m4 \ + $(top_srcdir)/m4/mntctl.m4 $(top_srcdir)/m4/modules.m4 \ + $(top_srcdir)/m4/notify.m4 $(top_srcdir)/m4/nsl.m4 \ + $(top_srcdir)/m4/off_t_max.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/pr_set_dumpable.m4 \ + $(top_srcdir)/m4/q_quotactl.m4 $(top_srcdir)/m4/quota.m4 \ + $(top_srcdir)/m4/random.m4 $(top_srcdir)/m4/rlimit.m4 \ + $(top_srcdir)/m4/sendfile.m4 $(top_srcdir)/m4/size_t_signed.m4 \ + $(top_srcdir)/m4/sockpeercred.m4 $(top_srcdir)/m4/sql.m4 \ + $(top_srcdir)/m4/ssl.m4 $(top_srcdir)/m4/st_tim.m4 \ + $(top_srcdir)/m4/static_array.m4 $(top_srcdir)/m4/test_with.m4 \ + $(top_srcdir)/m4/time_t.m4 $(top_srcdir)/m4/typeof.m4 \ + $(top_srcdir)/m4/typeof_dev_t.m4 \ + $(top_srcdir)/m4/uoff_t_max.m4 $(top_srcdir)/m4/vararg.m4 \ + $(top_srcdir)/m4/want_apparmor.m4 \ + $(top_srcdir)/m4/want_bsdauth.m4 \ + $(top_srcdir)/m4/want_bzlib.m4 \ + $(top_srcdir)/m4/want_cassandra.m4 \ + $(top_srcdir)/m4/want_cdb.m4 \ + $(top_srcdir)/m4/want_checkpassword.m4 \ + $(top_srcdir)/m4/want_clucene.m4 $(top_srcdir)/m4/want_db.m4 \ + $(top_srcdir)/m4/want_gssapi.m4 $(top_srcdir)/m4/want_icu.m4 \ + $(top_srcdir)/m4/want_ldap.m4 $(top_srcdir)/m4/want_lua.m4 \ + $(top_srcdir)/m4/want_lz4.m4 $(top_srcdir)/m4/want_lzma.m4 \ + $(top_srcdir)/m4/want_mysql.m4 $(top_srcdir)/m4/want_pam.m4 \ + $(top_srcdir)/m4/want_passwd.m4 $(top_srcdir)/m4/want_pgsql.m4 \ + $(top_srcdir)/m4/want_prefetch.m4 \ + $(top_srcdir)/m4/want_shadow.m4 \ + $(top_srcdir)/m4/want_sodium.m4 $(top_srcdir)/m4/want_solr.m4 \ + $(top_srcdir)/m4/want_sqlite.m4 \ + $(top_srcdir)/m4/want_stemmer.m4 \ + $(top_srcdir)/m4/want_systemd.m4 \ + $(top_srcdir)/m4/want_textcat.m4 \ + $(top_srcdir)/m4/want_unwind.m4 $(top_srcdir)/m4/want_zlib.m4 \ + $(top_srcdir)/m4/want_zstd.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginc_lib_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" \ + "$(DESTDIR)$(pkginc_libdir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES) +am_libdovecot_lda_la_OBJECTS = +libdovecot_lda_la_OBJECTS = $(am_libdovecot_lda_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libdovecot_lda_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libdovecot_lda_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +liblda_la_LIBADD = +am_liblda_la_OBJECTS = lda-settings.lo mail-deliver.lo mail-send.lo +liblda_la_OBJECTS = $(am_liblda_la_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/lda-settings.Plo \ + ./$(DEPDIR)/mail-deliver.Plo ./$(DEPDIR)/mail-send.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdovecot_lda_la_SOURCES) $(liblda_la_SOURCES) +DIST_SOURCES = $(libdovecot_lda_la_SOURCES) $(liblda_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(pkginc_lib_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPARMOR_LIBS = @APPARMOR_LIBS@ +AR = @AR@ +AUTH_CFLAGS = @AUTH_CFLAGS@ +AUTH_LIBS = @AUTH_LIBS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +BISON = @BISON@ +CASSANDRA_CFLAGS = @CASSANDRA_CFLAGS@ +CASSANDRA_LIBS = @CASSANDRA_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CDB_LIBS = @CDB_LIBS@ +CFLAGS = @CFLAGS@ +CLUCENE_CFLAGS = @CLUCENE_CFLAGS@ +CLUCENE_LIBS = @CLUCENE_LIBS@ +COMPRESS_LIBS = @COMPRESS_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LIBS = @CRYPT_LIBS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DICT_LIBS = @DICT_LIBS@ +DLLIB = @DLLIB@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FLEX = @FLEX@ +FUZZER_CPPFLAGS = @FUZZER_CPPFLAGS@ +FUZZER_LDFLAGS = @FUZZER_LDFLAGS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +KRB5CONFIG = @KRB5CONFIG@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LD_NO_WHOLE_ARCHIVE = @LD_NO_WHOLE_ARCHIVE@ +LD_WHOLE_ARCHIVE = @LD_WHOLE_ARCHIVE@ +LIBCAP = @LIBCAP@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_LA_LIBS = @LIBDOVECOT_LA_LIBS@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDAP = @LIBDOVECOT_LDAP@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBEXTTEXTCAT_CFLAGS = @LIBEXTTEXTCAT_CFLAGS@ +LIBEXTTEXTCAT_LIBS = @LIBEXTTEXTCAT_LIBS@ +LIBICONV = @LIBICONV@ +LIBICU_CFLAGS = @LIBICU_CFLAGS@ +LIBICU_LIBS = @LIBICU_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSODIUM_CFLAGS = @LIBSODIUM_CFLAGS@ +LIBSODIUM_LIBS = @LIBSODIUM_LIBS@ +LIBTIRPC_CFLAGS = @LIBTIRPC_CFLAGS@ +LIBTIRPC_LIBS = @LIBTIRPC_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBWRAP_LIBS = @LIBWRAP_LIBS@ +LINKED_STORAGE_LDADD = @LINKED_STORAGE_LDADD@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MODULE_LIBS = @MODULE_LIBS@ +MODULE_SUFFIX = @MODULE_SUFFIX@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_CONFIG = @MYSQL_CONFIG@ +MYSQL_LIBS = @MYSQL_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOPLUGIN_LDFLAGS = @NOPLUGIN_LDFLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANDOC = @PANDOC@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PG_CONFIG = @PG_CONFIG@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +QUOTA_LIBS = @QUOTA_LIBS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RPCGEN = @RPCGEN@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SETTING_FILES = @SETTING_FILES@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SQLITE_CFLAGS = @SQLITE_CFLAGS@ +SQLITE_LIBS = @SQLITE_LIBS@ +SQL_CFLAGS = @SQL_CFLAGS@ +SQL_LIBS = @SQL_LIBS@ +SSL_CFLAGS = @SSL_CFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +ZSTD_CFLAGS = @ZSTD_CFLAGS@ +ZSTD_LIBS = @ZSTD_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +dict_drivers = @dict_drivers@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +moduledir = @moduledir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +rundir = @rundir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sql_drivers = @sql_drivers@ +srcdir = @srcdir@ +ssldir = @ssldir@ +statedir = @statedir@ +sysconfdir = @sysconfdir@ +systemdservicetype = @systemdservicetype@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = liblda.la +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-settings \ + -I$(top_srcdir)/src/lib-smtp \ + -I$(top_srcdir)/src/lib-index \ + -I$(top_srcdir)/src/lib-imap \ + -I$(top_srcdir)/src/lib-smtp \ + -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-storage \ + -I$(top_srcdir)/src/lib-ssl-iostream + +liblda_la_SOURCES = \ + lda-settings.c \ + mail-deliver.c \ + mail-send.c + +headers = \ + lda-settings.h \ + mail-deliver.h \ + mail-send.h + +pkginc_libdir = $(pkgincludedir) +pkginc_lib_HEADERS = $(headers) +deps = ../lib-storage/libdovecot-storage.la ../lib-dovecot/libdovecot.la +pkglib_LTLIBRARIES = libdovecot-lda.la +libdovecot_lda_la_SOURCES = +libdovecot_lda_la_LIBADD = liblda.la $(deps) +libdovecot_lda_la_DEPENDENCIES = liblda.la $(deps) +libdovecot_lda_la_LDFLAGS = -export-dynamic +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib-lda/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/lib-lda/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libdovecot-lda.la: $(libdovecot_lda_la_OBJECTS) $(libdovecot_lda_la_DEPENDENCIES) $(EXTRA_libdovecot_lda_la_DEPENDENCIES) + $(AM_V_CCLD)$(libdovecot_lda_la_LINK) -rpath $(pkglibdir) $(libdovecot_lda_la_OBJECTS) $(libdovecot_lda_la_LIBADD) $(LIBS) + +liblda.la: $(liblda_la_OBJECTS) $(liblda_la_DEPENDENCIES) $(EXTRA_liblda_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(liblda_la_OBJECTS) $(liblda_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda-settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail-deliver.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail-send.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkginc_libHEADERS: $(pkginc_lib_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkginc_libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkginc_libdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkginc_libdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkginc_libdir)" || exit $$?; \ + done + +uninstall-pkginc_libHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginc_lib_HEADERS)'; test -n "$(pkginc_libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkginc_libdir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(pkginc_libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pkglibLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/lda-settings.Plo + -rm -f ./$(DEPDIR)/mail-deliver.Plo + -rm -f ./$(DEPDIR)/mail-send.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkginc_libHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/lda-settings.Plo + -rm -f ./$(DEPDIR)/mail-deliver.Plo + -rm -f ./$(DEPDIR)/mail-send.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkginc_libHEADERS uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-pkglibLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkginc_libHEADERS \ + install-pkglibLTLIBRARIES install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-pkginc_libHEADERS uninstall-pkglibLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/lib-lda/lda-settings.c b/src/lib-lda/lda-settings.c new file mode 100644 index 0000000..1bb02f8 --- /dev/null +++ b/src/lib-lda/lda-settings.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "hostpid.h" +#include "settings-parser.h" +#include "mail-storage-settings.h" +#include "smtp-submit-settings.h" +#include "lda-settings.h" + +#include <stddef.h> + +static bool lda_settings_check(void *_set, pool_t pool, const char **error_r); + +#undef DEF +#undef DEFLIST +#define DEF(type, name) \ + SETTING_DEFINE_STRUCT_##type(#name, name, struct lda_settings) +#define DEFLIST(field, name, defines) \ + { .type = SET_DEFLIST, .key = name, \ + .offset = offsetof(struct lda_settings, field), \ + .list_info = defines } + +static const struct setting_define lda_setting_defines[] = { + DEF(STR, hostname), + DEF(STR, rejection_subject), + DEF(STR, rejection_reason), + DEF(STR, deliver_log_format), + DEF(STR, recipient_delimiter), + DEF(STR, lda_original_recipient_header), + DEF(BOOL, quota_full_tempfail), + DEF(BOOL, lda_mailbox_autocreate), + DEF(BOOL, lda_mailbox_autosubscribe), + + SETTING_DEFINE_LIST_END +}; + +static const struct lda_settings lda_default_settings = { + .hostname = "", + .rejection_subject = "Rejected: %s", + .rejection_reason = + "Your message to <%t> was automatically rejected:%n%r", + .deliver_log_format = "msgid=%m: %$", + .recipient_delimiter = "+", + .lda_original_recipient_header = "", + .quota_full_tempfail = FALSE, + .lda_mailbox_autocreate = FALSE, + .lda_mailbox_autosubscribe = FALSE +}; + +static const struct setting_parser_info *lda_setting_dependencies[] = { + &mail_user_setting_parser_info, + &smtp_submit_setting_parser_info, + NULL +}; + +const struct setting_parser_info lda_setting_parser_info = { + .module_name = "lda", + .defines = lda_setting_defines, + .defaults = &lda_default_settings, + + .type_offset = SIZE_MAX, + .struct_size = sizeof(struct lda_settings), + + .parent_offset = SIZE_MAX, + +#ifndef CONFIG_BINARY + .check_func = lda_settings_check, +#endif + .dependencies = lda_setting_dependencies +}; + +static bool lda_settings_check(void *_set, pool_t pool, + const char **error_r ATTR_UNUSED) +{ + struct lda_settings *set = _set; + + if (*set->hostname == '\0') + set->hostname = p_strdup(pool, my_hostdomain()); + return TRUE; +} diff --git a/src/lib-lda/lda-settings.h b/src/lib-lda/lda-settings.h new file mode 100644 index 0000000..8b0c209 --- /dev/null +++ b/src/lib-lda/lda-settings.h @@ -0,0 +1,21 @@ +#ifndef LDA_SETTINGS_H +#define LDA_SETTINGS_H + +struct mail_user_settings; + +struct lda_settings { + const char *hostname; + const char *rejection_subject; + const char *rejection_reason; + const char *deliver_log_format; + const char *recipient_delimiter; + const char *lda_original_recipient_header; + + bool quota_full_tempfail; + bool lda_mailbox_autocreate; + bool lda_mailbox_autosubscribe; +}; + +extern const struct setting_parser_info lda_setting_parser_info; + +#endif diff --git a/src/lib-lda/mail-deliver.c b/src/lib-lda/mail-deliver.c new file mode 100644 index 0000000..e0f69da --- /dev/null +++ b/src/lib-lda/mail-deliver.c @@ -0,0 +1,810 @@ +/* Copyright (c) 2005-2018 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 "smtp-address.h" +#include "lda-settings.h" +#include "mail-storage.h" +#include "mail-namespace.h" +#include "mail-storage-private.h" +#include "mail-duplicate.h" +#include "mail-deliver.h" + +#define DUPLICATE_DB_NAME "lda-dupes" + +#define MAIL_DELIVER_USER_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, mail_deliver_user_module) +#define MAIL_DELIVER_STORAGE_CONTEXT(obj) \ + MODULE_CONTEXT_REQUIRE(obj, mail_deliver_storage_module) + +struct event_category event_category_mail_delivery = { + .name = "local-delivery", +}; + +struct mail_deliver_user { + union mail_user_module_context module_ctx; + struct mail_deliver_context *deliver_ctx; + bool want_storage_id; +}; + +deliver_mail_func_t *deliver_mail = NULL; + +struct mail_deliver_mailbox { + union mailbox_module_context module_ctx; +}; + +struct mail_deliver_transaction { + union mailbox_transaction_module_context module_ctx; + + struct mail_deliver_fields deliver_fields; +}; + +static const char *lda_log_wanted_headers[] = { + "From", "Message-ID", "Subject", + NULL +}; +static enum mail_fetch_field lda_log_wanted_fetch_fields = + MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE; +static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_user_module, + &mail_user_module_register); +static MODULE_CONTEXT_DEFINE_INIT(mail_deliver_storage_module, + &mail_storage_module_register); + +static struct message_address * +mail_deliver_get_message_address(struct mail *mail, const char *header) +{ + struct message_address *addr; + const char *str; + + if (mail_get_first_header(mail, header, &str) <= 0) + return NULL; + addr = message_address_parse(pool_datastack_create(), + (const unsigned char *)str, + strlen(str), 1, 0); + if (addr == NULL || addr->mailbox == NULL || addr->domain == NULL || + *addr->mailbox == '\0' || *addr->domain == '\0') + return NULL; + return addr; +} + +const struct smtp_address * +mail_deliver_get_address(struct mail *mail, const char *header) +{ + struct message_address *addr; + struct smtp_address *smtp_addr; + + addr = mail_deliver_get_message_address(mail, header); + if (addr == NULL || + smtp_address_create_from_msg_temp(addr, &smtp_addr) < 0) + return NULL; + return smtp_addr; +} + +static void +mail_deliver_update_event(struct mail_deliver_context *ctx) +{ + event_add_str(ctx->event, "message_id", ctx->fields.message_id); + event_add_str(ctx->event, "message_subject", ctx->fields.subject); + event_add_str(ctx->event, "message_from", ctx->fields.from); + if (ctx->fields.psize != UOFF_T_MAX) + event_add_int(ctx->event, "message_size", ctx->fields.psize); + if (ctx->fields.vsize != UOFF_T_MAX) + event_add_int(ctx->event, "message_vsize", ctx->fields.vsize); +} + +static void +update_str_field(pool_t pool, const char **old_str, const char *new_str) +{ + if (new_str == NULL || new_str[0] == '\0') + *old_str = NULL; + else if (*old_str == NULL || strcmp(*old_str, new_str) != 0) + *old_str = p_strdup(pool, new_str); +} + +static void +mail_deliver_fields_update(struct mail_deliver_fields *fields, pool_t pool, + struct mail *mail) +{ + const char *message_id = NULL, *subject = NULL, *from_envelope = NULL; + static struct message_address *from_addr; + const char *from; + + if (fields->filled) + return; + fields->filled = TRUE; + + if (mail_get_message_id(mail, &message_id) > 0) + message_id = str_sanitize(message_id, 200); + update_str_field(pool, &fields->message_id, message_id); + + if (mail_get_first_header_utf8(mail, "Subject", &subject) > 0) + subject = str_sanitize(subject, 80); + update_str_field(pool, &fields->subject, subject); + + from_addr = mail_deliver_get_message_address(mail, "From"); + from = (from_addr == NULL ? NULL : + t_strconcat(from_addr->mailbox, "@", from_addr->domain, NULL)); + update_str_field(pool, &fields->from, from); + + if (mail_get_special(mail, MAIL_FETCH_FROM_ENVELOPE, &from_envelope) > 0) + from_envelope = str_sanitize(from_envelope, 80); + update_str_field(pool, &fields->from_envelope, from_envelope); + + if (mail_get_physical_size(mail, &fields->psize) < 0) + fields->psize = 0; + if (mail_get_virtual_size(mail, &fields->vsize) < 0) + fields->vsize = 0; +} + +const struct var_expand_table * +mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx, + const char *message) +{ + unsigned int delivery_time_msecs; + + /* If a mail was saved/copied, the fields are already filled and the + following call is ignored. Otherwise, only the source mail exists. */ + mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail); + /* This call finishes a mail delivery. With Sieve there may be multiple + mail deliveries. */ + ctx->fields.filled = FALSE; + + mail_deliver_update_event(ctx); + + io_loop_time_refresh(); + delivery_time_msecs = timeval_diff_msecs(&ioloop_timeval, + &ctx->delivery_time_started); + + const struct var_expand_table stack_tab[] = { + { '$', message, NULL }, + { 'm', ctx->fields.message_id != NULL ? + ctx->fields.message_id : "unspecified", "msgid" }, + { 's', ctx->fields.subject, "subject" }, + { 'f', ctx->fields.from, "from" }, + { 'e', ctx->fields.from_envelope, "from_envelope" }, + { 'p', dec2str(ctx->fields.psize), "size" }, + { 'w', dec2str(ctx->fields.vsize), "vsize" }, + { '\0', dec2str(delivery_time_msecs), "delivery_time" }, + { '\0', dec2str(ctx->session_time_msecs), "session_time" }, + { '\0', smtp_address_encode(ctx->rcpt_params.orcpt.addr), "to_envelope" }, + { '\0', ctx->fields.storage_id, "storage_id" }, + { '\0', NULL, NULL } + }; + return p_memdup(unsafe_data_stack_pool, stack_tab, sizeof(stack_tab)); +} + +void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...) +{ + va_list args; + string_t *str; + const struct var_expand_table *tab; + const char *msg, *error; + + if (*ctx->set->deliver_log_format == '\0') + return; + + va_start(args, fmt); + msg = t_strdup_vprintf(fmt, args); + + str = t_str_new(256); + tab = mail_deliver_ctx_get_log_var_expand_table(ctx, msg); + if (var_expand(str, ctx->set->deliver_log_format, tab, &error) <= 0) { + e_error(ctx->event, + "Failed to expand deliver_log_format=%s: %s", + ctx->set->deliver_log_format, error); + } + + e_info(ctx->event, "%s", str_c(str)); + va_end(args); +} + +struct mail_deliver_session *mail_deliver_session_init(void) +{ + struct mail_deliver_session *session; + pool_t pool; + + pool = pool_alloconly_create("mail deliver session", 1024); + session = p_new(pool, struct mail_deliver_session, 1); + session->pool = pool; + return session; +} + +void mail_deliver_session_deinit(struct mail_deliver_session **_session) +{ + struct mail_deliver_session *session = *_session; + + *_session = NULL; + pool_unref(&session->pool); +} + +int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx, + const char *name, struct mailbox **box_r, + enum mail_error *error_r, const char **error_str_r) +{ + struct mailbox *box; + enum mailbox_flags flags = MAILBOX_FLAG_POST_SESSION; + + *box_r = NULL; + *error_r = MAIL_ERROR_NONE; + *error_str_r = NULL; + + if (!uni_utf8_str_is_valid(name)) { + *error_str_r = "Mailbox name not valid UTF-8"; + *error_r = MAIL_ERROR_PARAMS; + return -1; + } + + if (ctx->lda_mailbox_autocreate) + flags |= MAILBOX_FLAG_AUTO_CREATE; + if (ctx->lda_mailbox_autosubscribe) + flags |= MAILBOX_FLAG_AUTO_SUBSCRIBE; + *box_r = box = mailbox_alloc_for_user(ctx->user, name, flags); + + if (mailbox_open(box) == 0) + return 0; + *error_str_r = mailbox_get_last_internal_error(box, error_r); + return -1; +} + +static bool mail_deliver_check_duplicate(struct mail_deliver_session *session, + struct mailbox *box) +{ + struct mailbox_metadata metadata; + const guid_128_t *guid; + + if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) { + /* just play it safe and assume a duplicate */ + return TRUE; + } + + /* there shouldn't be all that many recipients, + so just do a linear search */ + if (!array_is_created(&session->inbox_guids)) + p_array_init(&session->inbox_guids, session->pool, 8); + array_foreach(&session->inbox_guids, guid) { + if (memcmp(metadata.guid, *guid, sizeof(metadata.guid)) == 0) + return TRUE; + } + array_push_back(&session->inbox_guids, &metadata.guid); + return FALSE; +} + +void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *session, + struct mail_save_context *save_ctx) +{ + struct mailbox_transaction_context *trans = + mailbox_save_get_transaction(save_ctx); + struct mailbox *box = mailbox_transaction_get_mailbox(trans); + guid_128_t guid; + + if (strcmp(mailbox_get_name(box), "INBOX") != 0) + 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. */ + if (mail_deliver_check_duplicate(session, box)) { + guid_128_generate(guid); + mailbox_save_set_guid(save_ctx, guid_128_to_string(guid)); + } +} + +void mail_deliver_init(struct mail_deliver_context *ctx, + struct mail_deliver_input *input) +{ + i_zero(ctx); + ctx->set = input->set; + ctx->smtp_set = input->smtp_set; + + ctx->session = input->session; + ctx->pool = input->session->pool; + pool_ref(ctx->pool); + + ctx->session_time_msecs = input->session_time_msecs; + ctx->delivery_time_started = input->delivery_time_started; + ctx->session_id = p_strdup(ctx->pool, input->session_id); + ctx->src_mail = input->src_mail; + ctx->save_dest_mail = input->save_dest_mail; + + ctx->mail_from = smtp_address_clone(ctx->pool, input->mail_from); + smtp_params_mail_copy(ctx->pool, &ctx->mail_params, + &input->mail_params); + ctx->rcpt_to = smtp_address_clone(ctx->pool, input->rcpt_to); + smtp_params_rcpt_copy(ctx->pool, &ctx->rcpt_params, + &input->rcpt_params); + ctx->rcpt_user = input->rcpt_user; + ctx->rcpt_default_mailbox = p_strdup(ctx->pool, + input->rcpt_default_mailbox); + + ctx->event = event_create(input->event_parent); + event_add_category(ctx->event, &event_category_mail_delivery); + + mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail); + mail_deliver_update_event(ctx); + + if (ctx->rcpt_to != NULL) { + event_add_str(ctx->event, "rcpt_to", + smtp_address_encode(ctx->rcpt_to)); + } + smtp_params_rcpt_add_to_event(&ctx->rcpt_params, ctx->event); +} + +void mail_deliver_deinit(struct mail_deliver_context *ctx) +{ + event_unref(&ctx->event); + pool_unref(&ctx->pool); +} + +static struct mail * +mail_deliver_open_mail(struct mailbox *box, uint32_t uid, + enum mail_fetch_field wanted_fields, + struct mailbox_transaction_context **trans_r) +{ + struct mailbox_transaction_context *t; + struct mail *mail; + + *trans_r = NULL; + + if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0) + return NULL; + + t = mailbox_transaction_begin(box, 0, __func__); + mail = mail_alloc(t, wanted_fields, NULL); + + if (!mail_set_uid(mail, uid)) { + mail_free(&mail); + mailbox_transaction_rollback(&t); + } + *trans_r = t; + return mail; +} + +int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox, + enum mail_flags flags, const char *const *keywords, + struct mail_storage **storage_r) +{ + struct mail_deliver_save_open_context open_ctx; + struct mailbox *box; + enum mailbox_transaction_flags trans_flags; + struct mailbox_transaction_context *t; + struct mail_save_context *save_ctx; + struct mailbox_header_lookup_ctx *headers_ctx; + struct mail_keywords *kw; + struct mail *dest_mail; + enum mail_error error; + const char *mailbox_name, *errstr, *guid; + struct mail_transaction_commit_changes changes; + bool default_save; + int ret = 0; + + i_assert(ctx->dest_mail == NULL); + + default_save = strcmp(mailbox, ctx->rcpt_default_mailbox) == 0; + if (default_save) + ctx->tried_default_save = TRUE; + + i_zero(&open_ctx); + open_ctx.user = ctx->rcpt_user; + open_ctx.lda_mailbox_autocreate = ctx->set->lda_mailbox_autocreate; + open_ctx.lda_mailbox_autosubscribe = ctx->set->lda_mailbox_autosubscribe; + + mailbox_name = str_sanitize(mailbox, 80); + if (mail_deliver_save_open(&open_ctx, mailbox, &box, + &error, &errstr) < 0) { + if (box != NULL) { + *storage_r = mailbox_get_storage(box); + mailbox_free(&box); + } + mail_deliver_log(ctx, "save failed to open mailbox %s: %s", + mailbox_name, errstr); + return -1; + } + *storage_r = mailbox_get_storage(box); + + trans_flags = MAILBOX_TRANSACTION_FLAG_EXTERNAL; + if (ctx->save_dest_mail) + trans_flags |= MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS; + t = mailbox_transaction_begin(box, trans_flags, __func__); + + kw = str_array_length(keywords) == 0 ? NULL : + mailbox_keywords_create_valid(box, keywords); + save_ctx = mailbox_save_alloc(t); + if (ctx->mail_from != NULL) { + mailbox_save_set_from_envelope(save_ctx, + smtp_address_encode(ctx->mail_from)); + } + mailbox_save_set_flags(save_ctx, flags, kw); + + headers_ctx = mailbox_header_lookup_init(box, lda_log_wanted_headers); + dest_mail = mailbox_save_get_dest_mail(save_ctx); + mail_add_temp_wanted_fields(dest_mail, lda_log_wanted_fetch_fields, NULL); + mailbox_header_lookup_unref(&headers_ctx); + mail_deliver_deduplicate_guid_if_needed(ctx->session, save_ctx); + + if (mailbox_save_using_mail(&save_ctx, ctx->src_mail) < 0) + ret = -1; + if (kw != NULL) + mailbox_keywords_unref(&kw); + + if (ret < 0) + mailbox_transaction_rollback(&t); + else + ret = mailbox_transaction_commit_get_changes(&t, &changes); + + if (ret == 0) { + ctx->saved_mail = TRUE; + 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. */ + i_assert(array_count(&changes.saved_uids) == 1); + const struct seq_range *range = + array_front(&changes.saved_uids); + i_assert(range->seq1 == range->seq2); + ctx->dest_mail = mail_deliver_open_mail(box, range->seq1, + MAIL_FETCH_STREAM_BODY | MAIL_FETCH_GUID, &t); + if (ctx->dest_mail == NULL) { + i_assert(t == NULL); + } else if (mail_get_special(ctx->dest_mail, MAIL_FETCH_GUID, &guid) < 0) { + mail_free(&ctx->dest_mail); + mailbox_transaction_rollback(&t); + } + } + mail_deliver_log(ctx, "saved mail to %s", mailbox_name); + pool_unref(&changes.pool); + } else { + mail_deliver_log(ctx, "save failed to %s: %s", mailbox_name, + mail_storage_get_last_internal_error(*storage_r, &error)); + } + + if (ctx->dest_mail == NULL) + mailbox_free(&box); + return ret; +} + +const struct smtp_address * +mail_deliver_get_return_address(struct mail_deliver_context *ctx) +{ + struct message_address *addr; + struct smtp_address *smtp_addr; + const char *path; + int ret; + + if (!smtp_address_isnull(ctx->mail_from)) + return ctx->mail_from; + + if ((ret=mail_get_first_header(ctx->src_mail, + "Return-Path", &path)) <= 0) { + if (ret < 0) { + struct mailbox *box = ctx->src_mail->box; + e_warning(ctx->event, + "Failed read return-path header: %s", + mailbox_get_last_internal_error(box, NULL)); + } + return NULL; + } + if (message_address_parse_path(pool_datastack_create(), + (const unsigned char *)path, + strlen(path), &addr) < 0 || + smtp_address_create_from_msg(ctx->pool, addr, &smtp_addr) < 0) { + e_warning(ctx->event, "Failed to parse return-path header"); + return NULL; + } + return smtp_addr; +} + +const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx) +{ + static int count = 0; + struct mail_user *user = ctx->rcpt_user; + const struct mail_storage_settings *mail_set = + mail_user_set_get_storage_set(user); + + return t_strdup_printf("<dovecot-%s-%s-%d@%s>", + dec2str(ioloop_timeval.tv_sec), + dec2str(ioloop_timeval.tv_usec), + count++, mail_set->hostname); +} + +static bool mail_deliver_is_tempfailed(struct mail_deliver_context *ctx, + struct mail_storage *storage) +{ + enum mail_error error; + + if (ctx->tempfail_error != NULL) + return TRUE; + if (storage != NULL) { + (void)mail_storage_get_last_error(storage, &error); + return error == MAIL_ERROR_TEMP; + } + return FALSE; +} + +static int +mail_do_deliver(struct mail_deliver_context *ctx, + struct mail_storage **storage_r) +{ + int ret; + + *storage_r = NULL; + if (deliver_mail == NULL) + ret = -1; + else { + ctx->dup_db = mail_duplicate_db_init(ctx->rcpt_user, + DUPLICATE_DB_NAME); + if (deliver_mail(ctx, storage_r) <= 0) { + /* if message was saved, don't bounce it even though + the script failed later. */ + ret = ctx->saved_mail ? 0 : -1; + } else { + /* success. message may or may not have been saved. */ + ret = 0; + } + mail_duplicate_db_deinit(&ctx->dup_db); + if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) + return -1; + } + + if (ret < 0 && !ctx->tried_default_save) { + /* plugins didn't handle this. save into the default mailbox. */ + ret = mail_deliver_save(ctx, ctx->rcpt_default_mailbox, 0, NULL, + storage_r); + if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) + return -1; + } + if (ret < 0 && strcasecmp(ctx->rcpt_default_mailbox, "INBOX") != 0) { + /* still didn't work. try once more to save it + to INBOX. */ + ret = mail_deliver_save(ctx, "INBOX", 0, NULL, storage_r); + } + return ret; +} + +int mail_deliver(struct mail_deliver_context *ctx, + enum mail_deliver_error *error_code_r, + const char **error_r) +{ + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(ctx->rcpt_user); + struct event_passthrough *e; + struct mail_storage *storage = NULL; + enum mail_deliver_error error_code = MAIL_DELIVER_ERROR_NONE; + const char *error = NULL; + int ret; + + i_assert(muser->deliver_ctx == NULL); + + mail_deliver_fields_update(&ctx->fields, ctx->pool, ctx->src_mail); + mail_deliver_update_event(ctx); + + muser->want_storage_id = + var_has_key(ctx->set->deliver_log_format, '\0', "storage_id"); + + muser->deliver_ctx = ctx; + + e = event_create_passthrough(ctx->event)-> + set_name("mail_delivery_started"); + e_debug(e->event(), "Local delivery started"); + + ret = mail_do_deliver(ctx, &storage); + + if (ret >= 0) + i_assert(ret == 0); /* ret > 0 has no defined meaning */ + else if (ctx->tempfail_error != NULL) { + error = ctx->tempfail_error; + error_code = MAIL_DELIVER_ERROR_TEMPORARY; + } else if (storage != NULL) { + enum mail_error mail_error; + + error = mail_storage_get_last_error(storage, &mail_error); + if (mail_error == MAIL_ERROR_NOQUOTA) { + error_code = MAIL_DELIVER_ERROR_NOQUOTA; + } else { + error_code = MAIL_DELIVER_ERROR_TEMPORARY; + } + } else { + /* This shouldn't happen */ + e_error(ctx->event, "BUG: Saving failed to unknown storage"); + error = "Temporary internal error"; + error_code = MAIL_DELIVER_ERROR_INTERNAL; + } + + e = event_create_passthrough(ctx->event)-> + set_name("mail_delivery_finished"); + if (ret == 0) { + e_debug(e->event(), "Local delivery finished successfully"); + } else { + e->add_str("error", error); + e_debug(e->event(), "Local delivery failed: %s", error); + } + + muser->deliver_ctx = NULL; + + *error_code_r = error_code; + *error_r = error; + return ret; +} + +deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook) +{ + deliver_mail_func_t *old_hook = deliver_mail; + + deliver_mail = new_hook; + return old_hook; +} + +static int mail_deliver_save_finish(struct mail_save_context *ctx) +{ + struct mailbox *box = ctx->transaction->box; + struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box); + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(box->storage->user); + struct mail_deliver_transaction *dt = + MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction); + + if (mbox->module_ctx.super.save_finish(ctx) < 0) + return -1; + + /* initialize most of the fields from dest_mail */ + mail_deliver_fields_update(&dt->deliver_fields, + muser->deliver_ctx->pool, + ctx->dest_mail); + return 0; +} + +static int mail_deliver_copy(struct mail_save_context *ctx, struct mail *mail) +{ + struct mailbox *box = ctx->transaction->box; + struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box); + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(box->storage->user); + struct mail_deliver_transaction *dt = + MAIL_DELIVER_STORAGE_CONTEXT(ctx->transaction); + + if (mbox->module_ctx.super.copy(ctx, mail) < 0) + return -1; + + /* initialize most of the fields from dest_mail */ + mail_deliver_fields_update(&dt->deliver_fields, + muser->deliver_ctx->pool, + ctx->dest_mail); + return 0; +} + +static void +mail_deliver_fields_update_post_commit(struct mailbox *orig_box, uint32_t uid) +{ + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(orig_box->storage->user); + struct mailbox *box; + struct mailbox_transaction_context *t; + struct mail *mail; + 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. */ + box = mailbox_alloc(orig_box->list, orig_box->vname, 0); + mail = mail_deliver_open_mail(box, uid, MAIL_FETCH_STORAGE_ID, &t); + if (mail != NULL) { + if (mail_get_special(mail, MAIL_FETCH_STORAGE_ID, &storage_id) < 0 || + storage_id[0] == '\0') + storage_id = NULL; + muser->deliver_ctx->fields.storage_id = + p_strdup(muser->deliver_ctx->pool, storage_id); + mail_free(&mail); + (void)mailbox_transaction_commit(&t); + } else { + muser->deliver_ctx->fields.storage_id = NULL; + } + mailbox_free(&box); +} + +static struct mailbox_transaction_context * +mail_deliver_transaction_begin(struct mailbox *box, + enum mailbox_transaction_flags flags, + const char *reason) +{ + struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box); + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(box->storage->user); + struct mailbox_transaction_context *t; + struct mail_deliver_transaction *dt; + + i_assert(muser->deliver_ctx != NULL); + + t = mbox->module_ctx.super.transaction_begin(box, flags, reason); + dt = p_new(muser->deliver_ctx->pool, struct mail_deliver_transaction, 1); + + MODULE_CONTEXT_SET(t, mail_deliver_storage_module, dt); + return t; +} + +static int +mail_deliver_transaction_commit(struct mailbox_transaction_context *ctx, + struct mail_transaction_commit_changes *changes_r) +{ + struct mailbox *box = ctx->box; + struct mail_deliver_mailbox *mbox = MAIL_DELIVER_STORAGE_CONTEXT(box); + struct mail_deliver_transaction *dt = MAIL_DELIVER_STORAGE_CONTEXT(ctx); + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(box->storage->user); + + i_assert(muser->deliver_ctx != NULL); + + /* 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->fields 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 ((box->flags & MAILBOX_FLAG_POST_SESSION) != 0) { + muser->deliver_ctx->fields = dt->deliver_fields; + mail_deliver_update_event(muser->deliver_ctx); + } + + if (mbox->module_ctx.super.transaction_commit(ctx, changes_r) < 0) + return -1; + + if (array_count(&changes_r->saved_uids) > 0) { + const struct seq_range *range = + array_front(&changes_r->saved_uids); + + mail_deliver_fields_update_post_commit(box, range->seq1); + } + return 0; +} + +static void mail_deliver_mail_user_created(struct mail_user *user) +{ + struct mail_deliver_user *muser; + + muser = p_new(user->pool, struct mail_deliver_user, 1); + MODULE_CONTEXT_SET(user, mail_deliver_user_module, muser); +} + +static void mail_deliver_mailbox_allocated(struct mailbox *box) +{ + struct mailbox_vfuncs *v = box->vlast; + struct mail_deliver_mailbox *mbox; + struct mail_deliver_user *muser = + MAIL_DELIVER_USER_CONTEXT(box->storage->user); + + /* we are doing something other than lda/lmtp delivery + and should not be involved */ + if (muser->deliver_ctx == NULL) + return; + + mbox = p_new(box->pool, struct mail_deliver_mailbox, 1); + mbox->module_ctx.super = *v; + box->vlast = &mbox->module_ctx.super; + v->save_finish = mail_deliver_save_finish; + v->copy = mail_deliver_copy; + v->transaction_begin = mail_deliver_transaction_begin; + v->transaction_commit = mail_deliver_transaction_commit; + + MODULE_CONTEXT_SET(box, mail_deliver_storage_module, mbox); + } + +static struct mail_storage_hooks mail_deliver_hooks = { + .mail_user_created = mail_deliver_mail_user_created, + .mailbox_allocated = mail_deliver_mailbox_allocated +}; + +void mail_deliver_hooks_init(void) +{ + mail_storage_hooks_add_internal(&mail_deliver_hooks); +} diff --git a/src/lib-lda/mail-deliver.h b/src/lib-lda/mail-deliver.h new file mode 100644 index 0000000..5396a82 --- /dev/null +++ b/src/lib-lda/mail-deliver.h @@ -0,0 +1,185 @@ +#ifndef MAIL_DELIVER_H +#define MAIL_DELIVER_H + +#include "guid.h" +#include "mail-types.h" +#include "mail-error.h" +#include "smtp-params.h" + +#include <sys/time.h> + +struct smtp_address; +struct mail_storage; +struct mail_save_context; +struct mailbox; + +enum mail_deliver_error { + MAIL_DELIVER_ERROR_NONE = 0, + + /* Temporary error */ + MAIL_DELIVER_ERROR_TEMPORARY, + /* Delivery rejected */ + MAIL_DELIVER_ERROR_REJECTED, + /* Out of storage quota for mailbox or user */ + MAIL_DELIVER_ERROR_NOQUOTA, + /* Internal error (BUG) */ + MAIL_DELIVER_ERROR_INTERNAL, +}; + +struct mail_deliver_session { + pool_t pool; + + /* List of INBOX GUIDs where this mail has already been saved to */ + ARRAY(guid_128_t) inbox_guids; +}; + +struct mail_deliver_input { + const struct lda_settings *set; + const struct smtp_submit_settings *smtp_set; + struct mail_deliver_session *session; + struct event *event_parent; + + unsigned int session_time_msecs; + struct timeval delivery_time_started; + + /* Session ID, used as log line prefix if non-NULL. */ + const char *session_id; + /* Mail to save */ + struct mail *src_mail; + + /* Envelope sender, if known. */ + const struct smtp_address *mail_from; + /* MAIL parameters */ + struct smtp_params_mail mail_params; + + /* Envelope recipient (final recipient) */ + const struct smtp_address *rcpt_to; + /* RCPT parameters (can contain original recipient) */ + struct smtp_params_rcpt rcpt_params; + /* Destination user */ + struct mail_user *rcpt_user; + /* Mailbox where mail should be saved, unless e.g. Sieve does + something to it. */ + const char *rcpt_default_mailbox; + + bool save_dest_mail:1; +}; + +struct mail_deliver_fields { + const char *message_id; + const char *subject; + const char *from; + const char *from_envelope; + const char *storage_id; + + uoff_t psize, vsize; + + bool filled:1; +}; + +struct mail_deliver_context { + pool_t pool; + const struct lda_settings *set; + const struct smtp_submit_settings *smtp_set; + struct mail_deliver_session *session; + struct event *event; + + unsigned int session_time_msecs; + struct timeval delivery_time_started; + + struct mail_duplicate_db *dup_db; + + /* Session ID, used as log line prefix if non-NULL. */ + const char *session_id; + /* Mail to save */ + struct mail *src_mail; + + /* Envelope sender, if known. */ + const struct smtp_address *mail_from; + /* MAIL parameters */ + struct smtp_params_mail mail_params; + + /* Envelope recipient (final recipient) */ + const struct smtp_address *rcpt_to; + /* RCPT parameters (can contain original recipient) */ + struct smtp_params_rcpt rcpt_params; + /* Destination user */ + struct mail_user *rcpt_user; + /* Mailbox where mail should be saved, unless e.g. Sieve does + something to it. */ + const char *rcpt_default_mailbox; + + /* Filled with destination mail, if save_dest_mail=TRUE. + The caller must free the mail, its transaction and close + the mailbox. */ + struct mail *dest_mail; + + /* Recorded field values for the transaction */ + struct mail_deliver_fields fields; + + /* Error message for a temporary failure. This is necessary only when + there is no storage where to get the error message from. */ + const char *tempfail_error; + + bool tried_default_save; + bool saved_mail; + bool save_dest_mail; + /* Delivery failed because user is out of quota / disk space */ + bool mailbox_full; + /* Send DSN instead of MDN */ + bool dsn; +}; + +struct mail_deliver_save_open_context { + struct mail_user *user; + bool lda_mailbox_autocreate; + bool lda_mailbox_autosubscribe; +}; + +typedef int deliver_mail_func_t(struct mail_deliver_context *ctx, + struct mail_storage **storage_r); + +extern deliver_mail_func_t *deliver_mail; + +const struct var_expand_table * +mail_deliver_ctx_get_log_var_expand_table(struct mail_deliver_context *ctx, + const char *message); +void mail_deliver_log(struct mail_deliver_context *ctx, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +const struct smtp_address * +mail_deliver_get_address(struct mail *mail, const char *header); +const struct smtp_address * +mail_deliver_get_return_address(struct mail_deliver_context *ctx); +const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx); + +struct mail_deliver_session *mail_deliver_session_init(void); +void mail_deliver_session_deinit(struct mail_deliver_session **session); + +void mail_deliver_init(struct mail_deliver_context *ctx, + struct mail_deliver_input *input); +void mail_deliver_deinit(struct mail_deliver_context *ctx); + +/* Try to open mailbox for saving. Returns 0 if ok, -1 if error. The box may + be returned even with -1, and the caller must free it then. */ +int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx, + const char *name, struct mailbox **box_r, + enum mail_error *error_r, const char **error_str_r); +int mail_deliver_save(struct mail_deliver_context *ctx, const char *mailbox, + enum mail_flags flags, const char *const *keywords, + struct mail_storage **storage_r) ATTR_NULL(4); +void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *session, + struct mail_save_context *save_ctx); + +int mail_deliver(struct mail_deliver_context *ctx, + enum mail_deliver_error *error_code_r, + const char **error_r); + +/* Sets the deliver_mail hook and returns the previous hook, + which the new_hook should call if it's non-NULL. */ +deliver_mail_func_t *mail_deliver_hook_set(deliver_mail_func_t *new_hook); + +/* Must be called before any storage is created. */ +void mail_deliver_hooks_init(void); + +#endif diff --git a/src/lib-lda/mail-send.c b/src/lib-lda/mail-send.c new file mode 100644 index 0000000..2027b0b --- /dev/null +++ b/src/lib-lda/mail-send.c @@ -0,0 +1,216 @@ +/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "ioloop.h" +#include "hostpid.h" +#include "istream.h" +#include "ostream.h" +#include "str.h" +#include "str-sanitize.h" +#include "var-expand.h" +#include "message-date.h" +#include "message-size.h" +#include "message-address.h" +#include "istream-header-filter.h" +#include "mail-storage.h" +#include "mail-storage-settings.h" +#include "iostream-ssl.h" +#include "lda-settings.h" +#include "mail-deliver.h" +#include "smtp-address.h" +#include "smtp-submit.h" +#include "mail-send.h" + +#include <sys/wait.h> + +static const struct var_expand_table * +get_var_expand_table(struct mail *mail, + const struct smtp_address *recipient, + const char *reason) +{ + const char *subject; + if (mail_get_first_header(mail, "Subject", &subject) <= 0) + subject = ""; + + const struct var_expand_table stack_tab[] = { + { 'n', "\r\n", "crlf" }, + { 'r', reason, "reason" }, + { 's', str_sanitize(subject, 80), "subject" }, + { 't', smtp_address_encode(recipient), "to" }, + { '\0', NULL, NULL } + }; + struct var_expand_table *tab; + + tab = t_malloc_no0(sizeof(stack_tab)); + memcpy(tab, stack_tab, sizeof(stack_tab)); + return tab; +} + +int mail_send_rejection(struct mail_deliver_context *ctx, + const struct smtp_address *recipient, + const char *reason) +{ + struct mail_user *user = ctx->rcpt_user; + struct ssl_iostream_settings ssl_set; + struct mail *mail = ctx->src_mail; + struct istream *input; + struct smtp_submit_input smtp_input; + struct smtp_submit *smtp_submit; + struct ostream *output; + const struct message_address *postmaster_addr; + const struct smtp_address *return_addr; + const char *hdr, *value, *msgid, *orig_msgid, *boundary, *error; + const struct var_expand_table *vtable; + string_t *str; + int ret; + + if (mail_get_first_header(mail, "Message-ID", &orig_msgid) < 0) + orig_msgid = NULL; + + if (mail_get_first_header(mail, "Auto-Submitted", &value) > 0 && + strcasecmp(value, "no") != 0) { + i_info("msgid=%s: Auto-submitted message discarded: %s", + orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80), + str_sanitize(reason, 512)); + return 0; + } + + return_addr = mail_deliver_get_return_address(ctx); + if (smtp_address_isnull(return_addr)) { + i_info("msgid=%s: Return-Path missing, rejection reason: %s", + orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80), + str_sanitize(reason, 512)); + return 0; + } + + if (!mail_user_get_postmaster_address(user, &postmaster_addr, &error)) { + i_error("msgid=%s: Invalid postmaster_address - can't send rejection: %s", + orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80), error); + return -1; + } + + e_debug(mail_event(mail), "Sending a rejection to <%s>: %s", + smtp_address_encode(return_addr), + str_sanitize(reason, 512)); + + vtable = get_var_expand_table(mail, recipient, reason); + + mail_user_init_ssl_client_settings(user, &ssl_set); + + i_zero(&smtp_input); + smtp_input.ssl = &ssl_set; + smtp_submit = smtp_submit_init_simple(&smtp_input, ctx->smtp_set, NULL); + smtp_submit_add_rcpt(smtp_submit, return_addr); + output = smtp_submit_send(smtp_submit); + + msgid = mail_deliver_get_new_message_id(ctx); + boundary = t_strdup_printf("%s/%s", my_pid, user->set->hostname); + + str = t_str_new(512); + str_printfa(str, "Message-ID: %s\r\n", msgid); + str_printfa(str, "Date: %s\r\n", message_date_create(ioloop_time)); + str_append(str, "From: "); + message_address_write(str, postmaster_addr); + str_append(str, "\r\n"); + str_printfa(str, "To: <%s>\r\n", smtp_address_encode(return_addr)); + str_append(str, "MIME-Version: 1.0\r\n"); + str_printfa(str, "Content-Type: " + "multipart/report; report-type=%s;\r\n" + "\tboundary=\"%s\"\r\n", + ctx->dsn ? "delivery-status" : "disposition-notification", + boundary); + str_append(str, "Subject: "); + if (var_expand(str, ctx->set->rejection_subject, + vtable, &error) <= 0) { + i_error("Failed to expand rejection_subject=%s: %s", + ctx->set->rejection_subject, error); + } + str_append(str, "\r\n"); + + str_append(str, "Auto-Submitted: auto-replied (rejected)\r\n"); + str_append(str, "Precedence: bulk\r\n"); + str_append(str, "\r\nThis is a MIME-encapsulated message\r\n\r\n"); + + /* human readable status report */ + str_printfa(str, "--%s\r\n", boundary); + str_append(str, "Content-Type: text/plain; charset=utf-8\r\n"); + str_append(str, "Content-Disposition: inline\r\n"); + str_append(str, "Content-Transfer-Encoding: 8bit\r\n\r\n"); + + if (var_expand(str, ctx->set->rejection_reason, + vtable, &error) <= 0) { + i_error("Failed to expand rejection_reason=%s: %s", + ctx->set->rejection_reason, error); + } + str_append(str, "\r\n"); + + if (ctx->dsn) { + /* DSN status report: For LDA rejects. currently only used when + user is out of quota */ + str_printfa(str, "--%s\r\n" + "Content-Type: message/delivery-status\r\n\r\n", + boundary); + str_printfa(str, "Reporting-MTA: dns; %s\r\n", user->set->hostname); + if (mail_get_first_header(mail, "Original-Recipient", &hdr) > 0) + str_printfa(str, "Original-Recipient: rfc822; %s\r\n", hdr); + str_printfa(str, "Final-Recipient: rfc822; %s\r\n", + smtp_address_encode(recipient)); + str_append(str, "Action: failed\r\n"); + str_printfa(str, "Status: %s\r\n", ctx->mailbox_full ? "5.2.2" : "5.2.0"); + } else { + /* MDN status report: For Sieve "reject" */ + str_printfa(str, "--%s\r\n" + "Content-Type: message/disposition-notification\r\n\r\n", + boundary); + str_printfa(str, "Reporting-UA: %s; Dovecot Mail Delivery Agent\r\n", + user->set->hostname); + if (mail_get_first_header(mail, "Original-Recipient", &hdr) > 0) + str_printfa(str, "Original-Recipient: rfc822; %s\r\n", hdr); + str_printfa(str, "Final-Recipient: rfc822; %s\r\n", + smtp_address_encode(recipient)); + + if (orig_msgid != NULL) + str_printfa(str, "Original-Message-ID: %s\r\n", orig_msgid); + str_append(str, "Disposition: " + "automatic-action/MDN-sent-automatically; deleted\r\n"); + } + str_append(str, "\r\n"); + + /* original message's headers */ + str_printfa(str, "--%s\r\nContent-Type: message/rfc822\r\n\r\n", boundary); + o_stream_nsend(output, str_data(str), str_len(str)); + + if (mail_get_hdr_stream(mail, NULL, &input) == 0) { + /* Note: If you add more headers, they need to be sorted. + We'll drop Content-Type because we're not including the message + body, and having a multipart Content-Type may confuse some + MIME parsers when they don't see the message boundaries. */ + static const char *const exclude_headers[] = { + "Content-Type" + }; + + input = i_stream_create_header_filter(input, + HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR | + HEADER_FILTER_HIDE_BODY, exclude_headers, + N_ELEMENTS(exclude_headers), + *null_header_filter_callback, NULL); + + o_stream_nsend_istream(output, input); + i_stream_unref(&input); + } + + str_truncate(str, 0); + str_printfa(str, "\r\n\r\n--%s--\r\n", boundary); + o_stream_nsend(output, str_data(str), str_len(str)); + if ((ret = smtp_submit_run(smtp_submit, &error)) < 0) { + i_error("msgid=%s: Temporarily failed to send rejection: %s", + orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80), + str_sanitize(error, 512)); + } else if (ret == 0) { + i_info("msgid=%s: Permanently failed to send rejection: %s", + orig_msgid == NULL ? "" : str_sanitize(orig_msgid, 80), + str_sanitize(error, 512)); + } + smtp_submit_deinit(&smtp_submit); + return ret < 0 ? -1 : 0; +} diff --git a/src/lib-lda/mail-send.h b/src/lib-lda/mail-send.h new file mode 100644 index 0000000..88f87ed --- /dev/null +++ b/src/lib-lda/mail-send.h @@ -0,0 +1,11 @@ +#ifndef MAIL_SEND_H +#define MAIL_SEND_H + +struct mail; +struct mail_deliver_context; + +int mail_send_rejection(struct mail_deliver_context *ctx, + const struct smtp_address *recipient, + const char *reason); + +#endif |