diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 17:36:47 +0000 |
commit | 0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch) | |
tree | 3f3789daa2f6db22da6e55e92bee0062a7d613fe /pigeonhole/src/plugins/lda-sieve | |
parent | Initial commit. (diff) | |
download | dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip |
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/src/plugins/lda-sieve')
-rw-r--r-- | pigeonhole/src/plugins/lda-sieve/Makefile.am | 19 | ||||
-rw-r--r-- | pigeonhole/src/plugins/lda-sieve/Makefile.in | 746 | ||||
-rw-r--r-- | pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c | 1128 | ||||
-rw-r--r-- | pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h | 11 |
4 files changed, 1904 insertions, 0 deletions
diff --git a/pigeonhole/src/plugins/lda-sieve/Makefile.am b/pigeonhole/src/plugins/lda-sieve/Makefile.am new file mode 100644 index 0000000..7c2797a --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_DICT_INCLUDE) \ + $(LIBDOVECOT_SMTP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) + +lib90_sieve_plugin_la_LDFLAGS = -module -avoid-version + +dovecot_module_LTLIBRARIES = lib90_sieve_plugin.la + +lib90_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_plugin_la_SOURCES = \ + lda-sieve-plugin.c + +noinst_HEADERS = \ + lda-sieve-plugin.h diff --git a/pigeonhole/src/plugins/lda-sieve/Makefile.in b/pigeonhole/src/plugins/lda-sieve/Makefile.in new file mode 100644 index 0000000..6f0fba0 --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/Makefile.in @@ -0,0 +1,746 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 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/plugins/lda-sieve +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/dovecot.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/dummy-config.h \ + $(top_builddir)/pigeonhole-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)$(dovecot_moduledir)" +LTLIBRARIES = $(dovecot_module_LTLIBRARIES) +lib90_sieve_plugin_la_DEPENDENCIES = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la +am_lib90_sieve_plugin_la_OBJECTS = lda-sieve-plugin.lo +lib90_sieve_plugin_la_OBJECTS = $(am_lib90_sieve_plugin_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 = +lib90_sieve_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(lib90_sieve_plugin_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +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-sieve-plugin.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 = $(lib90_sieve_plugin_la_SOURCES) +DIST_SOURCES = $(lib90_sieve_plugin_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 = $(noinst_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@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINARY_CFLAGS = @BINARY_CFLAGS@ +BINARY_LDFLAGS = @BINARY_LDFLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DOVECOT_BINARY_CFLAGS = @DOVECOT_BINARY_CFLAGS@ +DOVECOT_BINARY_LDFLAGS = @DOVECOT_BINARY_LDFLAGS@ +DOVECOT_CFLAGS = @DOVECOT_CFLAGS@ +DOVECOT_COMPRESS_LIBS = @DOVECOT_COMPRESS_LIBS@ +DOVECOT_INSTALLED = @DOVECOT_INSTALLED@ +DOVECOT_LIBS = @DOVECOT_LIBS@ +DOVECOT_LUA_CFLAGS = @DOVECOT_LUA_CFLAGS@ +DOVECOT_LUA_LIBS = @DOVECOT_LUA_LIBS@ +DOVECOT_SQL_LIBS = @DOVECOT_SQL_LIBS@ +DOVECOT_SSL_LIBS = @DOVECOT_SSL_LIBS@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDAP_LIBS = @LDAP_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBDOVECOT = @LIBDOVECOT@ +LIBDOVECOT_ACL_INCLUDE = @LIBDOVECOT_ACL_INCLUDE@ +LIBDOVECOT_AUTH_INCLUDE = @LIBDOVECOT_AUTH_INCLUDE@ +LIBDOVECOT_COMPRESS = @LIBDOVECOT_COMPRESS@ +LIBDOVECOT_COMPRESS_DEPS = @LIBDOVECOT_COMPRESS_DEPS@ +LIBDOVECOT_CONFIG_INCLUDE = @LIBDOVECOT_CONFIG_INCLUDE@ +LIBDOVECOT_DEPS = @LIBDOVECOT_DEPS@ +LIBDOVECOT_DOVEADM_INCLUDE = @LIBDOVECOT_DOVEADM_INCLUDE@ +LIBDOVECOT_DSYNC = @LIBDOVECOT_DSYNC@ +LIBDOVECOT_DSYNC_DEPS = @LIBDOVECOT_DSYNC_DEPS@ +LIBDOVECOT_DSYNC_INCLUDE = @LIBDOVECOT_DSYNC_INCLUDE@ +LIBDOVECOT_FTS_INCLUDE = @LIBDOVECOT_FTS_INCLUDE@ +LIBDOVECOT_IMAPC_INCLUDE = @LIBDOVECOT_IMAPC_INCLUDE@ +LIBDOVECOT_IMAP_INCLUDE = @LIBDOVECOT_IMAP_INCLUDE@ +LIBDOVECOT_IMAP_LOGIN_INCLUDE = @LIBDOVECOT_IMAP_LOGIN_INCLUDE@ +LIBDOVECOT_INCLUDE = @LIBDOVECOT_INCLUDE@ +LIBDOVECOT_LDA = @LIBDOVECOT_LDA@ +LIBDOVECOT_LDA_DEPS = @LIBDOVECOT_LDA_DEPS@ +LIBDOVECOT_LDA_INCLUDE = @LIBDOVECOT_LDA_INCLUDE@ +LIBDOVECOT_LIBFTS = @LIBDOVECOT_LIBFTS@ +LIBDOVECOT_LIBFTS_DEPS = @LIBDOVECOT_LIBFTS_DEPS@ +LIBDOVECOT_LIBFTS_INCLUDE = @LIBDOVECOT_LIBFTS_INCLUDE@ +LIBDOVECOT_LMTP_INCLUDE = @LIBDOVECOT_LMTP_INCLUDE@ +LIBDOVECOT_LOGIN = @LIBDOVECOT_LOGIN@ +LIBDOVECOT_LOGIN_DEPS = @LIBDOVECOT_LOGIN_DEPS@ +LIBDOVECOT_LOGIN_INCLUDE = @LIBDOVECOT_LOGIN_INCLUDE@ +LIBDOVECOT_LUA = @LIBDOVECOT_LUA@ +LIBDOVECOT_LUA_DEPS = @LIBDOVECOT_LUA_DEPS@ +LIBDOVECOT_LUA_INCLUDE = @LIBDOVECOT_LUA_INCLUDE@ +LIBDOVECOT_NOTIFY_INCLUDE = @LIBDOVECOT_NOTIFY_INCLUDE@ +LIBDOVECOT_POP3_INCLUDE = @LIBDOVECOT_POP3_INCLUDE@ +LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE = @LIBDOVECOT_PUSH_NOTIFICATION_INCLUDE@ +LIBDOVECOT_SERVICE_INCLUDE = @LIBDOVECOT_SERVICE_INCLUDE@ +LIBDOVECOT_SQL = @LIBDOVECOT_SQL@ +LIBDOVECOT_SQL_DEPS = @LIBDOVECOT_SQL_DEPS@ +LIBDOVECOT_SQL_INCLUDE = @LIBDOVECOT_SQL_INCLUDE@ +LIBDOVECOT_SSL = @LIBDOVECOT_SSL@ +LIBDOVECOT_SSL_DEPS = @LIBDOVECOT_SSL_DEPS@ +LIBDOVECOT_STORAGE = @LIBDOVECOT_STORAGE@ +LIBDOVECOT_STORAGE_DEPS = @LIBDOVECOT_STORAGE_DEPS@ +LIBDOVECOT_STORAGE_INCLUDE = @LIBDOVECOT_STORAGE_INCLUDE@ +LIBDOVECOT_SUBMISSION_INCLUDE = @LIBDOVECOT_SUBMISSION_INCLUDE@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +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@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +RANLIB = @RANLIB@ +RELRO_LDFLAGS = @RELRO_LDFLAGS@ +RUN_TEST = @RUN_TEST@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +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_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@ +docdir = @docdir@ +dovecot_docdir = @dovecot_docdir@ +dovecot_installed_moduledir = @dovecot_installed_moduledir@ +dovecot_moduledir = @dovecot_moduledir@ +dovecot_pkgincludedir = @dovecot_pkgincludedir@ +dovecot_pkglibdir = @dovecot_pkglibdir@ +dovecot_pkglibexecdir = @dovecot_pkglibexecdir@ +dovecot_statedir = @dovecot_statedir@ +dovecotdir = @dovecotdir@ +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@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sieve_docdir = @sieve_docdir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/lib-sieve \ + $(LIBDOVECOT_INCLUDE) \ + $(LIBDOVECOT_DICT_INCLUDE) \ + $(LIBDOVECOT_SMTP_INCLUDE) \ + $(LIBDOVECOT_LDA_INCLUDE) + +lib90_sieve_plugin_la_LDFLAGS = -module -avoid-version +dovecot_module_LTLIBRARIES = lib90_sieve_plugin.la +lib90_sieve_plugin_la_LIBADD = \ + $(top_builddir)/src/lib-sieve/libdovecot-sieve.la + +lib90_sieve_plugin_la_SOURCES = \ + lda-sieve-plugin.c + +noinst_HEADERS = \ + lda-sieve-plugin.h + +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/plugins/lda-sieve/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/lda-sieve/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): + +install-dovecot_moduleLTLIBRARIES: $(dovecot_module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(dovecot_module_LTLIBRARIES)'; test -n "$(dovecot_moduledir)" || 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)$(dovecot_moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(dovecot_moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dovecot_moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dovecot_moduledir)"; \ + } + +uninstall-dovecot_moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(dovecot_module_LTLIBRARIES)'; test -n "$(dovecot_moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dovecot_moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dovecot_moduledir)/$$f"; \ + done + +clean-dovecot_moduleLTLIBRARIES: + -test -z "$(dovecot_module_LTLIBRARIES)" || rm -f $(dovecot_module_LTLIBRARIES) + @list='$(dovecot_module_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}; \ + } + +lib90_sieve_plugin.la: $(lib90_sieve_plugin_la_OBJECTS) $(lib90_sieve_plugin_la_DEPENDENCIES) $(EXTRA_lib90_sieve_plugin_la_DEPENDENCIES) + $(AM_V_CCLD)$(lib90_sieve_plugin_la_LINK) -rpath $(dovecot_moduledir) $(lib90_sieve_plugin_la_OBJECTS) $(lib90_sieve_plugin_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda-sieve-plugin.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 + +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)$(dovecot_moduledir)"; 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-dovecot_moduleLTLIBRARIES clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/lda-sieve-plugin.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-dovecot_moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +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-sieve-plugin.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-dovecot_moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-dovecot_moduleLTLIBRARIES clean-generic clean-libtool \ + 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-dovecot_moduleLTLIBRARIES \ + 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-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-dovecot_moduleLTLIBRARIES + +.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/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c new file mode 100644 index 0000000..4e79c1f --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -0,0 +1,1128 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "array.h" +#include "home-expand.h" +#include "var-expand.h" +#include "eacces-error.h" +#include "smtp-address.h" +#include "smtp-submit.h" +#include "mail-storage.h" +#include "mail-deliver.h" +#include "mail-user.h" +#include "mail-duplicate.h" +#include "smtp-submit.h" +#include "mail-send.h" +#include "iostream-ssl.h" +#include "lda-settings.h" + +#include "sieve.h" +#include "sieve-script.h" +#include "sieve-storage.h" + +#include "lda-sieve-plugin.h" + +#include <sys/stat.h> +#include <dirent.h> + +/* + * Configuration + */ + +#define LDA_SIEVE_DEFAULT_LOCATION "~/.dovecot.sieve" + +#define LDA_SIEVE_MAX_USER_ERRORS 30 + +/* + * Global variables + */ + +static deliver_mail_func_t *next_deliver_mail; + +/* + * Settings handling + */ + +static const char * +lda_sieve_get_setting(void *context, const char *identifier) +{ + struct mail_deliver_context *mdctx = + (struct mail_deliver_context *)context; + const char *value = NULL; + + if (mdctx == NULL) + return NULL; + + if (mdctx->rcpt_user == NULL || + (value = mail_user_plugin_getenv( + mdctx->rcpt_user, identifier)) == NULL) { + if (strcmp(identifier, "recipient_delimiter") == 0) + value = mdctx->set->recipient_delimiter; + } + + return value; +} + +static const struct sieve_callbacks lda_sieve_callbacks = { + NULL, + lda_sieve_get_setting +}; + +/* + * Mail transmission + */ + +static void * +lda_sieve_smtp_start(const struct sieve_script_env *senv, + const struct smtp_address *mail_from) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + struct mail_user *user = dctx->rcpt_user; + struct ssl_iostream_settings ssl_set; + struct smtp_submit_input submit_input; + + i_zero(&ssl_set); + mail_user_init_ssl_client_settings(user, &ssl_set); + + i_zero(&submit_input); + submit_input.ssl = &ssl_set; + + return (void *)smtp_submit_init_simple(&submit_input, dctx->smtp_set, + mail_from); +} + +static void +lda_sieve_smtp_add_rcpt(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const struct smtp_address *rcpt_to) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + smtp_submit_add_rcpt(smtp_submit, rcpt_to); +} + +static struct ostream * +lda_sieve_smtp_send(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + return smtp_submit_send(smtp_submit); +} + +static void +lda_sieve_smtp_abort(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + + smtp_submit_deinit(&smtp_submit); +} + +static int +lda_sieve_smtp_finish(const struct sieve_script_env *senv ATTR_UNUSED, + void *handle, const char **error_r) +{ + struct smtp_submit *smtp_submit = (struct smtp_submit *) handle; + int ret; + + ret = smtp_submit_run(smtp_submit, error_r); + smtp_submit_deinit(&smtp_submit); + return ret; +} + +static int +lda_sieve_reject_mail(const struct sieve_script_env *senv, + const struct smtp_address *recipient, + const char *reason) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + + return mail_send_rejection(dctx, recipient, reason); +} + +/* + * Duplicate checking + */ + +static void * +lda_sieve_duplicate_transaction_begin(const struct sieve_script_env *senv) +{ + struct mail_deliver_context *dctx = + (struct mail_deliver_context *)senv->script_context; + + return mail_duplicate_transaction_begin(dctx->dup_db); +} + +static void lda_sieve_duplicate_transaction_commit(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_commit(&dup_trans); +} + +static void lda_sieve_duplicate_transaction_rollback(void **_dup_trans) +{ + struct mail_duplicate_transaction *dup_trans = *_dup_trans; + + *_dup_trans = NULL; + mail_duplicate_transaction_rollback(&dup_trans); +} + +static enum sieve_duplicate_check_result +lda_sieve_duplicate_check(void *_dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + switch (mail_duplicate_check(dup_trans, id, id_size, + senv->user->username)) { + case MAIL_DUPLICATE_CHECK_RESULT_EXISTS: + return SIEVE_DUPLICATE_CHECK_RESULT_EXISTS; + case MAIL_DUPLICATE_CHECK_RESULT_NOT_FOUND: + return SIEVE_DUPLICATE_CHECK_RESULT_NOT_FOUND; + case MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK: + case MAIL_DUPLICATE_CHECK_RESULT_LOCK_TIMEOUT: + return SIEVE_DUPLICATE_CHECK_RESULT_TEMP_FAILURE; + case MAIL_DUPLICATE_CHECK_RESULT_IO_ERROR: + case MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS: + break; + } + return SIEVE_DUPLICATE_CHECK_RESULT_FAILURE; +} + +static void +lda_sieve_duplicate_mark(void *_dup_trans, const struct sieve_script_env *senv, + const void *id, size_t id_size, time_t time) +{ + struct mail_duplicate_transaction *dup_trans = _dup_trans; + + mail_duplicate_mark(dup_trans, id, id_size, senv->user->username, time); +} + +/* + * Result logging + */ + +static const char * +lda_sieve_result_amend_log_message(const struct sieve_script_env *senv, + enum log_type log_type ATTR_UNUSED, + const char *message) +{ + struct mail_deliver_context *mdctx = senv->script_context; + const struct var_expand_table *table; + string_t *str; + const char *error; + + table = mail_deliver_ctx_get_log_var_expand_table(mdctx, message); + + str = t_str_new(256); + if (var_expand(str, mdctx->set->deliver_log_format, + table, &error) <= 0) { + e_error(mdctx->event, + "Failed to expand deliver_log_format=%s: %s", + mdctx->set->deliver_log_format, error); + } + return str_c(str); +} + +/* + * Plugin implementation + */ + +struct lda_sieve_run_context { + struct sieve_instance *svinst; + + struct mail_deliver_context *mdctx; + const char *home_dir; + + struct sieve_script **scripts; + unsigned int script_count; + + struct sieve_script *user_script; + struct sieve_script *main_script; + struct sieve_script *discard_script; + + const struct sieve_message_data *msgdata; + const struct sieve_script_env *scriptenv; + + struct sieve_error_handler *user_ehandler; + struct sieve_error_handler *master_ehandler; + struct sieve_error_handler *action_ehandler; + const char *userlog; +}; + +static int +lda_sieve_get_personal_storage(struct sieve_instance *svinst, + struct mail_user *user, + struct sieve_storage **storage_r, + enum sieve_error *error_r) +{ + *storage_r = sieve_storage_create_main(svinst, user, 0, error_r); + if (*storage_r == NULL) { + switch (*error_r) { + case SIEVE_ERROR_NOT_POSSIBLE: + case SIEVE_ERROR_NOT_FOUND: + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access user's personal storage " + "(temporary failure)"); + return -1; + default: + e_error(sieve_get_event(svinst), + "Failed to access user's personal storage"); + break; + } + return 0; + } + return 1; +} + +static int +lda_sieve_multiscript_get_scripts(struct sieve_instance *svinst, + const char *label, const char *location, + ARRAY_TYPE(sieve_script) *scripts, + enum sieve_error *error_r) +{ + struct sieve_script_sequence *seq; + struct sieve_script *script; + bool finished = FALSE; + int ret = 1; + + seq = sieve_script_sequence_create(svinst, location, error_r); + if (seq == NULL) + return (*error_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1); + + while (ret > 0 && !finished) { + script = sieve_script_sequence_next(seq, error_r); + if (script == NULL) { + switch (*error_r) { + case SIEVE_ERROR_NONE: + finished = TRUE; + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access %s script from `%s' " + "(temporary failure)", + label, location); + ret = -1; + default: + break; + } + continue; + } + + array_append(scripts, &script, 1); + } + + sieve_script_sequence_free(&seq); + return ret; +} + +static void +lda_sieve_binary_save(struct lda_sieve_run_context *srctx, + struct sieve_binary *sbin, struct sieve_script *script) +{ + enum sieve_error error; + + /* Save binary when compiled */ + if (sieve_save(sbin, FALSE, &error) < 0 && + error == SIEVE_ERROR_NO_PERMISSION && + script != srctx->user_script) { + /* Cannot save binary for global script */ + e_error(sieve_get_event(srctx->svinst), + "The LDA Sieve plugin does not have permission " + "to save global Sieve script binaries; " + "global Sieve scripts like `%s' need to be " + "pre-compiled using the sievec tool", + sieve_script_location(script)); + } +} + +static struct +sieve_binary *lda_sieve_open(struct lda_sieve_run_context *srctx, + struct sieve_script *script, + enum sieve_compile_flags cpflags, bool recompile, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_error_handler *ehandler; + struct sieve_binary *sbin; + const char *compile_name = "compile"; + + if (recompile) { + /* Warn */ + e_warning(sieve_get_event(svinst), + "Encountered corrupt binary: re-compiling script %s", + sieve_script_location(script)); + compile_name = "re-compile"; + } else { + e_debug(sieve_get_event(svinst), + "Loading script %s", sieve_script_location(script)); + } + + if (script == srctx->user_script) + ehandler = srctx->user_ehandler; + else + ehandler = srctx->master_ehandler; + + sieve_error_handler_reset(ehandler); + + if (recompile) + sbin = sieve_compile_script(script, ehandler, cpflags, error_r); + else + sbin = sieve_open_script(script, ehandler, cpflags, error_r); + + /* Load or compile the sieve script */ + if (sbin == NULL) { + switch (*error_r) { + /* Script not found */ + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Script `%s' is missing for %s", + sieve_script_location(script), + compile_name); + break; + /* Temporary failure */ + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(temporary failure)", + sieve_script_location(script), compile_name); + break; + /* Compile failed */ + case SIEVE_ERROR_NOT_VALID: + if (script == srctx->user_script && + srctx->userlog != NULL ) { + e_info(sieve_get_event(svinst), + "Failed to %s script `%s' " + "(view user logfile `%s' for more information)", + compile_name, + sieve_script_location(script), + srctx->userlog); + break; + } + e_error(sieve_get_event(svinst), + "Failed to %s script `%s'", + compile_name, sieve_script_location(script)); + break; + /* Cumulative resource limit exceeded */ + case SIEVE_ERROR_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s " + "(cumulative resource limit exceeded)", + sieve_script_location(script), compile_name); + break; + /* Something else */ + default: + e_error(sieve_get_event(svinst), + "Failed to open script `%s' for %s", + sieve_script_location(script), compile_name); + break; + } + + return NULL; + } + + if (!recompile) + lda_sieve_binary_save(srctx, sbin, script); + return sbin; +} + +static int +lda_sieve_handle_exec_status(struct lda_sieve_run_context *srctx, + struct sieve_script *script, int status) +{ + struct sieve_instance *svinst = srctx->svinst; + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_exec_status *estatus = srctx->scriptenv->exec_status; + const char *userlog_notice = ""; + enum log_type log_level, user_log_level; + enum mail_error mail_error = MAIL_ERROR_NONE; + int ret; + + log_level = user_log_level = LOG_TYPE_ERROR; + + if (estatus != NULL && estatus->last_storage != NULL && + estatus->store_failed) { + mail_storage_get_last_error(estatus->last_storage, &mail_error); + + /* Don't bother administrator too much with benign errors */ + if (mail_error == MAIL_ERROR_NOQUOTA) { + log_level = LOG_TYPE_INFO; + user_log_level = LOG_TYPE_INFO; + } + } + + if (script == srctx->user_script && srctx->userlog != NULL) { + userlog_notice = t_strdup_printf( + " (user logfile %s may reveal additional details)", + srctx->userlog); + user_log_level = LOG_TYPE_INFO; + } + + switch (status) { + case SIEVE_EXEC_FAILURE: + e_log(sieve_get_event(svinst), user_log_level, + "Execution of script %s failed, " + "but implicit keep was successful%s", + sieve_script_location(script), userlog_notice); + ret = 1; + break; + case SIEVE_EXEC_TEMP_FAILURE: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s was aborted due to temporary failure%s", + sieve_script_location(script), userlog_notice); + if (mail_error != MAIL_ERROR_TEMP && + mdctx->tempfail_error == NULL) { + mdctx->tempfail_error = + "Execution of Sieve filters was aborted due to temporary failure"; + } + ret = -1; + break; + case SIEVE_EXEC_BIN_CORRUPT: + e_error(sieve_get_event(svinst), + "!!BUG!!: Binary compiled from %s is still corrupt; " + "bailing out and reverting to default delivery", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_RESOURCE_LIMIT: + e_error(sieve_get_event(svinst), + "Execution of script %s was aborted " + "due to excessive resource usage", + sieve_script_location(script)); + ret = -1; + break; + case SIEVE_EXEC_KEEP_FAILED: + e_log(sieve_get_event(svinst), log_level, + "Execution of script %s failed with unsuccessful implicit keep%s", + sieve_script_location(script), userlog_notice); + ret = -1; + break; + default: + ret = status > 0 ? 1 : -1; + break; + } + + return ret; +} + +static int +lda_sieve_execute_script(struct lda_sieve_run_context *srctx, + struct sieve_multiscript *mscript, + struct sieve_script *script, + unsigned int index, bool discard_script, + enum sieve_error *error_r) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_error_handler *exec_ehandler; + struct sieve_binary *sbin = NULL; + enum sieve_compile_flags cpflags = 0; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + struct sieve_resource_usage *rusage = + &srctx->scriptenv->exec_status->resource_usage; + bool user_script; + int mstatus, ret; + + *error_r = SIEVE_ERROR_NONE; + + user_script = (script == srctx->user_script); + + sieve_resource_usage_init(rusage); + if (user_script) { + cpflags |= SIEVE_COMPILE_FLAG_NOGLOBAL; + exflags |= SIEVE_EXECUTE_FLAG_NOGLOBAL; + exec_ehandler = srctx->user_ehandler; + } else { + exec_ehandler = srctx->master_ehandler; + } + + /* Open */ + + if (!discard_script) { + e_debug(sieve_get_event(svinst), + "Opening script %d of %d from `%s'", + index, srctx->script_count, + sieve_script_location(script)); + } else { + e_debug(sieve_get_event(svinst), + "Opening discard script from `%s'", + sieve_script_location(script)); + } + + sbin = lda_sieve_open(srctx, script, cpflags, FALSE, error_r); + if (sbin == NULL) + return 0; + + /* Execute */ + + e_debug(sieve_get_event(svinst), + "Executing script from `%s'", + sieve_get_source(sbin)); + + if (!discard_script) { + ret = (sieve_multiscript_run(mscript, sbin, exec_ehandler, + exec_ehandler, exflags) ? 1 : 0); + } else { + sieve_multiscript_run_discard(mscript, sbin, exec_ehandler, + exec_ehandler, exflags); + ret = 0; + } + + mstatus = sieve_multiscript_status(mscript); + if (ret == 0 && mstatus == SIEVE_EXEC_BIN_CORRUPT && + sieve_is_loaded(sbin)) { + /* Close corrupt script */ + + sieve_close(&sbin); + + /* Recompile */ + + sbin = lda_sieve_open(srctx, script, cpflags, TRUE, + error_r); + if (sbin == NULL) + return 0; + + /* Execute again */ + + if (!discard_script) { + ret = (sieve_multiscript_run( + mscript, sbin, exec_ehandler, + exec_ehandler, exflags) ? 1 : 0); + } else { + sieve_multiscript_run_discard( + mscript, sbin, exec_ehandler, + exec_ehandler, exflags); + } + + /* Save new version */ + + mstatus = sieve_multiscript_status(mscript); + if (mstatus != SIEVE_EXEC_BIN_CORRUPT) + lda_sieve_binary_save(srctx, sbin, script); + } + if (ret == 0 && mstatus == SIEVE_EXEC_RESOURCE_LIMIT) + ret = -1; + + if (user_script) + (void)sieve_record_resource_usage(sbin, rusage); + + sieve_close(&sbin); + + return ret; +} + +static int lda_sieve_execute_scripts(struct lda_sieve_run_context *srctx) +{ + struct sieve_instance *svinst = srctx->svinst; + struct sieve_multiscript *mscript; + struct sieve_error_handler *exec_ehandler; + struct sieve_script *script, *last_script = NULL; + enum sieve_execute_flags exflags = SIEVE_EXECUTE_FLAG_LOG_RESULT; + bool discard_script; + enum sieve_error error; + unsigned int i; + int ret; + + i_assert(srctx->script_count > 0); + + /* Start execution */ + + mscript = sieve_multiscript_start_execute(svinst, srctx->msgdata, + srctx->scriptenv); + + /* Execute scripts */ + + i = 0; + discard_script = FALSE; + error = SIEVE_ERROR_NONE; + for (;;) { + if (!discard_script) { + /* normal script sequence */ + i_assert(i < srctx->script_count); + script = srctx->scripts[i]; + i++; + } else { + /* discard script */ + script = srctx->discard_script; + } + + i_assert(script != NULL); + last_script = script; + + ret = lda_sieve_execute_script(srctx, mscript, script, i, + discard_script, &error); + if (ret < 0) + break; + if (error == SIEVE_ERROR_NOT_FOUND) { + /* skip scripts which finally turn out not to exist */ + ret = 1; + } + + if (discard_script) { + /* Executed discard script, which is always final */ + break; + } else if (ret > 0) { + /* The "keep" action is applied; execute next script */ + i_assert(i <= srctx->script_count); + if (i == srctx->script_count) { + /* End of normal script sequence */ + break; + } + } else if (error != SIEVE_ERROR_NONE) { + break; + } else if (sieve_multiscript_will_discard(mscript) && + srctx->discard_script != NULL) { + /* Mail is set to be discarded, but we have a discard script. */ + discard_script = TRUE; + } else { + break; + } + } + + /* Finish execution */ + exec_ehandler = (srctx->user_ehandler != NULL ? + srctx->user_ehandler : srctx->master_ehandler); + ret = sieve_multiscript_finish(&mscript, exec_ehandler, exflags, + (error == SIEVE_ERROR_TEMP_FAILURE ? + SIEVE_EXEC_TEMP_FAILURE : + SIEVE_EXEC_OK)); + + /* Don't log additional messages about compile failure */ + if (error != SIEVE_ERROR_NONE && ret == SIEVE_EXEC_FAILURE) { + e_info(sieve_get_event(svinst), + "Aborted script execution sequence with successful implicit keep"); + return 1; + } + + return lda_sieve_handle_exec_status(srctx, last_script, ret); +} + +static int lda_sieve_find_scripts(struct lda_sieve_run_context *srctx) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_storage *main_storage; + const char *sieve_before, *sieve_after, *sieve_discard; + const char *setting_name; + enum sieve_error error; + ARRAY_TYPE(sieve_script) script_sequence; + struct sieve_script *const *scripts; + unsigned int after_index, count, i; + int ret = 1; + + /* Find the personal script to execute */ + + ret = lda_sieve_get_personal_storage(svinst, mdctx->rcpt_user, + &main_storage, &error); + if (ret == 0 && error == SIEVE_ERROR_NOT_POSSIBLE) + return 0; + if (ret > 0) { + srctx->main_script = + sieve_storage_active_script_open(main_storage, &error); + + if (srctx->main_script == NULL) { + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "User has no active script in storage `%s'", + sieve_storage_location(main_storage)); + break; + case SIEVE_ERROR_TEMP_FAILURE: + e_error(sieve_get_event(svinst), + "Failed to access active Sieve script in user storage `%s' " + "(temporary failure)", + sieve_storage_location(main_storage)); + ret = -1; + break; + default: + e_error(sieve_get_event(svinst), + "Failed to access active Sieve script in user storage `%s'", + sieve_storage_location(main_storage)); + break; + } + } else if (!sieve_script_is_default(srctx->main_script)) { + srctx->user_script = srctx->main_script; + } + sieve_storage_unref(&main_storage); + } + + if (ret >= 0 && srctx->main_script == NULL) { + e_debug(sieve_get_event(svinst), + "User has no personal script"); + } + + /* Compose script array */ + + t_array_init(&script_sequence, 16); + + /* before */ + if (ret >= 0) { + i = 2; + setting_name = "sieve_before"; + sieve_before = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + while (ret >= 0 && + sieve_before != NULL && *sieve_before != '\0') { + ret = lda_sieve_multiscript_get_scripts( + svinst, setting_name, sieve_before, + &script_sequence, &error); + if (ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE) { + ret = -1; + break; + } else if (ret == 0) { + e_debug(sieve_get_event(svinst), + "Location for %s not found: %s", + setting_name, sieve_before); + } + ret = 0; + setting_name = t_strdup_printf("sieve_before%u", i++); + sieve_before = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + } + + if (ret >= 0) { + scripts = array_get(&script_sequence, &count); + for (i = 0; i < count; i ++) { + e_debug(sieve_get_event(svinst), + "Executed before user's personal Sieve script(%d): %s", + i+1, sieve_script_location(scripts[i])); + } + } + } + + /* main */ + if (srctx->main_script != NULL) { + array_append(&script_sequence, &srctx->main_script, 1); + + if (ret >= 0) { + e_debug(sieve_get_event(svinst), + "Using the following location for user's Sieve script: %s", + sieve_script_location(srctx->main_script)); + } + } + + after_index = array_count(&script_sequence); + + /* after */ + if (ret >= 0) { + i = 2; + setting_name = "sieve_after"; + sieve_after = mail_user_plugin_getenv(mdctx->rcpt_user, setting_name); + while (sieve_after != NULL && *sieve_after != '\0') { + ret = lda_sieve_multiscript_get_scripts( + svinst, setting_name, sieve_after, + &script_sequence, &error); + if (ret < 0 && error == SIEVE_ERROR_TEMP_FAILURE) { + ret = -1; + break; + } else if (ret == 0) { + e_debug(sieve_get_event(svinst), + "Location for %s not found: %s", + setting_name, sieve_after); + } + ret = 0; + setting_name = t_strdup_printf("sieve_after%u", i++); + sieve_after = mail_user_plugin_getenv( + mdctx->rcpt_user, setting_name); + } + + if (ret >= 0) { + scripts = array_get(&script_sequence, &count); + for ( i = after_index; i < count; i ++ ) { + e_debug(sieve_get_event(svinst), + "executed after user's Sieve script(%d): %s", + i+1, sieve_script_location(scripts[i])); + } + } + } + + /* discard */ + sieve_discard = mail_user_plugin_getenv( + mdctx->rcpt_user, "sieve_discard"); + if (sieve_discard != NULL && *sieve_discard != '\0') { + srctx->discard_script = sieve_script_create_open( + svinst, sieve_discard, NULL, &error); + if (srctx->discard_script == NULL) { + switch (error) { + case SIEVE_ERROR_NOT_FOUND: + e_debug(sieve_get_event(svinst), + "Location for sieve_discard not found: %s", + sieve_discard); + break; + case SIEVE_ERROR_TEMP_FAILURE: + ret = -1; + break; + default: + break; + } + } + } + + if (ret < 0) { + mdctx->tempfail_error = + "Temporarily unable to access necessary Sieve scripts"; + } + srctx->scripts = + array_get_modifiable(&script_sequence, &srctx->script_count); + return ret; +} + +static void +lda_sieve_free_scripts(struct lda_sieve_run_context *srctx) +{ + unsigned int i; + + for (i = 0; i < srctx->script_count; i++) + sieve_script_unref(&srctx->scripts[i]); + if (srctx->discard_script != NULL) + sieve_script_unref(&srctx->discard_script); +} + +static void +lda_sieve_init_trace_log(struct lda_sieve_run_context *srctx, + const struct smtp_address *mail_from, + struct sieve_trace_config *trace_config_r, + struct sieve_trace_log **trace_log_r) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_trace_log *trace_log = NULL; + + if (sieve_trace_config_get(svinst, trace_config_r) < 0 || + sieve_trace_log_open(svinst, &trace_log) < 0) { + i_zero(trace_config_r); + *trace_log_r = NULL; + return; + } + + /* Write header for trace file */ + sieve_trace_log_printf(trace_log, + "Sieve trace log for message delivery:\n" + "\n" + " Username: %s\n", mdctx->rcpt_user->username); + if (mdctx->rcpt_user->session_id != NULL) { + sieve_trace_log_printf(trace_log, + " Session ID: %s\n", + mdctx->rcpt_user->session_id); + } + sieve_trace_log_printf(trace_log, + " Sender: %s\n" + " Final recipient: %s\n" + " Default mailbox: %s\n\n", + smtp_address_encode_path(mail_from), + smtp_address_encode_path(mdctx->rcpt_to), + (mdctx->rcpt_default_mailbox != NULL ? + mdctx->rcpt_default_mailbox : "INBOX")); + + *trace_log_r = trace_log; +} + +static int +lda_sieve_execute(struct lda_sieve_run_context *srctx, + struct mail_storage **storage_r) +{ + struct mail_deliver_context *mdctx = srctx->mdctx; + struct sieve_instance *svinst = srctx->svinst; + struct sieve_message_data msgdata; + struct sieve_script_env scriptenv; + struct sieve_exec_status estatus; + struct sieve_trace_config trace_config; + const struct smtp_address *mail_from; + struct sieve_trace_log *trace_log; + const char *error; + int ret; + + /* Check whether there are any scripts to execute at all */ + + if (srctx->script_count == 0) { + e_debug(sieve_get_event(svinst), + "No scripts to execute: " + "reverting to default delivery."); + + /* No error, but no delivery by this plugin either. A return + value of <= 0 for a deliver plugin is is considered a + failure. In deliver itself, saved_mail and tried_default_save + remain unset, meaning that deliver will then attempt the + default delivery. We return 0 to signify the lack of a real + error. + */ + return 0; + } + + /* Initialize user error handler */ + + if (srctx->user_script != NULL) { + const char *log_path = + sieve_user_get_log_path(svinst, srctx->user_script); + + if (log_path != NULL) { + srctx->userlog = log_path; + srctx->user_ehandler = sieve_logfile_ehandler_create( + svinst, srctx->userlog, + LDA_SIEVE_MAX_USER_ERRORS); + } + } + + /* Determine return address */ + + mail_from = mail_deliver_get_return_address(mdctx); + + /* Initialize trace logging */ + + lda_sieve_init_trace_log(srctx, mail_from, &trace_config, &trace_log); + + /* Collect necessary message data */ + + i_zero(&msgdata); + + msgdata.mail = mdctx->src_mail; + msgdata.auth_user = mdctx->rcpt_user->username; + msgdata.envelope.mail_from = mail_from; + msgdata.envelope.mail_params = &mdctx->mail_params; + msgdata.envelope.rcpt_to = mdctx->rcpt_to; + msgdata.envelope.rcpt_params = &mdctx->rcpt_params; + (void)mail_get_message_id(msgdata.mail, &msgdata.id); + + srctx->msgdata = &msgdata; + + /* Compose script execution environment */ + + if (sieve_script_env_init(&scriptenv, mdctx->rcpt_user, &error) < 0) { + e_error(sieve_get_event(svinst), + "Failed to initialize script execution: %s", error); + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + return -1; + } + + scriptenv.default_mailbox = mdctx->rcpt_default_mailbox; + scriptenv.mailbox_autocreate = mdctx->set->lda_mailbox_autocreate; + scriptenv.mailbox_autosubscribe = mdctx->set->lda_mailbox_autosubscribe; + scriptenv.smtp_start = lda_sieve_smtp_start; + scriptenv.smtp_add_rcpt = lda_sieve_smtp_add_rcpt; + scriptenv.smtp_send = lda_sieve_smtp_send; + scriptenv.smtp_abort = lda_sieve_smtp_abort; + scriptenv.smtp_finish = lda_sieve_smtp_finish; + scriptenv.duplicate_transaction_begin = + lda_sieve_duplicate_transaction_begin; + scriptenv.duplicate_transaction_commit = + lda_sieve_duplicate_transaction_commit; + scriptenv.duplicate_transaction_rollback = + lda_sieve_duplicate_transaction_rollback; + scriptenv.duplicate_mark = lda_sieve_duplicate_mark; + scriptenv.duplicate_check = lda_sieve_duplicate_check; + scriptenv.reject_mail = lda_sieve_reject_mail; + scriptenv.result_amend_log_message = lda_sieve_result_amend_log_message; + scriptenv.script_context = (void *) mdctx; + scriptenv.trace_log = trace_log; + scriptenv.trace_config = trace_config; + + i_zero(&estatus); + scriptenv.exec_status = &estatus; + + srctx->scriptenv = &scriptenv; + + /* Execute script(s) */ + + ret = lda_sieve_execute_scripts(srctx); + + /* Record status */ + + mdctx->tried_default_save = estatus.tried_default_save; + *storage_r = estatus.last_storage; + + if (trace_log != NULL) + sieve_trace_log_free(&trace_log); + + return ret; +} + +static int +lda_sieve_deliver_mail(struct mail_deliver_context *mdctx, + struct mail_storage **storage_r) +{ + struct lda_sieve_run_context srctx; + const struct mail_storage_settings *mail_set = + mail_user_set_get_storage_set(mdctx->rcpt_user); + bool debug = mdctx->rcpt_user->mail_debug; + struct sieve_environment svenv; + int ret = 0; + + /* Initialize run context */ + + i_zero(&srctx); + srctx.mdctx = mdctx; + (void)mail_user_get_home(mdctx->rcpt_user, &srctx.home_dir); + + /* Initialize Sieve engine */ + + memset((void*)&svenv, 0, sizeof(svenv)); + svenv.username = mdctx->rcpt_user->username; + svenv.home_dir = srctx.home_dir; + svenv.hostname = mail_set->hostname; + svenv.base_dir = mdctx->rcpt_user->set->base_dir; + svenv.temp_dir = mdctx->rcpt_user->set->mail_temp_dir; + svenv.event_parent = mdctx->event; + svenv.flags = SIEVE_FLAG_HOME_RELATIVE; + svenv.location = SIEVE_ENV_LOCATION_MDA; + svenv.delivery_phase = SIEVE_DELIVERY_PHASE_DURING; + + srctx.svinst = sieve_init(&svenv, &lda_sieve_callbacks, mdctx, debug); + + /* Initialize master error handler */ + + srctx.master_ehandler = sieve_master_ehandler_create(srctx.svinst, 0); + + sieve_error_handler_accept_infolog(srctx.master_ehandler, TRUE); + sieve_error_handler_accept_debuglog(srctx.master_ehandler, debug); + + *storage_r = NULL; + + /* Find Sieve scripts and run them */ + + T_BEGIN { + if (lda_sieve_find_scripts(&srctx) < 0) + ret = -1; + else if (srctx.scripts == NULL) + ret = 0; + else + ret = lda_sieve_execute(&srctx, storage_r); + + lda_sieve_free_scripts(&srctx); + } T_END; + + /* Clean up */ + + if (srctx.user_ehandler != NULL) + sieve_error_handler_unref(&srctx.user_ehandler); + sieve_error_handler_unref(&srctx.master_ehandler); + sieve_deinit(&srctx.svinst); + + return ret; +} + +/* + * Plugin interface + */ + +const char *sieve_plugin_version = DOVECOT_ABI_VERSION; +const char sieve_plugin_binary_dependency[] = "lda lmtp"; + +void sieve_plugin_init(void) +{ + /* Hook into the delivery process */ + next_deliver_mail = mail_deliver_hook_set(lda_sieve_deliver_mail); +} + +void sieve_plugin_deinit(void) +{ + /* Remove hook */ + mail_deliver_hook_set(next_deliver_mail); +} diff --git a/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h new file mode 100644 index 0000000..2357097 --- /dev/null +++ b/pigeonhole/src/plugins/lda-sieve/lda-sieve-plugin.h @@ -0,0 +1,11 @@ +#ifndef LDA_SIEVE_PLUGIN_H +#define LDA_SIEVE_PLUGIN_H + +/* + * Plugin interface + */ + +void sieve_plugin_init(void); +void sieve_plugin_deinit(void); + +#endif |