diff options
Diffstat (limited to '')
382 files changed, 50927 insertions, 0 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..5577ef7 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,23 @@ +if BUILD_DOCS +DOCDIRS = wiki example-config +endif + +SUBDIRS = man $(DOCDIRS) + +docfiles = \ + documentation.txt \ + securecoding.txt \ + thread-refs.txt \ + mkcert.sh \ + dovecot-openssl.cnf \ + solr-schema.xml \ + solr-schema-7.7.0.xml \ + solr-config-7.7.0.xml + +if BUILD_DOCS +doc_DATA = $(docfiles) +endif + +EXTRA_DIST = \ + dovecot-initd.sh \ + $(docfiles) diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..39e5fee --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,838 @@ +# 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 = doc +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 $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(docdir)" +DATA = $(doc_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +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 +DIST_SUBDIRS = man wiki example-config +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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@ +@BUILD_DOCS_TRUE@DOCDIRS = wiki example-config +SUBDIRS = man $(DOCDIRS) +docfiles = \ + documentation.txt \ + securecoding.txt \ + thread-refs.txt \ + mkcert.sh \ + dovecot-openssl.cnf \ + solr-schema.xml \ + solr-schema-7.7.0.xml \ + solr-config-7.7.0.xml + +@BUILD_DOCS_TRUE@doc_DATA = $(docfiles) +EXTRA_DIST = \ + dovecot-initd.sh \ + $(docfiles) + +all: all-recursive + +.SUFFIXES: +$(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 doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-docDATA: $(doc_DATA) + @$(NORMAL_INSTALL) + @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || 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_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-docDATA: + @$(NORMAL_UNINSTALL) + @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(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-recursive + +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-recursive + +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 + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-docDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-docDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean 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-docDATA 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 installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-docDATA + +.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/doc/documentation.txt b/doc/documentation.txt new file mode 100644 index 0000000..f5fcb64 --- /dev/null +++ b/doc/documentation.txt @@ -0,0 +1,130 @@ +The documentation in wiki/ directory has been imported from +http://wiki2.dovecot.org/. The actual Wiki may contain more up-to-date +information, so unless this is an old Dovecot release, you may want to use +the Wiki directly. + + * <QuickConfiguration.txt> for people in hurry + * <WhyDoesItNotWork.txt> - Why doesn't Dovecot work? + +Generic information about mail servers +====================================== + + * Mail protocols: IMAP [http://en.wikipedia.org/wiki/Imap], POP3 + [http://en.wikipedia.org/wiki/Pop3] and SMTP + [http://en.wikipedia.org/wiki/Smtp] + * <Mail delivery agents and Sieve> [MDA.txt] + * <Mailbox formats> [MailboxFormat.txt] + * <Dovecot's index files> [IndexFiles.txt] + * <User authentication> [Authentication.txt] + * <SASL> [Sasl.txt] + +Dovecot installation +==================== + +It's a good idea to start with a simple Dovecot installation to see that +everything works. After that you can start changing things one at a time, so if +you run into trouble you know immediately where the problem is. + +If you're in a hurry and you already know enough about mail servers, +<QuickConfiguration.txt> may be more helpful to you instead. + + 1. Installing + * <Compiling from sources> [CompilingSource.txt] + * <Installing prebuilt binaries> [PrebuiltBinaries.txt] + 2. <Checking where mail is delivered to> [FindMailLocation.txt] + 3. <Configuring Dovecot> [BasicConfiguration.txt] + 4. <Running Dovecot> [RunningDovecot.txt] + 5. <Logging.txt> + 6. <Testing that everything works> [TestInstallation.txt] + * <Testing POP3 installation> [TestPop3Installation.txt] + 7. <Finishing the test installation> [FinishBasicConfiguration.txt] + +Dovecot configuration +===================== + + * Starting guidelines + * <System users> [SystemUsers.txt] + * <Virtual users> [VirtualUsers.txt] + * <UNIX User IDs used by Dovecot> [UserIds.txt] + * <Authentication configuration> [Authentication.txt] + * <Password databases> [PasswordDatabase.txt] + * <User databases> [UserDatabase.txt] + * <Multiple authentication databases> + [Authentication.MultipleDatabases.txt] + * <Kerberos> [Authentication.Kerberos.txt] + * <Restricting users' access> [Authentication.RestrictAccess.txt] + * <Special authentication features> [PasswordDatabase.ExtraFields.txt] + * <Master users> [Authentication.MasterUsers.txt] + * <Caching> [Authentication.Caching.txt] + * <Mailbox location configuration> [MailLocation.txt] + * <Mails stored in local disk> [MailLocation.LocalDisk.txt] + * <Mails stored in shared filesystem> [MailLocation.SharedDisk.txt] + (<NFS.txt>, clustered FS) + * <Director.txt> for easily proxying same user to same server to + avoid caching problems. + * <Maildir configuration> [MailLocation.Maildir.txt] + * <Mbox configuration> [MailLocation.Mbox.txt] + * <Namespaces.txt> + * <Shared mailboxes> [SharedMailboxes.txt] + * <Login processes and their settings> [LoginProcess.txt] + * <SSL.txt> settings and certificate creation + * <Plugins.txt> + * <Quota.txt> + * <Access Control Lists> [ACL.txt] (ACLs) + * <Dovecot as a POP3 server> [POP3Server.txt] + * <Dovecot's local delivery agent> [LDA.txt] + * <Sieve.txt> and <ManageSieve.txt> + * <Post-login scripting> [PostLoginScripting.txt] + +HOWTOs, examples and tutorials +============================== + +Some HOWTOs haven't been included in wiki/. Use http://wiki2.dovecot.org/ +instead. + + * <HOWTOs, examples and tutorials> [HowTo.txt] for different installations + * Existing Dovecot installations + [http://wiki2.dovecot.org/DovecotServerInstallations] + +Migration from existing systems +=============================== + + * <From other IMAP/POP3 servers> [Migration.txt] + * <My mailboxes are lost after migrating to Dovecot!> + [MissingMailboxes.txt] + * <Upgrading Dovecot to a new version> [Upgrading.txt] + * <Converting between mailbox formats> [Migration.MailFormat.txt] (mbox <-> + Maildir, etc.) + +Troubleshooting +=============== + + * <Why doesn't Dovecot work?> [WhyDoesItNotWork.txt] + * <Finding the error message from logs> [Logging.txt] + * <Debugging authentication> [Debugging.Authentication.txt] + * <Process tracing> [Debugging.ProcessTracing.txt] is useful when Dovecot + seems slow or hangs completely + * Rawlog [Debugging.Rawlog.txt] can be used to log post-login IMAP/POP3 + traffic + * <mbox errors and crashes> [MboxProblems.txt] + * <Client issues and configuration> [Clients.txt] + * <Negative UIDs / message sets> [Clients.NegativeUIDs.txt] + * <Debugging using Thunderbird's logging> [Debugging.Thunderbird.txt] + * <"Time moved backwards" error> [TimeMovedBackwards.txt] + * <%d expands to empty string> [DomainLost.txt] + * <pre-authenticated sessions> [PreAuth.txt] + * Sending bug reports [http://dovecot.org/bugreport.html], debugging crashes + and sniffing network traffic + +Tuning +====== + + * <Performance tuning> [PerformanceTuning.txt] + * <Security tuning> [SecurityTuning.txt] + * <Chrooting.txt> + +Reference +========= + + * <Dovecot's design> [Design.txt] + * <Client issues and configuration> [Clients.txt] diff --git a/doc/dovecot-initd.sh b/doc/dovecot-initd.sh new file mode 100644 index 0000000..0da7426 --- /dev/null +++ b/doc/dovecot-initd.sh @@ -0,0 +1,79 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: dovecot +# Required-Start: $local_fs $remote_fs $network $syslog $time +# Required-Stop: $local_fs $remote_fs $network $syslog +# Should-Start: postgresql mysql slapd winbind +# Should-Stop: postgresql mysql slapd winbind +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Dovecot init script +# Description: Init script for dovecot services +### END INIT INFO + +# Example /etc/init.d/dovecot script. Change DAEMON if necessary. +# License is public domain. + +DAEMON=/usr/local/sbin/dovecot + +# Uncomment to allow Dovecot daemons to produce core dumps. +#ulimit -c unlimited + +# RedHat config +[ -e /etc/sysconfig/dovecot ] && . /etc/sysconfig/dovecot + +# Debian config +[ -e /etc/default/dovecot ] && . /etc/default/dovecot + +test -x $DAEMON || exit 1 +set -e + +base_dir=`$DAEMON config -h base_dir` +pidfile=$base_dir/master.pid + +if test -f $pidfile; then + running=yes +else + running=no +fi + +case "$1" in + start) + echo -n "Starting Dovecot" + $DAEMON + echo "." + ;; + stop) + if test $running = yes; then + echo "Stopping Dovecot" + kill `cat $pidfile` + echo "." + else + echo "Dovecot is already stopped." + fi + ;; + reload) + if test $running = yes; then + echo -n "Reloading Dovecot configuration" + kill -HUP `cat $pidfile` + echo "." + else + echo "Dovecot isn't running." + fi + ;; + restart|force-reload) + echo -n "Restarting Dovecot" + if test $running = yes; then + kill `cat $pidfile` + sleep 1 + fi + $DAEMON + echo "." + ;; + *) + echo "Usage: /etc/init.d/dovecot {start|stop|reload|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/doc/dovecot-openssl.cnf b/doc/dovecot-openssl.cnf new file mode 100644 index 0000000..f65a80c --- /dev/null +++ b/doc/dovecot-openssl.cnf @@ -0,0 +1,31 @@ +[ req ] +default_bits = 2048 +encrypt_key = yes +distinguished_name = req_dn +x509_extensions = cert_type +prompt = no + +[ req_dn ] +# country (2 letter code) +#C=FI + +# State or Province Name (full name) +#ST= + +# Locality Name (eg. city) +#L=Helsinki + +# Organization (eg. company) +#O=Dovecot + +# Organizational Unit Name (eg. section) +OU=IMAP server + +# Common Name (*.example.com is also possible) +CN=imap.example.com + +# E-mail contact +emailAddress=postmaster@example.com + +[ cert_type ] +nsCertType = server diff --git a/doc/example-config/Makefile.am b/doc/example-config/Makefile.am new file mode 100644 index 0000000..331d6e9 --- /dev/null +++ b/doc/example-config/Makefile.am @@ -0,0 +1,28 @@ +SUBDIRS = conf.d + +pkgsysconfdir = $(sysconfdir)/dovecot +nodist_pkgsysconf_DATA = README +# nodist_ prefix just doesn't seem to work, so rm it directly: +dist-hook: + rm -f $(distdir)/README + +README: README.in Makefile + cat $(srcdir)/README.in | sed "s|@exampledir@|$(exampledir)|" > README + +exampledir = $(docdir)/example-config +example_DATA = \ + dovecot.conf \ + dovecot-dict-auth.conf.ext \ + dovecot-dict-sql.conf.ext \ + dovecot-ldap.conf.ext \ + dovecot-oauth2.conf.ext \ + dovecot-sql.conf.ext + +EXTRA_DIST = \ + $(example_DATA) \ + README.in + +install-data-local: + $(mkdir_p) $(DESTDIR)/$(pkgsysconfdir) + +CLEANFILES = README diff --git a/doc/example-config/Makefile.in b/doc/example-config/Makefile.in new file mode 100644 index 0000000..794046a --- /dev/null +++ b/doc/example-config/Makefile.in @@ -0,0 +1,876 @@ +# 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 = doc/example-config +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 $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(exampledir)" \ + "$(DESTDIR)$(pkgsysconfdir)" +DATA = $(example_DATA) $(nodist_pkgsysconf_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +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 +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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@ +SUBDIRS = conf.d +pkgsysconfdir = $(sysconfdir)/dovecot +nodist_pkgsysconf_DATA = README +exampledir = $(docdir)/example-config +example_DATA = \ + dovecot.conf \ + dovecot-dict-auth.conf.ext \ + dovecot-dict-sql.conf.ext \ + dovecot-ldap.conf.ext \ + dovecot-oauth2.conf.ext \ + dovecot-sql.conf.ext + +EXTRA_DIST = \ + $(example_DATA) \ + README.in + +CLEANFILES = README +all: all-recursive + +.SUFFIXES: +$(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 doc/example-config/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/example-config/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-exampleDATA: $(example_DATA) + @$(NORMAL_INSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(exampledir)" || 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_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ + done + +uninstall-exampleDATA: + @$(NORMAL_UNINSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) +install-nodist_pkgsysconfDATA: $(nodist_pkgsysconf_DATA) + @$(NORMAL_INSTALL) + @list='$(nodist_pkgsysconf_DATA)'; test -n "$(pkgsysconfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgsysconfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgsysconfdir)" || 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_DATA) $$files '$(DESTDIR)$(pkgsysconfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgsysconfdir)" || exit $$?; \ + done + +uninstall-nodist_pkgsysconfDATA: + @$(NORMAL_UNINSTALL) + @list='$(nodist_pkgsysconf_DATA)'; test -n "$(pkgsysconfdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgsysconfdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(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-recursive + +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-recursive + +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 + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(exampledir)" "$(DESTDIR)$(pkgsysconfdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +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-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-data-local install-exampleDATA \ + install-nodist_pkgsysconfDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-exampleDATA uninstall-nodist_pkgsysconfDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am dist-hook distclean 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-data-local install-dvi install-dvi-am \ + install-exampleDATA install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-nodist_pkgsysconfDATA install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-exampleDATA \ + uninstall-nodist_pkgsysconfDATA + +.PRECIOUS: Makefile + +# nodist_ prefix just doesn't seem to work, so rm it directly: +dist-hook: + rm -f $(distdir)/README + +README: README.in Makefile + cat $(srcdir)/README.in | sed "s|@exampledir@|$(exampledir)|" > README + +install-data-local: + $(mkdir_p) $(DESTDIR)/$(pkgsysconfdir) + +# 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/doc/example-config/README.in b/doc/example-config/README.in new file mode 100644 index 0000000..9d93d9e --- /dev/null +++ b/doc/example-config/README.in @@ -0,0 +1,2 @@ +Configuration files go to this directory. See example configuration files in +@exampledir@/ diff --git a/doc/example-config/conf.d/10-auth.conf b/doc/example-config/conf.d/10-auth.conf new file mode 100644 index 0000000..3e9c4e4 --- /dev/null +++ b/doc/example-config/conf.d/10-auth.conf @@ -0,0 +1,127 @@ +## +## Authentication processes +## + +# Disable LOGIN command and all other plaintext authentications unless +# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP +# matches the local IP (ie. you're connecting from the same computer), the +# connection is considered secure and plaintext authentication is allowed. +# See also ssl=required setting. +#disable_plaintext_auth = yes + +# Authentication cache size (e.g. 10M). 0 means it's disabled. Note that +# bsdauth and PAM require cache_key to be set for caching to be used. +#auth_cache_size = 0 +# Time to live for cached data. After TTL expires the cached record is no +# longer used, *except* if the main database lookup returns internal failure. +# We also try to handle password changes automatically: If user's previous +# authentication was successful, but this one wasn't, the cache isn't used. +# For now this works only with plaintext authentication. +#auth_cache_ttl = 1 hour +# TTL for negative hits (user not found, password mismatch). +# 0 disables caching them completely. +#auth_cache_negative_ttl = 1 hour + +# Space separated list of realms for SASL authentication mechanisms that need +# them. You can leave it empty if you don't want to support multiple realms. +# Many clients simply use the first one listed here, so keep the default realm +# first. +#auth_realms = + +# Default realm/domain to use if none was specified. This is used for both +# SASL realms and appending @domain to username in plaintext logins. +#auth_default_realm = + +# List of allowed characters in username. If the user-given username contains +# a character not listed in here, the login automatically fails. This is just +# an extra check to make sure user can't exploit any potential quote escaping +# vulnerabilities with SQL/LDAP databases. If you want to allow all characters, +# set this value to empty. +#auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@ + +# Username character translations before it's looked up from databases. The +# value contains series of from -> to characters. For example "#@/@" means +# that '#' and '/' characters are translated to '@'. +#auth_username_translation = + +# Username formatting before it's looked up from databases. You can use +# the standard variables here, eg. %Lu would lowercase the username, %n would +# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into +# "-AT-". This translation is done after auth_username_translation changes. +#auth_username_format = %Lu + +# If you want to allow master users to log in by specifying the master +# username within the normal username string (ie. not using SASL mechanism's +# support for it), you can specify the separator character here. The format +# is then <username><separator><master username>. UW-IMAP uses "*" as the +# separator, so that could be a good choice. +#auth_master_user_separator = + +# Username to use for users logging in with ANONYMOUS SASL mechanism +#auth_anonymous_username = anonymous + +# Maximum number of dovecot-auth worker processes. They're used to execute +# blocking passdb and userdb queries (eg. MySQL and PAM). They're +# automatically created and destroyed as needed. +#auth_worker_max_count = 30 + +# Host name to use in GSSAPI principal names. The default is to use the +# name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab +# entries. +#auth_gssapi_hostname = + +# Kerberos keytab to use for the GSSAPI mechanism. Will use the system +# default (usually /etc/krb5.keytab) if not specified. You may need to change +# the auth service to run as root to be able to read this file. +#auth_krb5_keytab = + +# Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and +# ntlm_auth helper. <doc/wiki/Authentication/Mechanisms/Winbind.txt> +#auth_use_winbind = no + +# Path for Samba's ntlm_auth helper binary. +#auth_winbind_helper_path = /usr/bin/ntlm_auth + +# Time to delay before replying to failed authentications. +#auth_failure_delay = 2 secs + +# Require a valid SSL client certificate or the authentication fails. +#auth_ssl_require_client_cert = no + +# Take the username from client's SSL certificate, using +# X509_NAME_get_text_by_NID() which returns the subject's DN's +# CommonName. +#auth_ssl_username_from_cert = no + +# Space separated list of wanted authentication mechanisms: +# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp +# gss-spnego +# NOTE: See also disable_plaintext_auth setting. +auth_mechanisms = plain + +## +## Password and user databases +## + +# +# Password database is used to verify user's password (and nothing more). +# You can have multiple passdbs and userdbs. This is useful if you want to +# allow both system users (/etc/passwd) and virtual users to login without +# duplicating the system users into virtual database. +# +# <doc/wiki/PasswordDatabase.txt> +# +# User database specifies where mails are located and what user/group IDs +# own them. For single-UID configuration use "static" userdb. +# +# <doc/wiki/UserDatabase.txt> + +#!include auth-deny.conf.ext +#!include auth-master.conf.ext + +!include auth-system.conf.ext +#!include auth-sql.conf.ext +#!include auth-ldap.conf.ext +#!include auth-passwdfile.conf.ext +#!include auth-checkpassword.conf.ext +#!include auth-static.conf.ext diff --git a/doc/example-config/conf.d/10-director.conf b/doc/example-config/conf.d/10-director.conf new file mode 100644 index 0000000..073d8a8 --- /dev/null +++ b/doc/example-config/conf.d/10-director.conf @@ -0,0 +1,60 @@ +## +## Director-specific settings. +## + +# Director can be used by Dovecot proxy to keep a temporary user -> mail server +# mapping. As long as user has simultaneous connections, the user is always +# redirected to the same server. Each proxy server is running its own director +# process, and the directors are communicating the state to each others. +# Directors are mainly useful with NFS-like setups. + +# List of IPs or hostnames to all director servers, including ourself. +# Ports can be specified as ip:port. The default port is the same as +# what director service's inet_listener is using. +#director_servers = + +# List of IPs or hostnames to all backend mail servers. Ranges are allowed +# too, like 10.0.0.10-10.0.0.30. +#director_mail_servers = + +# How long to redirect users to a specific server after it no longer has +# any connections. +#director_user_expire = 15 min + +# How the username is translated before being hashed. Useful values include +# %Ln if user can log in with or without @domain, %Ld if mailboxes are shared +# within domain. +#director_username_hash = %Lu + +# To enable director service, uncomment the modes and assign a port. +service director { + unix_listener login/director { + #mode = 0666 + } + fifo_listener login/proxy-notify { + #mode = 0666 + } + unix_listener director-userdb { + #mode = 0600 + } + inet_listener { + #port = + } +} + +# Enable director for the wanted login services by telling them to +# connect to director socket instead of the default login socket: +service imap-login { + #executable = imap-login director +} +service pop3-login { + #executable = pop3-login director +} +service submission-login { + #executable = submission-login director +} + +# Enable director for LMTP proxying: +protocol lmtp { + #auth_socket_path = director-userdb +} diff --git a/doc/example-config/conf.d/10-logging.conf b/doc/example-config/conf.d/10-logging.conf new file mode 100644 index 0000000..beb15ba --- /dev/null +++ b/doc/example-config/conf.d/10-logging.conf @@ -0,0 +1,105 @@ +## +## Log destination. +## + +# Log file to use for error messages. "syslog" logs to syslog, +# /dev/stderr logs to stderr. +#log_path = syslog + +# Log file to use for informational messages. Defaults to log_path. +#info_log_path = +# Log file to use for debug messages. Defaults to info_log_path. +#debug_log_path = + +# Syslog facility to use if you're logging to syslog. Usually if you don't +# want to use "mail", you'll use local0..local7. Also other standard +# facilities are supported. +#syslog_facility = mail + +## +## Logging verbosity and debugging. +## + +# Log filter is a space-separated list conditions. If any of the conditions +# match, the log filter matches (i.e. they're ORed together). Parenthesis +# are supported if multiple conditions need to be matched together. +# +# See https://doc.dovecot.org/configuration_manual/event_filter/ for details. +# +# For example: event=http_request_* AND category=error AND category=storage +# +# Filter to specify what debug logging to enable. This will eventually replace +# mail_debug and auth_debug settings. +#log_debug = + +# Crash after logging a matching event. For example category=error will crash +# any time an error is logged, which can be useful for debugging. +#log_core_filter = + +# Log unsuccessful authentication attempts and the reasons why they failed. +#auth_verbose = no + +# In case of password mismatches, log the attempted password. Valid values are +# no, plain and sha1. sha1 can be useful for detecting brute force password +# attempts vs. user simply trying the same password over and over again. +# You can also truncate the value to n chars by appending ":n" (e.g. sha1:6). +#auth_verbose_passwords = no + +# Even more verbose logging for debugging purposes. Shows for example SQL +# queries. +#auth_debug = no + +# In case of password mismatches, log the passwords and used scheme so the +# problem can be debugged. Enabling this also enables auth_debug. +#auth_debug_passwords = no + +# Enable mail process debugging. This can help you figure out why Dovecot +# isn't finding your mails. +#mail_debug = no + +# Show protocol level SSL errors. +#verbose_ssl = no + +# mail_log plugin provides more event logging for mail processes. +plugin { + # Events to log. Also available: flag_change append + #mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename + # Available fields: uid, box, msgid, from, subject, size, vsize, flags + # size and vsize are available only for expunge and copy events. + #mail_log_fields = uid box msgid size +} + +## +## Log formatting. +## + +# Prefix for each line written to log file. % codes are in strftime(3) +# format. +#log_timestamp = "%b %d %H:%M:%S " + +# Space-separated list of elements we want to log. The elements which have +# a non-empty variable value are joined together to form a comma-separated +# string. +#login_log_format_elements = user=<%u> method=%m rip=%r lip=%l mpid=%e %c + +# Login log format. %s contains login_log_format_elements string, %$ contains +# the data we want to log. +#login_log_format = %$: %s + +# Log prefix for mail processes. See doc/wiki/Variables.txt for list of +# possible variables you can use. +#mail_log_prefix = "%s(%u)<%{pid}><%{session}>: " + +# Format to use for logging mail deliveries: +# %$ - Delivery status message (e.g. "saved to INBOX") +# %m / %{msgid} - Message-ID +# %s / %{subject} - Subject +# %f / %{from} - From address +# %p / %{size} - Physical size +# %w / %{vsize} - Virtual size +# %e / %{from_envelope} - MAIL FROM envelope +# %{to_envelope} - RCPT TO envelope +# %{delivery_time} - How many milliseconds it took to deliver the mail +# %{session_time} - How long LMTP session took, not including delivery_time +# %{storage_id} - Backend-specific ID for mail, e.g. Maildir filename +#deliver_log_format = msgid=%m: %$ diff --git a/doc/example-config/conf.d/10-mail.conf b/doc/example-config/conf.d/10-mail.conf new file mode 100644 index 0000000..de48f92 --- /dev/null +++ b/doc/example-config/conf.d/10-mail.conf @@ -0,0 +1,415 @@ +## +## Mailbox locations and namespaces +## + +# Location for users' mailboxes. The default is empty, which means that Dovecot +# tries to find the mailboxes automatically. This won't work if the user +# doesn't yet have any mail, so you should explicitly tell Dovecot the full +# location. +# +# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u) +# isn't enough. You'll also need to tell Dovecot where the other mailboxes are +# kept. This is called the "root mail directory", and it must be the first +# path given in the mail_location setting. +# +# There are a few special variables you can use, eg.: +# +# %u - username +# %n - user part in user@domain, same as %u if there's no domain +# %d - domain part in user@domain, empty if there's no domain +# %h - home directory +# +# See doc/wiki/Variables.txt for full list. Some examples: +# +# mail_location = maildir:~/Maildir +# mail_location = mbox:~/mail:INBOX=/var/mail/%u +# mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n +# +# <doc/wiki/MailLocation.txt> +# +#mail_location = + +# If you need to set multiple mailbox locations or want to change default +# namespace settings, you can do it by defining namespace sections. +# +# You can have private, shared and public namespaces. Private namespaces +# are for user's personal mails. Shared namespaces are for accessing other +# users' mailboxes that have been shared. Public namespaces are for shared +# mailboxes that are managed by sysadmin. If you create any shared or public +# namespaces you'll typically want to enable ACL plugin also, otherwise all +# users can access all the shared mailboxes, assuming they have permissions +# on filesystem level to do so. +namespace inbox { + # Namespace type: private, shared or public + #type = private + + # Hierarchy separator to use. You should use the same separator for all + # namespaces or some clients get confused. '/' is usually a good one. + # The default however depends on the underlying mail storage format. + #separator = + + # Prefix required to access this namespace. This needs to be different for + # all namespaces. For example "Public/". + #prefix = + + # Physical location of the mailbox. This is in same format as + # mail_location, which is also the default for it. + #location = + + # There can be only one INBOX, and this setting defines which namespace + # has it. + inbox = yes + + # If namespace is hidden, it's not advertised to clients via NAMESPACE + # extension. You'll most likely also want to set list=no. This is mostly + # useful when converting from another server with different namespaces which + # you want to deprecate but still keep working. For example you can create + # hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/". + #hidden = no + + # Show the mailboxes under this namespace with LIST command. This makes the + # namespace visible for clients that don't support NAMESPACE extension. + # "children" value lists child mailboxes, but hides the namespace prefix. + #list = yes + + # Namespace handles its own subscriptions. If set to "no", the parent + # namespace handles them (empty prefix should always have this as "yes") + #subscriptions = yes + + # See 15-mailboxes.conf for definitions of special mailboxes. +} + +# Example shared namespace configuration +#namespace { + #type = shared + #separator = / + + # Mailboxes are visible under "shared/user@domain/" + # %%n, %%d and %%u are expanded to the destination user. + #prefix = shared/%%u/ + + # Mail location for other users' mailboxes. Note that %variables and ~/ + # expands to the logged in user's data. %%n, %%d, %%u and %%h expand to the + # destination user's data. + #location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u + + # Use the default namespace for saving subscriptions. + #subscriptions = no + + # List the shared/ namespace only if there are visible shared mailboxes. + #list = children +#} +# Should shared INBOX be visible as "shared/user" or "shared/user/INBOX"? +#mail_shared_explicit_inbox = no + +# System user and group used to access mails. If you use multiple, userdb +# can override these by returning uid or gid fields. You can use either numbers +# or names. <doc/wiki/UserIds.txt> +#mail_uid = +#mail_gid = + +# Group to enable temporarily for privileged operations. Currently this is +# used only with INBOX when either its initial creation or dotlocking fails. +# Typically this is set to "mail" to give access to /var/mail. +#mail_privileged_group = + +# Grant access to these supplementary groups for mail processes. Typically +# these are used to set up access to shared mailboxes. Note that it may be +# dangerous to set these if users can create symlinks (e.g. if "mail" group is +# set here, ln -s /var/mail ~/mail/var could allow a user to delete others' +# mailboxes, or ln -s /secret/shared/box ~/mail/mybox would allow reading it). +#mail_access_groups = + +# Allow full filesystem access to clients. There's no access checks other than +# what the operating system does for the active UID/GID. It works with both +# maildir and mboxes, allowing you to prefix mailboxes names with eg. /path/ +# or ~user/. +#mail_full_filesystem_access = no + +# Dictionary for key=value mailbox attributes. This is used for example by +# URLAUTH and METADATA extensions. +#mail_attribute_dict = + +# A comment or note that is associated with the server. This value is +# accessible for authenticated users through the IMAP METADATA server +# entry "/shared/comment". +#mail_server_comment = "" + +# Indicates a method for contacting the server administrator. According to +# RFC 5464, this value MUST be a URI (e.g., a mailto: or tel: URL), but that +# is currently not enforced. Use for example mailto:admin@example.com. This +# value is accessible for authenticated users through the IMAP METADATA server +# entry "/shared/admin". +#mail_server_admin = + +## +## Mail processes +## + +# Don't use mmap() at all. This is required if you store indexes to shared +# filesystems (NFS or clustered filesystem). +#mmap_disable = no + +# Rely on O_EXCL to work when creating dotlock files. NFS supports O_EXCL +# since version 3, so this should be safe to use nowadays by default. +#dotlock_use_excl = yes + +# When to use fsync() or fdatasync() calls: +# optimized (default): Whenever necessary to avoid losing important data +# always: Useful with e.g. NFS when write()s are delayed +# never: Never use it (best performance, but crashes can lose data) +#mail_fsync = optimized + +# Locking method for index files. Alternatives are fcntl, flock and dotlock. +# Dotlocking uses some tricks which may create more disk I/O than other locking +# methods. NFS users: flock doesn't work, remember to change mmap_disable. +#lock_method = fcntl + +# Directory where mails can be temporarily stored. Usually it's used only for +# mails larger than >= 128 kB. It's used by various parts of Dovecot, for +# example LDA/LMTP while delivering large mails or zlib plugin for keeping +# uncompressed mails. +#mail_temp_dir = /tmp + +# Valid UID range for users, defaults to 500 and above. This is mostly +# to make sure that users can't log in as daemons or other system users. +# Note that denying root logins is hardcoded to dovecot binary and can't +# be done even if first_valid_uid is set to 0. +#first_valid_uid = 500 +#last_valid_uid = 0 + +# Valid GID range for users, defaults to non-root/wheel. Users having +# non-valid GID as primary group ID aren't allowed to log in. If user +# belongs to supplementary groups with non-valid GIDs, those groups are +# not set. +#first_valid_gid = 1 +#last_valid_gid = 0 + +# Maximum allowed length for mail keyword name. It's only forced when trying +# to create new keywords. +#mail_max_keyword_length = 50 + +# ':' separated list of directories under which chrooting is allowed for mail +# processes (ie. /var/mail will allow chrooting to /var/mail/foo/bar too). +# This setting doesn't affect login_chroot, mail_chroot or auth chroot +# settings. If this setting is empty, "/./" in home dirs are ignored. +# WARNING: Never add directories here which local users can modify, that +# may lead to root exploit. Usually this should be done only if you don't +# allow shell access for users. <doc/wiki/Chrooting.txt> +#valid_chroot_dirs = + +# Default chroot directory for mail processes. This can be overridden for +# specific users in user database by giving /./ in user's home directory +# (eg. /home/./user chroots into /home). Note that usually there is no real +# need to do chrooting, Dovecot doesn't allow users to access files outside +# their mail directory anyway. If your home directories are prefixed with +# the chroot directory, append "/." to mail_chroot. <doc/wiki/Chrooting.txt> +#mail_chroot = + +# UNIX socket path to master authentication server to find users. +# This is used by imap (for shared users) and lda. +#auth_socket_path = /var/run/dovecot/auth-userdb + +# Directory where to look up mail plugins. +#mail_plugin_dir = /usr/lib/dovecot + +# Space separated list of plugins to load for all services. Plugins specific to +# IMAP, LDA, etc. are added to this list in their own .conf files. +#mail_plugins = + +## +## Mailbox handling optimizations +## + +# Mailbox list indexes can be used to optimize IMAP STATUS commands. They are +# also required for IMAP NOTIFY extension to be enabled. +#mailbox_list_index = yes + +# Trust mailbox list index to be up-to-date. This reduces disk I/O at the cost +# of potentially returning out-of-date results after e.g. server crashes. +# The results will be automatically fixed once the folders are opened. +#mailbox_list_index_very_dirty_syncs = yes + +# Should INBOX be kept up-to-date in the mailbox list index? By default it's +# not, because most of the mailbox accesses will open INBOX anyway. +#mailbox_list_index_include_inbox = no + +# The minimum number of mails in a mailbox before updates are done to cache +# file. This allows optimizing Dovecot's behavior to do less disk writes at +# the cost of more disk reads. +#mail_cache_min_mail_count = 0 + +# When IDLE command is running, mailbox is checked once in a while to see if +# there are any new mails or other changes. This setting defines the minimum +# time to wait between those checks. Dovecot can also use inotify and +# kqueue to find out immediately when changes occur. +#mailbox_idle_check_interval = 30 secs + +# Save mails with CR+LF instead of plain LF. This makes sending those mails +# take less CPU, especially with sendfile() syscall with Linux and FreeBSD. +# But it also creates a bit more disk I/O which may just make it slower. +# Also note that if other software reads the mboxes/maildirs, they may handle +# the extra CRs wrong and cause problems. +#mail_save_crlf = no + +# Max number of mails to keep open and prefetch to memory. This only works with +# some mailbox formats and/or operating systems. +#mail_prefetch_count = 0 + +# How often to scan for stale temporary files and delete them (0 = never). +# These should exist only after Dovecot dies in the middle of saving mails. +#mail_temp_scan_interval = 1w + +# How many slow mail accesses sorting can perform before it returns failure. +# With IMAP the reply is: NO [LIMIT] Requested sort would have taken too long. +# The untagged SORT reply is still returned, but it's likely not correct. +#mail_sort_max_read_count = 0 + +protocol !indexer-worker { + # If folder vsize calculation requires opening more than this many mails from + # disk (i.e. mail sizes aren't in cache already), return failure and finish + # the calculation via indexer process. Disabled by default. This setting must + # be 0 for indexer-worker processes. + #mail_vsize_bg_after_count = 0 +} + +## +## Maildir-specific settings +## + +# By default LIST command returns all entries in maildir beginning with a dot. +# Enabling this option makes Dovecot return only entries which are directories. +# This is done by stat()ing each entry, so it causes more disk I/O. +# (For systems setting struct dirent->d_type, this check is free and it's +# done always regardless of this setting) +#maildir_stat_dirs = no + +# When copying a message, do it with hard links whenever possible. This makes +# the performance much better, and it's unlikely to have any side effects. +#maildir_copy_with_hardlinks = yes + +# Assume Dovecot is the only MUA accessing Maildir: Scan cur/ directory only +# when its mtime changes unexpectedly or when we can't find the mail otherwise. +#maildir_very_dirty_syncs = no + +# If enabled, Dovecot doesn't use the S=<size> in the Maildir filenames for +# getting the mail's physical size, except when recalculating Maildir++ quota. +# This can be useful in systems where a lot of the Maildir filenames have a +# broken size. The performance hit for enabling this is very small. +#maildir_broken_filename_sizes = no + +# Always move mails from new/ directory to cur/, even when the \Recent flags +# aren't being reset. +#maildir_empty_new = no + +## +## mbox-specific settings +## + +# Which locking methods to use for locking mbox. There are four available: +# dotlock: Create <mailbox>.lock file. This is the oldest and most NFS-safe +# solution. If you want to use /var/mail/ like directory, the users +# will need write access to that directory. +# dotlock_try: Same as dotlock, but if it fails because of permissions or +# because there isn't enough disk space, just skip it. +# fcntl : Use this if possible. Works with NFS too if lockd is used. +# flock : May not exist in all systems. Doesn't work with NFS. +# lockf : May not exist in all systems. Doesn't work with NFS. +# +# You can use multiple locking methods; if you do the order they're declared +# in is important to avoid deadlocks if other MTAs/MUAs are using multiple +# locking methods as well. Some operating systems don't allow using some of +# them simultaneously. +#mbox_read_locks = fcntl +#mbox_write_locks = dotlock fcntl + +# Maximum time to wait for lock (all of them) before aborting. +#mbox_lock_timeout = 5 mins + +# If dotlock exists but the mailbox isn't modified in any way, override the +# lock file after this much time. +#mbox_dotlock_change_timeout = 2 mins + +# When mbox changes unexpectedly we have to fully read it to find out what +# changed. If the mbox is large this can take a long time. Since the change +# is usually just a newly appended mail, it'd be faster to simply read the +# new mails. If this setting is enabled, Dovecot does this but still safely +# fallbacks to re-reading the whole mbox file whenever something in mbox isn't +# how it's expected to be. The only real downside to this setting is that if +# some other MUA changes message flags, Dovecot doesn't notice it immediately. +# Note that a full sync is done with SELECT, EXAMINE, EXPUNGE and CHECK +# commands. +#mbox_dirty_syncs = yes + +# Like mbox_dirty_syncs, but don't do full syncs even with SELECT, EXAMINE, +# EXPUNGE or CHECK commands. If this is set, mbox_dirty_syncs is ignored. +#mbox_very_dirty_syncs = no + +# Delay writing mbox headers until doing a full write sync (EXPUNGE and CHECK +# commands and when closing the mailbox). This is especially useful for POP3 +# where clients often delete all mails. The downside is that our changes +# aren't immediately visible to other MUAs. +#mbox_lazy_writes = yes + +# If mbox size is smaller than this (e.g. 100k), don't write index files. +# If an index file already exists it's still read, just not updated. +#mbox_min_index_size = 0 + +# Mail header selection algorithm to use for MD5 POP3 UIDLs when +# pop3_uidl_format=%m. For backwards compatibility we use apop3d inspired +# algorithm, but it fails if the first Received: header isn't unique in all +# mails. An alternative algorithm is "all" that selects all headers. +#mbox_md5 = apop3d + +## +## mdbox-specific settings +## + +# Maximum dbox file size until it's rotated. +#mdbox_rotate_size = 10M + +# Maximum dbox file age until it's rotated. Typically in days. Day begins +# from midnight, so 1d = today, 2d = yesterday, etc. 0 = check disabled. +#mdbox_rotate_interval = 0 + +# When creating new mdbox files, immediately preallocate their size to +# mdbox_rotate_size. This setting currently works only in Linux with some +# filesystems (ext4, xfs). +#mdbox_preallocate_space = no + +## +## Mail attachments +## + +# sdbox and mdbox support saving mail attachments to external files, which +# also allows single instance storage for them. Other backends don't support +# this for now. + +# Directory root where to store mail attachments. Disabled, if empty. +#mail_attachment_dir = + +# Attachments smaller than this aren't saved externally. It's also possible to +# write a plugin to disable saving specific attachments externally. +#mail_attachment_min_size = 128k + +# Filesystem backend to use for saving attachments: +# posix : No SiS done by Dovecot (but this might help FS's own deduplication) +# sis posix : SiS with immediate byte-by-byte comparison during saving +# sis-queue posix : SiS with delayed comparison and deduplication +#mail_attachment_fs = sis posix + +# Hash format to use in attachment filenames. You can add any text and +# variables: %{md4}, %{md5}, %{sha1}, %{sha256}, %{sha512}, %{size}. +# Variables can be truncated, e.g. %{sha256:80} returns only first 80 bits +#mail_attachment_hash = %{sha1} + +# Settings to control adding $HasAttachment or $HasNoAttachment keywords. +# By default, all MIME parts with Content-Disposition=attachment, or inlines +# with filename parameter are consired attachments. +# add-flags - Add the keywords when saving new mails or when fetching can +# do it efficiently. +# content-type=type or !type - Include/exclude content type. Excluding will +# never consider the matched MIME part as attachment. Including will only +# negate an exclusion (e.g. content-type=!foo/* content-type=foo/bar). +# exclude-inlined - Exclude any Content-Disposition=inline MIME part. +#mail_attachment_detection_options = diff --git a/doc/example-config/conf.d/10-master.conf b/doc/example-config/conf.d/10-master.conf new file mode 100644 index 0000000..64fa0f2 --- /dev/null +++ b/doc/example-config/conf.d/10-master.conf @@ -0,0 +1,133 @@ +#default_process_limit = 100 +#default_client_limit = 1000 + +# Default VSZ (virtual memory size) limit for service processes. This is mainly +# intended to catch and kill processes that leak memory before they eat up +# everything. +#default_vsz_limit = 256M + +# Login user is internally used by login processes. This is the most untrusted +# user in Dovecot system. It shouldn't have access to anything at all. +#default_login_user = dovenull + +# Internal user is used by unprivileged processes. It should be separate from +# login user, so that login processes can't disturb other processes. +#default_internal_user = dovecot + +service imap-login { + inet_listener imap { + #port = 143 + } + inet_listener imaps { + #port = 993 + #ssl = yes + } + + # Number of connections to handle before starting a new process. Typically + # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0 + # is faster. <doc/wiki/LoginProcess.txt> + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = $default_vsz_limit +} + +service pop3-login { + inet_listener pop3 { + #port = 110 + } + inet_listener pop3s { + #port = 995 + #ssl = yes + } +} + +service submission-login { + inet_listener submission { + #port = 587 + } + inet_listener submissions { + #port = 465 + } +} + +service lmtp { + unix_listener lmtp { + #mode = 0666 + } + + # Create inet listener only if you can't use the above UNIX socket + #inet_listener lmtp { + # Avoid making LMTP visible for the entire internet + #address = + #port = + #} +} + +service imap { + # Most of the memory goes to mmap()ing files. You may need to increase this + # limit if you have huge mailboxes. + #vsz_limit = $default_vsz_limit + + # Max. number of IMAP processes (connections) + #process_limit = 1024 +} + +service pop3 { + # Max. number of POP3 processes (connections) + #process_limit = 1024 +} + +service submission { + # Max. number of SMTP Submission processes (connections) + #process_limit = 1024 +} + +service auth { + # auth_socket_path points to this userdb socket by default. It's typically + # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have + # full permissions to this socket are able to get a list of all usernames and + # get the results of everyone's userdb lookups. + # + # The default 0666 mode allows anyone to connect to the socket, but the + # userdb lookups will succeed only if the userdb returns an "uid" field that + # matches the caller process's UID. Also if caller's uid or gid matches the + # socket's uid or gid the lookup succeeds. Anything else causes a failure. + # + # To give the caller full permissions to lookup all users, set the mode to + # something else than 0666 and Dovecot lets the kernel enforce the + # permissions (e.g. 0777 allows everyone full permissions). + unix_listener auth-userdb { + #mode = 0666 + #user = + #group = + } + + # Postfix smtp-auth + #unix_listener /var/spool/postfix/private/auth { + # mode = 0666 + #} + + # Auth process is run as this user. + #user = $default_internal_user +} + +service auth-worker { + # Auth worker process is run as root by default, so that it can access + # /etc/shadow. If this isn't necessary, the user should be changed to + # $default_internal_user. + #user = root +} + +service dict { + # If dict proxy is used, mail processes should have access to its socket. + # For example: mode=0660, group=vmail and global mail_access_groups=vmail + unix_listener dict { + #mode = 0600 + #user = + #group = + } +} diff --git a/doc/example-config/conf.d/10-metrics.conf b/doc/example-config/conf.d/10-metrics.conf new file mode 100644 index 0000000..f7a758f --- /dev/null +++ b/doc/example-config/conf.d/10-metrics.conf @@ -0,0 +1,74 @@ +## +## Statistics and metrics +## + +# Dovecot supports gathering statistics from events. +# Currently there are no statistics logged by default, and therefore they must +# be explicitly added using the metric configuration blocks. +# +# Unlike old stats, the new statistics do not require any plugins loaded. +# +# See https://doc.dovecot.org/configuration_manual/stats/ for more details. + +## +## Example metrics +## + +#metric auth_success { +# filter = event=auth_request_finished AND success=yes +#} +# +#metric auth_failures { +# filter = event=auth_request_finished AND NOT success=yes +#} +# +#metric imap_command { +# filter = event=imap_command_finished +# group_by = cmd_name tagged_reply_state +#} +# +#metric smtp_command { +# filter = event=smtp_server_command_finished +# group_by = cmd_name status_code duration:exponential:1:5:10 +#} +# +#metric mail_delivery { +# filter = event=mail_delivery_finished +# group_by = duration:exponential:1:5:10 +#} + +## +## Prometheus +## + +# To allow access to statistics with Prometheus, enable http listener +# on stats process. Stats will be available on /metrics path. +# +# See https://doc.dovecot.org/configuration_manual/stats/openmetrics/ for more +# details. + +#service stats { +# inet_listener http { +# port = 9900 +# } +#} + +## +## Event exporting +## + +# You can also export individual events. +# +# See https://doc.dovecot.org/configuration_manual/event_export/ for more +# details. + +#event_exporter log { +# format = json +# format_args = time-rfc3339 +# transport = log +#} +# +#metric imap_commands { +# exporter = log +# filter = event=imap_command_finished +#} diff --git a/doc/example-config/conf.d/10-ssl.conf b/doc/example-config/conf.d/10-ssl.conf new file mode 100644 index 0000000..ad84766 --- /dev/null +++ b/doc/example-config/conf.d/10-ssl.conf @@ -0,0 +1,82 @@ +## +## SSL settings +## + +# SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt> +#ssl = yes + +# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before +# dropping root privileges, so keep the key file unreadable by anyone but +# root. Included doc/mkcert.sh can be used to easily generate self-signed +# certificate, just make sure to update the domains in dovecot-openssl.cnf +ssl_cert = </etc/ssl/certs/dovecot.pem +ssl_key = </etc/ssl/private/dovecot.pem + +# If key file is password protected, give the password here. Alternatively +# give it when starting dovecot with -p parameter. Since this file is often +# world-readable, you may want to place this setting instead to a different +# root owned 0600 file by using ssl_key_password = <path. +#ssl_key_password = + +# PEM encoded trusted certificate authority. Set this only if you intend to use +# ssl_verify_client_cert=yes. The file should contain the CA certificate(s) +# followed by the matching CRL(s). (e.g. ssl_ca = </etc/ssl/certs/ca.pem) +#ssl_ca = + +# Require that CRL check succeeds for client certificates. +#ssl_require_crl = yes + +# Directory and/or file for trusted SSL CA certificates. These are used only +# when Dovecot needs to act as an SSL client (e.g. imapc backend or +# submission service). The directory is usually /etc/ssl/certs in +# Debian-based systems and the file is /etc/pki/tls/cert.pem in +# RedHat-based systems. Note that ssl_client_ca_file isn't recommended with +# large CA bundles, because it leads to excessive memory usage. +#ssl_client_ca_dir = +#ssl_client_ca_file = + +# Require valid cert when connecting to a remote server +#ssl_client_require_valid_cert = yes + +# Request client to send a certificate. If you also want to require it, set +# auth_ssl_require_client_cert=yes in auth section. +#ssl_verify_client_cert = no + +# Which field from certificate to use for username. commonName and +# x500UniqueIdentifier are the usual choices. You'll also need to set +# auth_ssl_username_from_cert=yes. +#ssl_cert_username_field = commonName + +# SSL DH parameters +# Generate new params with `openssl dhparam -out /etc/dovecot/dh.pem 4096` +# Or migrate from old ssl-parameters.dat file with the command dovecot +# gives on startup when ssl_dh is unset. +#ssl_dh = </etc/dovecot/dh.pem + +# Minimum SSL protocol version to use. Potentially recognized values are SSLv3, +# TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3, depending on the OpenSSL version used. +# +# Dovecot also recognizes values ANY and LATEST. ANY matches with any protocol +# version, and LATEST matches with the latest version supported by library. +#ssl_min_protocol = TLSv1.2 + +# SSL ciphers to use, the default is: +#ssl_cipher_list = ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH +# To disable non-EC DH, use: +#ssl_cipher_list = ALL:!DH:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH + +# Colon separated list of elliptic curves to use. Empty value (the default) +# means use the defaults from the SSL library. P-521:P-384:P-256 would be an +# example of a valid value. +#ssl_curve_list = + +# Prefer the server's order of ciphers over client's. +#ssl_prefer_server_ciphers = no + +# SSL crypto device to use, for valid values run "openssl engine" +#ssl_crypto_device = + +# SSL extra options. Currently supported options are: +# compression - Enable compression. +# no_ticket - Disable SSL session tickets. +#ssl_options = diff --git a/doc/example-config/conf.d/15-lda.conf b/doc/example-config/conf.d/15-lda.conf new file mode 100644 index 0000000..e1d6fcd --- /dev/null +++ b/doc/example-config/conf.d/15-lda.conf @@ -0,0 +1,48 @@ +## +## LDA specific settings (also used by LMTP) +## + +# Address to use when sending rejection mails. +# Default is postmaster@%d. %d expands to recipient domain. +#postmaster_address = + +# Hostname to use in various parts of sent mails (e.g. in Message-Id) and +# in LMTP replies. Default is the system's real hostname@domain. +#hostname = + +# If user is over quota, return with temporary failure instead of +# bouncing the mail. +#quota_full_tempfail = no + +# Binary to use for sending mails. +#sendmail_path = /usr/sbin/sendmail + +# If non-empty, send mails via this SMTP host[:port] instead of sendmail. +#submission_host = + +# Subject: header to use for rejection mails. You can use the same variables +# as for rejection_reason below. +#rejection_subject = Rejected: %s + +# Human readable error message for rejection mails. You can use variables: +# %n = CRLF, %r = reason, %s = original subject, %t = recipient +#rejection_reason = Your message to <%t> was automatically rejected:%n%r + +# Delimiter character between local-part and detail in email address. +#recipient_delimiter = + + +# Header where the original recipient address (SMTP's RCPT TO: address) is taken +# from if not available elsewhere. With dovecot-lda -a parameter overrides this. +# A commonly used header for this is X-Original-To. +#lda_original_recipient_header = + +# Should saving a mail to a nonexistent mailbox automatically create it? +#lda_mailbox_autocreate = no + +# Should automatically created mailboxes be also automatically subscribed? +#lda_mailbox_autosubscribe = no + +protocol lda { + # Space separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins +} diff --git a/doc/example-config/conf.d/15-mailboxes.conf b/doc/example-config/conf.d/15-mailboxes.conf new file mode 100644 index 0000000..71076d4 --- /dev/null +++ b/doc/example-config/conf.d/15-mailboxes.conf @@ -0,0 +1,86 @@ +## +## Mailbox definitions +## + +# Each mailbox is specified in a separate mailbox section. The section name +# specifies the mailbox name. If it has spaces, you can put the name +# "in quotes". These sections can contain the following mailbox settings: +# +# auto: +# Indicates whether the mailbox with this name is automatically created +# implicitly when it is first accessed. The user can also be automatically +# subscribed to the mailbox after creation. The following values are +# defined for this setting: +# +# no - Never created automatically. +# create - Automatically created, but no automatic subscription. +# subscribe - Automatically created and subscribed. +# +# special_use: +# A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the +# mailbox. There are no validity checks, so you could specify anything +# you want in here, but it's not a good idea to use flags other than the +# standard ones specified in the RFC: +# +# \All - This (virtual) mailbox presents all messages in the +# user's message store. +# \Archive - This mailbox is used to archive messages. +# \Drafts - This mailbox is used to hold draft messages. +# \Flagged - This (virtual) mailbox presents all messages in the +# user's message store marked with the IMAP \Flagged flag. +# \Important - This (virtual) mailbox presents all messages in the +# user's message store deemed important to user. +# \Junk - This mailbox is where messages deemed to be junk mail +# are held. +# \Sent - This mailbox is used to hold copies of messages that +# have been sent. +# \Trash - This mailbox is used to hold messages that have been +# deleted. +# +# comment: +# Defines a default comment or note associated with the mailbox. This +# value is accessible through the IMAP METADATA mailbox entries +# "/shared/comment" and "/private/comment". Users with sufficient +# privileges can override the default value for entries with a custom +# value. + +# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf. +namespace inbox { + # These mailboxes are widely used and could perhaps be created automatically: + mailbox Drafts { + special_use = \Drafts + } + mailbox Junk { + special_use = \Junk + } + mailbox Trash { + special_use = \Trash + } + + # For \Sent mailboxes there are two widely used names. We'll mark both of + # them as \Sent. User typically deletes one of them if duplicates are created. + mailbox Sent { + special_use = \Sent + } + mailbox "Sent Messages" { + special_use = \Sent + } + + # If you have a virtual "All messages" mailbox: + #mailbox virtual/All { + # special_use = \All + # comment = All my messages + #} + + # If you have a virtual "Flagged" mailbox: + #mailbox virtual/Flagged { + # special_use = \Flagged + # comment = All my flagged messages + #} + + # If you have a virtual "Important" mailbox: + #mailbox virtual/Important { + # special_use = \Important + # comment = All my important messages + #} +} diff --git a/doc/example-config/conf.d/20-imap.conf b/doc/example-config/conf.d/20-imap.conf new file mode 100644 index 0000000..e60b0cd --- /dev/null +++ b/doc/example-config/conf.d/20-imap.conf @@ -0,0 +1,99 @@ +## +## IMAP specific settings +## + +# If nothing happens for this long while client is IDLEing, move the connection +# to imap-hibernate process and close the old imap process. This saves memory, +# because connections use very little memory in imap-hibernate process. The +# downside is that recreating the imap process back uses some resources. +#imap_hibernate_timeout = 0 + +# Maximum IMAP command line length. Some clients generate very long command +# lines with huge mailboxes, so you may need to raise this if you get +# "Too long argument" or "IMAP command line too large" errors often. +#imap_max_line_length = 64k + +# IMAP logout format string: +# %i - total number of bytes read from client +# %o - total number of bytes sent to client +# %{fetch_hdr_count} - Number of mails with mail header data sent to client +# %{fetch_hdr_bytes} - Number of bytes with mail header data sent to client +# %{fetch_body_count} - Number of mails with mail body data sent to client +# %{fetch_body_bytes} - Number of bytes with mail body data sent to client +# %{deleted} - Number of mails where client added \Deleted flag +# %{expunged} - Number of mails that client expunged, which does not +# include automatically expunged mails +# %{autoexpunged} - Number of mails that were automatically expunged after +# client disconnected +# %{trashed} - Number of mails that client copied/moved to the +# special_use=\Trash mailbox. +# %{appended} - Number of mails saved during the session +#imap_logout_format = in=%i out=%o deleted=%{deleted} expunged=%{expunged} \ +# trashed=%{trashed} hdr_count=%{fetch_hdr_count} \ +# hdr_bytes=%{fetch_hdr_bytes} body_count=%{fetch_body_count} \ +# body_bytes=%{fetch_body_bytes} + +# Override the IMAP CAPABILITY response. If the value begins with '+', +# add the given capabilities on top of the defaults (e.g. +XFOO XBAR). +#imap_capability = + +# How long to wait between "OK Still here" notifications when client is +# IDLEing. +#imap_idle_notify_interval = 2 mins + +# ID field names and values to send to clients. Using * as the value makes +# Dovecot use the default value. The following fields have default values +# currently: name, version, os, os-version, support-url, support-email, +# revision. +#imap_id_send = + +# ID fields sent by client to log. * means everything. +#imap_id_log = + +# Workarounds for various client bugs: +# delay-newmail: +# Send EXISTS/RECENT new mail notifications only when replying to NOOP +# and CHECK commands. Some clients ignore them otherwise, for example OSX +# Mail (<v2.1). Outlook Express breaks more badly though, without this it +# may show user "Message no longer in server" errors. Note that OE6 still +# breaks even with this workaround if synchronization is set to +# "Headers Only". +# tb-extra-mailbox-sep: +# Thunderbird gets somehow confused with LAYOUT=fs (mbox and dbox) and +# adds extra '/' suffixes to mailbox names. This option causes Dovecot to +# ignore the extra '/' instead of treating it as invalid mailbox name. +# tb-lsub-flags: +# Show \Noselect flags for LSUB replies with LAYOUT=fs (e.g. mbox). +# This makes Thunderbird realize they aren't selectable and show them +# greyed out, instead of only later giving "not selectable" popup error. +# +# The list is space-separated. +#imap_client_workarounds = + +# Host allowed in URLAUTH URLs sent by client. "*" allows all. +#imap_urlauth_host = + +# Enable IMAP LITERAL- extension (replaces LITERAL+) +#imap_literal_minus = no + +# What happens when FETCH fails due to some internal error: +# disconnect-immediately: +# The FETCH is aborted immediately and the IMAP client is disconnected. +# disconnect-after: +# The FETCH runs for all the requested mails returning as much data as +# possible. The client is finally disconnected without a tagged reply. +# no-after: +# Same as disconnect-after, but tagged NO reply is sent instead of +# disconnecting the client. If the client attempts to FETCH the same failed +# mail more than once, the client is disconnected. This is to avoid clients +# from going into infinite loops trying to FETCH a broken mail. +#imap_fetch_failure = disconnect-immediately + +protocol imap { + # Space separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins + + # Maximum number of IMAP connections allowed for a user from each IP address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 +} diff --git a/doc/example-config/conf.d/20-lmtp.conf b/doc/example-config/conf.d/20-lmtp.conf new file mode 100644 index 0000000..0684e81 --- /dev/null +++ b/doc/example-config/conf.d/20-lmtp.conf @@ -0,0 +1,40 @@ +## +## LMTP specific settings +## + +# Support proxying to other LMTP/SMTP servers by performing passdb lookups. +#lmtp_proxy = no + +# When recipient address includes the detail (e.g. user+detail), try to save +# the mail to the detail mailbox. See also recipient_delimiter and +# lda_mailbox_autocreate settings. +#lmtp_save_to_detail_mailbox = no + +# Verify quota before replying to RCPT TO. This adds a small overhead. +#lmtp_rcpt_check_quota = no + +# Add "Received:" header to mails delivered. +#lmtp_add_received_header = yes + +# Which recipient address to use for Delivered-To: header and Received: +# header. The default is "final", which is the same as the one given to +# RCPT TO command. "original" uses the address given in RCPT TO's ORCPT +# parameter, "none" uses nothing. Note that "none" is currently always used +# when a mail has multiple recipients. +#lmtp_hdr_delivery_address = final + +# Workarounds for various client bugs: +# whitespace-before-path: +# Allow one or more spaces or tabs between `MAIL FROM:' and path and between +# `RCPT TO:' and path. +# mailbox-for-path: +# Allow using bare Mailbox syntax (i.e., without <...>) instead of full path +# syntax. +# +# The list is space-separated. +#lmtp_client_workarounds = + +protocol lmtp { + # Space separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins +} diff --git a/doc/example-config/conf.d/20-pop3.conf b/doc/example-config/conf.d/20-pop3.conf new file mode 100644 index 0000000..7b310ea --- /dev/null +++ b/doc/example-config/conf.d/20-pop3.conf @@ -0,0 +1,99 @@ +## +## POP3 specific settings +## + +# Don't try to set mails non-recent or seen with POP3 sessions. This is +# mostly intended to reduce disk I/O. With maildir it doesn't move files +# from new/ to cur/, with mbox it doesn't write Status-header. +#pop3_no_flag_updates = no + +# Support LAST command which exists in old POP3 specs, but has been removed +# from new ones. Some clients still wish to use this though. Enabling this +# makes RSET command clear all \Seen flags from messages. +#pop3_enable_last = no + +# If mail has X-UIDL header, use it as the mail's UIDL. +#pop3_reuse_xuidl = no + +# Allow only one POP3 session to run simultaneously for the same user. +#pop3_lock_session = no + +# POP3 requires message sizes to be listed as if they had CR+LF linefeeds. +# Many POP3 servers violate this by returning the sizes with LF linefeeds, +# because it's faster to get. When this setting is enabled, Dovecot still +# tries to do the right thing first, but if that requires opening the +# message, it fallbacks to the easier (but incorrect) size. +#pop3_fast_size_lookups = no + +# POP3 UIDL (unique mail identifier) format to use. You can use following +# variables, along with the variable modifiers described in +# doc/wiki/Variables.txt (e.g. %Uf for the filename in uppercase) +# +# %v - Mailbox's IMAP UIDVALIDITY +# %u - Mail's IMAP UID +# %m - MD5 sum of the mailbox headers in hex (mbox only) +# %f - filename (maildir only) +# %g - Mail's GUID +# +# If you want UIDL compatibility with other POP3 servers, use: +# UW's ipop3d : %08Xv%08Xu +# Courier : %f or %v-%u (both might be used simultaneously) +# Cyrus (<= 2.1.3) : %u +# Cyrus (>= 2.1.4) : %v.%u +# Dovecot v0.99.x : %v.%u +# tpop3d : %Mf +# +# Note that Outlook 2003 seems to have problems with %v.%u format which was +# Dovecot's default, so if you're building a new server it would be a good +# idea to change this. %08Xu%08Xv should be pretty fail-safe. +# +#pop3_uidl_format = %08Xu%08Xv + +# Permanently save UIDLs sent to POP3 clients, so pop3_uidl_format changes +# won't change those UIDLs. Currently this works only with Maildir. +#pop3_save_uidl = no + +# What to do about duplicate UIDLs if they exist? +# allow: Show duplicates to clients. +# rename: Append a temporary -2, -3, etc. counter after the UIDL. +#pop3_uidl_duplicates = allow + +# This option changes POP3 behavior so that it's not possible to actually +# delete mails via POP3, only hide them from future POP3 sessions. The mails +# will still be counted towards user's quota until actually deleted via IMAP. +# Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword). +# Make sure you can legally archive mails before enabling this setting. +#pop3_deleted_flag = + +# POP3 logout format string: +# %i - total number of bytes read from client +# %o - total number of bytes sent to client +# %t - number of TOP commands +# %p - number of bytes sent to client as a result of TOP command +# %r - number of RETR commands +# %b - number of bytes sent to client as a result of RETR command +# %d - number of deleted messages +# %{deleted_bytes} - number of bytes in deleted messages +# %m - number of messages (before deletion) +# %s - mailbox size in bytes (before deletion) +# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly +#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s + +# Workarounds for various client bugs: +# outlook-no-nuls: +# Outlook and Outlook Express hang if mails contain NUL characters. +# This setting replaces them with 0x80 character. +# oe-ns-eoh: +# Outlook Express and Netscape Mail breaks if end of headers-line is +# missing. This option simply sends it if it's missing. +# The list is space-separated. +#pop3_client_workarounds = + +protocol pop3 { + # Space separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins + + # Maximum number of POP3 connections allowed for a user from each IP address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 +} diff --git a/doc/example-config/conf.d/20-submission.conf b/doc/example-config/conf.d/20-submission.conf new file mode 100644 index 0000000..390089c --- /dev/null +++ b/doc/example-config/conf.d/20-submission.conf @@ -0,0 +1,112 @@ +## +## Settings specific to SMTP Submission +## + +# SMTP Submission logout format string: +# %i - total number of bytes read from client +# %o - total number of bytes sent to client +# %{command_count} - Number of commands received from client +# %{reply_count} - Number of replies sent to client +# %{session} - Session ID of the login session +# %{transaction_id} - ID of the current transaction, if any +#submission_logout_format = in=%i out=%o + +# Host name reported by the SMTP service, for example to the client in the +# initial greeting and to the relay server in the HELO/EHLO command. +# Default is the system's real hostname@domain. +#hostname = + +# Maximum size of messages accepted for relay. This announced in the SIZE +# capability. If not configured, this is either determined from the relay +# server or left unlimited if no limit is known (relay will reply with error +# if some unknown limit exists there, which is duly passed to our client). +#submission_max_mail_size = + +# Maximum number of recipients accepted per connection (default: unlimited) +#submission_max_recipients = + +# Workarounds for various client bugs: +# whitespace-before-path: +# Allow one or more spaces or tabs between `MAIL FROM:' and path and between +# `RCPT TO:' and path. +# mailbox-for-path: +# Allow using bare Mailbox syntax (i.e., without <...>) instead of full path +# syntax. +# +# The list is space-separated. +#submission_client_workarounds = + +# Relay server configuration: +# +# The Dovecot SMTP submission service directly proxies the mail transaction +# to the SMTP relay configured here. + +# Host name for the relay server (required) +#submission_relay_host = + +# Port for the relay server +#submission_relay_port = 25 + +# Is the relay server trusted? This determines whether we try to send +# (Postfix-specific) XCLIENT data to the relay server +#submission_relay_trusted = no + +# Authentication data for the relay server if authentication is required +#submission_relay_user = +#submission_relay_master_user = +#submission_relay_password = + +# SSL configuration for connection to relay server +# +# submission_relay_ssl: +# Indicates whether SSL is used for the connection to the relay server. The +# following values are defined for this setting: +# +# no - No SSL is used +# smtps - An SMTPS connection (immediate SSL) is used +# starttls - The STARTTLS command is used to establish SSL layer +#submission_relay_ssl = no + +# submission_relay_ssl_verify: +# Configures whether the SSL certificate of the relay server is to be +# verified. +#submission_relay_ssl_verify = yes + +# Write protocol logs for relay connection to this directory for debugging +#submission_relay_rawlog_dir = + +# BURL is configured implicitly by IMAP URLAUTH + +# Part of the SMTP capabilities that the submission service can offer to the +# client (as listed in the EHLO reply) depend on those capabilities also being +# provided by the relay server. These capabilities currently are: +# +# - 8BITMIME +# - BINARYMIME +# - DSN +# - VRFY (always returns 252 without support) +# +# By default, the submission service first connects to the relay server to +# determine the support for such capabilities before sending the initial EHLO +# reply to the client. If the list of capabilities returned by the relay server +# is somehow unreliable or it is undesirable to start the connection to the +# relay server before the first mail transaction is started, the backend +# capabilities can be configured explicitly using the +# submission_backend_capabilities setting. This is a space-separated list of +# SMTP capability names. This setting is only relevant for capabilities that +# depend on support from the relay server: including (or omitting) capabilities +# that are not listed above has no effect. When this setting is explicitly set +# to the empty string, none of the capabilities is enabled. To achieve the +# default behavior, this setting must be left unconfigured. +#submission_backend_capabilities = + +protocol submission { + # Space-separated list of plugins to load (default is global mail_plugins). + #mail_plugins = $mail_plugins + + # Maximum number of SMTP submission connections allowed for a user from + # each IP address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 +} + diff --git a/doc/example-config/conf.d/90-acl.conf b/doc/example-config/conf.d/90-acl.conf new file mode 100644 index 0000000..f0c0e7a --- /dev/null +++ b/doc/example-config/conf.d/90-acl.conf @@ -0,0 +1,19 @@ +## +## Mailbox access control lists. +## + +# vfile backend reads ACLs from "dovecot-acl" file from mail directory. +# You can also optionally give a global ACL directory path where ACLs are +# applied to all users' mailboxes. The global ACL directory contains +# one file for each mailbox, eg. INBOX or sub.mailbox. cache_secs parameter +# specifies how many seconds to wait between stat()ing dovecot-acl file +# to see if it changed. +plugin { + #acl = vfile:/etc/dovecot/global-acls:cache_secs=300 +} + +# To let users LIST mailboxes shared by other users, Dovecot needs a +# shared mailbox dictionary. For example: +plugin { + #acl_shared_dict = file:/var/lib/dovecot/shared-mailboxes +} diff --git a/doc/example-config/conf.d/90-plugin.conf b/doc/example-config/conf.d/90-plugin.conf new file mode 100644 index 0000000..8c8fccf --- /dev/null +++ b/doc/example-config/conf.d/90-plugin.conf @@ -0,0 +1,11 @@ +## +## Plugin settings +## + +# All wanted plugins must be listed in mail_plugins setting before any of the +# settings take effect. See <doc/wiki/Plugins.txt> for list of plugins and +# their configuration. Note that %variable expansion is done for all values. + +plugin { + #setting_name = value +} diff --git a/doc/example-config/conf.d/90-quota.conf b/doc/example-config/conf.d/90-quota.conf new file mode 100644 index 0000000..3308c05 --- /dev/null +++ b/doc/example-config/conf.d/90-quota.conf @@ -0,0 +1,83 @@ +## +## Quota configuration. +## + +# Note that you also have to enable quota plugin in mail_plugins setting. +# <doc/wiki/Quota.txt> + +## +## Quota limits +## + +# Quota limits are set using "quota_rule" parameters. To get per-user quota +# limits, you can set/override them by returning "quota_rule" extra field +# from userdb. It's also possible to give mailbox-specific limits, for example +# to give additional 100 MB when saving to Trash: + +plugin { + #quota_rule = *:storage=1G + #quota_rule2 = Trash:storage=+100M + + # LDA/LMTP allows saving the last mail to bring user from under quota to + # over quota, if the quota doesn't grow too high. Default is to allow as + # long as quota will stay under 10% above the limit. Also allowed e.g. 10M. + #quota_grace = 10%% + + # Quota plugin can also limit the maximum accepted mail size. + #quota_max_mail_size = 100M +} + +## +## Quota warnings +## + +# You can execute a given command when user exceeds a specified quota limit. +# Each quota root has separate limits. Only the command for the first +# exceeded limit is executed, so put the highest limit first. +# The commands are executed via script service by connecting to the named +# UNIX socket (quota-warning below). +# Note that % needs to be escaped as %%, otherwise "% " expands to empty. + +plugin { + #quota_warning = storage=95%% quota-warning 95 %u + #quota_warning2 = storage=80%% quota-warning 80 %u +} + +# Example quota-warning service. The unix listener's permissions should be +# set in a way that mail processes can connect to it. Below example assumes +# that mail processes run as vmail user. If you use mode=0666, all system users +# can generate quota warnings to anyone. +#service quota-warning { +# executable = script /usr/local/bin/quota-warning.sh +# user = dovecot +# unix_listener quota-warning { +# user = vmail +# } +#} + +## +## Quota backends +## + +# Multiple backends are supported: +# dirsize: Find and sum all the files found from mail directory. +# Extremely SLOW with Maildir. It'll eat your CPU and disk I/O. +# dict: Keep quota stored in dictionary (eg. SQL) +# maildir: Maildir++ quota +# fs: Read-only support for filesystem quota + +plugin { + #quota = dirsize:User quota + #quota = maildir:User quota + #quota = dict:User quota::proxy::quota + #quota = fs:User quota +} + +# Multiple quota roots are also possible, for example this gives each user +# their own 100MB quota and one shared 1GB quota within the domain: +plugin { + #quota = dict:user::proxy::quota + #quota2 = dict:domain:%d:proxy::quota_domain + #quota_rule = *:storage=102400 + #quota2_rule = *:storage=1048576 +} diff --git a/doc/example-config/conf.d/Makefile.am b/doc/example-config/conf.d/Makefile.am new file mode 100644 index 0000000..1950fd5 --- /dev/null +++ b/doc/example-config/conf.d/Makefile.am @@ -0,0 +1,32 @@ +pkgsysconfdir = $(sysconfdir)/dovecot + +exampledir = $(docdir)/example-config/conf.d +example_DATA = \ + auth-checkpassword.conf.ext \ + auth-deny.conf.ext \ + auth-dict.conf.ext \ + auth-ldap.conf.ext \ + auth-master.conf.ext \ + auth-passwdfile.conf.ext \ + auth-sql.conf.ext \ + auth-static.conf.ext \ + auth-system.conf.ext \ + 10-auth.conf \ + 10-director.conf \ + 10-logging.conf \ + 10-mail.conf \ + 10-master.conf \ + 10-metrics.conf \ + 10-ssl.conf \ + 15-lda.conf \ + 15-mailboxes.conf \ + 20-imap.conf \ + 20-lmtp.conf \ + 20-pop3.conf \ + 20-submission.conf \ + 90-acl.conf \ + 90-plugin.conf \ + 90-quota.conf + +EXTRA_DIST = \ + $(example_DATA) diff --git a/doc/example-config/conf.d/Makefile.in b/doc/example-config/conf.d/Makefile.in new file mode 100644 index 0000000..50d0562 --- /dev/null +++ b/doc/example-config/conf.d/Makefile.in @@ -0,0 +1,673 @@ +# 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 = doc/example-config/conf.d +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 $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(exampledir)" +DATA = $(example_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +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@ +pkgsysconfdir = $(sysconfdir)/dovecot +exampledir = $(docdir)/example-config/conf.d +example_DATA = \ + auth-checkpassword.conf.ext \ + auth-deny.conf.ext \ + auth-dict.conf.ext \ + auth-ldap.conf.ext \ + auth-master.conf.ext \ + auth-passwdfile.conf.ext \ + auth-sql.conf.ext \ + auth-static.conf.ext \ + auth-system.conf.ext \ + 10-auth.conf \ + 10-director.conf \ + 10-logging.conf \ + 10-mail.conf \ + 10-master.conf \ + 10-metrics.conf \ + 10-ssl.conf \ + 15-lda.conf \ + 15-mailboxes.conf \ + 20-imap.conf \ + 20-lmtp.conf \ + 20-pop3.conf \ + 20-submission.conf \ + 90-acl.conf \ + 90-plugin.conf \ + 90-quota.conf + +EXTRA_DIST = \ + $(example_DATA) + +all: all-am + +.SUFFIXES: +$(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 doc/example-config/conf.d/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/example-config/conf.d/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-exampleDATA: $(example_DATA) + @$(NORMAL_INSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(exampledir)" || 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_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ + done + +uninstall-exampleDATA: + @$(NORMAL_UNINSTALL) + @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +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 $(DATA) +installdirs: + for dir in "$(DESTDIR)$(exampledir)"; 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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-exampleDATA + +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 Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-exampleDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exampleDATA 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-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-exampleDATA + +.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/doc/example-config/conf.d/auth-checkpassword.conf.ext b/doc/example-config/conf.d/auth-checkpassword.conf.ext new file mode 100644 index 0000000..b2fb13a --- /dev/null +++ b/doc/example-config/conf.d/auth-checkpassword.conf.ext @@ -0,0 +1,21 @@ +# Authentication for checkpassword users. Included from 10-auth.conf. +# +# <doc/wiki/AuthDatabase.CheckPassword.txt> + +passdb { + driver = checkpassword + args = /usr/bin/checkpassword +} + +# passdb lookup should return also userdb info +userdb { + driver = prefetch +} + +# Standard checkpassword doesn't support direct userdb lookups. +# If you need checkpassword userdb, the checkpassword must support +# Dovecot-specific extensions. +#userdb { +# driver = checkpassword +# args = /usr/bin/checkpassword +#} diff --git a/doc/example-config/conf.d/auth-deny.conf.ext b/doc/example-config/conf.d/auth-deny.conf.ext new file mode 100644 index 0000000..ce3f1cf --- /dev/null +++ b/doc/example-config/conf.d/auth-deny.conf.ext @@ -0,0 +1,15 @@ +# Deny access for users. Included from 10-auth.conf. + +# Users can be (temporarily) disabled by adding a passdb with deny=yes. +# If the user is found from that database, authentication will fail. +# The deny passdb should always be specified before others, so it gets +# checked first. + +# Example deny passdb using passwd-file. You can use any passdb though. +passdb { + driver = passwd-file + deny = yes + + # File contains a list of usernames, one per line + args = /etc/dovecot/deny-users +} diff --git a/doc/example-config/conf.d/auth-dict.conf.ext b/doc/example-config/conf.d/auth-dict.conf.ext new file mode 100644 index 0000000..0be4847 --- /dev/null +++ b/doc/example-config/conf.d/auth-dict.conf.ext @@ -0,0 +1,16 @@ +# Authentication via dict backend. Included from 10-auth.conf. +# +# <doc/wiki/AuthDatabase.Dict.txt> + +passdb { + driver = dict + + # Path for dict configuration file, see + # example-config/dovecot-dict-auth.conf.ext + args = /etc/dovecot/dovecot-dict-auth.conf.ext +} + +userdb { + driver = dict + args = /etc/dovecot/dovecot-dict-auth.conf.ext +} diff --git a/doc/example-config/conf.d/auth-ldap.conf.ext b/doc/example-config/conf.d/auth-ldap.conf.ext new file mode 100644 index 0000000..5db32fa --- /dev/null +++ b/doc/example-config/conf.d/auth-ldap.conf.ext @@ -0,0 +1,33 @@ +# Authentication for LDAP users. Included from 10-auth.conf. +# +# <doc/wiki/AuthDatabase.LDAP.txt> + +passdb { + driver = ldap + + # Path for LDAP configuration file, see example-config/dovecot-ldap.conf.ext + args = /etc/dovecot/dovecot-ldap.conf.ext +} + +# "prefetch" user database means that the passdb already provided the +# needed information and there's no need to do a separate userdb lookup. +# <doc/wiki/UserDatabase.Prefetch.txt> +#userdb { +# driver = prefetch +#} + +userdb { + driver = ldap + args = /etc/dovecot/dovecot-ldap.conf.ext + + # Default fields can be used to specify defaults that LDAP may override + #default_fields = home=/home/virtual/%u +} + +# If you don't have any user-specific settings, you can avoid the userdb LDAP +# lookup by using userdb static instead of userdb ldap, for example: +# <doc/wiki/UserDatabase.Static.txt> +#userdb { + #driver = static + #args = uid=vmail gid=vmail home=/var/vmail/%u +#} diff --git a/doc/example-config/conf.d/auth-master.conf.ext b/doc/example-config/conf.d/auth-master.conf.ext new file mode 100644 index 0000000..2cf128f --- /dev/null +++ b/doc/example-config/conf.d/auth-master.conf.ext @@ -0,0 +1,16 @@ +# Authentication for master users. Included from 10-auth.conf. + +# By adding master=yes setting inside a passdb you make the passdb a list +# of "master users", who can log in as anyone else. +# <doc/wiki/Authentication.MasterUsers.txt> + +# Example master user passdb using passwd-file. You can use any passdb though. +passdb { + driver = passwd-file + master = yes + args = /etc/dovecot/master-users + + # Unless you're using PAM, you probably still want the destination user to + # be looked up from passdb that it really exists. pass=yes does that. + pass = yes +} diff --git a/doc/example-config/conf.d/auth-passwdfile.conf.ext b/doc/example-config/conf.d/auth-passwdfile.conf.ext new file mode 100644 index 0000000..c89d28c --- /dev/null +++ b/doc/example-config/conf.d/auth-passwdfile.conf.ext @@ -0,0 +1,20 @@ +# Authentication for passwd-file users. Included from 10-auth.conf. +# +# passwd-like file with specified location. +# <doc/wiki/AuthDatabase.PasswdFile.txt> + +passdb { + driver = passwd-file + args = scheme=CRYPT username_format=%u /etc/dovecot/users +} + +userdb { + driver = passwd-file + args = username_format=%u /etc/dovecot/users + + # Default fields that can be overridden by passwd-file + #default_fields = quota_rule=*:storage=1G + + # Override fields from passwd-file + #override_fields = home=/home/virtual/%u +} diff --git a/doc/example-config/conf.d/auth-sql.conf.ext b/doc/example-config/conf.d/auth-sql.conf.ext new file mode 100644 index 0000000..ccbea86 --- /dev/null +++ b/doc/example-config/conf.d/auth-sql.conf.ext @@ -0,0 +1,30 @@ +# Authentication for SQL users. Included from 10-auth.conf. +# +# <doc/wiki/AuthDatabase.SQL.txt> + +passdb { + driver = sql + + # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext + args = /etc/dovecot/dovecot-sql.conf.ext +} + +# "prefetch" user database means that the passdb already provided the +# needed information and there's no need to do a separate userdb lookup. +# <doc/wiki/UserDatabase.Prefetch.txt> +#userdb { +# driver = prefetch +#} + +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} + +# If you don't have any user-specific settings, you can avoid the user_query +# by using userdb static instead of userdb sql, for example: +# <doc/wiki/UserDatabase.Static.txt> +#userdb { + #driver = static + #args = uid=vmail gid=vmail home=/var/vmail/%u +#} diff --git a/doc/example-config/conf.d/auth-static.conf.ext b/doc/example-config/conf.d/auth-static.conf.ext new file mode 100644 index 0000000..90890c5 --- /dev/null +++ b/doc/example-config/conf.d/auth-static.conf.ext @@ -0,0 +1,24 @@ +# Static passdb. Included from 10-auth.conf. + +# This can be used for situations where Dovecot doesn't need to verify the +# username or the password, or if there is a single password for all users: +# +# - proxy frontend, where the backend verifies the password +# - proxy backend, where the frontend already verified the password +# - authentication with SSL certificates +# - simple testing + +#passdb { +# driver = static +# args = proxy=y host=%1Mu.example.com nopassword=y +#} + +#passdb { +# driver = static +# args = password=test +#} + +#userdb { +# driver = static +# args = uid=vmail gid=vmail home=/home/%u +#} diff --git a/doc/example-config/conf.d/auth-system.conf.ext b/doc/example-config/conf.d/auth-system.conf.ext new file mode 100644 index 0000000..dadb9f7 --- /dev/null +++ b/doc/example-config/conf.d/auth-system.conf.ext @@ -0,0 +1,74 @@ +# Authentication for system users. Included from 10-auth.conf. +# +# <doc/wiki/PasswordDatabase.txt> +# <doc/wiki/UserDatabase.txt> + +# PAM authentication. Preferred nowadays by most systems. +# PAM is typically used with either userdb passwd or userdb static. +# REMEMBER: You'll need /etc/pam.d/dovecot file created for PAM +# authentication to actually work. <doc/wiki/PasswordDatabase.PAM.txt> +passdb { + driver = pam + # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>] + # [cache_key=<key>] [<service name>] + #args = dovecot +} + +# System users (NSS, /etc/passwd, or similar). +# In many systems nowadays this uses Name Service Switch, which is +# configured in /etc/nsswitch.conf. <doc/wiki/AuthDatabase.Passwd.txt> +#passdb { + #driver = passwd + # [blocking=no] + #args = +#} + +# Shadow passwords for system users (NSS, /etc/shadow or similar). +# Deprecated by PAM nowadays. +# <doc/wiki/PasswordDatabase.Shadow.txt> +#passdb { + #driver = shadow + # [blocking=no] + #args = +#} + +# PAM-like authentication for OpenBSD. +# <doc/wiki/PasswordDatabase.BSDAuth.txt> +#passdb { + #driver = bsdauth + # [blocking=no] [cache_key=<key>] + #args = +#} + +## +## User databases +## + +# System users (NSS, /etc/passwd, or similar). In many systems nowadays this +# uses Name Service Switch, which is configured in /etc/nsswitch.conf. +userdb { + # <doc/wiki/AuthDatabase.Passwd.txt> + driver = passwd + # [blocking=no] + #args = + + # Override fields from passwd + #override_fields = home=/home/virtual/%u +} + +# Static settings generated from template <doc/wiki/UserDatabase.Static.txt> +#userdb { + #driver = static + # Can return anything a userdb could normally return. For example: + # + # args = uid=500 gid=500 home=/var/mail/%u + # + # LDA and LMTP needs to look up users only from the userdb. This of course + # doesn't work with static userdb because there is no list of users. + # Normally static userdb handles this by doing a passdb lookup. This works + # with most passdbs, with PAM being the most notable exception. If you do + # the user verification another way, you can add allow_all_users=yes to + # the args in which case the passdb lookup is skipped. + # + #args = +#} diff --git a/doc/example-config/dovecot-dict-auth.conf.ext b/doc/example-config/dovecot-dict-auth.conf.ext new file mode 100644 index 0000000..79f43de --- /dev/null +++ b/doc/example-config/dovecot-dict-auth.conf.ext @@ -0,0 +1,54 @@ +# This file is commonly accessed via passdb {} or userdb {} section in +# conf.d/auth-dict.conf.ext + +# Dictionary URI +#uri = + +# Default password scheme +default_pass_scheme = MD5 + +# Username iteration prefix. Keys under this are assumed to contain usernames. +iterate_prefix = userdb/ + +# Should iteration be disabled for this userdb? If this userdb acts only as a +# cache there's no reason to try to iterate the (partial & duplicate) users. +#iterate_disable = no + +# The example here shows how to do multiple dict lookups and merge the replies. +# The "passdb" and "userdb" keys are JSON objects containing key/value pairs, +# for example: { "uid": 1000, "gid": 1000, "home": "/home/user" } + +key passdb { + key = passdb/%u + format = json +} +key userdb { + key = userdb/%u + format = json +} +key quota { + key = userdb/%u/quota + #format = value + # The default_value is used if the key isn't found. If default_value setting + # isn't specified at all (even as empty), the passdb/userdb lookup fails with + # "user doesn't exist". + default_value = 100M +} + +# Space separated list of keys whose values contain key/value paired objects. +# All the key/value pairs inside the object are added as passdb fields. +passdb_objects = passdb + +#passdb_fields { +#} + +# Userdb key/value object list. +userdb_objects = userdb + +userdb_fields { + # dict:<key> refers to key names + quota_rule = *:storage=%{dict:quota} + + # dict:<key>.<objkey> refers to the objkey inside (JSON) object + mail = maildir:%{dict:userdb.home}/Maildir +} diff --git a/doc/example-config/dovecot-dict-sql.conf.ext b/doc/example-config/dovecot-dict-sql.conf.ext new file mode 100644 index 0000000..35aa107 --- /dev/null +++ b/doc/example-config/dovecot-dict-sql.conf.ext @@ -0,0 +1,23 @@ +# This file is commonly accessed via dict {} section in dovecot.conf + +#connect = host=localhost dbname=mails user=testuser password=pass + +# CREATE TABLE quota ( +# username varchar(100) not null, +# bytes bigint not null default 0, +# messages integer not null default 0, +# primary key (username) +# ); + +map { + pattern = priv/quota/storage + table = quota + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota + username_field = username + value_field = messages +} diff --git a/doc/example-config/dovecot-ldap.conf.ext b/doc/example-config/dovecot-ldap.conf.ext new file mode 100644 index 0000000..f4a65f2 --- /dev/null +++ b/doc/example-config/dovecot-ldap.conf.ext @@ -0,0 +1,151 @@ +# This file is commonly accessed via passdb {} or userdb {} section in +# conf.d/auth-ldap.conf.ext + +# This file is opened as root, so it should be owned by root and mode 0600. +# +# http://wiki2.dovecot.org/AuthDatabase/LDAP +# +# NOTE: If you're not using authentication binds, you'll need to give +# dovecot-auth read access to userPassword field in the LDAP server. +# With OpenLDAP this is done by modifying /etc/ldap/slapd.conf. There should +# already be something like this: + +# access to attribute=userPassword +# by dn="<dovecot's dn>" read # add this +# by anonymous auth +# by self write +# by * none + +# Space separated list of LDAP hosts to use. host:port is allowed too. +#hosts = + +# LDAP URIs to use. You can use this instead of hosts list. Note that this +# setting isn't supported by all LDAP libraries. +#uris = + +# Distinguished Name - the username used to login to the LDAP server. +# Leave it commented out to bind anonymously (useful with auth_bind=yes). +#dn = + +# Password for LDAP server, if dn is specified. +#dnpass = + +# Use SASL binding instead of the simple binding. Note that this changes +# ldap_version automatically to be 3 if it's lower. +#sasl_bind = no +# SASL mechanism name to use. +#sasl_mech = +# SASL realm to use. +#sasl_realm = +# SASL authorization ID, ie. the dnpass is for this "master user", but the +# dn is still the logged in user. Normally you want to keep this empty. +#sasl_authz_id = + +# Use TLS to connect to the LDAP server. +#tls = no +# TLS options, currently supported only with OpenLDAP: +#tls_ca_cert_file = +#tls_ca_cert_dir = +#tls_cipher_suite = +# TLS cert/key is used only if LDAP server requires a client certificate. +#tls_cert_file = +#tls_key_file = +# Valid values: never, hard, demand, allow, try +#tls_require_cert = + +# Use the given ldaprc path. +#ldaprc_path = + +# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. +# -1 = everything. You may need to recompile OpenLDAP with debugging enabled +# to get enough output. +#debug_level = 0 + +# Use authentication binding for verifying password's validity. This works by +# logging into LDAP server using the username and password given by client. +# The pass_filter is used to find the DN for the user. Note that the pass_attrs +# is still used, only the password field is ignored in it. Before doing any +# search, the binding is switched back to the default DN. +#auth_bind = no + +# If authentication binding is used, you can save one LDAP request per login +# if users' DN can be specified with a common template. The template can use +# the standard %variables (see user_filter). Note that you can't +# use any pass_attrs if you use this setting. +# +# If you use this setting, it's a good idea to use a different +# dovecot-ldap.conf.ext for userdb (it can even be a symlink, just as long as +# the filename is different in userdb's args). That way one connection is used +# only for LDAP binds and another connection is used for user lookups. +# Otherwise the binding is changed to the default DN before each user lookup. +# +# For example: +# auth_bind_userdn = cn=%u,ou=people,o=org +# +#auth_bind_userdn = + +# LDAP protocol version to use. Likely 2 or 3. +#ldap_version = 3 + +# LDAP base. %variables can be used here. +# For example: dc=mail, dc=example, dc=org +base = + +# Dereference: never, searching, finding, always +#deref = never + +# Search scope: base, onelevel, subtree +#scope = subtree + +# User attributes are given in LDAP-name=dovecot-internal-name list. The +# internal names are: +# uid - System UID +# gid - System GID +# home - Home directory +# mail - Mail location +# +# There are also other special fields which can be returned, see +# http://wiki2.dovecot.org/UserDatabase/ExtraFields +#user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid + +# Filter for user lookup. Some variables can be used (see +# http://wiki2.dovecot.org/Variables for full list): +# %u - username +# %n - user part in user@domain, same as %u if there's no domain +# %d - domain part in user@domain, empty if user there's no domain +#user_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Password checking attributes: +# user: Virtual user name (user@domain), if you wish to change the +# user-given username to something else +# password: Password, may optionally start with {type}, eg. {crypt} +# There are also other special fields which can be returned, see +# http://wiki2.dovecot.org/PasswordDatabase/ExtraFields +#pass_attrs = uid=user,userPassword=password + +# If you wish to avoid two LDAP lookups (passdb + userdb), you can use +# userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll +# also have to include user_attrs in pass_attrs field prefixed with "userdb_" +# string. For example: +#pass_attrs = uid=user,userPassword=password,\ +# homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid + +# Filter for password lookups +#pass_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Attributes and filter to get a list of all users +#iterate_attrs = uid=user +#iterate_filter = (objectClass=posixAccount) + +# Default password scheme. "{scheme}" before password overrides this. +# List of supported schemes is in: http://wiki2.dovecot.org/Authentication +#default_pass_scheme = CRYPT + +# By default all LDAP lookups are performed by the auth master process. +# If blocking=yes, auth worker processes are used to perform the lookups. +# Each auth worker process creates its own LDAP connection so this can +# increase parallelism. With blocking=no the auth master process can +# keep 8 requests pipelined for the LDAP connection, while with blocking=yes +# each connection has a maximum of 1 request running. For small systems the +# blocking=no is sufficient and uses less resources. +#blocking = no diff --git a/doc/example-config/dovecot-oauth2.conf.ext b/doc/example-config/dovecot-oauth2.conf.ext new file mode 100644 index 0000000..4b3b8ba --- /dev/null +++ b/doc/example-config/dovecot-oauth2.conf.ext @@ -0,0 +1,69 @@ +### OAuth2 password database configuration + +## url for verifying token validity. Token is appended to the URL +# tokeninfo_url = http://endpoint/oauth/tokeninfo?access_token= + +## introspection endpoint, used to gather extra fields and other information. +# introspection_url = http://endpoint/oauth/me + +## How introspection is made, valid values are +## auth = GET request with Bearer authentication +## get = GET request with token appended to URL +## post = POST request with token=bearer_token as content +## local = perform local validation only +# introspection_mode = auth + +## Force introspection even if tokeninfo contains wanted fields +## Set this to yes if you are using active_attribute +# force_introspection = no + +## Validation key dictionary (e.g. fs:posix:prefix=/etc/dovecot/keys/) +## Lookup key is /shared/<azp:default>/<alg>/<kid:default> +# local_validation_key_dict = + +## A single wanted scope of validity (optional) +# scope = something + +## username attribute in response (default: email) +# username_attribute = email + +## username normalization format (default: %Lu) +# username_format = %Lu + +## Attribute name for checking whether account is disabled (optional) +# active_attribute = + +## Expected value in active_attribute (empty = require present, but anything goes) +# active_value = + +## Expected issuer(s) for the token (space separated list) +# issuers = + +## URL to RFC 7628 OpenID Provider Configuration Information schema +# openid_configuration_url = + +## Extra fields to set in passdb response (in passdb static style) +# pass_attrs = + +## Timeout in milliseconds +# timeout_msecs = 0 + +## Enable debug logging +# debug = no + +## Max parallel connections (how many simultaneous connections to open) +# max_parallel_connections = 10 + +## Max pipelined requests (how many requests to send per connection, requires server-side support) +# max_pipelined_requests = 1 + +## HTTP request raw log directory +# rawlog_dir = /tmp/oauth2 + +## TLS settings +# tls_ca_cert_file = /path/to/ca-certificates.txt +# tls_ca_cert_dir = /path/to/certs/ +# tls_cert_file = /path/to/client/cert +# tls_key_file = /path/to/client/key +# tls_cipher_suite = HIGH:!SSLv2 +# tls_allow_invalid_cert = FALSE diff --git a/doc/example-config/dovecot-sql.conf.ext b/doc/example-config/dovecot-sql.conf.ext new file mode 100644 index 0000000..8bbcbae --- /dev/null +++ b/doc/example-config/dovecot-sql.conf.ext @@ -0,0 +1,144 @@ +# This file is commonly accessed via passdb {} or userdb {} section in +# conf.d/auth-sql.conf.ext + +# This file is opened as root, so it should be owned by root and mode 0600. +# +# http://wiki2.dovecot.org/AuthDatabase/SQL +# +# For the sql passdb module, you'll need a database with a table that +# contains fields for at least the username and password. If you want to +# use the user@domain syntax, you might want to have a separate domain +# field as well. +# +# If your users all have the same uig/gid, and have predictable home +# directories, you can use the static userdb module to generate the home +# dir based on the username and domain. In this case, you won't need fields +# for home, uid, or gid in the database. +# +# If you prefer to use the sql userdb module, you'll want to add fields +# for home, uid, and gid. Here is an example table: +# +# CREATE TABLE users ( +# username VARCHAR(128) NOT NULL, +# domain VARCHAR(128) NOT NULL, +# password VARCHAR(64) NOT NULL, +# home VARCHAR(255) NOT NULL, +# uid INTEGER NOT NULL, +# gid INTEGER NOT NULL, +# active CHAR(1) DEFAULT 'Y' NOT NULL +# ); + +# Database driver: mysql, pgsql, sqlite +#driver = + +# Database connection string. This is driver-specific setting. +# +# HA / round-robin load-balancing is supported by giving multiple host +# settings, like: host=sql1.host.org host=sql2.host.org +# +# pgsql: +# For available options, see the PostgreSQL documentation for the +# PQconnectdb function of libpq. +# Use maxconns=n (default 5) to change how many connections Dovecot can +# create to pgsql. +# +# mysql: +# Basic options emulate PostgreSQL option names: +# host, port, user, password, dbname +# +# But also adds some new settings: +# client_flags - See MySQL manual +# connect_timeout - Connect timeout in seconds (default: 5) +# read_timeout - Read timeout in seconds (default: 30) +# write_timeout - Write timeout in seconds (default: 30) +# ssl_ca, ssl_ca_path - Set either one or both to enable SSL +# ssl_cert, ssl_key - For sending client-side certificates to server +# ssl_cipher - Set minimum allowed cipher security (default: HIGH) +# ssl_verify_server_cert - Verify that the name in the server SSL certificate +# matches the host (default: no) +# option_file - Read options from the given file instead of +# the default my.cnf location +# option_group - Read options from the given group (default: client) +# +# You can connect to UNIX sockets by using host: host=/var/run/mysql.sock +# Note that currently you can't use spaces in parameters. +# +# sqlite: +# The path to the database file. +# +# Examples: +# connect = host=192.168.1.1 dbname=users +# connect = host=sql.example.com dbname=virtual user=virtual password=blarg +# connect = /etc/dovecot/authdb.sqlite +# +#connect = + +# Default password scheme. +# +# List of supported schemes is in +# http://wiki2.dovecot.org/Authentication/PasswordSchemes +# +#default_pass_scheme = MD5 + +# passdb query to retrieve the password. It can return fields: +# password - The user's password. This field must be returned. +# user - user@domain from the database. Needed with case-insensitive lookups. +# username and domain - An alternative way to represent the "user" field. +# +# The "user" field is often necessary with case-insensitive lookups to avoid +# e.g. "name" and "nAme" logins creating two different mail directories. If +# your user and domain names are in separate fields, you can return "username" +# and "domain" fields instead of "user". +# +# The query can also return other fields which have a special meaning, see +# http://wiki2.dovecot.org/PasswordDatabase/ExtraFields +# +# Commonly used available substitutions (see http://wiki2.dovecot.org/Variables +# for full list): +# %u = entire user@domain +# %n = user part of user@domain +# %d = domain part of user@domain +# +# Note that these can be used only as input to SQL query. If the query outputs +# any of these substitutions, they're not touched. Otherwise it would be +# difficult to have eg. usernames containing '%' characters. +# +# Example: +# password_query = SELECT userid AS user, pw AS password \ +# FROM users WHERE userid = '%u' AND active = 'Y' +# +#password_query = \ +# SELECT username, domain, password \ +# FROM users WHERE username = '%n' AND domain = '%d' + +# userdb query to retrieve the user information. It can return fields: +# uid - System UID (overrides mail_uid setting) +# gid - System GID (overrides mail_gid setting) +# home - Home directory +# mail - Mail location (overrides mail_location setting) +# +# None of these are strictly required. If you use a single UID and GID, and +# home or mail directory fits to a template string, you could use userdb static +# instead. For a list of all fields that can be returned, see +# http://wiki2.dovecot.org/UserDatabase/ExtraFields +# +# Examples: +# user_query = SELECT home, uid, gid FROM users WHERE userid = '%u' +# user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u' +# user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u' +# +#user_query = \ +# SELECT home, uid, gid \ +# FROM users WHERE username = '%n' AND domain = '%d' + +# If you wish to avoid two SQL lookups (passdb + userdb), you can use +# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll +# also have to return userdb fields in password_query prefixed with "userdb_" +# string. For example: +#password_query = \ +# SELECT userid AS user, password, \ +# home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ +# FROM users WHERE userid = '%u' + +# Query to get a list of all usernames. +#iterate_query = SELECT username AS user FROM users diff --git a/doc/example-config/dovecot.conf b/doc/example-config/dovecot.conf new file mode 100644 index 0000000..b67e9eb --- /dev/null +++ b/doc/example-config/dovecot.conf @@ -0,0 +1,101 @@ +## Dovecot configuration file + +# If you're in a hurry, see http://wiki2.dovecot.org/QuickConfiguration + +# "doveconf -n" command gives a clean output of the changed settings. Use it +# instead of copy&pasting files when posting to the Dovecot mailing list. + +# '#' character and everything after it is treated as comments. Extra spaces +# and tabs are ignored. If you want to use either of these explicitly, put the +# value inside quotes, eg.: key = "# char and trailing whitespace " + +# Most (but not all) settings can be overridden by different protocols and/or +# source/destination IPs by placing the settings inside sections, for example: +# protocol imap { }, local 127.0.0.1 { }, remote 10.0.0.0/8 { } + +# Default values are shown for each setting, it's not required to uncomment +# those. These are exceptions to this though: No sections (e.g. namespace {}) +# or plugin settings are added by default, they're listed only as examples. +# Paths are also just examples with the real defaults being based on configure +# options. The paths listed here are for configure --prefix=/usr +# --sysconfdir=/etc --localstatedir=/var + +# Protocols we want to be serving. +#protocols = imap pop3 lmtp submission + +# A comma separated list of IPs or hosts where to listen in for connections. +# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces. +# If you want to specify non-default ports or anything more complex, +# edit conf.d/master.conf. +#listen = *, :: + +# Base directory where to store runtime data. +#base_dir = /var/run/dovecot/ + +# Name of this instance. In multi-instance setup doveadm and other commands +# can use -i <instance_name> to select which instance is used (an alternative +# to -c <config_path>). The instance name is also added to Dovecot processes +# in ps output. +#instance_name = dovecot + +# Greeting message for clients. +#login_greeting = Dovecot ready. + +# Space separated list of trusted network ranges. Connections from these +# IPs are allowed to override their IP addresses and ports (for logging and +# for authentication checks). disable_plaintext_auth is also ignored for +# these networks. Typically you'd specify your IMAP proxy servers here. +#login_trusted_networks = + +# Space separated list of login access check sockets (e.g. tcpwrap) +#login_access_sockets = + +# With proxy_maybe=yes if proxy destination matches any of these IPs, don't do +# proxying. This isn't necessary normally, but may be useful if the destination +# IP is e.g. a load balancer's IP. +#auth_proxy_self = + +# Show more verbose process titles (in ps). Currently shows user name and +# IP address. Useful for seeing who are actually using the IMAP processes +# (eg. shared mailboxes or if same uid is used for multiple accounts). +#verbose_proctitle = no + +# Should all processes be killed when Dovecot master process shuts down. +# Setting this to "no" means that Dovecot can be upgraded without +# forcing existing client connections to close (although that could also be +# a problem if the upgrade is e.g. because of a security fix). +#shutdown_clients = yes + +# If non-zero, run mail commands via this many connections to doveadm server, +# instead of running them directly in the same process. +#doveadm_worker_count = 0 +# UNIX socket or host:port used for connecting to doveadm server +#doveadm_socket_path = doveadm-server + +# Space separated list of environment variables that are preserved on Dovecot +# startup and passed down to all of its child processes. You can also give +# key=value pairs to always set specific settings. +#import_environment = TZ + +## +## Dictionary server settings +## + +# Dictionary can be used to store key=value lists. This is used by several +# plugins. The dictionary can be accessed either directly or though a +# dictionary server. The following dict block maps dictionary names to URIs +# when the server is used. These can then be referenced using URIs in format +# "proxy::<name>". + +dict { + #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext +} + +# Most of the actual configuration gets included below. The filenames are +# first sorted by their ASCII value and parsed in that order. The 00-prefixes +# in filenames are intended to make it easier to understand the ordering. +!include conf.d/*.conf + +# A config file can also tried to be included without giving an error if +# it's not found: +!include_try local.conf diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am new file mode 100644 index 0000000..0b0b8fb --- /dev/null +++ b/doc/man/Makefile.am @@ -0,0 +1,118 @@ +pkgsysconfdir = $(sysconfdir)/dovecot + +SUFFIXES = .1.in .1 + +dist_man1_MANS = \ + deliver.1 \ + doveadm-backup.1 \ + doveadm-config.1 \ + doveadm-copy.1 \ + doveadm-reload.1 \ + doveadm-stop.1 \ + dsync.1 + +dist_man7_MANS = \ + doveadm-search-query.7 + +nodist_man1_MANS = \ + doveadm.1 \ + doveadm-acl.1 \ + doveadm-altmove.1 \ + doveadm-auth.1 \ + doveadm-batch.1 \ + doveadm-deduplicate.1 \ + doveadm-director.1 \ + doveadm-dump.1 \ + doveadm-exec.1 \ + doveadm-expunge.1 \ + doveadm-fetch.1 \ + doveadm-flags.1 \ + doveadm-fs.1 \ + doveadm-fts.1 \ + doveadm-import.1 \ + doveadm-instance.1 \ + doveadm-index.1 \ + doveadm-force-resync.1 \ + doveadm-help.1 \ + doveadm-kick.1 \ + doveadm-log.1 \ + doveadm-mailbox.1 \ + doveadm-mailbox-cryptokey.1 \ + doveadm-move.1 \ + doveadm-penalty.1 \ + doveadm-proxy.1 \ + doveadm-purge.1 \ + doveadm-pw.1 \ + doveadm-quota.1 \ + doveadm-rebuild.1 \ + doveadm-replicator.1 \ + doveadm-save.1 \ + doveadm-search.1 \ + doveadm-stats.1 \ + doveadm-sync.1 \ + doveadm-user.1 \ + doveadm-who.1 \ + doveconf.1 \ + dovecot.1 \ + dovecot-lda.1 \ + dovecot-sysreport.1 + +man_includefiles = \ + $(srcdir)/global-options-formatter.inc \ + $(srcdir)/global-options.inc \ + $(srcdir)/option-A.inc \ + $(srcdir)/option-F-file.inc \ + $(srcdir)/option-S-socket.inc \ + $(srcdir)/option-u-user.inc \ + $(srcdir)/reporting-bugs.inc + +EXTRA_DIST = \ + doveadm.1.in \ + doveadm-acl.1.in \ + doveadm-altmove.1.in \ + doveadm-auth.1.in \ + doveadm-batch.1.in \ + doveadm-deduplicate.1.in \ + doveadm-director.1.in \ + doveadm-dump.1.in \ + doveadm-exec.1.in \ + doveadm-expunge.1.in \ + doveadm-fetch.1.in \ + doveadm-flags.1.in \ + doveadm-fs.1.in \ + doveadm-fts.1.in \ + doveadm-import.1.in \ + doveadm-instance.1.in \ + doveadm-index.1.in \ + doveadm-force-resync.1.in \ + doveadm-help.1.in \ + doveadm-kick.1.in \ + doveadm-log.1.in \ + doveadm-mailbox.1.in \ + doveadm-mailbox-cryptokey.1.in \ + doveadm-move.1.in \ + doveadm-penalty.1.in \ + doveadm-proxy.1.in \ + doveadm-purge.1.in \ + doveadm-pw.1.in \ + doveadm-quota.1.in \ + doveadm-rebuild.1.in \ + doveadm-replicator.1.in \ + doveadm-save.1.in \ + doveadm-search.1.in \ + doveadm-stats.1.in \ + doveadm-sync.1.in \ + doveadm-user.1.in \ + doveadm-who.1.in \ + doveconf.1.in \ + dovecot.1.in \ + dovecot-lda.1.in \ + dovecot-sysreport.1.in \ + sed.sh \ + $(man_includefiles) + +CLEANFILES = $(nodist_man1_MANS) + +.1.in.1: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ diff --git a/doc/man/Makefile.in b/doc/man/Makefile.in new file mode 100644 index 0000000..00c7436 --- /dev/null +++ b/doc/man/Makefile.in @@ -0,0 +1,825 @@ +# 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 = doc/man +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 $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)" +man7dir = $(mandir)/man7 +NROFF = nroff +MANS = $(dist_man1_MANS) $(dist_man7_MANS) $(nodist_man1_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man1_MANS) $(dist_man7_MANS) \ + $(srcdir)/Makefile.in +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@ +pkgsysconfdir = $(sysconfdir)/dovecot +SUFFIXES = .1.in .1 +dist_man1_MANS = \ + deliver.1 \ + doveadm-backup.1 \ + doveadm-config.1 \ + doveadm-copy.1 \ + doveadm-reload.1 \ + doveadm-stop.1 \ + dsync.1 + +dist_man7_MANS = \ + doveadm-search-query.7 + +nodist_man1_MANS = \ + doveadm.1 \ + doveadm-acl.1 \ + doveadm-altmove.1 \ + doveadm-auth.1 \ + doveadm-batch.1 \ + doveadm-deduplicate.1 \ + doveadm-director.1 \ + doveadm-dump.1 \ + doveadm-exec.1 \ + doveadm-expunge.1 \ + doveadm-fetch.1 \ + doveadm-flags.1 \ + doveadm-fs.1 \ + doveadm-fts.1 \ + doveadm-import.1 \ + doveadm-instance.1 \ + doveadm-index.1 \ + doveadm-force-resync.1 \ + doveadm-help.1 \ + doveadm-kick.1 \ + doveadm-log.1 \ + doveadm-mailbox.1 \ + doveadm-mailbox-cryptokey.1 \ + doveadm-move.1 \ + doveadm-penalty.1 \ + doveadm-proxy.1 \ + doveadm-purge.1 \ + doveadm-pw.1 \ + doveadm-quota.1 \ + doveadm-rebuild.1 \ + doveadm-replicator.1 \ + doveadm-save.1 \ + doveadm-search.1 \ + doveadm-stats.1 \ + doveadm-sync.1 \ + doveadm-user.1 \ + doveadm-who.1 \ + doveconf.1 \ + dovecot.1 \ + dovecot-lda.1 \ + dovecot-sysreport.1 + +man_includefiles = \ + $(srcdir)/global-options-formatter.inc \ + $(srcdir)/global-options.inc \ + $(srcdir)/option-A.inc \ + $(srcdir)/option-F-file.inc \ + $(srcdir)/option-S-socket.inc \ + $(srcdir)/option-u-user.inc \ + $(srcdir)/reporting-bugs.inc + +EXTRA_DIST = \ + doveadm.1.in \ + doveadm-acl.1.in \ + doveadm-altmove.1.in \ + doveadm-auth.1.in \ + doveadm-batch.1.in \ + doveadm-deduplicate.1.in \ + doveadm-director.1.in \ + doveadm-dump.1.in \ + doveadm-exec.1.in \ + doveadm-expunge.1.in \ + doveadm-fetch.1.in \ + doveadm-flags.1.in \ + doveadm-fs.1.in \ + doveadm-fts.1.in \ + doveadm-import.1.in \ + doveadm-instance.1.in \ + doveadm-index.1.in \ + doveadm-force-resync.1.in \ + doveadm-help.1.in \ + doveadm-kick.1.in \ + doveadm-log.1.in \ + doveadm-mailbox.1.in \ + doveadm-mailbox-cryptokey.1.in \ + doveadm-move.1.in \ + doveadm-penalty.1.in \ + doveadm-proxy.1.in \ + doveadm-purge.1.in \ + doveadm-pw.1.in \ + doveadm-quota.1.in \ + doveadm-rebuild.1.in \ + doveadm-replicator.1.in \ + doveadm-save.1.in \ + doveadm-search.1.in \ + doveadm-stats.1.in \ + doveadm-sync.1.in \ + doveadm-user.1.in \ + doveadm-who.1.in \ + doveconf.1.in \ + dovecot.1.in \ + dovecot-lda.1.in \ + dovecot-sysreport.1.in \ + sed.sh \ + $(man_includefiles) + +CLEANFILES = $(nodist_man1_MANS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .1.in .1 +$(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 doc/man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/man/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man1: $(dist_man1_MANS) $(nodist_man1_MANS) + @$(NORMAL_INSTALL) + @list1='$(dist_man1_MANS) $(nodist_man1_MANS)'; \ + list2=''; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(dist_man1_MANS) $(nodist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +install-man7: $(dist_man7_MANS) + @$(NORMAL_INSTALL) + @list1='$(dist_man7_MANS)'; \ + list2=''; \ + test -n "$(man7dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.7[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \ + done; } + +uninstall-man7: + @$(NORMAL_UNINSTALL) + @list='$(dist_man7_MANS)'; test -n "$(man7dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +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 $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)"; 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: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +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-man1 install-man7 + +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 Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 uninstall-man7 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool 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-man1 install-man7 install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-man uninstall-man1 uninstall-man7 + +.PRECIOUS: Makefile + + +.1.in.1: $(man_includefiles) Makefile + $(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \ + $(pkglibexecdir) < $< > $@ + +# 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/doc/man/deliver.1 b/doc/man/deliver.1 new file mode 100644 index 0000000..4ac3824 --- /dev/null +++ b/doc/man/deliver.1 @@ -0,0 +1 @@ +.so man1/dovecot-lda.1
\ No newline at end of file diff --git a/doc/man/doveadm-acl.1.in b/doc/man/doveadm-acl.1.in new file mode 100644 index 0000000..b79bc6c --- /dev/null +++ b/doc/man/doveadm-acl.1.in @@ -0,0 +1,270 @@ +.\" Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-ACL 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-acl \- Manage Access Control List (ACL) +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI acl \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm acl +.I COMMANDS +can be used to execute various Access Control List related actions. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.BR table . +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I id +The id (identifier) is one of: +.RS +.RS +.TP 4 +* +.BR group\-override =\c +.I group_name +.\"----------------- +.TP +* +.BR user =\c +.I user_name +.\"----------------- +.TP +* +.B owner +.\"----------------- +.TP +* +.BR group =\c +.I group_name +.\"----------------- +.TP +* +.B authenticated +.\"----------------- +.TP +* +.BR anyone " (or " anonymous ", which is an alias for anyone)" +.\"----------------- +.RE +.PP +The ACLs are processed in the precedence given above, so for example if you +have given read\-access to a group, you can still remove that from specific +users inside the group. +.br +Group\-override identifier allows you to override users\(aq ACLs. +Probably the most useful reason to do this is to temporarily disable +access for some users. +For example: +.PP +.nf +user=timo rw +group\-override=tempdisabled +.fi +.PP +Now if timo is a member of the tempdisabled group, he has no access to the +mailbox. +This wouldn\(aqt be possible with a normal group identifier, because the +.B user=timo +would override it. +.RE +.\"------------------------------------- +.TP +.I mailbox +The name of the mailbox, for which the ACL manipulation should be done. +It\(aqs also possible to use the wildcard characters +.RB \(dq * "\(dq and/or \(dq" ? \(dq +in the mailbox name. +.\"------------------------------------- +.TP +.I right +Dovecot ACL right name. This isn\(aqt the same as the IMAP ACL letters, +which aren\(aqt currently supported. +Here is a mapping of the IMAP ACL letters to Dovecot ACL names: +.RS +.RS +.TP 4 +.B l \(-> lookup +.I Mailbox +is visible in mailbox list. +.I Mailbox +can be subscribed to. +.\"----------------- +.TP +.B r \(-> read +.I Mailbox +can be opened for reading. +.\"----------------- +.TP +.B w \(-> write +Message flags and keywords can be changed, except +.BR \(rsSeen " and " \(rsDeleted . +.\"----------------- +.TP +.B s \(-> write\-seen +.B \(rsSeen +flag can be changed. +.\"----------------- +.TP +.B t \(-> write\-deleted +.B \(rsDeleted +flag can be changed. +.\"----------------- +.TP +.B i \(-> insert +Messages can be written or copied to the +.IR mailbox . +.\"----------------- +.TP +.B p \(-> post +Messages can be posted to the +.I mailbox +by +.BR dovecot\-lda , +e.g. from Sieve scripts. +.\"----------------- +.TP +.B e \(-> expunge +Messages can be expunged. +.\"----------------- +.TP +.B k \(-> create +Mailboxes can be created/renamed directly under this +.I mailbox +(but not necessarily under its children, see +.I ACL Inheritance +in the wiki). +.br +Note: Renaming also requires the delete right. +.\"----------------- +.TP +.B x \(-> delete +.I Mailbox +can be deleted. +.\"----------------- +.TP +.B a \(-> admin +Administration rights to the +.I mailbox +(currently: ability to change ACLs for +.IR mailbox ). +.RE +.RE +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS acl add +.B doveadm acl add +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox id right +.RI [ right " ...]" +.PP +Add ACL rights to the +.IR mailbox / id . +If the +.I id +already exists, the existing rights are preserved. +.\"------------------------------------- +.SS acl debug +.B doveadm acl debug +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox +.PP +This command can be used to debug why a shared mailbox isn\(aqt +accessible to the user. +It will list exactly what the problem is. +.\"------------------------------------- +.SS acl delete +.B doveadm acl delete +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox id +.PP +Remove the whole ACL entry for the +.IR mailbox / id . +.\"------------------------------------- +.SS acl get +.B doveadm acl get +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-m ] +.I mailbox +.PP +Show all the ACLs for the +.IR mailbox . +.\"------------------------------------- +.SS acl recalc +.B doveadm acl recalc +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.PP +Make sure the +.IR user \(aqs +shared mailboxes exist correctly in the +.IR acl_shared_dict . +.\"------------------------------------- +.SS acl remove +.B doveadm acl remove +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox id right +.RI [ right " ...]" +.PP +Remove the specified ACL rights from the +.IR mailbox / id . +If all rights are removed, the entry still exists without any rights. +.\"------------------------------------- +.SS acl rights +.B doveadm acl rights +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox +.PP +Show the +.IR user \(aqs +current ACL rights for the +.IR mailbox . +.\"------------------------------------- +.SS acl set +.B doveadm acl set +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.I mailbox id right +.RI [ right " ...]" +.PP +Set ACL rights to the +.IR mailbox / id . +If the +.I id +already exists, the existing rights are replaced. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR dovecot\-lda (1) +.\"------------------------------------- +.PP +Additional resources: +.IP "ACL Inheritance" +http://wiki2.dovecot.org/ACL#ACL_Inheritance
\ No newline at end of file diff --git a/doc/man/doveadm-altmove.1.in b/doc/man/doveadm-altmove.1.in new file mode 100644 index 0000000..b33f472 --- /dev/null +++ b/doc/man/doveadm-altmove.1.in @@ -0,0 +1,104 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-ALTMOVE 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-altmove \- Move matching mails to the alternative storage (dbox\-only) +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " altmove " [" \-r "] ["\-S +.IR socket_path "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " altmove " [" \-r "] ["\-S +.IR socket_path "] " +.BI \-A " search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " altmove " [" \-r "] ["\-S +.IR socket_path "] " +.BI \-F " file search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " altmove " [" \-r "] ["\-S +.IR socket_path "] " +.BI \-u " user search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command can be used with sdbox or mdbox storage to move mails to +alternative storage path when :ALT=<path> is specified for the mail +location. +.PP +In the first form, +.BR doveadm (1) +will executed the +.B altmove +action with the environment of the logged in system user. +.PP +In the second form, the command will be performed for all users. +.PP +In the third form, the command will be performed for all users listed in +the given +.IR file . +.PP +In the fourth form, only matching mails of the given +.IR user (s) +will be moved to the alternative storage. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +.TP +.B \-r +When the +.B \-r +option is given this +.I command +works the other way round. +Mails will be moved from the alternative storage back to the default mail +location. +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I search_query +Messages matching this search query will be moved to alt storage. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/conf.d/10\-mail.conf +Mailbox locations and namespaces. +.TP +.I @pkgsysconfdir@/conf.d/auth\-*.conf.ext +Authentication processes, including userdb settings. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example moves seen mails older than one week to alternative storage +under /nfsmount: +.br +.nf +mail_location = mdbox:~/mdbox:ALT=/nfsmount/%h/mdbox +.fi +.PP +.nf +.ft B +doveadm altmove \-u johnd@example.com seen savedbefore 1w +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-auth.1.in b/doc/man/doveadm-auth.1.in new file mode 100644 index 0000000..f70bfda --- /dev/null +++ b/doc/man/doveadm-auth.1.in @@ -0,0 +1,216 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-AUTH 1 "2014-10-19" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-auth \- Flush/lookup/test authentication data +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI auth \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm \ auth +.I COMMANDS +can be used to perform various authentication related actions. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.BI \-x\ auth_info +.I auth_info +specifies additional conditions for the +.BR "auth lookup" " and " "auth test" +commands. +The +.I auth_info +option string has to be given as +.IB name = value +pair. +For multiple conditions the +.B \-x +option could be supplied multiple times. +.br +All the given fields are forwarded to the auth process without checking for +their validity. The important names for the +.I auth_info +are: +.RS +.TP +.B service +The service for which the authentication lookup should be tested. +The value may be the name of a service, commonly used with Dovecot. +For example: +.BR imap , +.BR pop3\ or +.BR smtp . +.TP +.B lip +The local IP address (server) for the test. +.TP +.B rip +The remote IP address (client) for the test. +.TP +.B lport +The local port, e.g. 143 +.TP +.B rport +The remote port, e.g. 24567 +.TP +.B real_lip +The "real" local IP address (server) for the test. This is intended to be the +local server\(aqs IP, while "lip" contains the connecting proxy server\(aqs +local IP. +.TP +.B real_rip +The "real" remote IP address (client) for the test. This is intended to be the +connecting proxy server\(aqs IP address, while "rip" contains the original +client\(aqs IP. +.TP +.B real_lport +The "real" local port for proxied connections. +.TP +.B real_rport +The "real" remote port for proxied connections. +.TP +.B local_name +Provide the client TLS connection\(aqs SNI name. +.TP +.B client_id +IMAP client ID string. +.TP +.B session +Session ID string, mainly for logging purposes. +.RE +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.\"------------------------------------- +.TP +.I user +The +.IR user \(aqs +login name. +Depending on the configuration, the login name may be for example +.BR jane " or " john@example.com . +.\"------------------------------------- +.TP +.I password +Optionally the user\(aqs password. +.BR doveadm (1) +will prompt for the password, if none was given. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS auth cache flush +.B doveadm auth cache flush +.RB [ \-a +.IR master_socket_path ] +.RI [ user " ...]" +.PP +Flush the authentication cache. +By default the cache is flushed for all the users (which can also be done +by sending SIGHUP to the auth process). +You can also flush the cache for one or more users by providing their +usernames. +.PP +.TP +.BI \-a \ master_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/auth\-master . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------- +.SS auth lookup +.B doveadm auth lookup +.RB [ \-a +.IR userdb_socket_path ] +.RB [ \-x +.IR auth_info ] +.RB [ \-f +.IR field ] \ user \ [...] +.PP +Similar to +.BR doveadm\-user (1) +command, except it performs a +.I passdb +lookup (without authentication) instead of a +.I userdb +lookup. +.PP +.TP +.BI \-a \ userdb_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/auth\-userdb . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"----------------- +.TP +.BI \-f \ field +When this option and the name of a userdb field is given, +.BR doveadm (1) +will show only the value of the specified field. +.\"------------------------------------- +.SS auth test +.B doveadm auth test +.RB [ \-a +.IR auth_socket_path ] +.RB [ \-x +.IR auth_info ] +.IR user \ [ password ] +.PP +Test authentication for the given user. +.\"------------------------------------- +.TP +.BI \-a\ auth_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/auth\-client . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . + +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example demonstrates an imap authentication test for user john, +assuming the user is connected from the host with the IP address +192.0.2.143. +.PP +.nf +.ft B +doveadm auth test \-x service=imap \-x rip=192.0.2.143 john +.ft P +Password: +passdb: john auth succeeded +extra fields: + user=john +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-user (1), +.BR doveconf (1)
\ No newline at end of file diff --git a/doc/man/doveadm-backup.1 b/doc/man/doveadm-backup.1 new file mode 100644 index 0000000..106321c --- /dev/null +++ b/doc/man/doveadm-backup.1 @@ -0,0 +1 @@ +.so man1/doveadm-sync.1
\ No newline at end of file diff --git a/doc/man/doveadm-batch.1.in b/doc/man/doveadm-batch.1.in new file mode 100644 index 0000000..778c3fa --- /dev/null +++ b/doc/man/doveadm-batch.1.in @@ -0,0 +1,103 @@ +.\" Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-BATCH 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-batch \- Execute multiple commands for multiple users +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " batch " [" \-S +.IR socket_path "] " +.BI \-A " sep command sep command" +[...] +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " batch " [" \-S +.IR socket_path "] " +.BI \-F " file sep command sep command" +[...] +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " batch " [" \-S +.IR socket_path "] " +.BI \-u " usermask sep command sep command" +[...] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The command +.B doveadm batch +is used to execute multiple +.BR doveadm (1) +.IR command s +sequentially for multiple users. +This is primarily an optimization where Dovecot can do all the mailbox +operations for the same user at once, instead of having to go through +the users multiple times. +.PP +In the first form +.BR doveadm (1) +will loop over all users, defined in the configured +.IR user_db (s), +and execute the sequence of +.IR command s +for each of them. +.PP +In the second form +.BR doveadm (1) +will loop over all users, listed in the given +.IR file . +.PP +In the third form the +.IR command s +will be executed for each user matching the given +.IR usermask . +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I command +Any +.BR doveadm (1) +command, with arguments and options \(em except for the +.BR \-A ", " \-S " and " \-u " options." +.\"------------------------------------- +.TP +.I sep +A single character used as command separator, e.g. \(aq:\(aq. +Be careful, unquoted characters, like +.BR ; " or " & , +may be interpreted by your shell and +.BR doveadm (1) +will never see them. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +In this example we move seen mails, older than one month, for all +example.net users to the alternative storage under /nfsmount: +.br +.nf +mail_location = mdbox:~/mdbox:ALT=/nfsmount/%h/mdbox +.fi +The second command will remove messages with refcount=0 from the +primary storage. +.PP +.nf +.ft B +doveadm batch \-u \(rs*@example.net : altmove seen savedbefore 30d : purge +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-config.1 b/doc/man/doveadm-config.1 new file mode 100644 index 0000000..e6fe3ec --- /dev/null +++ b/doc/man/doveadm-config.1 @@ -0,0 +1 @@ +.so man1/doveconf.1
\ No newline at end of file diff --git a/doc/man/doveadm-copy.1 b/doc/man/doveadm-copy.1 new file mode 100644 index 0000000..2880406 --- /dev/null +++ b/doc/man/doveadm-copy.1 @@ -0,0 +1 @@ +.so man1/doveadm-move.1 diff --git a/doc/man/doveadm-deduplicate.1.in b/doc/man/doveadm-deduplicate.1.in new file mode 100644 index 0000000..52fd9d3 --- /dev/null +++ b/doc/man/doveadm-deduplicate.1.in @@ -0,0 +1,93 @@ +.\" Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-DEDUPLICATE 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-deduplicate \- expunge duplicate messages +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " deduplicate " [" \-u +.IR user |\c +.BR \-A |\c +.BI \-F " file" \c +.RB "] [" \-S +.IR socket_path "] ["\c +.BR \-m ] +.I search_query +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command is used to expunge duplicated messages in mailboxes. +.B doveadm deduplicate +is mainly useful to revert some (more or less) accidental duplication of +messages, e.g. after +.BR "doveadm copy" " or " "doveadm import" . +.BR doveadm (1) +will delete the newest duplicated messages from the mailbox and keep the +oldest. +.br +Deduplication across multiple mailboxes is not supported. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\"------------------------------------- +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +.TP +.B \-m +if the +.B \-m +option is given, +.BR doveadm (1) +will deduplicate by Message\-Id header. +By default deduplication will be done by message GUIDs. +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I search_query +expunge duplicates found from messages matching the given search query. +Typically a search query like \(aq\fBmailbox\fP \fImailbox_name\fP +\fBOR mailbox\fP \fIother_box\fP\(aq will be sufficient. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example shows how to list and expunge duplicate messages from a +mailbox. +.sp +.nf +.ft B +doveadm \-f table fetch \-u jane \(aqguid uid\(aq mailbox a_Box | sort +.ft P +guid uid +8aad0f0a30169f4bea620000ca356bad 18751 +8aad0f0a30169f4bea620000ca356bad 18756 +923e301ab9219b4b4f440000ca356bad 18748 +923e301ab9219b4b4f440000ca356bad 18753 +\&... +.ft B +doveadm deduplicate \-u jane mailbox a_Box +doveadm \-f table fetch \-u jane \(aqguid uid\(aq mailbox a_Box | sort +.ft P +guid uid +8aad0f0a30169f4bea620000ca356bad 18751 +923e301ab9219b4b4f440000ca356bad 18748 +a7999e1530739c4bd26d0000ca356bad 18749 +\&... +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-copy (1), +.BR doveadm\-fetch (1), +.BR doveadm\-import (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-director.1.in b/doc/man/doveadm-director.1.in new file mode 100644 index 0000000..2a2c688 --- /dev/null +++ b/doc/man/doveadm-director.1.in @@ -0,0 +1,283 @@ +.\" Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-DIRECTOR 1 "2014-08-30" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-director \- Manage Dovecot directors +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI director \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm director +can be used to manage and query the status of the list of backend mail +servers where Dovecot proxy can redirect connections to. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.BI \-a\ director_socket_path +This option is used to specify an alternative socket. +The option\(aqs argument is either an absolute path to a local UNIX domain +socket, or a hostname and port +.RI ( hostname : port ), +in order to connect a remote host via a TCP socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/director\-admin . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I host +A mail server\(aqs hostname or IP address. +.\"------------------------------------- +.TP +.I ip +A director\(aqs IP address. +.\"------------------------------------- +.TP +.I port +The TCP port, on which the director server is listening for connections. +The default port is the same as what the local director is listening in. +.\"------------------------------------- +.TP +.I user +Is a +.IR user \(aqs +login name. +Depending on the configuration, a login name may be for example +.BR jane " or " john@example.com . +.\"------------------------------------- +.TP +.I vhost_count +The number of \(dqvirtual hosts\(dq to assign to this server. The higher +the number is relative to other servers, the more connections it gets. The +default is 100. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS director add +.B doveadm director add +[\fB\-a\fP \fIdirector_socket_path\fP] +.I host +.RI [ vhost_count ] +.PP +The command\(aqs tasks are: +.TP 4 +* +assign a new mail server to the director. +.TP +* +increase/decrease the +.I vhost_count +of an already assigned server. +.PP +.\"------------------------------------- +.SS director dump +.B doveadm director dump +[\fB\-a\fP \fIdirector_socket_path\fP] +.PP +Dump the current host configuration as doveadm commands. These commands can +be easily run after a full director cluster restart to get back to the +dumped state. +.\"------------------------------------- +.SS director flush +.B doveadm director flush +[\fB\-a\fP \fIdirector_socket_path\fP] +[\fB\-F\fP] +[\fB\-\-max\-parallel\fP \fIn\fP] +\fIhost\fP|\fBall\fP +.PP +.B doveadm director flush +removes all user associations either from the given +.I host +or +.B all +hosts. All the existing connections will be kicked. If +.B director_flush_socket +is specified, a flush script is also automatically executed. +.PP +Because the kicking and moving of users to new backends creates a temporary +load spike, all the users aren\'t moved at once. The +.B \-\-max\-parallel +parameter specifies how many users can be moved concurrently. +The default is 100. +.PP +If the +.B \-F +parameter is used, the user associations are simply dropped. Existing +connections won\'t be kicked and flush scripts aren\'t run. +.\"------------------------------------- +.SS director kick +.B doveadm director kick +[\fB\-a\fP \fIdirector_socket_path\fP] +.I user +.PP +Kick the specified +.I user +from the entire Dovecot cluster. +This is similar to doveadm proxy kick, but this command needs to be run +only once instead of in each director server. +.\"------------------------------------- +.SS director map +.B doveadm director map +[\fB\-a\fP \fIdirector_socket_path\fP] +[\fB\-f\fP \fIusers_file\fP] +[\fB\-h\fP|\fB\-u\fP] +.RI [ host ] +.PP +The command +.B doveadm director map +is used to list current +.IR user "\ \(->\ " host +mappings. Note that the director works using 32bit hashes which makes +collisions quite likely, so this command can\(aqt reliably list exactly +which users have recently logged in. +.PP +.TP +.BI \-f\ users_file +Path to a file containing all user names (one per line). +When given no +.I userdb +lookup will be performed. +This may be a helpful alternative when for example the network connection +to the LDAP or SQL server is slow. +.\"----------------- +.TP +.B \-h +Output all usernames, which match the given hash. +.\"----------------- +.TP +.B \-u +Output hash for the given username. +.\"----------------- +.TP +.I host +Specify a server\(aqs IP address or hostname, to list only mappings of the +given +.IR host . +.\"------------------------------------- +.SS director move +.B doveadm director move +[\fB\-a\fP \fIdirector_socket_path\fP] +.I user host +.PP +Move the +.I user +to the specified backend +.IR host . +If the +.I user +has any existing connections they will be killed. +.\"------------------------------------- +.SS director remove +.B doveadm director remove +[\fB\-a\fP \fIdirector_socket_path\fP] +.I host +.PP +Use this command in order to remove the given +.I host +from the director. +.\"------------------------------------- +.SS director ring add +.B doveadm director ring add +[\fB\-a\fP \fIdirector_socket_path\fP] +.IR ip \ [ port ] +.PP +Add a new director to the ring. +.\"------------------------------------- +.SS director ring remove +.B doveadm director ring remove +[\fB\-a\fP \fIdirector_socket_path\fP] +.IR ip \ [ port ] +.PP +Remove a director from the ring. +.\"------------------------------------- +.SS director ring status +.B doveadm director ring status +[\fB\-a\fP \fIdirector_socket_path\fP] +.PP +Show the status of all the directors currently in the ring. +.\"------------------------------------- +.SS director status +.B doveadm director status +[\fB\-a\fP \fIdirector_socket_path\fP] +.RI [ user ] +.PP +This command is used to show the current usage of all assigned mail +servers. +.br +When a user name is given, this command shows which server the +.I user +is currently assigned to, where the user will be assigned after the current +saved assignment gets removed and where the user would be assigned to if +the whole proxy cluster was restarted fresh. +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/10\-director.conf +Director specific settings. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Add a director with vhost count 150 (or change existing one\(aqs +vhost count to 150): +.PP +.nf +.B doveadm \-v director add x1357.imap.ha.example.net 150 +2001:db8:543:6861:143::1357: OK +.fi +.\"------------------------------------- +.PP +Remove a director: +.PP +.nf +.B doveadm director remove x1357.imap.ha.example.net +.fi +.\"------------------------------------- +.PP +Query the status of mail hosts in a director: +.PP +.nf +.B doveadm director status +mail server ip vhosts users +192.168.10.1 100 125 +192.168.10.2 100 144 +192.168.10.3 100 115 +.fi +.\"------------------------------------- +.PP +Query the status of a user\(aqs assignment: +.PP +.nf +.B doveadm director status user@example.com +Current: 192.168.10.1 (expires 2010\-06\-18 20:17:04) +Hashed: 192.168.10.2 +Initial config: 192.168.10.3 +.fi +.PP +This means that the user is currently assigned to mail server on IP +192.168.10.1. After all of user\(aqs connections have logged out, the +assignment will be removed (currently it looks like at 20:17:04, but +that may be increased). After the assignment has expired, the user will +next time be redirected to 192.168.10.2 (assuming no changes to director +settings). If the entire Dovecot proxy cluster was restarted, so that all +of the director configuration would revert back to its initial values, the +user would be redirected to 192.168.10.3. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-dump.1.in b/doc/man/doveadm-dump.1.in new file mode 100644 index 0000000..4582b4f --- /dev/null +++ b/doc/man/doveadm-dump.1.in @@ -0,0 +1,93 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-DUMP 1 "2014-08-24" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-dump \- Dump the content of Dovecot\(aqs binary mailbox index/log +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " dump " [" \-t +.IR type "] " path +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +Dovecot uses several binary index and log files in order to improve +performance for accessing mails. For some mailbox formats, such as sdbox +and mdbox, the index files are part of the format itself. +For details about index files, see also: http://wiki2.dovecot.org/IndexFiles +.PP +.B doveadm dump +is used to show the contents of those mailbox index/log files, in human +readable format. This is mainly useful for Dovecot developers when +debugging some problem. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.TP +.BI \-t\ type +the file type of the file to be dumped. +If the +.I type +was omitted, +.BR doveadm (1) +tries to detect the type of +.IR path . +.I type +can be: +.RS +.TP 12 +.B dbox +\(rA m.\c +.I n +(sdbox or mdbox mailbox file) +.TP +.B fts\-expunge\-log +Dump the list of expunged mails in +.IR dovecot\-expunges.log . +Currently used only by fts\-lucene. +.TP +.B fts\-lucene +Dump the list of indexed mails in +.I lucene\-indexes +directory +.TP +.B imapzlib +Uncompress an IMAP traffic log, which contains data compressed using the +IMAP COMPRESSION extension. +.TP +.B dcrypt-file +Dump metadata of a dcrypt encrypted file. +.TP +.B dcrypt-key +Dump metadata of a dcrypt key. +.TP +.B index +\(rA dovecot.index, dovecot.map.index +.TP +.B log +\(rA dovecot.index.log, dovecot.map.index.log +.TP +.B mailboxlog +\(rA dovecot.mailbox.log +.TP +.B thread +\(rA dovecot.index.thread +.RE +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I path +The path to the corresponding dbox storage, index or log file. +If only a directory is specified, doveadm tries to detect the type of files +under it and dumps them. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Look at the contents of a mailbox\(aqs index: +.PP +.nf +.B doveadm dump ~/Maildir/.work/ +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-exec.1.in b/doc/man/doveadm-exec.1.in new file mode 100644 index 0000000..dd4757c --- /dev/null +++ b/doc/man/doveadm-exec.1.in @@ -0,0 +1,47 @@ +.\" Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-EXEC 1 "2013-08-05" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-exec \- easily execute commands from Dovecot\(aqs libexec_dir +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " exec +.IR binary " [" "binary arguments" ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command allows administrators and local users to simply execute +commands from within +.IR libexec_dir . +So for example a logged in system user could start a pre\-authenticated +imap session, using the command: +.BR "doveadm exec imap" . +An administrator would use the command: +.B "doveadm exec imap \-u" +.IR username . +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I binary +the name of an executable located in +.IR @pkglibexecdir@ . +.\"------------------------------------- +.TP +.I binary arguments +options and arguments, which will be passed through to the +.IR binary . +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example demonstrates how to deliver a message from a file to a +user\(aqs mailbox. +.sp +.nf +.B doveadm exec dovecot\-lda \-d user@example.net \(rs +.B \-f admin@example.net < \(ti/stuff/welcome.msg +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR dovecot\-lda (1)
\ No newline at end of file diff --git a/doc/man/doveadm-expunge.1.in b/doc/man/doveadm-expunge.1.in new file mode 100644 index 0000000..34c3b5b --- /dev/null +++ b/doc/man/doveadm-expunge.1.in @@ -0,0 +1,101 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-EXPUNGE 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-expunge \- Expunge messages matching given search query +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " expunge " [" \-S +.IR socket_path ] +.RB [ \-d ] +.I search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " expunge " [" \-S +.IR socket_path ] +.RB [ \-d ] +.BI \-A " search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " expunge " [" \-S +.IR socket_path ] +.RB [ \-d ] +.BI \-F " file search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " expunge " [" \-S +.IR socket_path ] +.RB [ \-d ] +.BI \-u " user search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command can be used to expunge mails matching the given search query. +It is typically used to expunge old mails from users\(aq Trash and/or Spam +mailboxes. To test which messages a given search query would match, you can +use +.I doveadm fetch +or +.I doveadm search +commands. +.PP +In the first form, +.BR doveadm (1) +will execute the +.B expunge +action with the environment of the logged in system user. +.PP +In the second form, the command will be performed for all users. +.PP +In the third form, +.BR doveadm (1) +will expunge messages of the users listed +in the given +.IR file . +.PP +In the fourth form, only matching mails of the given +.IR user (s) +will be expunged. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +.TP +.B \-d +Delete the mailbox if it is empty after expunging. +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I search_query +Expunge messages matching this search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example expunges messages from Spam mailbox that were saved/copied +there more than two weeks ago: +.PP +.nf +.ft B +doveadm expunge \-u jane.doe@example.org mailbox Spam savedbefore 2w +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-fetch (1), +.BR doveadm\-purge (1), +.BR doveadm\-search (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-fetch.1.in b/doc/man/doveadm-fetch.1.in new file mode 100644 index 0000000..4cfc854 --- /dev/null +++ b/doc/man/doveadm-fetch.1.in @@ -0,0 +1,197 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-FETCH 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-fetch \- Fetch partial/full messages or message information +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR fetch " [" \-S +.IR socket_path "] " "fields search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR fetch " [" \-S +.IR socket_path "]" +.BI \-A " fields search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR fetch " [" \-S +.IR socket_path "]" +.BI \-F " file fields search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR fetch " [" \-S +.IR socket_path "]" +.BI \-u " user fields search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm fetch +can be used to fetch messages\(aq contents and metadata. This can be useful +for scripts and for debugging. If you want to fetch messages one at a time, +see +.BR doveadm\-search (1). +.IP Important: +Please respect your users\(aq privacy. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.BR pager . +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I fields +One or more result field names to display, if the +.I search_query +matches any messages. +In order to specify multiple fields, enclose them in single or double +quotes. +.br +Supported +.I fields +are: +.RS +.TP +.B body +.\"----------------- +The body of a message. +.TP +.B date.received +Date and time of final delivery, when the message was delivered to a +user\(aqs mailbox for the first time. +.br +The internal date and time of the source message, when the message was +copied by the IMAP COPY command. +.br +The date\-time attribute when present, otherwise the current time, when the +message was saved by the IMAP APPEND command. +.\"----------------- +.TP +.B date.saved +Date and time when the message was saved to mailbox. +.\"----------------- +.TP +.B date.sent +Date and time of the message\(aqs Date: header. +.\"----------------- +.TP +.B flags +A message\(aqs IMAP flags, e.g. \(rsSeen +.\"----------------- +.TP +.B guid +A message\(aqs globally unique identifier. +.\"----------------- +.TP +.B hdr +The header of the message. +.\"----------------- +.TP +.B imap.body +IMAP BODY output of the message (see RFC 3501). +.\"----------------- +.TP +.B imap.bodystructure +IMAP BODYSTRUCTURE output of the message (see RFC 3501). +.\"----------------- +.TP +.B imap.envelope +IMAP ENVELOPE output of the message (see RFC 3501). +.\"----------------- +.TP +.B mailbox +Name of the mailbox, in which the message is stored. The name is in UTF\-8. +.\"----------------- +.TP +.B mailbox\-guid +The globally unique identifier of the mailbox, in which the message is +located. +.\"----------------- +.TP +.B pop3.uidl +A message\(aqs unique (POP3) identifier within a mailbox. +.\"----------------- +.TP +.B seq +A message\(aqs sequence number in a mailbox. +.\"----------------- +.TP +.B size.physical +A message\(aqs physical size. +.\"----------------- +.TP +.B size.virtual +A message\(aqs virtual size, computed with CRLF line terminators. +.\"----------------- +.TP +.B text +The entire message (header and body). +.\"----------------- +.TP +.B text.utf8 +The entire message (header and body) \(em UTF\-8 encoded. +.\"----------------- +.TP +.B uid +A message\(aqs unique (IMAP) identifier in a mailbox. +.\"----------------- +.TP +.B user +A message owner\(aqs login name. +.\"----------------- +.RE +.\"------------------------------------- +.TP +.I search_query +Fetch messages matching this search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example based on the first example from +.BR doveadm\-search (1). +We are fetching the fields +.BR mailbox\ and\ date.sent +from user bob\(aqs mailbox with the guid +\(dq3a94c928d66ebe4bda04000015811c6a\(dq for the messages with the +UIDs +.BR 8 ,\ 25 \ and \ 45 . +.PP +.nf +.B doveadm fetch \-u bob \(dqmailbox date.sent\(dq \(rs +.B mailbox\-guid 3a94c928d66ebe4bda04000015811c6a uid 8,25,45 +mailbox: dovecot/pigeonhole/2.0 +date.sent: 2010\-01\-19 01:17:41 (+0100) +^L +mailbox: dovecot/pigeonhole/2.0 +date.sent: 2010\-01\-28 09:38:49 (+0100) +^L +mailbox: dovecot/pigeonhole/2.0 +date.sent: 2010\-03\-28 18:41:14 (+0200) +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-flags.1.in b/doc/man/doveadm-flags.1.in new file mode 100644 index 0000000..4e72d44 --- /dev/null +++ b/doc/man/doveadm-flags.1.in @@ -0,0 +1,120 @@ +.\" Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-FLAGS 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-flags \- add, remove or replace messages\(aq flags +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " flags " [" \-S +.IR socket_path "] " "command flags search_query" +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " flags " [" \-S +.IR socket_path "] " "command flags search_query" +.B \-A +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " flags " [" \-S +.IR socket_path "] " "command flags search_query" +.BI "\-F " file +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " flags " [" \-S +.IR socket_path "] " "command flags search_query" +.BI "\-u " user +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command is used to manipulate flags of messages. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\"------------------------------------- +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I flags +Message flags as described in RFC 3501, section 2.3.2 (Flags Message +Attribute): +.BR \(rsAnswered ", " \(rsDeleted ", " \(rsDraft ", " \(rsFlagged ", " +.BR \(rsRecent " and " \(rsSeen . +And the IMAP keywords +.BR \(DoForwarded ", " \(DoMDNSent ", " \(DoSubmitPending " and " +.B \(DoSubmitted +or user\-defined keywords, e.g. Junk, \(DoNonSpam or \(DoLabel1. +.br +One or multiple flags and/or keywords can be specified. +.\"------------------------------------- +.TP +.I search_query +Manipulate the flags of messages matching the given search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS flags add +.BR "doveadm flags add" " [" \-u +.IR user |\c +.BR \-A | \-F +.IR file ] +.RB [ \-S +.IR socket_path "] " "flags search_query" +.PP +This command is used to extend the current set of flags with the given +.IR flags . +.\"------------------------------------- +.SS flags remove +.BR "doveadm flags remove" " [" \-u +.IR user |\c +.BR \-A | \-F +.IR file ] +.RB [ \-S +.IR socket_path "] " "flags search_query" +.PP +In order to remove the given +.I flags +from the current set of flags, use this command. +.\"------------------------------------- +.SS flags replace +.BR "doveadm flags replace" " [" \-u +.IR user |\c +.BR \-A | \-F +.IR file ] +.RB [ \-S +.IR socket_path "] " "flags search_query" +.PP +This command is used to replace ALL current flags with the given +.IR flags . +.\"------------------------------------------------------------------------ +.SH EXAMPLE +List and manipulate the message flags of the message with uid 81563 +.sp +.nf +.ft B +doveadm fetch \-u bob \(aquid flags\(aq mailbox dovecot uid 81563 +.ft P +uid: 81563 +flags: \(rsAnswered \(rsSeen NonJunk + +.ft B +doveadm flags remove \-u bob NonJunk mailbox dovecot uid 81563 +doveadm flags add \-u bob \(aq\(rsFlagged \(DoForwarded\(aq \ +mailbox dovecot uid 81563 +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-fetch (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-force-resync.1.in b/doc/man/doveadm-force-resync.1.in new file mode 100644 index 0000000..1e23e75 --- /dev/null +++ b/doc/man/doveadm-force-resync.1.in @@ -0,0 +1,65 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-FORCE\-RESYNC 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-force\-resync \- Repair broken mailboxes +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " force\-resync " [" \-S +.IR socket_path "] " mailbox +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " force\-resync " [" \-S +.IR socket_path "] " +.BI \-A \ mailbox +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " force\-resync " [" \-S +.IR socket_path "] " +.BI "\-F" " file mailbox" +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " force\-resync " [" \-S +.IR socket_path "] " +.BI \-u " user mailbox" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +Under certain circumstances it may happen, that +.BR dovecot (1) +is unable to automatically solve problems with mailboxes. +In such situations the +.B force\-resync +command may be helpful. +It tries to fix all problems. +For sdbox and mdbox mailboxes the storage files will be also checked. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I mailbox +The name of the mailbox to fix. With mdbox all of the mailboxes are fixed, +so you can use for example INBOX as the name. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Fix bob\(aqs INBOX: +.PP +.nf +.B doveadm force\-resync \-u bob INBOX +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-fs.1.in b/doc/man/doveadm-fs.1.in new file mode 100644 index 0000000..53946a5 --- /dev/null +++ b/doc/man/doveadm-fs.1.in @@ -0,0 +1,93 @@ +.\" Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-PROXY 1 "2016-04-26" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-fs \- Interact with the abstract mail storage filesystem +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI fs \ command +.RI [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm fs +.I commands +are used to abstractly interact with the storage backend defined in the +Dovecot configuration. It allows access to the mailbox structure without +needing to know details of how the storage backend is architected. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the +.B table +output formatter. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS fs copy +.B doveadm fs copy +.I fs-driver +.I fs-args +.I source-path +.I dest-path +.PP +Copy source path to the destination path. +.\"------------------------------------- +.SS fs delete +.B doveadm fs delete +[\fB\-R\fP] [\fB\-n\fP \fIcount\fP] +.I fs-driver +.I fs-args +.I path +[\fIpath\fP ...] +.PP +Delete all data associated with the path provided. +.\"------------------------------------- +.SS fs get +.B doveadm fs get +.I fs-driver +.I fs-args +.I path +.PP +Retrieve data associated with the path provided. +.\"------------------------------------- +.SS fs iter +.B doveadm fs iter +.I fs-driver +.I fs-args +.I path +.PP +Iterate through all data files in the path provided. +.\"------------------------------------- +.SS fs iter-dirs +.B doveadm fs iter-dirs +.I fs-driver +.I fs-args +.I path +.PP +Iterate through all directories in the path provided. +.\"------------------------------------- +.SS fs put +.B doveadm fs put +[\fB\-h\fP \fIhash\fP] +.I fs-driver +.I fs-args +.I input_path +.I path +.PP +Store data at the path provided. +.\"------------------------------------- +.SS fs stat +.B doveadm fs stat +.I fs-driver +.I fs-args +.I path +.PP +Retrieve files status for the path provided. Currently, only the total size +(in bytes) of the item is returned. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1) diff --git a/doc/man/doveadm-fts.1.in b/doc/man/doveadm-fts.1.in new file mode 100644 index 0000000..0c9e6a1 --- /dev/null +++ b/doc/man/doveadm-fts.1.in @@ -0,0 +1,168 @@ +.\" Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-FTS 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-fts \- Manipulate the Full Text Search (FTS) index +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +.\" [\fB\-f\fP \fIformatter\fP] +.BI fts \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +doveadm fts +.I COMMANDS +can be used to manipulate the Full Text Search (FTS) index. +.\"------------------------------------------------------------------------ +.\" @INCLUDE:global-options-formatter@ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.B flow +(without the +.IR key = +prefix). +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I namespace +The name of a namespace, e.g. the name of the shared namespace. +When no namespace was given, the user\(aqs private namespace will be used. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS fts optimize +.B doveadm fts optimize +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RI [ namespace ] +.PP +Optimize the full text search index. +This is also done automatically by the full text search engines, but this +enforces it to happen. +.\"------------------------------------- +.SS fts rescan +.B doveadm fts rescan +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RI [ namespace ] +.PP +Scan what mails exist in the full text search index and compare those to +what actually exist in mailboxes. +This removes mails from the index that have already been expunged and +makes sure that the next +.B doveadm index +will index all the missing mails (if any). Note that currently most FTS +backends do not implement this properly, but instead they delete all the +FTS indexes. This may change in the future versions. +.\"------------------------------------- +.SS fts check fast +.B doveadm fts check fast +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RI [ \--refresh ] +.RI [ \--print-mismatches-only ] +.RI [ namespace ] +.PP +This command exists only when the fts_dovecot plugin (Dovecot Pro FTS) is +loaded. +.PP +This command can be used to check FTS indexes for consistency. It performs +a fast check using only information in local caches (fts.S, metacache). +.PP +.\"------------------------------------- +.TP +.B \--refresh +Refresh any necessary local caches for the command to run successfully. +This can be used if the command otherwise fails with exit code 68. +.\"------------------------------------- +.TP +.B \--print-mismatches-only +Print only mailboxes that have inconsistencies. +.\"------------------------------------- +.RE +.PP +Exit codes: +.PP +.\"------------------------------------- +.TP +.B 0 +The mailbox is fully consistent +.\"------------------------------------- +.TP +.B 2 +The mailbox is not fully consistent +.\"------------------------------------- +.TP +.B 68 +There is not enough information in local metacache to know whether the +mailbox is fully consistent. Use either the +.B \--refresh +parameter or the "full" check. +.\"------------------------------------- +.RE +.PP +.\"------------------------------------- +.SS fts check full +.B doveadm fts check full +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RI [ \--print-details ] +.RI [ \--print-mismatches-only ] +.RI [ namespace ] +.PP +This command exists only when the fts_dovecot plugin (Dovecot Pro FTS) is +loaded. +.PP +This command can be used to check FTS indexes for consistency. It performs +a full check to give detailed output of inconsistencies. +.PP +.\"------------------------------------- +.TP +.B \--print-details +Print also IMAP UID numbers and FTS triplet names for each email. +.\"------------------------------------- +.TP +.B \--print-mismatches-only +Print only mailboxes (or emails, with +.B \--print-details +that have inconsistencies. +.\"------------------------------------- +.RE +.PP +Exit codes: +.PP +.\"------------------------------------- +.TP +.B 0 +The mailbox is fully consistent +.\"------------------------------------- +.TP +.B 2 +The mailbox is not fully consistent +.\"------------------------------------- +.RE +.PP +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-index (1) +.\"------------------------------------- +.PP +Additional resources: +.IP "Full text search indexing" +http://wiki2.dovecot.org/Plugins/FTS
\ No newline at end of file diff --git a/doc/man/doveadm-help.1.in b/doc/man/doveadm-help.1.in new file mode 100644 index 0000000..83064ba --- /dev/null +++ b/doc/man/doveadm-help.1.in @@ -0,0 +1,36 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-HELP 1 "2010-06-22" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-help \- Show information about doveadm commands +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " help +.RI [ command ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.br +With no +.I command +argument given, +.B doveadm help +will print: +.TP 4 +* +the synopsis for the most of the +.BR doveadm (1) +commands. +.TP +* +groups of commands, e.g. +.BR log " or " mailbox . +.PP +When the name of a +.I command +(or a group) was given, it will show the man page for that command. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-import.1.in b/doc/man/doveadm-import.1.in new file mode 100644 index 0000000..cec27e9 --- /dev/null +++ b/doc/man/doveadm-import.1.in @@ -0,0 +1,142 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-IMPORT 1 "2015-08-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-import \- Import messages matching given search query +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " import " [" \-S +.IR socket_path ] +.RB [ \-U +.IR source_user ] +.RB [ \-s ] +.I source_location dest_parent search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " import " [" \-S +.IR socket_path ] +.RB [ \-U +.IR source_user ] +.RB [ \-s ] +.BI \-A " source_location dest_parent search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " import " [" \-S +.IR socket_path ] +.RB [ \-s ] +.BI \-F " file source_location dest_parent search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " import " [" \-S +.IR socket_path ] +.RB [ \-U +.IR source_user ] +.RB [ \-s ] +.BI \-u " user source_location dest_parent search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +This command can be used to import mails from another mail storage specified by +.I source_location +to one or more user\(aqs mailboxes. All the mailboxes are imported under the +given +.I dest_parent +mailbox, or to root level if +.I dest_parent +is empty (\(dq\(dq). The +.I search_query +can be used to restrict which mailboxes or messages are imported. By default +the import is done in destination user's context, you can use \-U to change +this. + +In the first form, +.BR doveadm (1) +will executed the +.B import +action with the environment of the logged in system user. +.PP +In the second form, the mails will be imported for all users. +.PP +In the third form, the mails will be imported for all users listed in the +given +.IR file . +.PP +In the fourth form, the mails will be imported only for given +.IR user (s). +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +.TP +.B \-s +When the +.B \-s +option is present, +.I dest_parent +and all new mailboxes under it will be subscribed to. +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.TP +.B \-U username +When the +.B \-U +option is present, the source box is opened with given username. +.SH ARGUMENTS +.TP +.I dest_parent +The name of the destination mailbox, under which the mails should be +imported. +.BR doveadm (1) +will create the +.I dest_parent +mailbox if it doesn\(aqt exist. +.TP +.I search_query +Copy messages matching this search query. +See +.BR doveadm\-search\-query (7) +for details. +.TP +.I source_location +This argument specifies the mailbox format and location of the source +location. The syntax is the same as for the +.I mail_location +setting. +For example: +.B maildir:/backup/20101126/jane.doe/Maildir +or +.B mdbox:/srv/mail/john.doe/mdbox:ALT=/nfsmount/john.doe/mdbox +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example imports all mails from a backup under a +.I backup\-20101026 +mailbox: +.PP +.nf +.B doveadm import \-u jane.doe@example.org \(rs +.B mdbox:/backup/20101026/jane.doe/mdbox backup\-20101026 all +.fi +.PP +Another example that imports only messages from foo@example.org in the +backup mdbox\(aqs INBOX to jane\(aqs INBOX: +.PP +.nf +.B doveadm import \-u jane.doe@example.org \(rs +.B mdbox:~/mdbox\-backup \(dq\(dq mailbox INBOX from foo@example.org +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-fetch (1), +.BR doveadm\-search (1), +.BR doveadm\-search\-query (7) diff --git a/doc/man/doveadm-index.1.in b/doc/man/doveadm-index.1.in new file mode 100644 index 0000000..dafeb16 --- /dev/null +++ b/doc/man/doveadm-index.1.in @@ -0,0 +1,102 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-INDEX 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-index \- Index mailboxes +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " index " [" \-S +.IR socket_path ] +.RB [ \-q "] [" \-n +.IR max_recent "] " mailbox +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " index " [" \-S +.IR socket_path "] " +.B \-A +.RB [ \-q "] [" \-n +.IR max_recent "] " mailbox +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " index " [" \-S +.IR socket_path "] " +.BI \-F " file" +.RB [ \-q "] [" \-n +.IR max_recent "] " mailbox +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " index " [" \-S +.IR socket_path "] " +.BI \-u \ user +.RB [ \-q "] [" \-n +.IR max_recent "] " mailbox +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +Add unindexed messages in a mailbox into index/cache file. If full text +search is enabled, also add unindexed messages to the fts database. +.PP +The caching adds only the fields that were previously added to the +mailbox\(aqs caching decisions, so it won\(aqt do anything useful for +mailboxes that user\(aqs client hasn\(aqt accessed yet. You can use +.B doveadm dump +command to show a specific mailbox\(aqs current caching decisions. +.PP +Messages can also be added automatically to full text search index using: +.sp +.nf +plugin { + ... + fts_autoindex = yes +} +.fi +in +.IR @pkgsysconfdir@/conf.d/90\-plugin.conf . +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +.TP +.BI \-n \ max_recent +An integer value, which specifies the maximum number of \(rsRecent +messages in mailboxes. +If the mailbox contains more than +.I max_recent +messages with \(rsRecent flag set, the mailbox will not be indexed. +This may be useful to avoid unnecessary indexing for large mailboxes that +are never opened. +.\"------------------------------------- +.TP +.B \-q +Queues the indexing to be run by indexer process. +Without \-q the indexing is done directly by the +.BR doveadm (1) +process. +Some backends like fts\-lucene can\(aqt handle multiple processes updating +the indexes simultaneously, so \-q should usually be used on production. +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I mailbox +The name of the mailbox to index. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Index bob\(aqs INBOX: +.PP +.nf +.B doveadm index \-u bob INBOX +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-instance.1.in b/doc/man/doveadm-instance.1.in new file mode 100644 index 0000000..b3e5dc9 --- /dev/null +++ b/doc/man/doveadm-instance.1.in @@ -0,0 +1,63 @@ +.\" Copyright (c) 2012-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-INSTANCE 1 "2012-02-16" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-instance \- Manage the list of running Dovecot instances +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.B instance list +.br +.BR doveadm " [" \-Dv "] " "instance remove" +.IR name " | " base_dir +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm instance +commands are used to manage the list of Dovecot instances running on the +server. +In most installations there is only one Dovecot instance, but in some cases +is may be useful to have more (e.g. running director proxy and backend in +the same server). +.PP +Instances are added to the list automatically when Dovecot is started. +Each instance is uniquely identified by its +.I base_dir +setting. +Instances can be named by setting +.I instance_name +in each instance\(aqs +.IR dovecot.conf . +When an instance is named, it can be accessed easily by giving +.BI \-i\ instance_name +command line parameter for Dovecot binaries (e.g. doveadm). +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I name +The value of an instance\(aqs +.I instance_name +setting. +.\"------------------------------------- +.TP +.I base_dir +The base directory of a Dovecot instance. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS instance list +.B doveadm instance list +.PP +This command lists the seen Dovecot instances. +.\"------------------------------------- +.SS instance remove +.B doveadm instance remove +.IR name " | " base_dir +.PP +This command removes the specified instance. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-kick.1.in b/doc/man/doveadm-kick.1.in new file mode 100644 index 0000000..4bf10ed --- /dev/null +++ b/doc/man/doveadm-kick.1.in @@ -0,0 +1,138 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-KICK 1 "2010-06-12" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-kick \- Disconnect users by user name and/or IP address +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " kick " [ \-a +.IR anvil_socket_path ] +.RB [ \-f ] +.I user +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " kick " [ \-a +.IR anvil_socket_path ] +.RB [ \-f ] +\fIip\fP[\fB/\fP\fImask\fP] +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " kick " [ \-a +.IR anvil_socket_path ] +.RB [ \-f ] +.I user +\fIip\fP[\fB/\fP\fImask\fP] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.BR doveadm \(aqs\ kick +command is used to disconnect users by +.I user +name and/or the +.I ip +address, from which they are connected. +.PP +In the first form, all users, whose login name matches the +.I user +argument, will be disconnected. +.PP +In the second form, all users, connected from the given IP address or +network range, will be disconnected. +.PP +In the last form, only users connected from the given IP address or +networks range and a matching login name will be disconnected. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.BI \-a\ anvil_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/anvil . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------- +.TP +.B \-f +Enforce the disconnect, even when there are multiple +.IR user s, +from different networks, connected to a single process. +This option may be only required when you have configured something like: +.sp +.nf +service imap { + ... + client_limit = \fI1+n\fP + service_count = 0 + ... +} +.fi +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.IR ip [/ mask ] +.I ip +or +.IB ip /\c +.I mask +is the host or network, from which the users are connected. +.\"------------------------------------- +.TP +.I user +Is a +.IR user \(aqs +login name. +Depending on the configuration, a login name may be for example +.BR jane " or " john@example.com . +It\(aqs also possible to use +.RB \(aq * \(aq +and +.RB \(aq ? \(aq +wildcards (e.g. \-u *@example.org). +.\"------------------------------------------------------------------------ +.SH EXAMPLE +If you don\(aqt want to disconnect all users at once, you can check +who\(aqs currently logged in. +The first example demonstrates how to disconnect all users whose login name +is 3 characters long and begins with +.BR ba . +.sp +.nf +.B doveadm who \-1 ja* +username proto pid ip +jane imap 8192 ::1 +james imap 8203 2001:db8:543:2::1 +.B doveadm kick ba? +kicked connections from the following users: +bar baz +.fi +.PP +The next example shows how to kick user foo\(aqs connections from 192.0.2.*. +.sp +.nf +.B doveadm who \-1 foo +username proto pid ip +foo imap 8135 fd95:4eed:38ba::25 +foo imap 9112 192.0.2.53 +foo imap 8216 192.0.2.111 +.B doveadm kick foo 192.0.2.0/24 +kicked connections from the following users: +foo +.B doveadm who f* +username # proto (pids) (ips) +foo 1 imap (8135) (fd95:4eed:38ba::25) +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-who (1)
\ No newline at end of file diff --git a/doc/man/doveadm-log.1.in b/doc/man/doveadm-log.1.in new file mode 100644 index 0000000..6662d7d --- /dev/null +++ b/doc/man/doveadm-log.1.in @@ -0,0 +1,122 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-LOG 1 "2013-11-24" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-log \- Locate, test or reopen Dovecot\(aqs log files +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " "log errors" " [" \-s +.IR min_timestamp ] +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " "log find" +.RI [ directory ] +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " "log reopen" +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " "log test" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm log +.I commands +are used to locate and reopen the log files of +.BR dovecot (1). +It\(aqs also possible to test the configured targets of the +.I *log_path +settings. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS log errors +.BR "doveadm log errors" " [" \-s +.IR min_timestamp ] +.PP +The +.B log errors +command is used to show the last \- up to 1,000 \- errors and warnings. +If no output is generated, no errors have occurred since the last start. +.PP +.TP +.BI \-s \ min_timestamp +An integer value, representing seconds since the epoch \- also known as +Unix timestamp. +When a min_timestamp was given, +.BR doveadm (1) +will only show errors occurred since that point in time. +.\"------------------------------------- +.SS log find +.B doveadm log find +.RI [ directory ] +.PP +The +.B log find +command is used to show the location of the log files, to which +.BR dovecot (1) +sends its log messages. +If +.BR dovecot (1) +logs its messages through +.BR syslogd (8) +and +.BR doveadm (1) +could not find any log files, you can specify the +.I directory +where your syslogd writes its log files. +.\"------------------------------------- +.SS log reopen +.B doveadm log reopen +.PP +This command causes +.B doveadm +to send a SIGUSR1 signal to master process, which causes it to +reopen all log files configured in the +.IR log_path , +.I info_log_path +and +.I debug_log_path +settings. +These settings are configured in +.IR @pkgsysconfdir@/conf.d/10\-logging.conf . +.br +The master process also signals the log process to do the same. +This is mainly useful after manually rotating the log files. +.\"------------------------------------- +.SS log test +.B doveadm log test +.PP +This command causes +.B doveadm +to write the message \(dqThis is Dovecot\(aqs +.I priority +log +.RI ( timestamp )\(dq +to the configured log files. +The used priorities are: +.BR debug , +.BR info , +.BR warning , +.BR error +and +.BR fatal . +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example shows how to locate the log files used by +.BR dovecot (1). +.sp +.nf +.B doveadm log find +Looking for log files from /var/log +Debug: /var/log/dovecot.debug +Info: /var/log/mail.log +Warning: /var/log/mail.log +Error: /var/log/mail.log +Fatal: /var/log/mail.log +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-mailbox-cryptokey.1.in b/doc/man/doveadm-mailbox-cryptokey.1.in new file mode 100644 index 0000000..c6ebf66 --- /dev/null +++ b/doc/man/doveadm-mailbox-cryptokey.1.in @@ -0,0 +1,96 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-MAILBOX\-CRYPTOKEY 1 "2016-01-12" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-mailbox\-cryptokey \- Mail crypt plugin management +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " -o +.IR plugin/mail_crypt_private_password=password " +.BR [ " \-Dv " ] [ " \-f +.IR formatter " ] +.BR " mailbox cryptokey export|generate|list|password " [ " \-u +.IR username +.BR | " \-A " ] [ " \-S " ] [ " \-F " +.IR file " ] +.BR [ " +.IR other " +.IR options " ] +.br +.SH DESCRIPTION +Generate new keypair for user or folder. The new keypair is marked as active. +.SH OPTIONS +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.TP +.BI \-o\ plugin/mail_crypt_private_password=password +Dovecot option, needed if you use password protected keys +.SH SUBCOMMANDS +.BR export " [ " \-U " ] " | +.IR mailbox-mask +.TP +.B \-U +Operate on user keypair only +.PP +Exports user's or folder's keypair(s) in PEM format. +If the keys are password protected, \-o is needed. +.PP +.\"------------------------------------------------------------------------ +.BR generate " [ " \-Rf " [ " \-U " ] " | +.IR mailbox-mask " ] +.TP +.B \-U +Operate on user keypair only +.TP +.BI \-R +Re-encrypt all folder keys with current active user key +.TP +.B \-f +Force keypair creation, normally keypair is only created if none found +.PP +Generates new keypair for user or folder. If you want to generate new user key +and use it to secure your folder keys, use generate \-u username \-UR. +.PP +If you want to password-protect your key here, use \-o. +.PP +.\"------------------------------------------------------------------------ +.BR list " [ " \-U " ] " | +.IR mailbox-mask +.TP +.B \-U +Operate on user keypair only +.PP +List all keys for user or folder. No password is required. +.PP +.\"------------------------------------------------------------------------ +.BR password " [ " \-N " | " \-n +.IR password " ] +.BR " [ " \-O " | " \-o +.IR password " ] +.BR [ " \-C " ] +.TP +.B \-O +Ask for old password +.TP +.BI \-o\ old-password +Provide old password +.TP +.B \-N +Ask for new password +.TP +.BI \-n\ new-password +Provide new password +.TP +.B \-C +Clear (unset/remove) password. Your key will not be protected by password. +.PP +Set, change or clear password from your user key. +.SH SEE ALSO +.BR doveadm(1) diff --git a/doc/man/doveadm-mailbox.1.in b/doc/man/doveadm-mailbox.1.in new file mode 100644 index 0000000..8e0bfee --- /dev/null +++ b/doc/man/doveadm-mailbox.1.in @@ -0,0 +1,409 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-MAILBOX 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-mailbox \- Commands related to handling mailboxes +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter "] " mailbox_cmd " [" options "] [" arguments ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm mailbox +can be used to query and modify mailboxes. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I mailbox +Is the name of a +.IR mailbox , +as visible to IMAP clients, except in UTF\-8 format. The hierarchy +separator between a parent and child mailbox is commonly +.RB \(aq / \(aq +or +.RB \(aq . \(aq, +but this depends on your selected mailbox storage format and namespace +configuration. The mailbox names may also require a namespace prefix. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS mailbox create +.B doveadm mailbox create +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-g +.IR guid ] +.RB [ \-s ] +.IR mailbox\ ... +.PP +This command is used to create one or more mailboxes. +The mailbox format of the created mailboxes depends on the +.I mail_location +setting, or the user\(aqs +.I mail +field, returned by the userdb. +.PP +.TP +.BI \-g \ guid +Create the mailbox with the specified GUID. +.TP +.B \-s +When this +option was given, the created mailboxes will be also added to the user\(aqs +subscriptions. +.\"------------------------------------------------------------------------ +.SS mailbox cryptokey +.B mailbox cryptokey export|generate|list|password +.PP +This command is used to manage mail crypt plugin cryptographic keys. +Please see doveadm-mailbox-cryptokey(1) for more details. +.\"------------------------------------------------------------------------ +.SS mailbox delete +.B doveadm mailbox delete +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-s ] +.RB [ \-r ] +.RB [ \-e ] +.RB [ \-Z ] +.IR mailbox\ ... +.PP +This command deletes a mailbox and expunges all the messages it contains. +If the mailbox has any children, they won\(aqt be deleted, unless +.B \-r +is given. +.PP +.\"------------------------------------- +.TP +.B \-r +Delete mailboxes recursively +.\"------------------------------------- +.TP +.B \-s +Unsubscribe deleted mailboxes. +.\"------------------------------------- +.TP +.B \-e +Require mailboxes to be empty before deleting. +.\"------------------------------------- +.TP +.B \-Z +Delete the mailbox as efficiently as possible, but the user may not be in fully consistent state afterwards. For example quota may be wrong. This option is mainly useful when deleting the entire user. +.\"------------------------------------------------------------------------ +.SS mailbox list +.B doveadm mailbox list +.RB [ \-7 | \-8 ] +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-s ] +[\fImailbox\fP ...] +.PP +To get an overview of existing mailboxes use this command. +It\(aqs also possible to use wildcards in the +.I mailbox +name. +.br +When the +.B \-s +option is present, only subscribed mailboxes will be listed. Listed +subscriptions may also contain mailboxes that are already deleted. +.PP +.\"------------------------------------- +.TP +.B \-7 +Lists the mailboxes with mUTF\-7 encoding. +.\"------------------------------------- +.TP +.B \-8 +Lists the mailboxes with UTF\-8 encoding. +.\"------------------------------------------------------------------------ +.SS mailbox mutf7 +.B doveadm mailbox mutf7 +.RB [ \-7 | \-8 ] +.IR name\ ... +.PP +The +.B mailbox mutf7 +command may be used to convert the international mailbox +.I name +into a modified version of the UTF\-7 encoding and vice versa. +See RFC 3501, section 5.1.3 (Mailbox International Naming Convention). +.PP +.\"------------------------------------- +.TP +.B \-7 +Indicates that the +.IR name \(aqs +string representation is mUTF\-7 encoded and it should be converted to +UTF\-8. +.\"------------------------------------- +.TP +.B \-8 +Indicates that the +.IR name \(aqs +is UTF\-8 encoded and should be converted to mUTF\-7 (default). +.TP +.I name +One or more mailbox names that should be converted. +.\"------------------------------------------------------------------------ +.SS mailbox rename +.B doveadm mailbox rename +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-s ] +.I old_name +.I new_name +.PP +The +.B mailbox rename +command is used to rename the mailbox +.I old_name +to +.IR new_name . +.br +When the +.B \-s +option is given, +.I old_name +will be unsubscribed +and +.I new_name +will be subscribed. +.\"------------------------------------------------------------------------ +.SS mailbox status +.BR doveadm " [" \-f +.IR formatter ] +.B mailbox status +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] [\fB\-t\fP] +.IR "fields mailbox\ " ... +.PP +Show the +.B status +of one or more mailboxes. +The +.I mailbox +name may also contain wildcards. +.br +This command uses by default the output +.I formatter +.BR flow . +.TP +.B \-t +Summarize the values of the status +.I fields +.BR messages , +.BR recent , +.BR unseen " and/or" +.B vsize +of multiple mailboxes to a sum (total). +.\"------------------------------------- +.TP +.I fields +Specify the status +.I fields +which should be shown. +In order to specify multiple status +.IR fields , +enclosed them in quotes. +.RS +.TP +.B all +This is a special status field name. +It means show all of the following +.IR fields . +When the +.B \-t +option is present, it means show only the +.BR messages , +.BR recent , +.BR unseen " and" +.B vsize +.IR fields . +.TP +.B guid +The +.IR mailbox \(aqs +globally unique identifier. +.TP +.B highestmodseq +The highest mod\-sequence value of all messages in the +.IR mailbox . +.TP +.B messages +The number of messages in the +.IR mailbox . +.TP +.B recent +The number of messages with the \(rsRecent flag set. +.TP +.B uidnext +The next unique identifier value. +.TP +.B uidvalidity +The unique identifier validity value. +.TP +.B unseen +The message sequence number of the first unseen message in the +.IR mailbox . +.TP +.B vsize +The +.IR mailbox \(aqs +virtual size, computed with CRLF line terminators. +.TP +.B firstsaved +Saved time of the first mail in the mailbox. +.RE +.PP +.\"------------------------------------------------------------------------ +.SS mailbox subscribe +.B doveadm mailbox subscribe +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.IR mailbox\ ... +.PP +This command is used to subscribe one or more mailboxes. +.\"------------------------------------------------------------------------ +.SS mailbox unsubscribe +.B doveadm mailbox unsubscribe +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.IR mailbox\ ... +.PP +This command is used to unsubscribe one or more mailboxes. +.\"------------------------------------------------------------------------ +.SS mailbox update +.B doveadm mailbox update +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP] +[\fB\-S\fP \fIsocket_path\fP] +[\fB\--mailbox-guid\fP \fIguid\fP] +[\fB\--uid-validity\fP \fIuid\fP] +[\fB\--min-next-uid\fP \fIuid\fP] +[\fB\--min-first-recent-uid\fP \fIuid\fP] +[\fB\--min-highest-modseq\fP \fIseq\fP] +[\fB\--min-highest-pvt-modseq\fP \fIseq\fP] +.IR mailbox\ ... +.PP +This command is used to set UID validity, next UID, first recent UID and modification sequence values. +.PP +Usually this is only ever to be used during migration, or restoring mailbox after disaster. +Settings these values is highly discouraged, and is not supported for all mail backends. +.\"------------------------------------------------------------------------ +.SS mailbox cache purge +.B doveadm mailbox cache purge +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.IR mailbox\ ... +.PP +Purge the dovecot.index.cache file. Most importantly this frees up disk space +from mails that were already deleted. Normally there i no need to run this +command manually, because the compression is also run automatically. +.\"------------------------------------------------------------------------ +.SS mailbox cache decision +.B doveadm mailbox cache decision +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +[\fB\--all\fP] +[\fB\--fields\fP \fIlist of fields\fP] +[\fB\--last-used\fP \fIunix timestamp\fP] +[\fB\--decision\fP \fIno|temp|yes\fP] +.IR mailbox\ ... +.PP +This command is used to list or change caching decisions for field(s) in mailbox(es). +You can list decisions by leaving out decision and last-used parameters. +.PP +.\"------------------------------------- +.TP +.B \--all +List or change all fields. +.\"------------------------------------- +.TP +.B \--fields +List or change these comma/space separated fields. +.\"------------------------------------- +.TP +.B \--decision +Set field caching decision. Yes means it's always cached. +Temp means it's provisionally cached. +No means the field is not cached. +.\"------------------------------------- +.TP +.B \--last-used +Set field's last used timestamp. +.\"------------------------------------- +.RE +.PP +NOTE. This command cannot be used to add new fields to cache! \ +You need to first add them to configuration. \ +Setting caching to no will not immediately drop field from cache, \ +it will stop adding the field to cache. +.\"------------------------------------------------------------------------ +.SS mailbox cache remove +.B doveadm mailbox cache remove +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.IR search query +.PP +Remove any matching mail(s) from cache. +.PP +WARNING! This command can erase ALL cached data, causing system slowness. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +List subscribed mailboxes, beginning with \(aqdovecot\(aq, of user bob. +.sp +.nf +.ft B +doveadm mailbox list \-s \-u bob dovecot* +.ft P +dovecot +dovecot/pigeonhole +dovecot/pigeonhole/2.0 +.fi +.\"------------------------------------- +.PP +Now have a look at the status of user bob\(aqs dovecot mailboxes. +.sp +.nf +.ft B +doveadm \-f table mailbox status \-u bob \(dqmessages vsize\(dq dovecot* +.ft P +mailbox messages vsize +dovecot 20501 93968492 +dovecot/pigeonhole 0 0 +dovecot/pigeonhole/2.0 47 323474 +.fi +.\"------------------------------------- +.PP +Converting an internationalized mailbox name from mUTF\-7 to UTF\-8 and +vice versa. +.sp +.nf +.ft B +doveadm mailbox mutf7 \-7 \(dq~peter/mail/&U,BTFw\-/&ZeVnLIqe\-\(dq +.ft P +~peter/mail/台北/日本語 +.ft B +doveadm mailbox mutf7 ~peter/mail/台北/日本語 +.ft P +~peter/mail/&U,BTFw\-/&ZeVnLIqe\- +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1) +.BR doveadm-search-query (7) +.BR doveadm-mailbox-cryptokey(1) diff --git a/doc/man/doveadm-move.1.in b/doc/man/doveadm-move.1.in new file mode 100644 index 0000000..3aa43fb --- /dev/null +++ b/doc/man/doveadm-move.1.in @@ -0,0 +1,169 @@ +.\" Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-MOVE 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-move \- Move messages matching the given search query into another +mailbox +.br +doveadm\-copy \- Copy messages matching the given search query into another +mailbox +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " move " [" \-S +.IR socket_path "] " destination +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " move " [" \-S +.IR socket_path "] " +.BI \-A " destination +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " move " [" \-S +.IR socket_path "] " +.BI \-F " file destination" +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " move " [" \-S +.IR socket_path "] " +.BI \-u " user destination +.RB [ user +.IR source_user "] " search_query +.\"------------------------------------- +.PP +.BR doveadm " [" \-Dv "] " copy " [" \-S +.IR socket_path "] " "destination +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " copy " [" \-S +.IR socket_path "] " +.BI \-A " destination +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " copy " [" \-S +.IR socket_path "] " +.BI \-F " file destination" +.RB [ user +.IR source_user "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] " copy " [" \-S +.IR socket_path "] " +.BI \-u " user destination +.RB [ user +.IR source_user "] " search_query +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm move +can be used for moving mails between mailboxes for one or more users. +The +.I search_query +is used to restrict which messages are moved into the +.I destination +mailbox. +.br +.B doveadm copy +behaves the same as +.BR "doveadm move" , +except that copied messages will not be expunged after copying. +.PP +In the first form, +.BR doveadm (1) +will execute the +.BR move / copy +action with the environment of the logged in system user. +.PP +In the second form, +.BR doveadm (1) +will iterate over all users, found in the configured +.IR user_db (s), +and move or copy each user\(aqs messages, matching the given +.IR search_query , +into the user\(aqs +.IR destination " mailbox." +.PP +In the third form, +.BR doveadm (1) +will iterate over all users, found in the given +.IR file , +and move or copy each user\(aqs messages, matching the given +.IR search_query , +into the user\(aqs +.IR destination \ mailbox. +.PP +In the fourth form, matching mails will be moved or copied only for given +.IR user (s). +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I destination +The name of the destination mailbox, into which the mails should be moved +or copied. +The +.I destination +mailbox must exist, otherwise this command will fail. +.\"------------------------------------- +.TP +.I search_query +Move/copy messages matching the given search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------- +.TP +.BI user \ source_user +The keyword +.B user +followed by a valid user name. +When this argument is present, +.BR doveadm (1) +will apply the +.I search_query +to the +.IR source_user "\(aqs " mail_location . +.br +.B Limitation: +Currently the users, specified by +.BI \-u " user" +and +.BI user " source_user," +must share the same UID and GID. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Move jane\(aqs messages \- received in September 2011 \- from her INBOX +into her archive. +.PP +.nf +.ft B +doveadm move \-u jane Archive/2011/09 mailbox INBOX BEFORE \(rs +2011\-10\-01 SINCE 01\-Sep\-2011 +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-penalty.1.in b/doc/man/doveadm-penalty.1.in new file mode 100644 index 0000000..8a94d93 --- /dev/null +++ b/doc/man/doveadm-penalty.1.in @@ -0,0 +1,58 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-PENALTY 1 "2010-07-12" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-penalty \- Show current penalties +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " penalty " [" \-a +.IR anvil_socket_path ] +[\fIip\fP[\fB/\fP\fImask\fP]] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm penalty +command can be used to see the current penalties. +(Extend me!/explain it) +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.TP +.BI \-a\ anvil_socket_path +This option is used to specify an alternative socket. +The option\(aqs argument is either an absolute path to a local UNIX domain +socket, or a hostname and port +.RI ( hostname : port ), +in order to connect a remote host via a TCP socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/anvil . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.IR ip [/ mask ] +To reduce/filter the output supply an IP address or a network range in +CIDR notation (ip/mask). +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Show current penalties +.sp +.nf +.B doveadm penalty +IP penalty last_penalty last_update +192.0.2.222 3 2010\-06\-15 15:19:27 15:19:27 +192.0.2.53 3 2010\-06\-15 15:19:34 15:19:34 +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-proxy.1.in b/doc/man/doveadm-proxy.1.in new file mode 100644 index 0000000..c9aa70c --- /dev/null +++ b/doc/man/doveadm-proxy.1.in @@ -0,0 +1,87 @@ +.\" Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-PROXY 1 "2014-11-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-proxy \- Handle Dovecot proxy connections +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI proxy \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm proxy +.I commands +are used to list or kick active Dovecot proxy connections. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the +.B table +output formatter. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.BI \-a \ ipc_socket_path +This option is used to specify an alternative socket. +The option\(aqs argument is either an absolute path to a local UNIX domain +socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/ipc . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I user +Is a +.IR user \(aqs +login name. +Depending on the configuration, a login name may be for example +.BR jane " or " john@example.com . +It\(aqs also possible to use +.RB \(dq * \(dq +and +.RB \(dq ? \(dq +wildcards (e.g. *@example.org). +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS proxy kick +.B doveadm proxy kick +[\fB\-a\fP \fIipc_socket_path\fP] +[\fB\-f\fP \fIpassdb_field\fP] +[\fB\-h\fP \fIhost_list\fP | \fIuser_list\fP] +.PP +Kick all the connections being proxied for the given +.IR user_list +or for the given backend +.IR host_list . +.\"------------------------------------- +.SS proxy list +.B doveadm proxy list +[\fB\-a\fP \fIipc_socket_path\fP] +.PP +List all the users currently being proxied. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +List all currently active proxy connections: +.PP +.nf +.B doveadm proxy list +username proto src ip dest ip port +jane@example.net imap 192.168.0.100 192.168.0.5 143 +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-purge.1.in b/doc/man/doveadm-purge.1.in new file mode 100644 index 0000000..2049cd7 --- /dev/null +++ b/doc/man/doveadm-purge.1.in @@ -0,0 +1,71 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-PURGE 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-purge \- Remove messages with refcount=0 from mdbox files +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " purge " [" \-S +.IR socket_path "] " +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " purge " [" \-S +.IR socket_path ] +.B \-A +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " purge " [" \-S +.IR socket_path ] +.BI \-F\ file +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " purge " [" \-S +.IR socket_path "] " +.BI \-u \ user +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B doveadm purge +command is used to remove all messages with refcount=0 from a user\(aqs +mail storage. +The refcount of a message is decreased to 0 when the user (or some +administration utility) has expunged all instances of a message from all +mailboxes. +.PP +In the first form, +.BR doveadm (1) +will perform the +.B purge +action for the currently logged in user. +.PP +In the second form, the command will be executed for all users. +.PP +In the third form, the command will be executed for all users listed in +the given +.IR file . +.PP +In the last form, only messages of the given +.IR user (s) +will be purged. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-expunge (1) +.PP +See http://wiki2.dovecot.org/MailboxFormat/dbox#Multi\-dbox for some +details.
\ No newline at end of file diff --git a/doc/man/doveadm-pw.1.in b/doc/man/doveadm-pw.1.in new file mode 100644 index 0000000..a67f422 --- /dev/null +++ b/doc/man/doveadm-pw.1.in @@ -0,0 +1,163 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-PW 1 "2015-06-05" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-pw \- Dovecot\(aqs password hash generator +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " "pw \-l" +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " pw +[\fB\-p\fP \fIpassword\fP] +[\fB\-r\fP \fIrounds\fP] +[\fB\-s\fP \fIscheme\fP] +[\fB\-u\fP \fIuser\fP] +.RB [ \-V ] +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] " "pw \-t" +.I hash +[\fB\-p\fP \fIpassword\fP] +[\fB\-u\fP \fIuser\fP] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm pw +is used to generate password hashes for different password +.IR scheme s +and optionally verify the generated hash. +.PP +All generated password hashes have a +.RI { scheme } +prefix, for example +.RB { SHA512\-CRYPT.HEX }. +All passdbs have a default scheme for passwords stored without the +.RI { scheme } +prefix. +The default scheme can be overridden by storing the password with the +scheme prefix. +.PP +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.B \-l +List all supported password +.IR scheme s +and exit successfully. +.br +There are up to three optional password +.IR scheme s: +.BR BLF\-CRYPT " (Blowfish crypt)," +.BR SHA256\-CRYPT\ and +.BR SHA512\-CRYPT . +Their availability depends on the system\(aqs currently used libc. +.\"------------------------------------- +.TP +.BI \-p\ password +The plain text +.I password +for which the hash should be generated. +If no +.I password +was given +.BR doveadm (1) +will prompt interactively for one. +.\"------------------------------------- +.TP +.BI \-r\ rounds +The password +.IR scheme s +.BR BLF\-CRYPT , +.BR SHA256\-CRYPT\ and +.B SHA512\-CRYPT +supports a variable number of encryption +.IR rounds . +The following table shows the minimum/maximum number of encryption +.I rounds +per scheme. +When the +.B \-r +option was omitted the default number of encryption rounds will be applied. +.\" +.sp +.nf + Scheme | Minimum | Maximum | Default +---------------------------------------------- + BLF\-CRYPT | 4 | 31 | 5 + SHA256\-CRYPT | 1000 | 999999999 | 5000 + SHA512\-CRYPT | 1000 | 999999999 | 5000 +.fi +.\" +.\"------------------------------------- +.TP +.BI \-s\ scheme +The password +.I scheme +which should be used to generate the hashed password. +By default the +.BI CRYPT\ scheme +will be used (with the $2y$ bcrypt format). +It is also possible to append an encoding suffix to the +.IR scheme . +Supported encoding suffixes are: +.BR .b64 , +.BR .base64\ and +.BR .hex . +.br +See also http://wiki2.dovecot.org/Authentication/PasswordSchemes for more +details about password schemes. +.\"------------------------------------- +.TP +.BI \-t\ hash +Test if the given password +.I hash +matches a given plain text password. +You should enclose the password +.I hash +in single quotes, if it contains one or more dollar signs +.RB ( $ ). +The plain text password may be passed using the +.BR \-p " option." +When no password was specified, +.BR doveadm (1) +will prompt interactively for one. +.\"------------------------------------- +.TP +.BI \-u\ user +When the +.BI DIGEST\-MD5\ scheme +is used, also the +.I user +name must be given, because the user name is a part of the generated hash. +For more information about Digest\-MD5 please read also: +http://wiki2.dovecot.org/Authentication/Mechanisms/DigestMD5 +.\"------------------------------------- +.TP +.B \-V +When this option is given, the hashed password will be internally verified. +The result of the verification will be shown after the hashed password, +enclosed in parenthesis. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +The first password hash is a DIGEST\-MD5 hash for jane.roe@example.com. +The second password hash is a CRAM\-MD5 hash for john.doe@example.com. +.sp +.nf +.B doveadm pw \-s digest\-md5 \-u jane.roe@example.com +Enter new password: +Retype new password: +{DIGEST\-MD5}9b9dcb4466233a9307bbc33708dffda0 +.B doveadm pw +Enter new password: +Retype new password: +{CRAM\-MD5}913331d8782236a8ecba7764a63aa27b26437fd40ca878d887f11d81245c2c6b +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-quota.1.in b/doc/man/doveadm-quota.1.in new file mode 100644 index 0000000..98f7072 --- /dev/null +++ b/doc/man/doveadm-quota.1.in @@ -0,0 +1,131 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-QUOTA 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-quota \- Initialize/recalculate or show current quota usage +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR quota " [" \-S +.IR socket_path "] " command +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR quota " [" \-S +.IR socket_path "]" +.IB command\ \-A +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR quota " [" \-S +.IR socket_path "]" +.IB command\ \-F \ file +.\"------------------------------------- +.br +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR quota " [" \-S +.IR socket_path "]" +.IB command\ \-u \ user +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +In the first form, +.BR doveadm (1) +will execute the +.I command +for the currently logged in user. +.PP +In the second form, the +.I command +will be performed for all users. +.PP +In the third form, the +.I command +will be performed for all users listed in the given +.IR file . +.PP +In the fourth form, the +.I command +will affect only the matching +.IR user (s). +.IP Note: +The +.B quota get +and +.B quota recalc +commands are only available when the global +.I mail_plugins +setting contains the +.B quota +plugin. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS quota get +.BR doveadm " [" \-f +.IR formatter ] +.B quota get +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +.PP +The +.B quota get +command is used to display the current quota usage. +The storage values are reported in kilobytes. +.PP +This command uses by default the output formatter +.BR table . +.\"------------------------------------- +.SS quota recalc +.B doveadm quota recalc +[\fB\-A\fP|\fB\-u\fP \fIuser\fP|\fB\-F\fP \fIfile\fP] +.PP +The +.B quota recalc +command is used to recalculate the current quota usage. +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file, including the +.I dict +section. +.TP +.I @pkgsysconfdir@/dovecot\-dict\-sql.conf.ext +SQL dictionary proxy settings. +.TP +.I @pkgsysconfdir@/conf.d/10\-mail.conf +Mailbox locations and namespaces, including global +.I mail_location +.TP +.I @pkgsysconfdir@/conf.d/90\-quota.conf +Quota configuration. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Get the current quota usage of user jane. +.sp +.nf +.B doveadm quota get \-u jane +Quota name Type Value Limit % +user STORAGE 90099 102400 87 +user MESSAGE 20548 30000 68 +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-rebuild.1.in b/doc/man/doveadm-rebuild.1.in new file mode 100644 index 0000000..d8261b6 --- /dev/null +++ b/doc/man/doveadm-rebuild.1.in @@ -0,0 +1,112 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-REBUILD 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-rebuild - Commands related to rebuilding various aspects of mails matching +given search query. +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR rebuild \ <command> " [" \-S +.IR socket_path "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR rebuild \ <command> " [" \-S +.IR socket_path ] +.BI \-A \ search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR rebuild \ <command> " [" \-S +.IR socket_path ] +.BI \-F " file search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR rebuild \ <command> " [" \-S +.IR socket_path ] +.BI \-u " user search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B rebuild attachments +command is used to rebuilds attachment presence. +.BR doveadm (1) +will print the message\(aqs uid for each match. +.br +When used with the +.B \-A +or +.BI \-u \ wildcard +options, +.BR doveadm (1) +will print the fields +.BR username \ and +.B uid +for each matching message. +.PP +In the first form, +.BR doveadm (1) +will execute the +.B rebuild +action with the environment of the logged in system user. +.PP +In the second form, the command will be performed for all users. +.PP +In the third form, the command will be performed for all users listed in +the given +.IR file . +.PP +In the fourth form, only matching mails of the given +.IR user (s) +will be rebuilded +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.B flow +(without the +.IR key = +prefix). +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I search_query +Resets attachment indicator for messages matching this search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example demonstrates how to rebuild user bob\(aqs attachment status. +.PP +.nf +.ft B +doveadm rebuild attachments \-u bob ALL +.ft P +1 +2 +3 +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search\-query (7) diff --git a/doc/man/doveadm-reload.1 b/doc/man/doveadm-reload.1 new file mode 100644 index 0000000..7184fe8 --- /dev/null +++ b/doc/man/doveadm-reload.1 @@ -0,0 +1 @@ +.so man1/doveadm.1
\ No newline at end of file diff --git a/doc/man/doveadm-replicator.1.in b/doc/man/doveadm-replicator.1.in new file mode 100644 index 0000000..53b6b46 --- /dev/null +++ b/doc/man/doveadm-replicator.1.in @@ -0,0 +1,123 @@ +.\" Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-REPLICATOR 1 "2014-10-05" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-replicator \- Manage users\(aq mail replication +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv ] +[\fB\-f\fP \fIformatter\fP] +.BI replicator \ command +.RI [ OPTIONS ]\ [ ARGUMENTS ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +doveadm replicator +.I COMMANDS +can be used to manage the automated replication of users\(aq mail. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.B flow +(without the +.IR key = +prefix). +.PP +Command specific +.IR options : +.TP +.BI \-a \ replicator_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/replicator\-doveadm . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I user_mask +Specifies for which users the command should be executed. +In most cases you would like to use patterns which contains wildcards, +e.g. \(rs*@example.net for all users of the example.net domain, or simply +\(rs* for all users. +.sp +When the SQL userdb module is used make sure that the +.I iterate_query +setting in +.I @pkgsysconfdir@/dovecot\-sql.conf.ext +matches your database layout. +When using the LDAP userdb module, make sure that the +.IR iterate_attrs " and " iterate_filter +settings in +.I @pkgsysconfdir@/dovecot\-ldap.conf.ext +match your LDAP schema. +Otherwise +.BR doveadm (1) +will be unable to iterate over all users. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.SS replicator add +.B doveadm replicator add +[\fB\-a\fP \fIreplicator_socket_path\fP] +.I user_mask +.PP +Add the specified user(s) to the replicator. +If the +.I user_mask +contains \(dq?\(dq or \(dq*\(dq wildcards, the list of usernames is looked +up from the +.IR userdb . +.\"------------------------------------- +.SS replicator dsync\-status +.B doveadm replicator dsync\-status +[\fB\-a\fP \fIreplicator_socket_path\fP] +.PP +Show the status for the currently running dsync processes. +.\"------------------------------------- +.SS replicator remove +.B doveadm replicator remove +[\fB\-a\fP \fIreplicator_socket_path\fP] +.I username +.PP +Remove the specified user from replicator. +.\"------------------------------------- +.SS replicator replicate +.B doveadm replicator replicate +[\fB\-a\fP \fIreplicator_socket_path\fP] +.RB [ \-f ] +[\fB\-p\fP \fIpriority\fP] +.I user_mask +.PP +Start replication for the specified users now. +If the \-f parameter is given, full replication is done for the user. +You can also specify the priority, which can be either +.B high " or " low. +If the user mask contains \(dq?\(dq or \(dq*\(dq wildcards, the list of +usernames is looked up from the users that currently exist in replicator +(not from the +.IR userdb ). +.\"------------------------------------- +.SS replicator status +.B doveadm replicator status +[\fB\-a\fP \fIreplicator_socket_path\fP] +.I user_mask +.PP +Show the replication status for users. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-sync (1), +.\"------------------------------------- +.PP +Additional resources: +.IP "Replication with dsync" +http://wiki2.dovecot.org/Replication
\ No newline at end of file diff --git a/doc/man/doveadm-save.1.in b/doc/man/doveadm-save.1.in new file mode 100644 index 0000000..284ba50 --- /dev/null +++ b/doc/man/doveadm-save.1.in @@ -0,0 +1,66 @@ +.\" Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-SAVE 1 "2017-05-11" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-save \- Save email to a user's mailbox +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] +.BR save " [" \-S +.IR socket_path "]" +.BI \-u " user " +.RI "["\-m +.IR mailbox "] " +.RI "[" mail-file "]" +.br +.\"------------------------------------------------------------------------ +.BR doveadm " [" \-Dv "] +.BR save " [" \-S +.IR socket_path "]" +.BI \-A +.RI "["\-m +.IR mailbox "] " +.RI "[" mail-file "]" +.br +.\"------------------------------------------------------------------------ +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR save " [" \-S +.IR socket_path "]" +.BI \-F " file " +.RI "["\-m +.IR mailbox "] " +.RI "[" mail-file "]" +.br +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm save +can be used to save messages. This can be useful for scripts and for debugging. +Sieve is not invoked for saved messages, but quota is enforced. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------- +.TP +.BI \-m\ mailbox +Store mail to specified mailbox instead of INBOX. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +echo "hello, world" | doveadm save -u testuser@testdomain +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search (1), +.BR doveadm\-search\-query (7) diff --git a/doc/man/doveadm-search-query.7 b/doc/man/doveadm-search-query.7 new file mode 100644 index 0000000..1f65bba --- /dev/null +++ b/doc/man/doveadm-search-query.7 @@ -0,0 +1,428 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-SEARCH\-QUERY 7 "2015-10-19" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-search\-query \- Overview of search queries for doveadm mailbox \ +commands +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +Several +.BR doveadm (1) +commands use a +.I search_query +in order to act only on matching messages. +This manual page describes all +.IR SEARCH\ KEYS , +which can be used in a +.IR search_query . +The query is mostly compatible with the IMAP SEARCH command parameters, +although there are some differences. +.PP +Each +.I search_query +consists at least of one +.IR SEARCH\ KEY . +Most of the +.I SEARCH KEYS +require an argument. +All +.I SEARCH\ KEYS +are case\-insensitive. +The shortest valid +.I search_query +is +.BR ALL . +For example: +.sp +.RS +.nf +doveadm search ALL +.fi +.RE +.PP +Multiple search query expressions will be combined with the +.B AND +operator by default. +To find all messages that are new and greater than 50 kilobyte, one can +use: +.sp +.RS +.nf +doveadm search NEW LARGER 50k +.fi +.RE +.PP +.BR OR \-ed +.I SEARCH KEYS +have to be written in parenthesis, when mixing ANDs and ORs. +Shells commonly require escaping for parentheses. +To find messages that were saved on the \(dq13th of April 2007\(dq AND +have the \(rsSeen and/or \(rsFlagged flag set, one +can use for example: +.sp +.RS +.nf +doveadm search SAVEDON 2007\-04\-13 \(rs( SEEN OR FLAGGED \(rs) +.fi +.RE +.PP +It\(aqs also possible to specify the mailbox, in which should be searched. +Use either the keyword +.B mailbox +and the name of the mailbox or the keyword +.B mailbox\-guid +and the mailbox\(aqs globally unique identifier in the +.IR search_query . +To find all messages in the mailbox with the GUID +\(dq44f68b13ce97044b837f000035ca9452\(dq use: +.sp +.RS +.nf +doveadm search mailbox\-guid 44f68b13ce97044b837f000035ca9452 ALL +.fi +.RE +.PP +To list all deleted messages in the \(dqTrash\(dq folder use: +.sp +.RS +.nf +doveadm search mailbox Trash DELETED +.fi +.RE +.\"------------------------------------------------------------------------ +.SH SEARCH KEYS +The following search keys from the specification of IMAP version 4 revision +1 (see: RFC 3501, section 6.4.4) are supported: +.\"----------------- +.TP +.I sequence\-set +Matches messages with the given sequence numbers. The +.I sequence\-set +may be a single UID. +Can be a sequence range, written as +.IR from : to , +.RB e.g.\ 100 : 125 . +As comma separated list of sequences, e.g. +.BR 11,50,4 . +It\(aqs also possible to combine multiple sequences, e.g. +.BR 1,3,5,7,10:20 . +Using +.BR * +selects the last mail in the mailbox. +.br +For example 1:100 matches the first 100 mails and 101:200 the next second +hundred mails. 1,5,* matches the first, the fifth and the last email. +.\"----------------- +.TP +.B ALL +Matches all messages. +.\"----------------- +.TP +.B ANSWERED +Matches messages with the IMAP flag \(rsAnswered set. +.\"----------------- +.TP +.BI BCC\ string +Matches messages, which contain +.I string +in the BCC field of the message\(aqs IMAP envelope structure. +.\"----------------- +.TP +.BI BEFORE \ date\ specification +Matches messages with an internal date before +.IR date\ specification . +.\"----------------- +.TP +.BI BODY\ string +Matches messages, which contain +.I string +in the body part. +.\"----------------- +.TP +.BI CC\ string +Matches messages, which contain +.I string +in the CC field of the message\(aqs IMAP envelope structure. +.\"----------------- +.TP +.B DELETED +Matches messages with the IMAP flag \(rsDeleted set. +.\"----------------- +.TP +.B DRAFT +Matches messages with the IMAP flag \(rsDraft set. +.\"----------------- +.TP +.B FLAGGED +Matches messages with the IMAP flag \(rsFlagged set. +.\"----------------- +.TP +.BI FROM\ string +Matches messages, which contain +.I string +in the FROM field of the message\(aqs IMAP envelope structure. +.\"----------------- +.TP +\fBHEADER\fP \fIfield\fP \fIstring\fP +Matches messages, which either have the named header +.IR field , +when empty +.I string +was given. +Or messages, where the given header +.IR field \(aqs +value contains the specified +.IR string . +.\"----------------- +.TP +.BI KEYWORD\ keyword +Matches messages with the given IMAP +.I keyword +(e.g. \(DoForwarded) flag set. +.\"----------------- +.TP +.BI LARGER\ size +Matches messages that are larger than the specified +.IR size . +.\"----------------- +.TP +.BI MAILBOX\ name +Matches messages in the mailbox with the specified +.IR name . +.\"----------------- +.TP +.BI MAILBOX\-GUID\ guid +Matches messages in the mailbox with the specified +.IR guid . +.\"----------------- +.TP +.B NEW +Matches messages, which have the IMAP flag \(rsRecent set +.B but not +the IMAP flag \(rsSeen. +.\"----------------- +.TP +.BI NOT\ search\ key +Inverse matching \- matches massages, where the search doesn\(aqt match +the specified +.I search\ key +or its value. +.\"----------------- +.TP +.B OLD +Matches messages, which do not have the IMAP flag \(rsRecent set. +.\"----------------- +.TP +.BI ON\ date\ specification +Matches messages whose internal date matches the given +.IR date\ specification . +.\"----------------- +.TP +.IB search\ key\ OR\ search\ key +Matches messages where one of the OR\-ed search keys matches. +.br +Note: IMAP4rev1 uses the syntax: +.BI OR\ search\ key\ search\ key +.\"----------------- +.TP +.B RECENT +Matches messages with the IMAP flag \(rsRecent set. +.\"----------------- +.TP +.B SEEN +Matches messages with the IMAP flag \(rsSeen set. +.\"----------------- +.TP +.BI SENTBEFORE\ date\ specification +Matches messages with a Date: header before +.IR date\ specification . +.\"----------------- +.TP +.BI SENTON\ date\ specification +Matches messages with a Date: header matching the given +.IR date\ specification . +.\"----------------- +.TP +.BI SENTSINCE\ date\ specification +Matches messages with a Date: header matching or after the given +.IR date\ specification . +.\"----------------- +.TP +.BI SINCE\ date\ specification +Matches messages whose internal date is within or after the given +.IR date\ specification . +.\"----------------- +.TP +.BI SMALLER\ size +Matches messages with a size smaller than the given +.IR size . +.\"----------------- +.TP +.BI SUBJECT\ string +Matches messages, which contain +.I string +in the SUBJECT field of the message\(aqs IMAP envelope structure. +.\"----------------- +.TP +.BI TEXT\ string +Matches messages, which contain +.I string +in the message headers or body. +.\"----------------- +.TP +.BI TO\ string +Matches messages, which contain +.I string +in the TO field of the message\(aqs IMAP envelope structure. +.\"----------------- +.TP +.BI UID\ sequence\-set +Matches messages with the given IMAP UID(s). See the +.BI sequence\-set +description for details on it. For example +.BR 1:10,100:200,* +matches the UIDs from 1 to 10, 100 to 200 and also the last mail. +.\"----------------- +.TP +.B UNANSWERED +Matches messages, which do not have the IMAP flag \(rsAnswered set. +.\"----------------- +.TP +.B UNDELETED +Matches messages, which do not have the IMAP flag \(rsDeleted set. +.\"----------------- +.TP +.B UNDRAFT +Matches messages, which do not have the IMAP flag \(rsDraft set. +.\"----------------- +.TP +.B UNFLAGGED +Matches messages, which do not have the IMAP flag \(rsFlagged set. +.\"----------------- +.TP +.BI UNKEYWORD\ keyword +Matches messages, which do not have the given IMAP +.I keyword +flag set +.\"----------------- +.TP +.B UNSEEN +Matches messages, which do not have the IMAP flag \(rsSeen set. +.\"------------------------------------- +.SS DOVEADM SEARCH KEYS +Additional search keys, provided by +.BR doveadm (1). +.\"----------------- +.TP +.BI SAVEDBEFORE\ date\ specification +Matches messages, which were saved before +.IR date\ specification . +.\"----------------- +.TP +.BI SAVEDON\ date\ specification +Matches messages whose save date matches the given +.IR date\ specification . +.\"----------------- +.TP +.BI SAVEDSINCE\ date\ specification +Matches messages with a save date matching or after the given +.IR date\ specification . +.\"------------------------------------------------------------------------ +.SH DATE SPECIFICATION +.BR doveadm (1) +supports a few additional +.I date specification +formats. +They can be used anywhere, where a +.I date specification +value is obligatory. +.TP +.IB day \- month \- year +Default IMAP4rev1 date format. +.br +.IR day , +the day of month: +.BR 1 \- 31 . +.br +.IR month , +the abbreviated month name: +.BR Jan , +.BR Feb , +.BR Mar , +.BR Apr , +.BR May , +.BR Jun , +.BR Jul , +.BR Aug , +.BR Sep , +.BR Oct , +.BR Nov \ or +.BR Dec . +.br +.IR year , +four digits of year, e.g. +.BR 2007 . +.br +For example the \(dq13th of April 2007\(dq will be represented as +.BR 13\-Apr\-2007 . +. +.TP +.I interval +Combination of a positive integer +.I number +and a +.IR time\ unit . +.br +Available +.I time\ units +are: +.BR weeks " (abbr: " w ), +.BR days " (abbr: " d ), +.BR hours " (abbr: " h ), +.BR mins " (abbr: " m ") and" +.BR secs " (abbr: " s ). +.br +To match messages from last week, you may specify for example: +.BR since\ 1w , +.BR since\ 1weeks \ or +.BR since\ 7days . +. +.TP +.I Unix timestamp +A 10 digit Unix timestamp, seconds since the 1st of January 1970, 00:00:00 +UTC. +For example the \(dq13th of April 2007\(dq will be represented as +.BR 1176418800 . +. +.TP +.I YYYY\-MM\-DD +Extended ISO\-8601 calendar date format. +For example the \(dq13th of April 2007\(dq will be represented as +.BR 2007\-04\-13 . +.\"------------------------------------------------------------------------ +.SH SIZE +.BR doveadm (1) +provides also an additional +.I size +representation format. +The following formats can be used anywhere, where a +.I size +value is obligatory. +.TP +.I octets +The message size in octets, as specified in the IMAP4rev1 specification. +.TP +.I size +The message size in +.BR B \ (byte), +.BR k \ (kilobyte), +.BR M \ (megabyte), +.BR G \ (gigabyte)\ or +.BR T \ (terabyte). +.br +To match messages, bigger than 1 megabyte, you may specify for example: +.BR larger\ 1M \ or +.BR larger\ 1024k . +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-search (1) diff --git a/doc/man/doveadm-search.1.in b/doc/man/doveadm-search.1.in new file mode 100644 index 0000000..1cf413a --- /dev/null +++ b/doc/man/doveadm-search.1.in @@ -0,0 +1,129 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-SEARCH 1 "2015-05-09" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-search \- Show a list of mailbox GUIDs and message UIDs matching \ +given search query. +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR search " [" \-S +.IR socket_path "] " search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR search " [" \-S +.IR socket_path ] +.BI \-A \ search_query +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR search " [" \-S +.IR socket_path ] +.BI \-F " file search_query" +.br +.\"------------------------------------- +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR search " [" \-S +.IR socket_path ] +.BI \-u " user search_query" +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B search +command is used to find matching messages. +.BR doveadm (1) +will print the mailbox\(aqs guid and the message\(aqs uid for each match. +.br +When used with the +.B \-A +or +.BI \-u \ wildcard +options, +.BR doveadm (1) +will print the fields +.BR username , +.BR mailbox\-guid \ and +.B uid +for each matching message. +.PP +In the first form, +.BR doveadm (1) +will executed the +.B search +action with the environment of the logged in system user. +.PP +In the second form, the command will be performed for all users. +.PP +In the third form, the command will be performed for all users listed in +the given +.IR file . +.PP +In the fourth form, only matching mails of the given +.IR user (s) +will be searched. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.B flow +(without the +.IR key = +prefix). +.PP +Command specific +.IR options : +.\"------------------------------------- +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I search_query +Show messages matching this search query. +See +.BR doveadm\-search\-query (7) +for details. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +This example demonstrates how to search in user bob\(aqs dovecot mailboxes +all messages, which contains the word \(dqtodo\(dq in the Subject: header. +.PP +.nf +.ft B +doveadm search \-u bob mailbox dovecot\(rs* subject todo +.ft P +3a94c928d66ebe4bda04000015811c6a 8 +3a94c928d66ebe4bda04000015811c6a 25 +3a94c928d66ebe4bda04000015811c6a 45 +.fi +.PP +The search command is mainly useful when used together with +.I doveadm\ fetch +command. For example to save message bodies of all messages from INBOX +that have "todo" in subject, use: +.PP +.nf +.ft B +doveadm search \-u bob mailbox INBOX subject todo | +while read guid uid; do +\ \ doveadm fetch \-u bob body mailbox\-guid $guid uid $uid > msg.$uid +done +.ft P +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-fetch (1), +.BR doveadm\-search\-query (7)
\ No newline at end of file diff --git a/doc/man/doveadm-stats.1.in b/doc/man/doveadm-stats.1.in new file mode 100644 index 0000000..8819215 --- /dev/null +++ b/doc/man/doveadm-stats.1.in @@ -0,0 +1,73 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-DUMP 1 "2016-01-12" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-stats \- Inspect or reset stats +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm\ stats\ dump " [ " \-s\ <stats\ socket\ path> " ] " <type> " [ " <filter> " ]" +.PP +.BR doveadm\ stats\ top " [ " \-s\ <stats\ socket\ path> " ] " "[ " -b " ]" " [ " sort field> " ]" +.PP +.BR doveadm\ stats\ reset " [ " \-s\ <stats\ socket\ path> " ] " +.PP +.BR doveadm\ stats\ add " [ " \-\-description\ <string> " ] [ " \-\-exporter\ <name> " [ " \-\-exporter-include\ <field> " ]] [ " \-\-fields\ <fields> " ] [ " \-\-group_by\ <fields> " ] " <name>\ <filter> +.PP +.BR doveadm\ stats\ remove\ <name> +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm stats dump +is used to output statistics +.PP +.B doveadm stats top +is used to monitor statistics +.PP +.B doveadm stats reset +is used to reset statistics +.PP +.B doveadm stats add +is used to add metrics to statistics +.PP +.B doveadm stats remove +is used to remove metrics from statistics +.\"------------------------------------------------------------------------ +.SH OPTIONS +Command specific +.IR options : +.TP +.BI \-s socketpath +Sets stats socket path +.TP +.B \-b +Show disk input/output bytes +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.BR dump +accepts following types: command, session, user, domain, ip and global. +.PP +Filter can be +.TP +.B user=<wildcard> +Match given user. +.TP +.B domain=<wildcard> +Match given DNS domain name +.TP +.B session=<str> +Match session identifier +.TP +.B ip=<ip>"["/<mask>"]" +Match local or remote IP +.TP +.B since=<timestamp> +Match session start time +.TP +.B connected +Show only connected sessions +.PP +.BR top +accepts any valid field name to sort along with. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1) diff --git a/doc/man/doveadm-stop.1 b/doc/man/doveadm-stop.1 new file mode 100644 index 0000000..7184fe8 --- /dev/null +++ b/doc/man/doveadm-stop.1 @@ -0,0 +1 @@ +.so man1/doveadm.1
\ No newline at end of file diff --git a/doc/man/doveadm-sync.1.in b/doc/man/doveadm-sync.1.in new file mode 100644 index 0000000..9f926e3 --- /dev/null +++ b/doc/man/doveadm-sync.1.in @@ -0,0 +1,458 @@ +.\" Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-SYNC 1 "2015-08-31" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-sync \- Dovecot\(aqs two\-way mailbox synchronization utility +.br +doveadm\-backup \- Dovecot\(aqs one\-way mailbox synchronization utility +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " sync +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-1fPRU ] +[\fB\-l\fP \fIsecs\fP] +[\fB\-r\fP \fIrawlog path\fP] +[\fB\-m\fP \fImailbox\fP] +[\fB\-g\fP \fImailbox guid\fP] +[\fB\-n\fP \fInamespace\fP|\fB\-N\fP] +[\fB\-x\fP \fIexclude\fP] +[\fB\-a\fP \fIall mailbox\fP] +[\fB\-s\fP \fIstate\fP] +[\fB\-T\fP \fIsecs\fP] +[\fB\-t\fP \fIstart date\fP] +[\fB\-e\fP \fIend date\fP] +[\fB\-O\fP \fIsync flag\fP] +[\fB\-I\fP \fImax size\fP] +\fB\-d\fP|\fIdestination\fP +.\"------------------------------------- +.PP +.BR doveadm " [" \-Dv "] " backup +[\fB\-u\fP \fIuser\fP|\fB\-A\fP|\fB\-F\fP \fIfile\fP] +[\fB\-S\fP \fIsocket_path\fP] +.RB [ \-fPRU ] +[\fB\-l\fP \fIsecs\fP] +[\fB\-r\fP \fIrawlog path\fP] +[\fB\-m\fP \fImailbox\fP] +[\fB\-g\fP \fImailbox guid\fP] +[\fB\-n\fP \fInamespace\fP|\fB\-N\fP] +[\fB\-x\fP \fIexclude\fP] +[\fB\-a\fP \fIall mailbox\fP] +[\fB\-s\fP \fIstate\fP] +[\fB\-T\fP \fIsecs\fP] +[\fB\-t\fP \fIstart date\fP] +[\fB\-e\fP \fIend date\fP] +[\fB\-O\fP \fIsync flag\fP] +[\fB\-I\fP \fImax size\fP] +\fB\-d\fP|\fIdestination\fP +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +dsync is Dovecot\(aqs mailbox synchronization utility. +It can be used for several different use cases: Two\-way synchronization of +mailboxes, creating backups of mails, and convert mailboxes from/to +different mailbox formats. +All of these can be used within the same server or between different +servers (via +.BR ssh (1) +or tcp connections). +Remote mailboxes can be accessed also via IMAP protocol, which allows using +dsync for mailbox migration purposes. +.PP +You can run dsync in one of three modes: +.RS +.\"------------------------------------- +.IP \(bu +.B doveadm backup +performs one\-way synchronization. +If there are any changes in the destination they will be deleted, so the +destination will look exactly like the source. +.\"------------------------------------- +.IP \(bu +.B doveadm sync +performs two\-way synchronization. +It merges all changes without losing anything. +Both the mailboxes will end up looking identical after the synchronization +is finished. +.\"------------------------------------- +.IP \(bu +.B doveadm sync \-1 +performs one\-way synchronization, but it merges the changes in destination +without deleting anything. +This doesn\(aqt currently work perfectly, so its use should be limited. +Its main purpose is that during mailbox migration you can run +.B doveadm backup +multiple times, then switch mails to be delivered to the new mailbox and +run +.B doveadm sync \-1 +once more to transfer any last new mails from the old mailbox. +.IP +The one\-way algorithm is the same as two-way dsync algorithm except the +source account is not modified. It fetches the message's GUID (Global UID), +which is used to identify any conflicting UIDs in messages. As long as the +source and destination side has matching UID<\->GUID mapping, those emails +are assumed to be synced correctly. Only after the first mismatch will +changes begin. +.IP +Example: Source mailbox has messages UID 1..5; source mailbox is sync'd +using +.B doveadm backup +to the destination. Subsequently, UID 6 is delivered to the source mailbox +and UID 1 is expunged from the destination mailbox. In this example, UID 1 +is kept removed (in destination) because UID 1..5 have identical +Date+Message\-ID headers. UID 6 is not seen in destination so it's copied. +.IP +If both source and destination have UID 6, but the messages are different, +the headers don't match and both the messages are kept in the destination but +they're given new UIDs 7 and 8 just to be sure any client didn't get confused +about what UID 6 actually was. Thus, one\-way sync begins to quickly diverge +from the source mailbox once changes start to occur on either side; one\-way +sync should therefore normally only be used within a short period of time +after a +.B doveadm backup +or +.B doveadm sync +command was used to synchronize the mailboxes. +.\"------------------------------------- +.RE +.PP +There are also three different synchronization algorithms: +.RS +.\"------------------------------------- +.IP \(bu +Full synchronization (\-f parameter) scans through all the messages in all +the mailboxes. +This guarantees that everything will be synchronized, but it\(aqs +unnecessarily slow for incremental synchronization. +.\"------------------------------------- +.IP \(bu +Fast synchronization (default) first attempts to find mailboxes that have +changed, and synchronize only those. +This is done by checking the mailboxes\(aq metadata (NEXTUID and +HIGHESTMODSEQ). +Usually this works fine, especially with one\-way synchronization, but if +both sides do exactly the same number of changes, the metadata may end up +containing the same values even if the changes were different. +.\"------------------------------------- +.IP \(bu +Stateful synchronization (\-s parameter) is the most efficient way to +synchronize mailboxes. +It relies on having the earlier dsync run\(aqs state saved somewhere and +being passed to the next dsync run. +Based on this state dsync can send only the changes that happened after the +previous dsync run. +As long as the state or the mailboxes aren\(aqt corrupted this algorithm +should work perfectly. +The replicator process uses this internally to perform most of the +synchronization. +.\"------------------------------------- +.RE +.PP +The syncing is done as perfectly as possible: an IMAP or a POP3 client +shouldn\(aqt be able to notice any differences between the two mailboxes. +Two\-way syncing means that it\(aqs safe to do any kind of modifications in +both sides, and dsync will merge the changes without losing any changes +done on either side. +This is possible because dsync can access Dovecot\(aqs index logs that keep +track of changes. +It\(aqs of course possible to have conflicts during merging, these are +resolved in a safe way. +See the +.I dsync design +document for more information. +.PP +dsync uses the same configuration files as the rest of Dovecot (via +.BR doveconf (1) +binary). +The entire configuration can be changed by giving \-c parameter to another +configuration file, or using \-o parameter to override specific settings. +When executing a remote dsync program it works the same way: +it uses its own local configuration. +.PP +dsync can be run completely standalone. +It doesn\(aqt require any Dovecot server processes to be running, except +when using \-u parameter to do a +.I userdb +lookup from auth process. +.PP +dsync can sync either one or multiple users using the \-u or \-A +parameters. +For continuous replication you can use the Dovecot replicator process, +which automatically runs dsync whenever messages have changed. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +@INCLUDE:option-A@ +.\"------------------------------------- +@INCLUDE:option-F-file@ +.\"------------------------------------- +.TP +.B \-1 +Do one\-way synchronization instead of two\-way synchronization. +.\"------------------------------------- +.TP +.B \-f +Do full synchronization. +.\"------------------------------------- +.TP +.B \-N +Synchronize all the available namespaces. +By default only namespaces that don\(aqt have explicit location setting +are synchronized. +.\"------------------------------------- +.TP +.B \-P +Run a +.BR doveadm\-purge (1) +for the destination (remote) storage after synchronization. +.\"------------------------------------- +.TP +.B \-R +Do a reverse sync. Normally, messages would be pushed from the local +system to the destination (remote). This option reverses the flow, and +will instead pull messages from the remote to the local storage. +.\"------------------------------------- +@INCLUDE:option-S-socket@ +.\"------------------------------------- +.TP +.BI \-T \ secs +Specify the time in seconds, how long +.BR doveadm (1) +should wait for stalled I/O operations. +The default timeout is 600 seconds. +.\"------------------------------------- +.TP +.B \-U +This is used internally by replicator to have dsync notify it when the +synchronization is finished. +.\"------------------------------------- +.TP +.B \-d +Use the default destination, which is looked up from the +.I mail_replica userdb +extra field. +.\"------------------------------------- +.TP +.BI \-g \ mailbox_guid +Same as \-m, but find the mailbox to be synchronized by its GUID instead +of by name. +.\"------------------------------------- +.TP +.BI \-l \ secs +Lock the dsync for this user. +Wait for maximum +.I secs +before giving up. +This parameter should be used to avoid broken synchronization if it\(aqs +possible that dsync is being run concurrently for the same user. +.\"------------------------------------- +.TP +.BI \-m \ mailbox +Synchronize only this mailbox name. +.\"------------------------------------- +.TP +.BI \-n \ namespace +Synchronize only the specified namespace. +This parameter can be used multiple times. +.\"------------------------------------- +.TP +.BI \-a \ all\ mailbox +Name for the "All mails" virtual mailbox. If specified, mails are attempted to +be copied from this mailbox instead of being saved separately. This may +reduce the total disk space usage as well as disk IO. +.\"------------------------------------- +.TP +.BI \-t \ start\ date +Skip any mails whose received-timestamp is older than the specified time. +.\"------------------------------------- +.TP +.BI \-e \ end\ date +Skip any mails whose received-timestamp is newer than the specified time. +.\"------------------------------------- +.TP +.BI \-O \ sync\ flag +Sync only mails that have the specified flag. +If the flag name begins with \(dq\fB\-\fP\(dq, sync all mails except the ones +with the specified flag. +.\"------------------------------------- +.TP +.BI \-I \ max\ size +Skip any mails larger than the specified size. +.\"------------------------------------- +.TP +.BI \-r \ rawlog_path +Running dsync remotely, write the remote input/output traffic to the +specified log file. +.\"------------------------------------- +.TP +.BI \-s \ previous_state +Use stateful synchronization. +If the previous state is unknown, use an empty string. +The new state is always printed to standard output. +.\"------------------------------------- +@INCLUDE:option-u-user@ +.\"------------------------------------- +.TP +.BI \-x \ mailbox_mask +Exclude the specified mailbox name/mask. +The mask may contain \(dq\fB?\fP\(dq and \(dq\fB*\fP\(dq wildcards. +The mask can also be a special-use name (e.g. \\Trash). +This parameter can be used multiple times. +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I destination +This argument specifies the synchronized destination. +It can be one of: +.RS +.TP +location +Same as +.I mail_location +setting, e.g. maildir:\(ti/Maildir +.TP +.BI remote: login@host +Uses +.I dsync_remote_cmd +setting to connect to the remote host (usually via ssh) +.TP +.I remoteprefix:login@host +This is the same as remote, except \(dquser@domain\(rsn\(dq is sent before +dsync protocol starts. +This allows implementing a trusted wrapper script that runs doveadm +dsync\-server by reading the username from the first line. +.TP +.BI tcp: host[:port] +Connects to remote doveadm server via TCP. +The default port is specified by +.IR doveadm_port " setting." +.TP +.BI tcps: host[:port] +This is the same as tcp, but with SSL. +.TP +.BI command\ [arg1\ [,\ arg2,\ ...]] +Runs a local command that connects its standard input & output +to a dsync server. +.RE +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B dsync +will exit with one of the following values: +.TP 4 +.B 0 +Synchronization was done perfectly. +.TP +.B 2 +Synchronization was done without errors, but some changes couldn\(aqt be done, +so the mailboxes aren\(aqt perfectly synchronized. Running dsync again +usually fixes this. Typically this occurs for message modification +sequences with newly created mailboxes. It can also occur if one of the +mailboxes change during the syncing. +.TP +.B 1, >2 +Synchronization failed. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +.SS SYNCHRONIZATION +Synchronize mailboxes with a remote server. +Any errors are written to stderr. +.PP +.RS +.nf +.ft B +doveadm sync \-u username@example.com remote:server\-replica.example.com +.ft P +.fi +.RE +.PP +If you need more complex parameters to ssh, you can use e.g.: +.PP +.RS +.nf +.ft B +doveadm sync \-u username@example.com ssh \-i id_dsa.dovecot \(rs +mailuser@example.com doveadm dsync\-server \-u username@example.com +.ft P +.fi +.RE +.\"------------------------------------------------------------------------ +.SS CONVERTING +Assuming that the +.I mail_location +setting in +.I @pkgsysconfdir@/conf.d/10\-mail.conf +is set to: +.BR "mail_location = mdbox:\(ti/mdbox" , +a logged in system user may convert her/his mails from its Maildir in +her/his home directory to the mdbox mailbox format. +The user has to execute the command: +.PP +.RS +.nf +.ft B +doveadm sync maildir:\(ti/Maildir +.ft P +.fi +.RE +.PP +If you want to do this without any downtime, you can do the conversion one +user at a time. +Initially: +.RS 4 +.IP \(bu 4 +Configuration uses +.B mail_location = maildir:\(ti/Maildir +.IP \(bu +Set up the possibility of doing per\-user mail location using +.I userdb +extra fields. +.RE +.PP +Then for each user: +.RS 4 +.IP 1. 4 +Run +.I doveadm sync +once to do the initial conversion. +.IP 2. +Run +.I doveadm sync +again, because the initial conversion could have taken a while and new +changes could have occurred during it. +This second time only applies changes, so it should be fast. +.IP 3. +Update mail extra field in userdb to +.BR mdbox:\(ti/mdbox . +If you\(aqre using auth cache, you need to flush it, e.g. +.BR "doveadm auth cache flush" . +.IP 4. +Wait for a few seconds and then kill (doveadm kick) the user\(aqs all +existing imap and pop3 sessions (that are still using maildir). +.IP 5. +Run +.I doveadm sync +once more to apply final changes that were possibly done. +After this there should be no changes to Maildir, because the user\(aqs +mail location has been changed and all existing processes using it have +been killed. +.RE +.PP +Once all users have been converted, you can set the default +.I mail_location +to mdbox and remove the per\-user mail locations from +.IR userdb . +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-auth (1), +.BR doveadm\-kick (1), +.BR doveadm\-purge (1), +.BR doveconf (1) +.\"------------------------------------- +.PP +Additional resources: +.IP "dsync design" +http://wiki2.dovecot.org/Design/Dsync diff --git a/doc/man/doveadm-user.1.in b/doc/man/doveadm-user.1.in new file mode 100644 index 0000000..a86e108 --- /dev/null +++ b/doc/man/doveadm-user.1.in @@ -0,0 +1,165 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-USER 1 "2013-11-23" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-user \- Perform a user lookup in Dovecot\(aqs userdbs +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] " user +[\fB\-a\fP \fIuserdb_socket_path\fP] +[\fB\-f\fP \fIfield\fP] +.RB [ \-u ] +[\fB\-x\fP \fIauth_info\fP] +.IR user\ ... +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B user +command is used to perform a user lookup \- to show what information +Dovecot sees about the +.IR user (s), +or if it exists at all in the configured +.IR userdb (s). +.PP +The +.I auth_info +may be useful when the userdb is for example a SQL database and you are +using %variables, like +.B %s +or +.BR %l , +in the +.I user_query +setting. +Or when you have configured the userdb in a way like this: +.sp +.nf +userdb { + driver = passwd\-file + args = /etc/%s.passwd +} +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:global-options@ +.\" --- command specific options --- "/. +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.BI \-a\ userdb_socket_path +This option is used to specify an absolute path to an alternative UNIX +domain socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/auth\-userdb . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------- +.TP +.BI \-f\ field +When this option and the name of a userdb field is given, +.BR doveadm (1) +will show only the value of the specified field. +.\"------------------------------------- +.TP +.B \-u +When this option is given, +.BR doveadm (1) +will only show values from the +.IR userdb . +Without \-u parameter if any of the +.IR uid ", " gid ", " home " or " mail +fields are missing, their defaults are taken from configuration file. +.\"------------------------------------- +.TP +.BI \-x\ auth_info +.I auth_info +specifies additional conditions for the +.B user +command. +The +.I auth_info +option string has to be given as +.IB name = value +pair. +For multiple conditions the +.B \-x +option could be supplied multiple times. +.br +Possible names for the +.I auth_info +are: +.RS +.TP +.B service +The service for which the userdb lookup should be tested. +The value may be the name of a service, commonly used with Dovecot. +For example: +.BR imap , +.BR pop3\ or +.BR smtp . +.TP +.B lip +The local IP address (server) for the test. +.TP +.B rip +The remote IP address (client) for the test. +.TP +.B lport +The local port, e.g. 143 +.TP +.B rport +The remote port, e.g. 24567 +.RE +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +.I user +Is a +.IR user \(aqs +login name. +Depending on the configuration, a login name may be for example +.BR jane " or " john@example.com . +It\(aqs also possible to use +.RB \(aq * \(aq +and +.RB \(aq ? \(aq +wildcards (e.g. \-u *@example.org). +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Perform a user lookup for the users jane and john@example.com. +.sp +.nf +.B doveadm user jane john@example.com +userdb: jane + uid : 8001 + gid : 8001 + home : /home/jane + mail : sdbox:~/sdbox + plugins : sieve + quota_rule: *:storage=150M + +userdb: john@example.com + home : /srv/mail/8/70312/79832 + uid : 79832 + gid : 70312 + mail : mdbox:~/mdbox +.fi +.PP +The next example shows a user lookup, using wildcards. +.sp +.nf +.B doveadm user *.?oe@example.net +jane.doe@example.net +judy.roe@example.net +john.doe@example.net +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1)
\ No newline at end of file diff --git a/doc/man/doveadm-who.1.in b/doc/man/doveadm-who.1.in new file mode 100644 index 0000000..585580b --- /dev/null +++ b/doc/man/doveadm-who.1.in @@ -0,0 +1,96 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM\-WHO 1 "2010-07-12" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm\-who \- Show who is logged in to the Dovecot server +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.BR who\ [ \-1 ] +[\fB\-a\fP \fIanvil_socket_path\fP] +.RI [ user ] +[\fIip\fP[\fB/\fP\fImask\fP]] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B who +command is used to show which users from which hosts are currently +connected to which service. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\" --- command specific options --- "/. +.PP +This command uses by default the output formatter +.BR table . +.PP +Command specific +.IR options : +.\"------------------------------------- +.TP +.B \-1 +Print one line per user and connection. +Otherwise the connections are grouped by the username. +.\"------------------------------------- +.TP +.BI \-a\ anvil_socket_path +This option is used to specify an alternative socket. +The option\(aqs argument is either an absolute path to a local UNIX domain +socket, or a hostname and port +.RI ( hostname : port ), +in order to connect a remote host via a TCP socket. +.sp +By default +.BR doveadm (1) +will use the socket +.IR @rundir@/anvil . +The socket may be located in another directory, when the default +.I base_dir +setting was overridden in +.IR @pkgsysconfdir@/dovecot.conf . +.\"------------------------------------------------------------------------ +.SH ARGUMENTS +.TP +\fIip\fP[\fB/\fP\fImask\fP] +Specify an +.I ip +address or network range, in CIDR notation, to reduce the result to +matching connections. +.\"------------------------------------- +.TP +.I user +List only users, whose name match +.IR user . +It\(aqs also possible to use wildcards in the +.I user +name. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +Show authenticated sessions, filtered by the client\(aqs IP address. +.sp +.nf +.B doveadm who ::1 +username # proto (pids) (ips) +jane 2 imap (30155 30412) (::1) +.B doveadm who 192.0.2.0/24 +username # proto (pids) (ips) +john@example.com 1 imap (30257) (192.0.2.34) +.fi +.PP +Show authenticated sessions, filtered by username. +.sp +.nf +.B doveadm who pvo +username # proto (pids) (ips) +pvo 1 sieve (30343) (fd95:4eed:38ba::25) +pvo 4 imap (25693 25686 25679 25669) (fd95:4eed:38ba::25) +.B doveadm who ja* +username # proto (pids) (ips) +james 1 imap (30091) (127.0.0.1) +jane 2 imap (30155 30412) (::1) +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveadm\-kick (1)
\ No newline at end of file diff --git a/doc/man/doveadm.1.in b/doc/man/doveadm.1.in new file mode 100644 index 0000000..ae5acba --- /dev/null +++ b/doc/man/doveadm.1.in @@ -0,0 +1,270 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVEADM 1 "2014-10-07" "Dovecot v2.3" "Dovecot" +.SH NAME +doveadm \- Dovecot\(aqs administration utility +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR doveadm " [" \-Dv "] [" \-f +.IR formatter ] +.IR command " [" command_options "] [" command_arguments ] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveadm +is the Dovecot administration tool. It can be used to manage various parts +of Dovecot, as well as access users\(aq mailboxes. +.br +Execute +.BR doveadm\ help , +for a command usage listing. +.\"------------------------------------------------------------------------ +@INCLUDE:global-options-formatter@ +.\"------------------------------------------------------------------------ +.SH COMMANDS +.\"------------------------------------------------------------------------ +These commands work directly with Dovecot\(aqs master process. +.\"------------------------------------- +.SS reload +.B doveadm reload +.PP +Force +.BR dovecot (1) +to reload the configuration. +.\"------------------------------------------------------------------------ +.SS stop +.B doveadm stop +.PP +Stop +.BR dovecot (1) +and all its child processes. +.\"------------------------------------------------------------------------ +.SS ADDITIONAL MASTER COMMANDS +.TP +.B doveadm config +.BR doveadm\-config (1), +Dump Dovecot configuration. +.\"------------------------------------- +.TP +.B doveadm director +.BR doveadm\-director (1), +Manage Dovecot directors (if used by proxy servers). +.\"------------------------------------- +.TP +.B doveadm exec +.BR doveadm\-exec (1), +Easily execute commands from Dovecot\(aqs libexec_dir. +.\"------------------------------------- +.TP +.B doveadm instance +.BR doveadm\-instance (1), +Manage the list of running Dovecot instances. +.\"------------------------------------- +.TP +.B doveadm kick +.BR doveadm\-kick (1), +Disconnect users by user name and/or IP address. +.\"------------------------------------- +.TP +.B doveadm log +.BR doveadm\-log (1), +Locate, test or reopen Dovecot\(aqs log files. +.\"------------------------------------- +.TP +.B doveadm penalty +.BR doveadm\-penalty (1), +Show current penalties. +.\"------------------------------------- +.TP +.B doveadm proxy +.BR doveadm\-proxy (1), +Handle Dovecot proxy connections. +.\"------------------------------------- +.TP +.B doveadm who +.BR doveadm\-who (1); +Show who is logged in to the Dovecot server. +.\"------------------------------------------------------------------------ +.SS AUTHENTICATION COMMANDS +.\"------------------------------------- +.TP +.B doveadm auth +.BR doveadm\-auth (1), +Test authentication for a user. +.\"------------------------------------- +.TP +.B doveadm pw +.BR doveadm\-pw (1), +Dovecot\(aqs password hash generator. +.\"------------------------------------- +.TP +.B doveadm user +.BR doveadm\-user (1), +Perform a user lookup in Dovecot\(aqs userdbs +.\"------------------------------------------------------------------------ +.SS MAILBOX COMMANDS +.TP +.B doveadm acl +.BR doveadm\-acl (1), +Manage Access Control List (ACL). +.\"------------------------------------- +.TP +.B doveadm altmove +.BR doveadm\-altmove (1), +Move matching mails to the alternative storage. +.\"------------------------------------- +.TP +.B doveadm backup +.BR doveadm\-backup (1), +Dovecot\(aqs one\-way mailbox synchronization utility. +.\"------------------------------------- +.TP +.B doveadm batch +.BR doveadm\-batch (1), +Execute multiple commands for multiple users. +.\"------------------------------------- +.TP +.B doveadm copy +.BR doveadm\-copy (1), +Copy messages matching the given search query into another mailbox. +.\"------------------------------------- +.TP +.B doveadm deduplicate +.BR doveadm\-deduplicate (1), +Expunge duplicate messages. +.\"------------------------------------- +.TP +.B doveadm dump +.BR doveadm\-dump (1), +Dump the content of Dovecot\(aqs binary mailbox index/log. +.\"------------------------------------- +.TP +.B doveadm expunge +.BR doveadm\-expunge (1), +Expunge messages matching given search query. +.\"------------------------------------- +.TP +.B doveadm fetch +.BR doveadm\-fetch (1), +Fetch messages matching given search query. +.\"------------------------------------- +.TP +.B doveadm flags +.BR doveadm\-flags (1), +Add, remove or replace messages\(aq flags. +.\"------------------------------------- +.TP +.B doveadm force\-resync +.BR doveadm\-force\-resync (1), +Repair broken mailboxes, in case Dovecot doesn\(aqt automatically do that. +.\"------------------------------------- +.TP +.B doveadm fs +.BR doveadm\-fs (1), +Interact with the abstract mail storage filesystem. +.\"------------------------------------- +.TP +.B doveadm fts +.BR doveadm\-fts (1), +Manipulate the Full Text Search (FTS) index. +.\"------------------------------------- +.TP +.B doveadm import +.BR doveadm\-import (1), +Import messages matching given search query. +.\"------------------------------------- +.TP +.B doveadm index +.BR doveadm\-index (1), +Index messages in a given mailbox. +.\"------------------------------------- +.TP +.B doveadm mailbox +.BR doveadm\-mailbox (1), +Various commands related to handling mailboxes. +.\"------------------------------------- +.TP +.B doveadm mailbox cryptokey +.BR doveadm\-mailbox\-cryptokey (1), +Mail crypt plugin management. +.\"------------------------------------- +.TP +.B doveadm move +.BR doveadm\-move (1) +Move messages matching the given search query into another mailbox. +.\"------------------------------------- +.TP +.B doveadm purge +.BR doveadm\-purge (1) +Remove messages with refcount=0 from mdbox files. +.\"------------------------------------- +.TP +.B doveadm quota +.BR doveadm\-quota (1), +Initialize/recalculate or show current quota usage. +.\"------------------------------------- +.TP +.B doveadm rebuild +.BR doveadm\-rebuild (1), +Rebuild index metadata from message data. +.\"------------------------------------- +.TP +.B doveadm replicator +.BR doveadm\-replicator (1), +Manage users\(aq mail replication. +.\"------------------------------------- +.TP +.B doveadm save +.BR doveadm\-save (1), +Save email to users\(aq mailboxes. +.\"------------------------------------- +.TP +.B doveadm search +.BR doveadm\-search (1), +Show a list of mailbox GUIDs and message UIDs matching given search query. +.\"------------------------------------- +.TP +.B doveadm stats +.BR doveadm\-stats (1), +Inspect or reset stats. +.\"------------------------------------- +.TP +.B doveadm sync +.BR doveadm\-sync (1), +Dovecot\(aqs two\-way mailbox synchronization utility. +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B doveadm +will exit with one of the following values: +.TP 4 +.B 0 +Selected command was executed successful. +.TP +.B >0 +Command failed in some way. +.\"------------------------------------------------------------------------ +.SH ENVIRONMENT +.TP +.B USER +This environment variable is used to determine the +.I user +if a command accepts a +.I user +but none was specified. +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/10\-mail.conf +Mailbox locations and namespaces. +.TP +.I @pkgsysconfdir@/conf.d/90\-plugin.conf +Plugin specific settings. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm\-help (1), +.BR doveconf (1), +.BR dovecot (1), +.BR doveadm\-search\-query (7) diff --git a/doc/man/doveconf.1.in b/doc/man/doveconf.1.in new file mode 100644 index 0000000..060f0e0 --- /dev/null +++ b/doc/man/doveconf.1.in @@ -0,0 +1,220 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVECONF 1 "2014-10-19" "Dovecot v2.3" "Dovecot" +.SH NAME +doveconf \- Dovecot\(aqs configuration dumping utility +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B doveconf +.RB [ \-adnPNSx ] +[\fB\-c\fP \fIconfig\-file\fP] +[\fB\-f\fP \fIfilter\fP] +[\fB\-m\fP \fImodule\fP] +.\"------------------------------------- +.br +.B doveconf +.RB [ \-n ] +[\fB\-c\fP \fIconfig\-file\fP] +.IR section_name \ ... +.\"------------------------------------- +.br +.B doveconf +.RB [ \-h ] +[\fB\-c\fP \fIconfig\-file\fP] +[\fB\-f\fP \fIfilter\fP] +.IR setting_name \ ... +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B doveconf +reads and parses Dovecot\(aqs configuration files and converts them into a +simpler format used by the rest of Dovecot. All standalone programs, such +as +.BR dovecot (1) +and +.BR dovecot\-lda (1), +will first get their settings by executing doveconf. +.PP +For system administrators, +.B doveconf +is mainly useful for dumping the configuration in easy human readable +output. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.B \-a +Show all settings with their currently configured values. +.\"--------------------------------- +.TP +.BI \-c \ config\-file +read configuration from the given +.IR config\-file . +By default +.I @pkgsysconfdir@/dovecot.conf +will be used. +.\"--------------------------------- +.TP +.B \-d +Show the setting\(aqs default value instead of the one currently +configured. +.\"--------------------------------- +.TP +.BI \-f \ filter +Show the matching configuration for the specified +.I filter +condition. +The +.I filter +option string has to be given as +.IB name = value +pair. +For multiple filter conditions the +.B \-f +option can be supplied multiple times. +.br +Possible names for the +.I filter +are: +.RS +.TP +.B lname +The local hostname, e.g. mail.example.com. +This will only match hostnames which were configured like: +.br +.B local_name mail.example.com { # special settings } +.TP +.B local +The server\(aqs hostname or IP address. +This will also match hostnames which were configured like: +.br +.B local imap.example.net { # special settings } +.TP +.B protocol, service +The protocol, e.g. imap or pop3 +.TP +.B remote +The client\(aqs hostname or IP address. +.RE +.\"--------------------------------- +.TP +.B \-h +Hide the setting\(aqs name, show only the setting\(aqs value. +.\"--------------------------------- +.TP +.BI \-m\ module +Show only settings for the given +.IR module . +.RS +e.g. +.BR imap , +.BR imap\-login , +.BR lmtp , +.BR pop3\ or +.B pop3\-login +.RE +.\"--------------------------------- +.TP +.B \-n +Show only settings with non\-default values. +.\"--------------------------------- +.TP +.B \-N +Show settings with non\-default values and explicitly set default values. +.\"--------------------------------- +.TP +.B \-S +Dump settings in simplified machine parsable/readable format. +.\"--------------------------------- +.TP +.B \-s +Show also hidden settings. The hidden settings should not be changed normally. +.\"--------------------------------- +.TP +.\"--------------------------------- +.TP +.B \-P +Show passwords and other sensitive values. +.\"--------------------------------- +.TP +.B \-x +Expand configuration variables (e.g. \(Domail_plugins \(rA quota) and show +file contents (from e.g. ssl_cert = </etc/ssl/certs/dovecot.pem). +.\"--------------------------------- +.TP +.I section_name +Show only the current configuration of one or more specified sections. +.\"--------------------------------- +.TP +.I setting_name +Show only the setting of one or more +.IR setting_name (s) +with the currently configured value. You can show a setting inside a +section using \(aq/\(aq as the section separator, e.g. +service/imap/executable. +.\"------------------------------------------------------------------------ +.SH EXAMPLE +When Dovecot was configured to use different settings for some +networks/subnets it is possible to show which settings will be applied +for a specific connection. +.sp +.nf +.ft B +doveconf \-f local=10.0.0.110 \-f remote=10.11.1.2 \-f service=pop3 \-n +.ft P +.fi +.PP +.B doveconf +can be also used to convert v1.x configuration files into v2.x format. +.sp +.nf +.ft B +doveconf \-n \-c /oldpath/dovecot.conf > \ +@pkgsysconfdir@/dovecot.conf.new +.ft P +.fi +.\"------------------------------------- +.PP +This example shows how to ask +.B doveconf +for a global setting and a protocol specific setting. +The second command uses also the +.B \-h +option, in order to hide the setting\(aqs name. +.sp +.nf +.ft B +doveconf mail_plugins +.ft P +mail_plugins = quota +.ft B +doveconf \-h \-f protocol=imap mail_plugins +.ft P +quota imap_quota +.fi +.\"------------------------------------- +.PP +This example demonstrates how to dump a whole configuration section. +.sp +.nf +.ft B +doveconf dict +.ft P +dict { + quota = pgsql:@pkgsysconfdir@/dovecot\-dict\-sql.conf.ext +} +.fi +.PP +Or how to dump only the quota dict: +.sp +.nf +.ft B +doveconf dict/quota +.ft P +dict/quota = pgsql:@pkgsysconfdir@/dovecot\-dict\-sql.conf.ext +.fi +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR dovecot (1), +.BR dovecot\-lda (1), +.BR dsync (1)
\ No newline at end of file diff --git a/doc/man/dovecot-lda.1.in b/doc/man/dovecot-lda.1.in new file mode 100644 index 0000000..7f8033b --- /dev/null +++ b/doc/man/dovecot-lda.1.in @@ -0,0 +1,166 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVECOT\-LDA 1 "2011-01-16" "Dovecot v2.3" "Dovecot" +.SH NAME +dovecot\-lda \- Dovecot\(aqs local mail delivery agent +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.B dovecot\-lda +.RB [ \-ek ] +[\fB\-a\fP \fIaddress\fP] +[\fB\-c\fP \fIconfig_file\fP] +[\fB\-d\fP \fIusername\fP] +[\fB\-f\fP \fIenvelope_sender\fP] +[\fB\-m\fP \fImailbox\fP] +[\fB\-o\fP \fIsetting=value\fP] +[\fB\-p\fP \fIpath\fP] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +The +.B dovecot\-lda +is a local mail delivery agent which takes mail from an MTA and delivers +it to a user\(aqs mailbox, while keeping Dovecot index files up to date. +.PP +Main features of the +.B dovecot\-lda +are: +.TP 4 +* +Mailbox indexing during mail delivery, providing faster mailbox access +later +.TP +* +Quota enforcing by the quota plugin +.TP +* +Sieve language support by the Pigeonhole sieve plugin +.\"------------------------------------------------------------------------ +.SH OPTIONS +Options accepted by +.BR dovecot\-lda : +.\"------------------------------------- +.TP +.BI \-a\ address +Destination address (e.g. user+ext@domain). Default is the same as +.IR username . +.\"------------------------------------- +.TP +.BI \-c\ config_file +Alternative configuration file path. +.\"------------------------------------- +.TP +.BI \-d\ username +Destination +.IR username . +If given, the user information is looked up from userdb. +Typically used with virtual users, but not necessarily with system users. +.\"------------------------------------- +.TP +.B \-e +If mail gets rejected, write the rejection reason to stderr and exit with +status 77 (EX_NOPERM). +The default is to send a rejection mail ourself. +.\"------------------------------------- +.TP +.BI \-f\ envelope_sender +Envelope sender address. +.\"------------------------------------- +.TP +.B \-k +Don\(aqt clear all environment at startup. +.\"------------------------------------- +.TP +.BI \-m\ mailbox +Destination mailbox (default is +.BR INBOX ). +If the mailbox doesn\(aqt exist, it will not be created (unless the +.I lda_mailbox_autocreate +setting is set to +.BR yes ). +If a message couldn\(aqt be saved to the +.I mailbox +for any reason, it\(aqs delivered to +.B INBOX +instead. +.\"--------------------------------- +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.\"------------------------------------- +.TP +.BI \-p\ path +Path to the mail to be delivered instead of reading from stdin. +If using maildir the file is hard linked to the destination if possible. +This allows a single mail to be delivered to multiple users using hard +links, but currently it also prevents deliver from updating cache file so +it shouldn\(aqt be used unless really necessary. +.\"------------------------------------------------------------------------ +.SH "EXIT STATUS" +.B dovecot\-lda +will exit with one of the following values: +.TP 4 +.B 0 +Delivery was successful. (EX_OK) +.TP +.B 64 +Invalid parameter given. (EX_USAGE) +.TP +.B 77 +.B \-e +option was used and mail was rejected. +Typically this happens when user is over quota and +.B quota_full_tempfail = no +is configured. (EX_NOPERM) +.TP +.B 75 +A temporary failure. This is returned for almost all failures. See the log +file for details. (EX_TEMPFAIL) +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/conf.d/10\-mail.conf +Mailbox locations and namespaces. +.TP +.I @pkgsysconfdir@/conf.d/15\-lda.conf +LDA specific settings. +.TP +.I @pkgsysconfdir@/conf.d/90\-plugin.conf +Plugin specific settings. +.TP +.I @pkgsysconfdir@/conf.d/90\-quota.conf +Quota configuration. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR dovecot (1), +.BR doveconf (1), +.BR dsync (1) +.PP +Related MTA specific documentation: +.\"------------------------------------- +.TP +Postfix: +.BR postconf (5), +.BR transport (5), +.BR pipe (8) +.\"------------------------------------- +.PP +Exim: +.IP "The accept router" +http://exim.org/exim\-html\-current/doc/html/spec_html/ch16.html +.IP "Generic options for transports" +http://exim.org/exim\-html\-current/doc/html/spec_html/ch24.html +.IP "The pipe transport" +http://exim.org/exim\-html\-current/doc/html/spec_html/ch29.html diff --git a/doc/man/dovecot-sysreport.1.in b/doc/man/dovecot-sysreport.1.in new file mode 100644 index 0000000..e3b30ce --- /dev/null +++ b/doc/man/dovecot-sysreport.1.in @@ -0,0 +1,40 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVECOT-SYSREPORT 1 "2020-01-21" "Dovecot v2.3" "Dovecot" +.SH NAME +dovecot-sysreport \- Dovecot\(aqs system report utility +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +.BR dovecot-sysreport " [" \-h|\-\-help "] [" \-c|\-\-core " ["\c +.IR binary "] " core " [...]]" +.BR "[\-d|\-\-destination +.IR dest "] +.BR "[\-k|\-\-keeptemp] +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +.B dovecot-sysreport +is a utility that should be used to gather information from the current +system to be reported for dovecot bug fixes. It will collect dovecot's +ps output, service status, process status, uptime command's output, +error log, stats dump and if given, a core file along with its binary +dependencies. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.B \-h|\-\-help +Prints a help message. +.TP +.BI \-c|\-\-config\ root_config_file +Sets the root file of the dovecot's configuration. If not set, it will be +assumed to be in the default configuration path. +.TP +.BI \-o|\-\-core\ [ binary "] " core " [...]]" +Includes core files along with their dependencies extracted from the +specified binary file. +.TP +.BI \-d|\-\-destination\ dest +Sets the file location which the report archive should be put to. The default +value is dovecot-sysreport-<hostname>-<current_timestamp>.tar.gz in the +current path. +.TP +.B \-k|\-\-keeptemp +If set, temp files would not be deleted at the end.
\ No newline at end of file diff --git a/doc/man/dovecot.1.in b/doc/man/dovecot.1.in new file mode 100644 index 0000000..a161b54 --- /dev/null +++ b/doc/man/dovecot.1.in @@ -0,0 +1,167 @@ +.\" Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file +.TH DOVECOT 1 "2013-08-06" "Dovecot v2.3" "Dovecot" +.SH NAME +dovecot \- a secure and highly configurable IMAP and POP3 server +.\"------------------------------------------------------------------------ +.SH SYNOPSIS +\fBdovecot\fP [\fB\-Fp\fP] [\fB\-c\fP \fIconfig\-file\fP] +.br +.B dovecot \-a +[\fB\-c\fP \fIconfig\-file\fP] +.br +.B dovecot \-n +[\fB\-c\fP \fIconfig\-file\fP] +.br +.B dovecot \-\-build\-options +.br +.B dovecot \-\-help +.br +.B dovecot \-\-hostdomain +.br +.B dovecot \-\-version +.br +.B dovecot reload +.br +.B dovecot stop +.\"------------------------------------------------------------------------ +.SH DESCRIPTION +Dovecot is an open source IMAP and POP3 server for Linux/UNIX\-like +systems, written with security primarily in mind. +Dovecot is an excellent choice for both small and large installations. +It\(aqs fast, simple to set up, requires no special administration and it +uses very little memory. +.\"------------------------------------------------------------------------ +.SH OPTIONS +.TP +.B \-a +Dump all configuration settings to stdout and exit successfully. +The same as +.IR doveconf\ \-a . +.TP +.BI \-c\ config\-file +Start +.B dovecot +with an alternative configuration. +.TP +.B \-F +Run +.B dovecot +in foreground, do not daemonize. +.TP +.B \-n +Dump non\-default settings to stdout and exit successfully. +The same as +.IR doveconf\ \-n . +.TP +.B \-p +Prompt for the ssl key password for the configured +.I ssl_key +on startup. +.TP +.B \-\-build\-options +Show Dovecot\(aqs build options and exit successfully. +.TP +.B \-\-help +Print a usage message to stdout and exit successfully. +.TP +.B \-\-hostdomain +Shows the current +.IR host . domain +name of the system. +If the domain lookup should fail for some reason, only the hostname will +be shown. +.TP +.B \-\-version +Show Dovecot\(aqs version and exit successfully. +.\"------------------------------------------------------------------------ +.SH COMMANDS +.TP +.B reload +Force +.B dovecot +to reload its configuration. +.TP +.B stop +Shutdown +.B dovecot +and all its child processes. +.PP +When +.I shutdown_clients +is set to +.BR no , +existing sessions will continue to use the old settings, after a +.BR "dovecot reload" . +Also all sessions will keep alive after a +.BR "dovecot stop" . +.br +By default all active sessions will be shut down. +.\"------------------------------------------------------------------------ +.SH SIGNALS +Dovecot handles the following +.I signals +as described: +.TP +.B HUP +Force +.B dovecot +to reload its configuration. +.TP +.B INT +Shutdown +.B dovecot +and all its child processes. +.TP +.B TERM +Shutdown +.B dovecot +and all its child processes. +.TP +.B USR1 +Force +.B dovecot +to reopen all configured log files (\c +.IR log_path , +.IR info_log_path\ and +.IR debug_log_path ). +. +.PP +The +.I signals +.BR ALARM\ and +.B PIPE +are ignored. +.\"------------------------------------------------------------------------ +.SH FILES +.TP +.I @pkgsysconfdir@/dovecot.conf +Dovecot\(aqs main configuration file. +.TP +.I @pkgsysconfdir@/dovecot\-ldap.conf.ext +Dovecot\(aqs LDAP authdb/userdb module configuration file. +.TP +.I @pkgsysconfdir@/dovecot\-sql.conf.ext +Dovecot\(aqs SQL authdb/userdb module configuration file. +.TP +.I @pkgsysconfdir@/dovecot\-dict\-sql.conf.ext +Dovecot\(aqs dict configuration with SQL\-backend. +.TP +.I @pkgsysconfdir@/conf.d/auth\-*\-conf.ext +Configuration files of different authentication modules. +.TP +.I @pkgsysconfdir@/conf.d/*.conf +Configuration files of different services and settings. +.\"------------------------------------------------------------------------ +@INCLUDE:reporting-bugs@ +.\"------------------------------------------------------------------------ +.SH AUTHOR +Dovecot <http://dovecot.org> and its manual pages were written by the +Dovecot authors <http://dovecot.org/doc/AUTHORS>, mainly Timo Sirainen <tss +at iki.fi>, and are licensed under the terms of the MIT and LGPLv2.1 +licenses, see <http://dovecot.org/doc/COPYING> for details. +.\"------------------------------------------------------------------------ +.SH SEE ALSO +.BR doveadm (1), +.BR doveconf (1), +.BR dovecot\-lda (1), +.BR dsync (1)
\ No newline at end of file diff --git a/doc/man/dsync.1 b/doc/man/dsync.1 new file mode 100644 index 0000000..106321c --- /dev/null +++ b/doc/man/dsync.1 @@ -0,0 +1 @@ +.so man1/doveadm-sync.1
\ No newline at end of file diff --git a/doc/man/global-options-formatter.inc b/doc/man/global-options-formatter.inc new file mode 100644 index 0000000..cb792e1 --- /dev/null +++ b/doc/man/global-options-formatter.inc @@ -0,0 +1,46 @@ +.SH OPTIONS +Global +.BR doveadm (1) +.IR options : +.TP +.B \-D +Enables verbosity and debug messages. +.TP +.BI \-f\ formatter +Specifies the +.I formatter +for formatting the output. +Supported formatters are: +.RS +.TP +.B flow +prints each line with +.IB key = value +pairs. +.TP +.B pager +prints each +.IR key :\ value +pair on its own line and separates records with form feed character +.RB ( ^L ). +.TP +.B tab +prints a table header followed by tab separated value lines. +.TP +.B table +prints a table header followed by adjusted value lines. +.RE +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.B \-v +Enables verbosity, including progress counter. diff --git a/doc/man/global-options.inc b/doc/man/global-options.inc new file mode 100644 index 0000000..bf99294 --- /dev/null +++ b/doc/man/global-options.inc @@ -0,0 +1,21 @@ +.SH OPTIONS +Global +.BR doveadm (1) +.IR options : +.TP +.B \-D +Enables verbosity and debug messages. +.TP +.BI \-o\ setting = value +Overrides the configuration +.I setting +from +.I @pkgsysconfdir@/dovecot.conf +and from the userdb with the given +.IR value . +In order to override multiple settings, the +.B \-o +option may be specified multiple times. +.TP +.B \-v +Enables verbosity, including progress counter. diff --git a/doc/man/option-A.inc b/doc/man/option-A.inc new file mode 100644 index 0000000..256e939 --- /dev/null +++ b/doc/man/option-A.inc @@ -0,0 +1,27 @@ +.TP +.B \-A +If the +.B \-A +option is present, the +.I command +will be performed for all users. +Using this option in combination with system users from +.B userdb { driver = passwd } +is not recommended, because it contains also users with a lower UID than +the one configured with the +.I first_valid_uid +setting. +.sp +When the SQL userdb module is used make sure that the +.I iterate_query +setting in +.I @pkgsysconfdir@/dovecot\-sql.conf.ext +matches your database layout. +When using the LDAP userdb module, make sure that the +.IR iterate_attrs " and " iterate_filter +settings in +.I @pkgsysconfdir@/dovecot-ldap.conf.ext +match your LDAP schema. +Otherwise +.BR doveadm (1) +will be unable to iterate over all users. diff --git a/doc/man/option-F-file.inc b/doc/man/option-F-file.inc new file mode 100644 index 0000000..ac561b0 --- /dev/null +++ b/doc/man/option-F-file.inc @@ -0,0 +1,15 @@ +.TP +.BI \-F\ file +Execute the +.I command +for all the users in the +.IR file . +This is similar to the +.B \-A +option, +but instead of getting the list of users from the userdb, +they are read from the given +.IR file . +The +.I file +contains one username per line. diff --git a/doc/man/option-S-socket.inc b/doc/man/option-S-socket.inc new file mode 100644 index 0000000..2e0e374 --- /dev/null +++ b/doc/man/option-S-socket.inc @@ -0,0 +1,10 @@ +.TP +.BI \-S\ socket_path +The option\(aqs argument is either an absolute path to a local UNIX domain +socket, or a hostname and port +.RI ( hostname : port ), +in order to connect a remote host via a TCP socket. +.sp +This allows an administrator to execute +.BR doveadm (1) +mail commands through the given socket. diff --git a/doc/man/option-u-user.inc b/doc/man/option-u-user.inc new file mode 100644 index 0000000..aa6beac --- /dev/null +++ b/doc/man/option-u-user.inc @@ -0,0 +1,22 @@ +.TP +.BI \-u\ user/mask +Run the +.I command +only for the given +.IR user . +It\(aqs also possible to use +.RB \(aq * \(aq +and +.RB \(aq ? \(aq +wildcards (e.g. \-u *@example.org). +.br +When neither the +.B \-A +option, nor the +.BI \-F\ file +option, nor the +.BI \-u\ user +was specified, the +.I command +will be executed with the environment of the +currently logged in user. diff --git a/doc/man/reporting-bugs.inc b/doc/man/reporting-bugs.inc new file mode 100644 index 0000000..1823ca2 --- /dev/null +++ b/doc/man/reporting-bugs.inc @@ -0,0 +1,6 @@ +.SH REPORTING BUGS +Report bugs, including +.I doveconf \-n +output, to the Dovecot Mailing List <dovecot@dovecot.org>. +Information about reporting bugs is available at: +http://dovecot.org/bugreport.html diff --git a/doc/man/sed.sh b/doc/man/sed.sh new file mode 100644 index 0000000..2bab52a --- /dev/null +++ b/doc/man/sed.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +SRCDIR="${1:-`pwd`}" +RUNDIR="${2:-/usr/local/var/run/dovecot}" +PKGSYSCONFDIR="${3:-/usr/local/etc/dovecot}" +PKGLIBEXECDIR="${4:-/usr/local/libexec/dovecot}" + +sed -e "/^@INCLUDE:global-options@$/{ + r ${SRCDIR}/global-options.inc + d + }" \ + -e "/^@INCLUDE:global-options-formatter@$/{ + r ${SRCDIR}/global-options-formatter.inc + d + }" \ + -e "/^@INCLUDE:option-A@$/{ + r ${SRCDIR}/option-A.inc + d + }" \ + -e "/^@INCLUDE:option-F-file@$/{ + r ${SRCDIR}/option-F-file.inc + d + }" \ + -e "/^@INCLUDE:option-S-socket@$/{ + r ${SRCDIR}/option-S-socket.inc + d + }" \ + -e "/^@INCLUDE:option-u-user@$/{ + r ${SRCDIR}/option-u-user.inc + d + }" \ + -e "/^@INCLUDE:reporting-bugs@$/{ + r ${SRCDIR}/reporting-bugs.inc + d + }" | sed -e "s|@pkgsysconfdir@|${PKGSYSCONFDIR}|" \ + -e "s|@rundir@|${RUNDIR}|" \ + -e "s|@pkglibexecdir@|${PKGLIBEXECDIR}|" + diff --git a/doc/mkcert.sh b/doc/mkcert.sh new file mode 100644 index 0000000..f7e484c --- /dev/null +++ b/doc/mkcert.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# Generates a self-signed certificate. +# Edit dovecot-openssl.cnf before running this. + +umask 077 +OPENSSL=${OPENSSL-openssl} +SSLDIR=${SSLDIR-/etc/ssl} +OPENSSLCONFIG=${OPENSSLCONFIG-dovecot-openssl.cnf} + +CERTDIR=$SSLDIR/certs +KEYDIR=$SSLDIR/private + +CERTFILE=$CERTDIR/dovecot.pem +KEYFILE=$KEYDIR/dovecot.pem + +if [ ! -d $CERTDIR ]; then + echo "$SSLDIR/certs directory doesn't exist" + exit 1 +fi + +if [ ! -d $KEYDIR ]; then + echo "$SSLDIR/private directory doesn't exist" + exit 1 +fi + +if [ -f $CERTFILE ]; then + echo "$CERTFILE already exists, won't overwrite" + exit 1 +fi + +if [ -f $KEYFILE ]; then + echo "$KEYFILE already exists, won't overwrite" + exit 1 +fi + +$OPENSSL req -new -x509 -nodes -config $OPENSSLCONFIG -out $CERTFILE -keyout $KEYFILE -days 365 || exit 2 +chmod 0600 $KEYFILE +echo +$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2 diff --git a/doc/securecoding.txt b/doc/securecoding.txt new file mode 100644 index 0000000..72489ae --- /dev/null +++ b/doc/securecoding.txt @@ -0,0 +1,142 @@ +Simplicity provides security. The more you have to remember to maintain +security the easier it is to forget something. + + +Use Multiple Layers of Security +------------------------------- + +Input validation is useful to prevent clients from taking too much server +resources. Add the restrictions only where it's useful. For example a +simple "maximum line length" will limit the length of pretty much all +possible client input. + +Don't rely on input validation. Maybe you missed something. Maybe someone +calls your function somewhere else where you didn't originally intend it. +Maybe someone makes the input validation less restrictive for some reason. +Point is, it's not an excuse to cause a security hole just because input +wasn't what you expected it to be. + +Don't trust memory. If code somewhere overflowed a buffer, don't make it +easier to exploit it. For example if you have code: + + static char staticbuf[100]; + .. + char stackbuf[100]; + strcpy(stackbuf, staticbuf); + +Just because staticbuf was declared as [100], it doesn't mean it couldn't +contain more data. Overflowing static buffers can't be directly exploited, +but the strcpy() overflowing stackbuf makes it possible. Always copy data +with bounds checking. + + +Prevent Buffer Overflows +------------------------ + +Avoid writing to buffers directly. Write everything through buffer API +(lib/buffer.h) which guarantees protection against buffer overflows. +There are various safe string APIs as well (lib/str.h, lib/strfuncs.h). +Dovecot also provides a type safe array API (lib/array.h). + +If you do write to buffers directly, mark the code with /* @UNSAFE */ +unless it's _obviously_ safe. Only obviously safe code is calling a +function with (buffer, sizeof(buffer)) parameters. If you do _any_ +calculations with buffer size, mark it unsafe. + +Use const with buffers whenever you can. It guarantees that you can't +accidentally modify it. + +Use "char *" only for NUL-terminated strings. Use "unsigned char *" +if it's not guaranteed to be NUL-terminated. + + +Avoid free() +------------ + +Accessing freed memory is the most difficult problem to solve with C code. +Only real solution is to use garbage collector, but it's not possible to +write a portable GC without radical changes in how you write code. + +There are a few ways to avoid most free() calls however: data stack and +memory pools. + +Data stack works in somewhat similar way to C's control stack. alloca() is +quite near to what it does, but there's one major difference: Stack frames +are explicitly defined, so functions can return values allocated from data +stack. t_strdup_printf() call is an excellent example of why this is +useful. Rather than creating some arbitrary sized buffer and using +snprintf() which may truncate the value, you can just use t_strdup_printf() +without worrying about buffer sizes being large enough. + +Try to keep the allocations from data stack small, since the data stack's +highest memory usage size is kept for the rest of the process's lifetime. +The initial data stack size is 32kB and it should be enough in normal use. +See lib/data-stack.h. + +Memory pools are useful when you have to construct an object from multiple +pieces and you can free it all at once. Actually Dovecot's Memory Pool API +is just an abstract class for allocating memory. There's system_pool for +allocating memory with calloc(), realloc() and free() and you can create a +pool to allocate memory from data stack. If your function needs to allocate +memory for multiple objects, you may want to take struct pool as parameter +to allow caller to specify where the memory is allocated from. +See lib/mempool.h + + +Deinitialize safely +------------------- + +Whenever you free a pointer, set it to NULL. That way if you accidentally +try to free it again, it's less likely to cause a security hole. Dovecot +does this automatically with most of its free() calls, but you should also +make it a habit of making all your _destroy() functions take a +pointer-to-pointer parameter which you set to NULL. + +Don't Keep Secrets +------------------ + +We don't do anything special to protect ourself against read access buffer +overflows, so don't store anything sensitive in memory. We use multiple +processes to protect sensitive information between users. + +When dealing with passwords and such, erase them from memory after you +don't need it anymore. Note that such memset() may be optimized away by +compiler, use safe_memset(). + + +Use GCC Extensions +------------------ + +GCC makes it easy to catch some potential errors: + +Format string vulnerabilities can be prevented by marking all functions +using format strings with __attr_format__() and __attr_format_arg__() +macros and using -Wformat=2 GCC option. + +-W option checks that you don't compare signed and unsigned variables. + +I hope GCC will later emit a warning whenever there's potential integer +truncation. -Wconversion kind of does that, but it's not really meant for +it and it gives too many other useless warnings. + + +Use union Safely +---------------- + +Suppose there was code: + +union { + unsigned int number; + char *str; +} u; + +If it was possible for user to set number arbitrarily, but access the union +as string it'd be possible to read or write arbitrary memory locations. + +There's two ways to handle this. First would be to avoid union entirely and +use a struct instead. You don't really need the extra few bytes of memory +that union saves. + +Another way is to access the union only through macro that verifies that +you're accessing it correctly. See IMAP_ARG_*() macros in +lib-imap/imap-parser.h. diff --git a/doc/solr-config-7.7.0.xml b/doc/solr-config-7.7.0.xml new file mode 100644 index 0000000..3661874 --- /dev/null +++ b/doc/solr-config-7.7.0.xml @@ -0,0 +1,289 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!-- This is the default config with stuff non-essential to Dovecot removed. --> + +<config> + <!-- Controls what version of Lucene various components of Solr + adhere to. Generally, you want to use the latest version to + get all bug fixes and improvements. It is highly recommended + that you fully re-index after changing this setting as it can + affect both how text is indexed and queried. + --> + <luceneMatchVersion>7.7.0</luceneMatchVersion> + + <!-- A 'dir' option by itself adds any files found in the directory + to the classpath, this is useful for including all jars in a + directory. + + When a 'regex' is specified in addition to a 'dir', only the + files in that directory which completely match the regex + (anchored on both ends) will be included. + + If a 'dir' option (with or without a regex) is used and nothing + is found that matches, a warning will be logged. + + The examples below can be used to load some solr-contribs along + with their external dependencies. + --> + <lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*\.jar" /> + <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-\d.*\.jar" /> + + <lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*\.jar" /> + <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-\d.*\.jar" /> + + <lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*\.jar" /> + <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-\d.*\.jar" /> + + <lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*\.jar" /> + <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-\d.*\.jar" /> + + <!-- Data Directory + + Used to specify an alternate directory to hold all index data + other than the default ./data under the Solr home. If + replication is in use, this should match the replication + configuration. + --> + <dataDir>${solr.data.dir:}</dataDir> + + <!-- The default high-performance update handler --> + <updateHandler class="solr.DirectUpdateHandler2"> + + <!-- Enables a transaction log, used for real-time get, durability, and + and solr cloud replica recovery. The log can grow as big as + uncommitted changes to the index, so use of a hard autoCommit + is recommended (see below). + "dir" - the target directory for transaction logs, defaults to the + solr data directory. + "numVersionBuckets" - sets the number of buckets used to keep + track of max version values when checking for re-ordered + updates; increase this value to reduce the cost of + synchronizing access to version buckets during high-volume + indexing, this requires 8 bytes (long) * numVersionBuckets + of heap space per Solr core. + --> + <updateLog> + <str name="dir">${solr.ulog.dir:}</str> + <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int> + </updateLog> + + <!-- AutoCommit + + Perform a hard commit automatically under certain conditions. + Instead of enabling autoCommit, consider using "commitWithin" + when adding documents. + + http://wiki.apache.org/solr/UpdateXmlMessages + + maxDocs - Maximum number of documents to add since the last + commit before automatically triggering a new commit. + + maxTime - Maximum amount of time in ms that is allowed to pass + since a document was added before automatically + triggering a new commit. + openSearcher - if false, the commit causes recent index changes + to be flushed to stable storage, but does not cause a new + searcher to be opened to make those changes visible. + + If the updateLog is enabled, then it's highly recommended to + have some sort of hard autoCommit to limit the log size. + --> + <autoCommit> + <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> + <openSearcher>false</openSearcher> + </autoCommit> + + <!-- softAutoCommit is like autoCommit except it causes a + 'soft' commit which only ensures that changes are visible + but does not ensure that data is synced to disk. This is + faster and more near-realtime friendly than a hard commit. + --> + <autoSoftCommit> + <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> + </autoSoftCommit> + + <!-- Update Related Event Listeners + + Various IndexWriter related events can trigger Listeners to + take actions. + + postCommit - fired after every commit or optimize command + postOptimize - fired after every optimize command + --> + + </updateHandler> + + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Query section - these settings control query time things like caches + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> + <query> + <!-- Solr Internal Query Caches + + There are two implementations of cache available for Solr, + LRUCache, based on a synchronized LinkedHashMap, and + FastLRUCache, based on a ConcurrentHashMap. + + FastLRUCache has faster gets and slower puts in single + threaded operation and thus is generally faster than LRUCache + when the hit ratio of the cache is high (> 75%), and may be + faster under other scenarios on multi-cpu systems. + --> + + <!-- Filter Cache + + Cache used by SolrIndexSearcher for filters (DocSets), + unordered sets of *all* documents that match a query. When a + new searcher is opened, its caches may be prepopulated or + "autowarmed" using data from caches in the old searcher. + autowarmCount is the number of items to prepopulate. For + LRUCache, the autowarmed items will be the most recently + accessed items. + + Parameters: + class - the SolrCache implementation LRUCache or + (LRUCache or FastLRUCache) + size - the maximum number of entries in the cache + initialSize - the initial capacity (number of entries) of + the cache. (see java.util.HashMap) + autowarmCount - the number of entries to prepopulate from + and old cache. + maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed + to occupy. Note that when this option is specified, the size + and initialSize parameters are ignored. + --> + <filterCache class="solr.FastLRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Query Result Cache + + Caches results of searches - ordered lists of document ids + (DocList) based on a query, a sort, and the range of documents requested. + Additional supported parameter by LRUCache: + maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed + to occupy + --> + <queryResultCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Document Cache + + Caches Lucene Document objects (the stored fields for each + document). Since Lucene internal document ids are transient, + this cache will not be autowarmed. + --> + <documentCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- custom cache currently used by block join --> + <cache name="perSegFilter" + class="solr.search.LRUCache" + size="10" + initialSize="0" + autowarmCount="10" + regenerator="solr.NoOpRegenerator" /> + + <!-- Lazy Field Loading + + If true, stored fields that are not requested will be loaded + lazily. This can result in a significant speed improvement + if the usual case is to not load all stored fields, + especially if the skipped fields are large compressed text + fields. + --> + <enableLazyFieldLoading>true</enableLazyFieldLoading> + + <!-- Result Window Size + + An optimization for use with the queryResultCache. When a search + is requested, a superset of the requested number of document ids + are collected. For example, if a search for a particular query + requests matching documents 10 through 19, and queryWindowSize is 50, + then documents 0 through 49 will be collected and cached. Any further + requests in that range can be satisfied via the cache. + --> + <queryResultWindowSize>20</queryResultWindowSize> + + <!-- Maximum number of documents to cache for any entry in the + queryResultCache. + --> + <queryResultMaxDocsCached>200</queryResultMaxDocsCached> + + <!-- Use Cold Searcher + + If a search request comes in and there is no current + registered searcher, then immediately register the still + warming searcher and use it. If "false" then all requests + will block until the first searcher is done warming. + --> + <useColdSearcher>false</useColdSearcher> + + </query> + + + <!-- Request Dispatcher + + This section contains instructions for how the SolrDispatchFilter + should behave when processing requests for this SolrCore. + + --> + <requestDispatcher> + <httpCaching never304="true" /> + </requestDispatcher> + + <!-- Request Handlers + + http://wiki.apache.org/solr/SolrRequestHandler + + Incoming queries will be dispatched to a specific handler by name + based on the path specified in the request. + + If a Request Handler is declared with startup="lazy", then it will + not be initialized until the first request that uses it. + + --> + <!-- SearchHandler + + http://wiki.apache.org/solr/SearchHandler + + For processing Search Queries, the primary Request Handler + provided with Solr is "SearchHandler" It delegates to a sequent + of SearchComponents (see below) and supports distributed + queries across multiple shards + --> + <requestHandler name="/select" class="solr.SearchHandler"> + <!-- default values for query parameters can be specified, these + will be overridden by parameters in the request + --> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <int name="rows">10</int> + </lst> + </requestHandler> + + <initParams path="/update/**,/select"> + <lst name="defaults"> + <str name="df">_text_</str> + </lst> + </initParams> + + <!-- Response Writers + + http://wiki.apache.org/solr/QueryResponseWriter + + Request responses will be written using the writer specified by + the 'wt' request parameter matching the name of a registered + writer. + + The "default" writer is the default and will be used if 'wt' is + not specified in the request. + --> + <queryResponseWriter name="xml" + default="true" + class="solr.XMLResponseWriter" /> +</config> diff --git a/doc/solr-schema-7.7.0.xml b/doc/solr-schema-7.7.0.xml new file mode 100644 index 0000000..601a290 --- /dev/null +++ b/doc/solr-schema-7.7.0.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<schema name="dovecot" version="2.0"> + <fieldType name="string" class="solr.StrField" omitNorms="true" sortMissingLast="true"/> + <fieldType name="long" class="solr.LongPointField" positionIncrementGap="0"/> + <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/> + + <fieldType name="text" class="solr.TextField" autoGeneratePhraseQueries="true" positionIncrementGap="100"> + <analyzer type="index"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/> + <filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/> + <filter class="solr.FlattenGraphFilterFactory"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> + <filter class="solr.PorterStemFilterFactory"/> + </analyzer> + <analyzer type="query"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/> + <filter class="solr.FlattenGraphFilterFactory"/> + <filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/> + <filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> + <filter class="solr.PorterStemFilterFactory"/> + </analyzer> + </fieldType> + + <field name="id" type="string" indexed="true" required="true" stored="true"/> + <field name="uid" type="long" indexed="true" required="true" stored="true"/> + <field name="box" type="string" indexed="true" required="true" stored="true"/> + <field name="user" type="string" indexed="true" required="true" stored="true"/> + + <field name="hdr" type="text" indexed="true" stored="false"/> + <field name="body" type="text" indexed="true" stored="false"/> + + <field name="from" type="text" indexed="true" stored="false"/> + <field name="to" type="text" indexed="true" stored="false"/> + <field name="cc" type="text" indexed="true" stored="false"/> + <field name="bcc" type="text" indexed="true" stored="false"/> + <field name="subject" type="text" indexed="true" stored="false"/> + + <!-- Used by Solr internally: --> + <field name="_version_" type="long" indexed="true" stored="true"/> + + <uniqueKey>id</uniqueKey> +</schema> diff --git a/doc/solr-schema.xml b/doc/solr-schema.xml new file mode 100644 index 0000000..cea6a3b --- /dev/null +++ b/doc/solr-schema.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<!-- +For fts-solr: + +This is the Solr schema file, place it into solr/conf/schema.xml. You may +want to modify the tokenizers and filters. +--> +<schema name="dovecot" version="1.5"> + <types> + <!-- IMAP has 32bit unsigned ints but java ints are signed, so use longs --> + <fieldType name="string" class="solr.StrField" /> + <fieldType name="long" class="solr.TrieLongField" /> + <fieldType name="boolean" class="solr.BoolField" /> + + <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> + <analyzer type="index"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/> + <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.EnglishPossessiveFilterFactory"/> + <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> + <filter class="solr.EnglishMinimalStemFilterFactory"/> + </analyzer> + <analyzer type="query"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> + <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/> + <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.EnglishPossessiveFilterFactory"/> + <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/> + <filter class="solr.EnglishMinimalStemFilterFactory"/> + </analyzer> + </fieldType> + </types> + + + <fields> + <field name="id" type="string" indexed="true" stored="true" required="true" /> + <field name="uid" type="long" indexed="true" stored="true" required="true" /> + <field name="box" type="string" indexed="true" stored="true" required="true" /> + <field name="user" type="string" indexed="true" stored="true" required="true" /> + + <field name="hdr" type="text" indexed="true" stored="false" /> + <field name="body" type="text" indexed="true" stored="false" /> + + <field name="from" type="text" indexed="true" stored="false" /> + <field name="to" type="text" indexed="true" stored="false" /> + <field name="cc" type="text" indexed="true" stored="false" /> + <field name="bcc" type="text" indexed="true" stored="false" /> + <field name="subject" type="text" indexed="true" stored="false" /> + + <!-- Used by Solr internally: --> + <field name="_version_" type="long" indexed="true" stored="true"/> + </fields> + + <uniqueKey>id</uniqueKey> +</schema> diff --git a/doc/thread-refs.txt b/doc/thread-refs.txt new file mode 100644 index 0000000..484aee9 --- /dev/null +++ b/doc/thread-refs.txt @@ -0,0 +1,223 @@ +Optimistic incremental THREAD=REFERENCES + +Step (1) is the slowest stage for building a THREAD=REFERENCES tree. If its +result tree is permanently saved, the following thread builds can be based +on it by updating the tree incrementally. + +Adding new messages to the tree is simple: simply follow the normal rules +as when building a new tree from scratch. Expunging messages gets more +problematic though. + +Each node in the tree keeps a "link reference count" which specifies how +many messages contain a "this message" -> "parent message" reference +(number of links to parent node). The first reference is usually added by +the message's own References: or In-Reply-To: header and the latter +references are added by References: headers. This link refcount must be +updated when adding and expunging messages. When the link refcount drops to +zero, the message becomes a root. The link refcount doesn't tell much about +the number of children the node has, because References: headers may +reference any number of its ancestors. + +The optimistic approach assumes that usually there are no problematic +links. In such case expunging a message simply updates the link refcounts +and marks the message's node as expunged. Expunged messages may still act +as dummy nodes. The node may be removed only after there are no nodes which +point to it. + +Problematic links are handled by marking nodes affected by them. If such a +node is expunged or its link is unreferenced, the thread tree must be +rebuilt. This is assumed to be a rarely occurring event. The problematic +cases are: + +1) Duplicate Message-ID: headers. If the first message having it is +expunged, the thread tree must be rebuilt. + +2) Message-ID loops. If a message referencing the looping path gets +expunged, the loop may break and the thread tree must be rebuilt. Because +it can't be determined easily which loops get broken by which expunges, +this case can be handled in a bit easier way: When detecting a loop between +parent and child, rebuild the tree if any link between the parent and child +gets unreferenced. + +3) A message changes its parent because an earlier message's References: +header contained a different link. If the message gets expunged, the thread +tree must be rebuilt to get the original parent back. + +4) A link in a message's References: header is ignored, because the +referenced child already specified a different parent to itself. If the +message gets expunged, the thread tree must be rebuilt to determine its new +parent. + +5) A link in a message's References: header is ignored, because an earlier +message's References: header already specified a different link. If the +earlier message gets expunged, the parent may change. The earlier message +could be found out quickly by keeping some extra state (or with a slow +scan), but since this is assumed to be a rare problem, there's an easier +(but less specific) way to handle this: Rebuild the tree if a link to the +child node is unreferenced (or alternatively if a link to the original +parent node is unreferenced, but it probably happens more often). + +Pseudocode: + +node { + parent: Pointer to parent node. Children pointers aren't required. + uid: Message's UID (0 = expunged or never even existed) + + parent_link_refcount: Number of messages containing "this message" -> "parent + message" link, i.e. "number of links to parent node". However since parents + can change, not all of these references might be from our current child + nodes. When this refcount reaches 0, it means we must detach from our + parent. + expunge_rebuilds: If this message gets expunged, rebuild the thread tree. + child_unref_rebuilds: If a link between this node and its child gets + unreferenced, rebuild the thread tree. +} + +link_reference(parent_node, child_node) + child_node.parent_link_refcount++ + if is_ancestor(child_node, parent_node) + // child_node is an ancestor of parent_node. Adding child_node -> + // parent_node would introduce a loop. If any messages referencing the + // path between parent_node's parent and child_node get expunged, we + // have to rebuild the tree because the loop might break. For example: + // #1: a -> b (a.ref=1, b.ref=1) + // #2: b -> a (a.ref=2, b.ref=2) + // #3: c -> a -> b (a.ref=3, b.ref=3, c.ref=1) + // Expunging #3 wouldn't break the loop, but expunging #1 would. + for node in nodes[parent_node.parent .. child_node] + node.child_unref_rebuilds = true + else if child_node.parent == parent_node + // The same link already exists + else + // Set parent_node as child_node's parent + if child_node.parent == NIL + child_node.parent = parent_node + else + // Conflicting parent already exists, keep the original. + // We get here only when handling References: header. + if child_node.uid != 0 + // We've already seen this message. It specifies its own parent and + // it doesn't matter what any other reference says. The only way its + // parent can change is if the message itself gets expunged. + child_node.expunge_rebuilds = true + else + // Message doesn't exist, so it was one of the node's children + // that created the original reference. If that reference gets + // dropped, the parent is changed. We could catch this in one of + // several ways: + // a) Link to original parent node gets unreferenced + // b) Link to this node gets unreferenced + // c) Any of the child nodes gets expunged + // b) is probably the least likely to happen, so use it + child_node.child_unref_rebuilds = true + +thread_add_msg(uid) + // get the Message-IDs as specified by the thread spec + (msgid, parent_msgid, references) = message_get_thread_headers(uid) + + if msgid != NIL + if nodes[msgid].uid == 0 + nodes[msgid].uid = uid + else + // duplicate Message-ID. if the original ever gets expunged, + // rebuild the thread tree + nodes[msgid].expunge_rebuilds = true + msgid = NIL + + if msgid == NIL + msgid = get_unique_msg_id() + + node = nodes[msgid] + if node.parent != NIL and + (parent_msgid == NIL or node.parent.msgid != parent_msgid) + // Conflicting parent, remove it. If this message gets expunged, we have + // to revert back to the original parent. + node.parent = NIL + node.expunge_rebuilds = true + + if parent_msgid != NIL + link_reference(nodes[parent_msgid], node) + + // go through References (skipping the last one) + for (ref_parent, ref_child) in references + link_reference(nodes[ref_parent], nodes[ref_child]) + +unref_link(parent, child) + if parent.child_unref_rebuilds + return false + + child.parent_link_refcount-- + if child.parent_link_refcount == 0 + child.parent = NIL + return true + +// returns false if thread tree needs to be rebuilt +thread_expunge_msg(uid) + // get the Message-IDs as specified by the thread spec + (msgid, in_reply_to_msgid, references) = message_get_thread_headers(uid) + + node = nodes[msgid] + if node.uid != uid + // Removing a duplicate Message-ID + return false + + if node.expunge_rebuilds + return false + + if parent_msgid != NIL and + not unref_link(nodes[parent_msgid], nodes[child_msgid]) + return false + + if references != NIL + // go through References + for (parent_msgid, child_msgid) in references + if not unref_link(nodes[parent_msgid], nodes[child_msgid]) + return false + last_parent_msgid = references.last + else if in_reply_to_msgid != NIL + last_parent_msgid = in_reply_to_msgid + + if last_parent_msgid != NIL and + not unref_link(nodes[last_parent_msgid], node) + return false + + // mark this node as expunged + node.uid = 0 + return true + +thread_iterate() + root_nodes = [] + referenced = [] + children = [][] + // Steps (2) and (3) + for node in nodes + if node.parent != NIL + root_nodes[] = node + else + referenced[node.parent] = true + if node.uid != 0 + // Find the node's first non-dummy parent and add the node as its child. + // If there are no non-dummy parents, add it as the highest dummy's + // child. + nondummy_parent = node.parent + while nondummy_parent.uid == 0 and nondummy_parent.parent != NIL + nondummy_parent = nondummy_parent.parent + children[nondummy_parent][] = node + + for node in root_nodes + if node.uid == 0 + if children[node] == NIL + // remove dummy roots that have no children. + delete(node) + else if count(children[node]) == 1 + // dummy root has a single child, replace the root with its child + node = children[node] + + for node in nodes + if node.uid == 0 and !referenced[node] + free(node) + + // root_nodes and children now contain a tree equivalent to a tree built by + // THREAD=REFERENCES specification steps (1)-(3). The rest of the steps + // can be performed using them. Note that node.parent should not (and need + // not) be used because it points its parent before steps (2) and (3). diff --git a/doc/wiki/ACL.txt b/doc/wiki/ACL.txt new file mode 100644 index 0000000..486d71c --- /dev/null +++ b/doc/wiki/ACL.txt @@ -0,0 +1,258 @@ +Access Control Lists +==================== + +This page talks mainly about how ACLs work, for more general description of how +shared mailboxes work, see <SharedMailboxes.txt>. + +Dovecot v1.0 and v1.1 supports administrator-configured ACL files. v1.2+ +supports also IMAP ACL extension, which allows users to change ACLs themselves. +The ACL code was written to allow multiple ACL backends, but currently Dovecot +supports only virtual ACL files. Note that using ACLs doesn't grant mail +processes any extra filesystem permissions that they already don't have. <You +must make sure that the processes have enough permissions> +[SharedMailboxes.Permissions.txt] to be able to access the mailboxes. When +testing you could first try accessing shared/public mailboxes without ACL +plugin even enabled. + +ACLs can be enabled in dovecot.conf with: + +---%<------------------------------------------------------------------------- +mail_plugins = acl +protocol imap { + mail_plugins = $mail_plugins imap_acl +} + +plugin { + # Without global ACLs: + acl = vfile + + # With global ACL files in /etc/dovecot/dovecot-acls file (v2.2.11+): + #acl = vfile:/etc/dovecot/dovecot-acl + + # With global ACLs in /etc/dovecot/acls/ directory (obsolete): + #acl = vfile:/etc/dovecot/acls + + # If enabled, don't try to find dovecot-acl files from mailbox directories. + # This reduces unnecessary disk I/O when only global ACLs are used. +(v2.2.31+) + #acl_globals_only = yes +} +---%<------------------------------------------------------------------------- + +ACL groups support works by returning a comma-separated 'acl_groups' <extra +field> [UserDatabase.ExtraFields.txt] from userdb, which contains all the +groups the user belongs to. User's UNIX groups have no effect on ACLs (you can +"enable" them by using a special <post-login script> [PostLoginScripting.txt]). + +The default ACL for mailboxes is to give the mailbox owner all permissions and +other users none. Mailboxes in public namespaces don't have owners, so by +default no one can access them. + +Master users +------------ + +Note that master users have their own ACLs. They're not the the mailbox owners, +so by default they have no permissions to any of the mailboxes. See +Authentication/MasterUsers#ACLs for more information. + +ACL vfile backend +----------------- + +vfile backend supports per-mailbox ACLs and global ACLs. + +Per-mailbox ACLs are stored in 'dovecot-acl' named file, which exists in: + + * maildir: The Maildir's mail directory (eg. '~/Maildir', + '~/Maildir/.folder/') + * mbox: Control directory. You should explicitly specify ':CONTROL=<path>' in + mail location. + * dbox: dbox's mail directory (eg. '~/dbox/INBOX/dbox-Mails/') + +ACL Inheritance +--------------- + +Every time you create a new mailbox, it gets its ACLs from the parent mailbox. +If you're creating a root-level mailbox, it uses the namespace's default ACLs. +There is no actual inheritance, however: If you modify parent's ACLs, the +child's ACLs stay the same. There is currently no support for ACL inheritance. + + * Maildir: Namespace's default ACLs are read from "dovecot-acl" file in the + namespace's mail root directory (e.g.'/var/public/Maildir'). Note that + currently these default ACLs are used only when creating new mailboxes, they + aren't used for mailboxes without ACLs. + * v2.2.2+: If 'plugin { acl_defaults_from_inbox=yes } ', the default ACLs for + private and shared namespaces (but not public namespaces) are taken from the + INBOX. This means that giving somebody access to your INBOX will give them + access to all your other mailboxes as well, unless the specific mailboxes' + ACLs override the INBOX's. + +*NOTE*: Currently the default ACLs are merged with the mailbox-specific ACLs. +So if a default ACL gives access to "user1" and a per-mailbox ACL gives access +to "user2", the "user1" still has access to that mailbox. + +Global ACLs +----------- + +Global ACLs can be used to apply ACLs globally to all user's specific +mailboxes. They are used mainly for two purposes: + + 1. Removing some permissions from users' personal mailboxes. For example each + user might have an "Invoices" mailbox which will be read-only. + 2. Giving permissions to master user logins. See + <Authentication/MasterUsers#ACLs> [Authentication.MasterUsers.txt] for more + information. + +If a mailbox has both global ACLs and the per-mailbox ACL file, both of them +are read and the ACLs are merged. If there are any conflicts, the global ACL +file overrides per-mailbox ACL file. This is because users can modify their own +per-mailbox ACL files via IMAP ACL extension. Global ACLs can only be modified +by administrator, so users shouldn't be able to override them. + +Global ACL file (v2.2.11+) +-------------------------- + +Global ACL file path is specified as a parameter to vfile backend in 'acl' +setting ('/etc/dovecot/dovecot-acl' in the above example). The file contains +otherwise the same data as regular per-mailbox 'dovecot-acl' files, except each +line is prefixed by the mailbox name pattern. The pattern may contain "*" and +"?" wildcards. For example: + +---%<------------------------------------------------------------------------- +* user=foo lrw +Public user=bar lrwstipekxa +Public/* user=bar lrwstipekxa +---%<------------------------------------------------------------------------- + +Global ACL directory (obsolete) +------------------------------- + +Global ACL directory is specified as a parameter to vfile backend in 'acl' +setting ('/etc/dovecot/acls/' in the above example). They are looked up using +the mailbox's virtual name. For example: + + * INBOX: '/etc/dovecot/acls/INBOX' + * archives.2007: '/etc/dovecot/acls/archives.2007' + * archives/2007: '/etc/dovecot/acls/archives/2007' + +The filenames must start with namespace prefix (if it has one). For example +with namespace 'prefix=INBOX/' containing mailbox "foo" use +'/etc/dovecot/acls/INBOX/foo'. + +There is an extra problem with mailbox formats that use '/' as the separator +(e.g. mbox, dbox): For example if you have mailboxes "foo" and "foo/bar" and +you wish to give ACLs to both of them, you can't create both +'/etc/dovecot/acls/foo' and '/etc/dovecot/acls/foo/bar' files. The 'foo' has to +be either a directory or a file, it can't be both. To solve this problem, you +can instead create a .DEFAULT file for "foo": + + * foo: '/etc/dovecot/acls/foo/.DEFAULT' + * foo/bar: '/etc/dovecot/acls/foo/bar' + +ACL files +--------- + +The files themselves are in format: + +---%<------------------------------------------------------------------------- +<identifier> <ACLs> [:<named ACLs>] +---%<------------------------------------------------------------------------- + +Where *identifier* is one of: + + * group-override=*group name* + * user=*user name* + * owner + * group=*group name* + * authenticated + * anyone (or anonymous, which is alias for anyone) + +The ACLS are processed in the precedence given above, so for example if you +have given read-access to a group, you can still remove that from specific +users inside the group. + +Group-override identifier allows you to override users' ACLs. Probably the most +useful reason to do this is to temporarily disable access for some users. For +example: + +---%<------------------------------------------------------------------------- +user=timo rw +group-override=tempdisabled +---%<------------------------------------------------------------------------- + +Now if /timo/ is in /tempdisabled/ group, he has no access to the mailbox. This +wouldn't be possible with a normal group identifier, because the 'user=timo' +would override it. + +The currently supported ACLs and their corresponding named ACLs are: ++---+---------------+---------------------------------------------------------+ +| l | lookup | Mailbox is visible in mailbox list. Mailbox can be | +| | | subscribed to. | ++---+---------------+---------------------------------------------------------+ +| r | read | Mailbox can be opened for reading. | ++---+---------------+---------------------------------------------------------+ +| w | write | Message flags and keywords can be changed, except \Seen | +| | | and \Deleted | ++---+---------------+---------------------------------------------------------+ +| s | write-seen | \Seen flag can be changed | ++---+---------------+---------------------------------------------------------+ +| t | write-deleted | \Deleted flag can be changed | ++---+---------------+---------------------------------------------------------+ +| i | insert | Messages can be written or copied to the mailbox | ++---+---------------+---------------------------------------------------------+ +| p | post | Messages can be posted to the mailbox by <LDA.txt>, e.g.| +| | | from <Sieve> [Pigeonhole.Sieve.txt] scripts | ++---+---------------+---------------------------------------------------------+ +| e | expunge | Messages can be expunged | ++---+---------------+---------------------------------------------------------+ +| k | create | Mailboxes can be created (or renamed) directly under | +| | | this mailbox (but not necessarily under its children, | +| | | see ACL Inheritance section above) (renaming also | +| | | requires delete rights) | ++---+---------------+---------------------------------------------------------+ +| x | delete | Mailbox can be deleted | ++---+---------------+---------------------------------------------------------+ +| a | admin | Administration rights to the mailbox (currently: ability| +| | | to change ACLs for mailbox) | ++---+---------------+---------------------------------------------------------+ + +The ACLs are compatible with RFC 4314 (IMAP ACL extension, updated version). + +Unknown ACL letters are complained about, but unknown named ACLs are ignored. +Named ACLs are mostly intended for future extensions. + +Note that the file is rather picky about formatting; using a tab (or multiple +spaces) instead of a space character between fields may not work. If you are +having problems, make sure to check for tabs, extra spaces and other unwanted +characters. + +Examples +-------- + +Mailbox owner has all privileges, "timo" has list-read privileges: + +---%<------------------------------------------------------------------------- +owner lrwstipekxa +user=timo lr +---%<------------------------------------------------------------------------- + +Allow everyone to list and read a public mailbox (public namespace has no +owner): + +---%<------------------------------------------------------------------------- +anyone lr +---%<------------------------------------------------------------------------- + +Prevent all users from deleting their Spam folder (notice no x flag) + +---%<------------------------------------------------------------------------- +INBOX.Spam owner lrwstipeka +---%<------------------------------------------------------------------------- + +List cache +---------- + +'dovecot-acl-list' file lists all mailboxes that have "l" rights assigned. If +you manually add/edit 'dovecot-acl' files, you may need to delete the +'dovecot-acl-list' to get the mailboxes visible. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AixPluginsSupport.txt b/doc/wiki/AixPluginsSupport.txt new file mode 100644 index 0000000..444c00d --- /dev/null +++ b/doc/wiki/AixPluginsSupport.txt @@ -0,0 +1,141 @@ +Plugins Support on AIX +====================== + +/How to build Dovecot with plugins supported on AIX./ + +Tested with: + + * AIX 5.2, VAC 5.0.2 and Dovecot 1.0rc21 to 1.0.13 /(Dovecot 1.1.x does not + build with VAC 5.0.2)/ + * AIX 5.2, VAC 8.0.0 and Dovecot 1.1.1 + +The Problem +----------- + + * When you trying to use plugins on AIX you seen error messages like this: + ---%<---------------------------------------------------------------------- + imap(root): Error: + dlopen(/usr/local/lib/dovecot/imap/lib20_zlib_plugin.so) failed: + rtld: 0712-001 Symbol i_error was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol i_stream_get_data was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol i_stream_skip was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol i_stream_seek was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol i_stream_close was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol i_panic was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + rtld: 0712-001 Symbol pool_get_exp_grown_size was referenced + from module /usr/local/lib/dovecot/imap/lib20_zlib_plugin.so(), + but a runtime definition of the symbol was not found. + Additional errors occurred but are not reported. + ---%<---------------------------------------------------------------------- + + * .. produced by executing + ---%<---------------------------------------------------------------------- + # MAIL_PLUGINS=zlib /usr/local/libexec/dovecot/imap + ---%<---------------------------------------------------------------------- + +Compiler Script +--------------- + + * Create a compiler script to rewrite the /xlc/ command line on the fly: + *dovecot-cc* + + ---%<---------------------------------------------------------------------- + #!/bin/bash + + xlc=/usr/bin/xlc + ar=/bin/ar + sed=/bin/sed + + dest=NOBINARY + + for i in "$@"; do + case "$i" in + '-o') dest=;; + *) if [ -z "$dest" ]; then dest="$i"; break; fi;; + esac + done + + case "$dest" in + imap-login) args1="../lib-charset/libcharset.a ../lib-mail/libmail.a + -liconv";; + imap) args1="../lib-sql/libsql.a";; + pop3) args1="../lib-sql/libsql.a";; + deliver) args1="../lib-sql/libsql.a";; + esac + + for i in "$@" $args1; do + case "$i" in + */*.a) lib="${i##*/}"; obj=`$ar -t $i | $sed "s:^:${i%/*}/:"`;; + *.a) lib="$i"; obj=`$ar -t $i | $sed "s:^:./:"`;; + *) continue;; + esac + test -d .libs || mkdir .libs + > .libs/${lib%.a}.exp + args2="$args2 -bE:.libs/${lib%.a}.exp" + + (set -x ; exec $xlc -qmkshrobj -qexpfile=.libs/${lib%.a}.exp $obj) + 2>/dev/null + done + (set -x ; exec $xlc "$@" $args1 $args2) + ---%<---------------------------------------------------------------------- + +Compiling Dovecot +----------------- + + * Expand Dovecot: + ---%<---------------------------------------------------------------------- + gzip -cd doveccot-1.0.rc21.tar.gz | tar xvf - + ---%<---------------------------------------------------------------------- + + * Setup build environment: + ---%<---------------------------------------------------------------------- + export CC=$PWD/dovecot-cc + export LDFLAGS="-bexpall -brtl" + ---%<---------------------------------------------------------------------- + + * Configure and build Dovecot + ---%<---------------------------------------------------------------------- + cd dovecot-1.0.rc21 + bash configure + make + ---%<---------------------------------------------------------------------- + + * Test a plugin (e.g. zlib) + ---%<---------------------------------------------------------------------- + echo 0 logout | MAIL_PLUGIN_DIR=src/plugins/zlib/.libs/ MAIL_PLUGINS="zlib" + MAIL=maildir:/tmp src/imap/imap + ---%<---------------------------------------------------------------------- + + you should see this: + ---%<---------------------------------------------------------------------- + * PREAUTH [CAPABILITY IMAP4rev1 SASL-IR SORT THREAD=REFERENCES MULTIAPPEND + UNSELECT LITERAL+ IDLE CHILDREN NAMESPACE LOGIN-REFERRALS] Logged in as root + * BYE Logging out + 0 OK Logout completed. + imap(root): Info: Disconnected: Logged out + ---%<---------------------------------------------------------------------- + + * Install Dovecot + ---%<---------------------------------------------------------------------- + make install + ---%<---------------------------------------------------------------------- + +Prebuild Binaries for AIX 5.2 +----------------------------- + +You will find prebuild AIX 5.2 binaries here: +http://www.fh-trier.de/~beckerr/dovecot/ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AttachmentIndicator.txt b/doc/wiki/AttachmentIndicator.txt new file mode 100644 index 0000000..1acac6f --- /dev/null +++ b/doc/wiki/AttachmentIndicator.txt @@ -0,0 +1,31 @@ +Attachment indicator +==================== + +Since 2.2.34/2.3.1 dovecot has a feature that indicates whether email has an +attachment or not via keywords. These keywords could be used by IMAP clients. +These keywords will likely become standardized - for now the latest information +is in https://www.ietf.org/mail-archive/web/imapext/current/msg05858.html + +Configuration +------------- + +To enable this feature, you can set *mail_attachment_detection_options*. + +It supports following options + + * add-flags-on-save - Enables the feature, attachments are detected and marked + during save + * content-type=type|!type - Include or exclude given content type. Including + will only negate an exclusion (e.g. content-type=!foo/* + content-type=foo/bar). + * exclude-inlined - Do not consider any attachment with disposition inlined. + +Usage +----- + +Once enabled, mails that are saved, are marked with $Has ''Attachment or $Has +''No ''Attachment keyword. These keywords can be cleared, and are not +protected. Since v2.3.3 it is possible to post-process attachments with +'doveadm rebuild attachments' command. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.CheckPassword.txt b/doc/wiki/AuthDatabase.CheckPassword.txt new file mode 100644 index 0000000..c285868 --- /dev/null +++ b/doc/wiki/AuthDatabase.CheckPassword.txt @@ -0,0 +1,234 @@ +CheckPassword +============= + +Since v2.3.0 You can also use Lua to write your custom authentication, see +<AuthDatabase.Lua.txt> + +Checkpassword is an authentication interface originally implemented by qmail +[http://www.qmail.org/]. Checkpassword combines both the <password database> +[PasswordDatabase.txt] and <user database> [UserDatabase.txt] lookups into a +single checkpassword lookup, which makes the standard implementation unsuitable +for a standalone userdb. With Dovecot extensions it's also possible to use +checkpassword as a userdb. + +Typically you'll use <prefetch> [UserDatabase.Prefetch.txt] as the userdb, but +it's not required that you use the checkpassword script's userdb capabilities. +You can still use for example <static userdb> [UserDatabase.Static.txt] if +you're using only a single UID and GID, and your home directory fits into a +template. + +Security +-------- + +The standard checkpassword design is incompatible with Dovecot's security +model. If the system has local users and the checkpassword script setuid()s +into a local user, the user is able to ptrace into the communication and change +the authentication results. This is of course undesirable, so v2.2.7+ will just +refuse to run in such environments by default. The possibilities to solve this +are: + + 1. If possible, change the checkpassword to return 'userdb_uid' and + 'userdb_gid' extra fields instead of using 'setuid()' and 'setgid()'. This + also improves the performance. + 2. If you can't change the script, you can make Dovecot's + 'checkpassword-reply' binary setuid or setgid (e.g.'chgrp dovecot + /usr/local/libexec/dovecot/checkpassword-reply; chmod g+s + /usr/local/libexec/dovecot/checkpassword-reply') + 3. If you don't have any untrusted local users and you just don't care about + this check, you can set 'INSECURE_SETUID=1' environment e.g. with a wrapper + checkpassword script. + +Deliver +------- + +If your checkpassword script doesn't support Dovecot extensions, you can't use +it as a user database. This means that if you wish to use <LDA.txt>, you can't +use the '-d' parameter to do userdb lookups. There are two ways to solve this: + + 1. Use another userdb which does the lookup for deliver, for example <SQL> + [AuthDatabase.SQL.txt] or <static> [UserDatabase.Static.txt]. Add this + userdb after the prefetch userdb. + 2. Use a script to look up the user's home directory and run deliver without + '-d' parameter. For example: + +---%<------------------------------------------------------------------------- +#!/bin/sh + +# <<Lookup user's home directory here.>> + +# If users have different UIDs/GIDs, make sure to also change this process's +UID and GID. +# If you want to override any settings, use dovecot-lda's -o parameter +# (e.g. dovecot-lda -o mail_location=maildir:~/Maildir). + +export HOME +exec /usr/local/libexec/dovecot/dovecot-lda +---%<------------------------------------------------------------------------- + +Checkpassword Interface +----------------------- + +The interface is specified in http://cr.yp.to/checkpwd/interface.html. However +here's a quick tutorial for writing a script: + + * Read '<username> NUL <password> NUL' from fd 3. + * Verify the username and password. + * If the authentication fails, exit with code 1. This makes Dovecot give + "Authentication failed" error to user. + * This error is returned both for password mismatch and also if the user + doesn't exist at all. Internally Dovecot maps this as password + mismatch. + * If you encounter an internal error, exit with code 111. This makes + Dovecot give "Temporary authentication failure" error to user. + * If the authentication succeeds, you'll need to: + * Set user's home directory to '$HOME' environment. This isn't required, + <but highly encouraged> [VirtualUsers.txt]. + * Set '$USER' environment variable. If the user name was changed (eg. if + you lowercased "Username" to "username"), you can tell about it to + Dovecot by setting '$USER' to the changed user name. + * Return the user's <UNIX UID and GID> [UserIds.txt] using 'userdb_uid' and + 'userdb_gid' environments and add them to the 'EXTRA' environment (see + below for Dovecot extensions). + * This is recommended over actually changing the UID/GID using + setuid()/setgid() as specified by the standard checkpassword + interface, because it's <incompatible with Dovecot's security model> + [AuthDatabase.CheckPassword.txt]. + * Your program received a path to 'checkpassword-reply' binary as the first + parameter. Execute it. + +Qmail-LDAP +---------- + +Note that auth_imap that comes with qmail-ldap is not compatible with this +interface. You can get a patch that adds auth_dovecot functionality to +qmail-ldap here +[http://japc.uncovering.org/dovecot/qmail-ldap-1.03-20060201-dovecot.patch]. Or +you can use auth_pop instead, but you may need to pass /aliasempty/ to let +auth_pop find the Maildir, so it is recommended to write a +/var/qmail/bin/auth_dovecot wrapper (don't forget to chmod +x it) around +auth_pop. + +---%<------------------------------------------------------------------------- +#!/bin/sh +QMAIL="/var/qmail" +if [ -e $QMAIL/control/defaultdelivery ]; then + ALIASEMPTY=`head -n 1 $QMAIL/control/defaultdelivery 2> /dev/null` +else + ALIASEMPTY=`head -n 1 $QMAIL/control/aliasempty 2> /dev/null` +fi +ALIASEMPTY=${ALIASEMPTY:-"./Maildir/"} +exec $QMAIL/bin/auth_pop "$@" $ALIASEMPTY +---%<------------------------------------------------------------------------- + +you can also use this wrapper to pass LOGLEVEL environmental variable to +auth_pop. + +Dovecot Extensions +------------------ + +If you wish to return <extra fields> [PasswordDatabase.ExtraFields.txt] for +Dovecot, set them in environment variables and then list them in EXTRA +environment variable. The <userdb extra fields> [UserDatabase.ExtraFields.txt] +can be returned by prefixing them with 'userdb_'. For example: + +---%<------------------------------------------------------------------------- +userdb_quota_rule=*:storage=10000 +userdb_mail=mbox:$HOME/mboxes +EXTRA=userdb_quota_rule userdb_mail +---%<------------------------------------------------------------------------- + +Dovecot also sets some environment variables that the script may use: + + * 'SERVICE': contains eg. imap, pop3 or smtp + * 'TCPLOCALIP' and 'TCPREMOTEIP': Client socket's IP addresses if available + * 'MASTER_USER': If master login is attempted. This means that the password + contains the master user's password and the normal username contains the + user who master wants to log in as. + * 'AUTH_*': All of the <auth variables> [Variables.txt] are available as + 'AUTH_<long name>' extra fields. For example '%{cert}' is in 'AUTH_CERT'. + (v2.0.16+) + +Checkpassword as userdb +----------------------- + +Dovecot calls the script with 'AUTHORIZED=1' environment set when performing a +userdb lookup. The script must acknowledge this by changing the environment to +'AUTHORIZED=2', otherwise the lookup fails. Other than that, the script works +the same way as a passdb checkpassword script. If user doesn't exist, use exit +code 3. + +Checkpassword with passdb lookups (v2.1.2+) +------------------------------------------- + +Normally checkpassword answers to questions "is user X's password Y?" This +doesn't work with non-plaintext auth mechanisms, or when Dovecot wants to do a +non-authenticating passdb lookup (e.g. for LMTP proxy). These passdb +credentials lookups can be implemented the same way as a userdb lookup (i.e. +change the 'AUTHORIZED' environment). + + * 'AUTHORIZED=1' is set, just like for userdb lookup + * When doing a non-plaintext authentication: + * 'CREDENTIALS_LOOKUP=1' environment is set + * The password scheme that Dovecot wants is available in 'SCHEME' + environment (e.g.'SCHEME=CRAM-MD5') + * If a password is returned, it must be returned as + 'password={SCHEME}secret'. + * When doing a passdb lookup, e.g. a proxy which doesn't really want the + password, just the passdb extra fields: + * Neither 'CREDENTIALS_LOOKUP' nor 'SCHEME' is set. + * FIXME: Unfortunately it looks like you currently can't easily + differentiate a passdb lookup from userdb lookup! + * If user doesn't exist, use exit code 3. + * If you get an error about checkpassword exiting with code 0, you didn't + execute the 'checkpassword-reply' binary as you should have (which exits + with code 2 on success) + +Example +------- + +The standard way: + +---%<------------------------------------------------------------------------- +passdb { + driver = checkpassword + args = /usr/bin/checkpassword +} +userdb { + driver = prefetch +} +# If you want to use deliver -d and your users are in SQL: +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +Using checkpassword only to verify the password: + +---%<------------------------------------------------------------------------- +passdb { + driver = checkpassword + args = /usr/bin/checkpassword +} +userdb { + driver = static + args = uid=vmail gid=vmail home=/home/%u +} +---%<------------------------------------------------------------------------- + +Performance +----------- + +The <CheckPassword.txt> backend is not suited for heavy traffic. Especially if +the script spawned has to launch an entire language interpreter. + +If your user database is only accessible with custom code an alternative might +be using the <Dict AuthDatabase over a UNIX socket> [AuthDatabase.Dict.txt]. + +Specific checkpassword implementations +-------------------------------------- + + * phpBB dovecot checkpassword authentication, written in python: + https://github.com/ser/checkpassword-phpbb + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.Dict.txt b/doc/wiki/AuthDatabase.Dict.txt new file mode 100644 index 0000000..4a4405a --- /dev/null +++ b/doc/wiki/AuthDatabase.Dict.txt @@ -0,0 +1,391 @@ +Key-value authentication database +================================= + +Key-value databases can be used as auth backends. They probably should be used +only for caching in front of e.g. SQL auth backends. Iteration is supported if +the underlying dict provider supports iteration. See <Dictionary.txt> for list +of supported databases. + +Auth configuration +------------------ + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +passdb { + driver = dict + args = /etc/dovecot/dovecot-dict-auth.conf +} +userdb { + driver = dict + args = /etc/dovecot/dovecot-dict-auth.conf +} +---%<------------------------------------------------------------------------- + +Dict configuration +------------------ + +---%<------------------------------------------------------------------------- +uri = redis:host=127.0.0.1:port=6379 + +# Dictionary URI +#uri = + +# Default password scheme +default_pass_scheme = MD5 + +# Username iteration prefix. Keys under this are assumed to contain usernames. +iterate_prefix = userdb/ + +# Should iteration be disabled for this userdb? If this userdb acts only as a +# cache there's no reason to try to iterate the (partial & duplicate) users. +#iterate_disable = no + +# The example here shows how to do multiple dict lookups and merge the replies. +# The "passdb" and "userdb" keys are JSON objects containing key/value pairs, +# for example: { "uid": 1000, "gid": 1000, "home": "/home/user" } + +key passdb { + key = passdb/%u + format = json +} +key userdb { + key = userdb/%u + format = json +} +key quota { + key = userdb/%u/quota # or e.g. quota/%{userdb:quota_class} + #format = value + # The default_value is used if the key isn't found. If default_value setting + # isn't specified at all (even as empty), the passdb/userdb lookup fails with + # "user doesn't exist". + default_value = 100M +} + +# Space separated list of keys whose values contain key/value paired objects. +# All the key/value pairs inside the object are added as passdb fields. +# This can only be used for JSON formatted values. +passdb_objects = passdb + +#passdb_fields { +#} + +# Userdb key/value object list. +userdb_objects = userdb + +userdb_fields { + # dict:<key> refers to key names + quota_rule = *:storage=%{dict:quota} + + # dict:<key>.<objkey> refers to the objkey inside (JSON) object + mail = maildir:%{dict:userdb.home}/Maildir +} +---%<------------------------------------------------------------------------- + +Example values +-------------- + +The value formats are either "value" that contains a direct value, or "json". +For example userdb lookup should return something like: + +---%<------------------------------------------------------------------------- +{ "uid": 123, "gid": 123, "home": "/home/username" } +---%<------------------------------------------------------------------------- + +dict proxying +------------- + +It may be useful to do the lookups via the "dict" or "dict-async" service. For +example: + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +dict { + cassandra-userdb = cassandra:/etc/dovecot/dovecot-dict-userdb-cql.conf.ext +} +---%<------------------------------------------------------------------------- + +'dovecot-dict-auth.conf.ext': + +---%<------------------------------------------------------------------------- +uri = proxy:dict-async:cassandra-userdb +iterate_disable = yes +# The _key and _path suffixes are not necessary, they're just here to help +# understand how to match them between different parts of the configuration. +key email_key { + key = userdb/email_path/%u +} +key displayname_key { + key = userdb/displayname_path/%u +} +userdb_fields { + # these fields will be visible as %{userdb:u_email} and +%{userdb:u_displayname} + u_email = %{dict:email_key} + u_displayname = %{dict:displayname_key} +} +---%<------------------------------------------------------------------------- + +'dovecot-dict-userdb-cql.conf.ext': + +---%<------------------------------------------------------------------------- +driver = cassandra +connect = host=127.0.0.1 dbname=email_users + +# SELECT displayname FROM user_profile WHERE id = %u +map { + # pattern must match the "key" path, except with added shared/ prefix. %u +gets caught into $username + pattern = shared/userdb/displayname_path/$username + table = user_profile + value_field = displayname + value_type = string + fields { + id = $username + } +} + +# SELECT email FROM user_profile WHERE id = %u +map { + pattern = shared/userdb/email_path/$username + table = user_profile + value_field = email + value_type = string + fields { + id = $username + } +} +---%<------------------------------------------------------------------------- + +Complete example for authenticating via the CDB dictionary +---------------------------------------------------------- + +This example uses the CDB dictionary to store the userdb and passdb. + +Auth configuration +------------------ + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +# Access to the CDB has to go through a dict process. +dict { + auth = cdb:/etc/dovecot/auth.cdb +} + +passdb { + driver = dict + args = /etc/dovecot/dovecot-cdb.conf +} + +userdb { + driver = dict + args = /etc/dovecot/dovecot-cdb.conf +} +---%<------------------------------------------------------------------------- + +Dict configuration +------------------ + +The CDB dictionary doesn't support iteration yet. + +'dovecot-cdb.conf': + +---%<------------------------------------------------------------------------- +uri = proxy::auth + +# FIXME: obsolete configuration - should use the key { .. } instead +password_key = passdb/%u +user_key = userdb/%u +# iterate_prefix = userdb/ # no yet supported +iterate_disable = yes + +default_pass_scheme = BLF-CRYPT +---%<------------------------------------------------------------------------- + +Complete example for authenticating via a UNIX socket +----------------------------------------------------- + +The Dict auth backend can be used to query a local UNIX socket for users. This +can be handy for accessing user databases which would otherwise only be +accessible via the <CheckPassword> [AuthDatabase.CheckPassword.txt] backend and +a scripting language. + +When given a <"proxy:"> [Quota.Dict.txt] URL the Dict backend speaks a simple +protocol over a UNIX socket. The protocol is defined in +'src/lib-dict/dict-client.h' (GitHub +[https://github.com/dovecot/core/blob/master/src/lib-dict/dict-client.h]). + +Auth configuration +------------------ + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +passdb { + driver = dict + args = /etc/dovecot/dovecot-dict-auth.conf +} +userdb { + # optional + driver = prefetch +} +userdb { + driver = dict + args = /etc/dovecot/dovecot-dict-auth.conf +} +---%<------------------------------------------------------------------------- + +Dict configuration +------------------ + +The last "dictionary name" ("somewhere") argument is redundant here. + +'/etc/dovecot/dovecot-dict-auth.conf.ext': + +---%<------------------------------------------------------------------------- +uri = proxy:/var/run/auth_proxy_dovecot/socket:somewhere + +# FIXME: obsolete configuration - should use the key { .. } instead +password_key = passdb/%u +user_key = userdb/%u +iterate_disable = yes +#default_pass_scheme = plain +---%<------------------------------------------------------------------------- + +Server process for answering Dict lookups +----------------------------------------- + +The server process listening on '/var/run/auth_proxy_dovecot/socket' can be +written in any language.Here's an example in Perl: + +---%<------------------------------------------------------------------------- +package AuthProxyDovecot; +use base qw( Net::Server::PreFork ); + +use strict; +use warnings; + +use JSON::XS; + +AuthProxyDovecot->run() or die "Could not initialize"; + +sub default_values +{ + return { + port => '/var/run/auth_proxy_dovecot/socket|unix', + + log_level => 2, + log_file => 'Sys::Syslog', + syslog_logsock => 'unix', + syslog_ident => 'auth_proxy_dovecot', + syslog_facility => 'daemon', + + background => 1, + setsid => 1, + pid_file => '/var/run/auth_proxy_dovecot.pid', + + user => 'root', + group => 'root', + + max_spare_servers => 2, + min_spare_servers => 1, + min_servers => 2, + max_servers => 10, + + }; +} ## end sub default_values + +################################################## + +sub process_request { + my $self = shift; + + my %L_handler = ( + passdb => sub { + my ($arg) = @_; + my $ret = { + password => '$1$JrTuEHAY$gZA1y4ElkLHtnsrWNHT/e.', + userdb_home => "/home/username/", + userdb_uid => 1000, + userdb_gid => 1000, + }; + return $ret; + }, + userdb => sub { + my ($arg) = @_; + my $ret = { + home => "/home/username/", + uid => 1000, + gid => 1000, + }; + return $ret; + }, + ); + + # protocol from src/lib-dict/dict-client.h + my $json = JSON::XS->new; + + eval { + my $ret; + # Dict protocol is multiline... go through the lines. + while (<STDIN>) { + $self->log(2, "Got request: $_"); + chomp; + my $cmd = substr($_,0,1); + next if $cmd eq 'H'; # "hello", skip this line, assume it's ok + die "Protocol error: Bad command $cmd" unless ($cmd eq 'L'); + # Process request + + my ($namespace,$type,$arg) = split ('/',substr($_,1),3); + + if ($namespace eq 'shared') { + my $f = $L_handler{$type}; + + if (defined $f && defined $arg) { + $ret = $f->($arg); + } + else { + die 'Protocol error: Bad arg'; + } + } + else { + die 'Protocol error: Bad namespace' + } + last; # Got an "L" , now respond. + } + if ($ret) { + my $json = JSON::XS->new->indent(0)->utf8->encode($ret); + $self->log(3,"O:$json"); + print "O".$json."\n"; + } + else { + $self->log(3,"NOUSER"); + print "N\n"; + } + 1; + } or do { + $self->log(2, "Error: $@"); + print "F\n"; + }; +} + +sub pre_loop_hook { + my $self = shift; + + $self->log(1, 'Starting server'); +} + +sub pre_server_close_hook { + my $self = shift; + + $self->log(1, 'Server is shut down'); +} + +1; + +__END__ +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.LDAP.AuthBinds.txt b/doc/wiki/AuthDatabase.LDAP.AuthBinds.txt new file mode 100644 index 0000000..a81eef3 --- /dev/null +++ b/doc/wiki/AuthDatabase.LDAP.AuthBinds.txt @@ -0,0 +1,89 @@ +Passdb LDAP with authentication binds +===================================== + +Advantages over <password lookups> [AuthDatabase.LDAP.PasswordLookups.txt]: + + * LDAP server verifies the password, so Dovecot doesn't need to know what + format the password is stored in. + * A bit more secure, as a security hole in Dovecot doesn't give attacker + access to all the users' password hashes. (And Dovecot admins in general + don't have direct access to them.) + +You can enable authentication binds by setting 'auth_bind=yes'. Next Dovecot +needs to know what DN to use in the binding. There are two ways to configure +this: lookup or template. + +DN lookup +--------- + +DN is looked up by sending a 'pass_filter' LDAP request and getting the DN from +the reply. This is very similar to doing a <password lookup> +[AuthDatabase.LDAP.PasswordLookups.txt]. The only difference is that +userPassword attribute isn't returned. Just as with password lookups, the +'pass_attrs' may contain special <extra fields> +[PasswordDatabase.ExtraFields.txt]. + +Example: + +---%<------------------------------------------------------------------------- +auth_bind = yes +pass_attrs = uid=user +pass_filter = (&(objectClass=posixAccount)(uid=%u)) +---%<------------------------------------------------------------------------- + +DN template +----------- + +The main reason to use DN template is to avoid doing the DN lookup, so that the +authentication consists only of one LDAP request. With IMAP and POP3 logins the +same optimization can be done by using <prefetch userdb> +[UserDatabase.Prefetch.txt] and returning userdb info in the DN lookup (a total +of two LDAP requests per login in both cases). If you're also using Dovecot for +SMTP AUTH, it doesn't do a userdb lookup so the prefetch optimization doesn't +help. + +If you're using DN template, 'pass_attrs' and 'pass_filter' settings are +completely ignored. That means you can't make passdb return any <extra fields> +[PasswordDatabase.ExtraFields.txt]. You should also set 'auth_username_format = +%Lu' in 'dovecot.conf' to normalize the username by lowercasing it. + +Example: + +---%<------------------------------------------------------------------------- +auth_bind = yes +auth_bind_userdn = cn=%u,ou=people,o=org +---%<------------------------------------------------------------------------- + +Connection optimization +----------------------- + +When using + + * auth binds and + * userdb ldap lookups, + +the userdb lookups should use a separate connection to the LDAP server. That +way it can send LDAP requests asynchronously to the server, which improves the +performance. This can be done by specifying different filenames in the LDAP +passdb and userdb args. The second file could be a symlink to the first one. +For example: + +---%<------------------------------------------------------------------------- +passdb { + driver = ldap + args = /etc/dovecot/dovecot-ldap.conf.ext +} +userdb { + driver = ldap + args = /etc/dovecot/dovecot-ldap-userdb.conf.ext +} +---%<------------------------------------------------------------------------- + +And create the symlink: + +---%<------------------------------------------------------------------------- +ln -s /etc/dovecot/dovecot-ldap.conf.ext +/etc/dovecot/dovecot-ldap-userdb.conf.ext +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.LDAP.PasswordLookups.txt b/doc/wiki/AuthDatabase.LDAP.PasswordLookups.txt new file mode 100644 index 0000000..a9232d5 --- /dev/null +++ b/doc/wiki/AuthDatabase.LDAP.PasswordLookups.txt @@ -0,0 +1,98 @@ +Passdb LDAP with password lookups +================================= + +Advantages over <authentication binds> [AuthDatabase.LDAP.AuthBinds.txt]: + + * Faster, because Dovecot can keep sending multiple LDAP requests + asynchronously to the server. With auth binds Dovecot must wait for each + request to finish before sending the next one. + * Supports non-plaintext <authentication mechanisms> + [Authentication.Mechanisms.txt] (if returning plaintext/ <properly hashed + passwords> [Authentication.PasswordSchemes.txt]). + * When using <LDA.txt> and static userdb, deliver can check if destination + user exists. With auth binds this check isn't possible. + +LDAP server permissions +----------------------- + +Normally LDAP server doesn't give anyone access to users' passwords, so you'll +need to create an administrator account that has access to the userPassword +field. With OpenLDAP this can be done by modifying '/etc/ldap/slapd.conf': + +---%<------------------------------------------------------------------------- +# there should already be something like this in the file: +access to attribute=userPassword + by dn="<dovecot's dn>" read # just add this line + by anonymous auth + by self write + by * none +---%<------------------------------------------------------------------------- + +Replace <dovecot's dn> with the DN you specified in 'dovecot-ldap.conf's' 'dn' +setting. + +Dovecot configuration +--------------------- + +The two important settings in password lookups are: + + * 'pass_filter' specifies the LDAP filter how user is found from the LDAP. You + can use all the normal <variables> [Variables.txt] like '%u' in the filter. + * 'pass_attrs' specifies a comma-separated list of attributes that are + returned from the LDAP. If you set it to empty, all the attributes are + returned. + +Usually the LDAP attribute names aren't the same as <the field names that +Dovecot uses internally> [PasswordDatabase.txt]. You must create a mapping +between them to get the wanted results. This is done by listing the fields as +'<ldap attribute>=<dovecot field>'. For example: + +---%<------------------------------------------------------------------------- +pass_attrs = uid=user, userPassword=password +---%<------------------------------------------------------------------------- + +This maps the LDAP "uid" attribute to Dovecot's "user" field and LDAP's +"userPassword" attribute to Dovecot's "password" field. These two fields should +always be returned, but it's also possible to return other special <extra +fields> [PasswordDatabase.ExtraFields.txt]. + +Password +-------- + +Most importantly the 'pass_attrs' must return a "password" field, which +contains the user's password. The next thing Dovecot needs to know is what +format the password is in. If all the passwords are in same format, you can use +'default_pass_scheme' setting in 'dovecot-ldap.conf' to specify it. Otherwise +each password needs to be prefixed with "{password-scheme}", for example +"{plain}plaintext-password". See <Authentication.PasswordSchemes.txt> for a +list of supported password schemes. + +Username +-------- + +LDAP lookups are case-insensitive. Unless you somehow normalize the username, +it's possible that a user logging in as "user", "User" and "uSer" are treated +differently. The easiest way to handle this is to tell Dovecot to change the +username to the same case as it's in the LDAP database. You can do this by +returning "user" field in the 'pass_attrs', as shown in the above example. + +If you can't normalize the username in LDAP, you can alternatively lowercase +the username in 'dovecot.conf': + +---%<------------------------------------------------------------------------- +auth_username_format = %Lu +---%<------------------------------------------------------------------------- + +Example +------- + +A typical configuration would look like: + +---%<------------------------------------------------------------------------- +auth_bind = no +pass_attrs = uid=user, userPassword=password +pass_filter = (&(objectClass=posixAccount)(uid=%u)) +default_pass_scheme = MD5 +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.LDAP.Userdb.txt b/doc/wiki/AuthDatabase.LDAP.Userdb.txt new file mode 100644 index 0000000..3371325 --- /dev/null +++ b/doc/wiki/AuthDatabase.LDAP.Userdb.txt @@ -0,0 +1,181 @@ +Userdb LDAP +=========== + +Usually your LDAP database also contains the <userdb information> +[UserDatabase.txt]. If your home directory can be specified with a template and +you're using only a single <UID and GID> [UserIds.txt], you should use <static +userdb> [UserDatabase.Static.txt] instead to avoid an unnecessary LDAP lookup. +You can also use <prefetch userdb> [UserDatabase.Prefetch.txt] to avoid the +userdb LDAP lookup. + +Userdb lookups are always done using the default DN ('dn' setting) bind. It's +not possible to do the lookup using the user's DN (remember that e.g. <LDA.txt> +needs to do userdb lookups without knowing the user's password). + +The userdb lookups are configured in very much the same way as <LDAP password +lookups> [AuthDatabase.LDAP.PasswordLookups.txt]. Instead of 'pass_attrs' and +'pass_filter', the userdb uses 'user_attrs' and 'user_filter'. Typically +'pass_filter' and 'user_filter' are equivalent. + +If you're using a single UID and GID for all the users, you can specify them +globally with 'mail_uid' and 'mail_gid' settings instead of returning them from +LDAP. + +Example: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =home=%{ldap:homeDirectory}, \ + =uid=%{ldap:uidNumber}, \ + =gid=%{ldap:gidNumber} +user_filter = (&(objectClass=posixAccount)(uid=%u)) + +# For using doveadm -A: +iterate_attrs = =user=%{ldap:uid} +iterate_filter = (objectClass=posixAccount) +---%<------------------------------------------------------------------------- + +Attribute templates (v2.1+) +--------------------------- + +You can mix static text with the value returned from LDAP by using %{ldap:*} +variables, which expand to the named LDAP attribute's value. Some examples: + +Create a "quota_rule" field with value "*:bytes=<n>" where <n> comes from +"quotaBytes" LDAP attribute: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =quota_rule=*:bytes=%{ldap:quotaBytes} +---%<------------------------------------------------------------------------- + +Create a "mail" field with value "maildir:/var/mail/<dir>/Maildir" where <dir> +comes from "sAMAccountName" LDAP attribute: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =mail=maildir:/var/spool/vmail/%{ldap:sAMAccountName}/Maildir +---%<------------------------------------------------------------------------- + +You can add static fields that aren't looked up from LDAP. For example create a +"mail" field with value "maildir:/var/vmail/%d/%n/Maildir": + +---%<------------------------------------------------------------------------- +user_attrs = \ + =quota_rule=*:bytes=%{ldap:quotaBytes}, \ + =mail=maildir:/var/vmail/%d/%n/Maildir +---%<------------------------------------------------------------------------- + +If you don't want a field to exist at all when its LDAP attribute doesn't +exist, you can give the attribute name before the first "=" character. For +example this doesn't return "home" or "mail" fields if "mailboxPath" doesn't +exist: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =quota_rule=*:bytes=%{ldap:quotaBytes}, \ + mailboxPath=home=/home/%{ldap:mailboxPath}, \ + mailboxPath=mail=maildir:~/Maildir +---%<------------------------------------------------------------------------- + +It's also possible to give default values to nonexistent attributes in v2.1.11+ +by using e.g.'%{ldap:userDomain:example.com} ' where if userDomain attribute +doesn't exist, example.com is used instead. + +Subqueries and pointers (v2.2) +------------------------------ + +LDAP values can now have DN pointers to other entries that are queried. + +*Note*: These aren't actually very useful anymore. See the next section for how +to do multiple queries more easily using multiple userdbs. + +Example: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =user=%{ldap:uid}, \ + @mail=%{ldap:mailDN}, \ + =uid=%{ldap:uidNumber@mail}, \ + =gid=%{ldap:gidNumber@mail}, \ + =home=%{ldap:rootPath@mail}/%d/%n +---%<------------------------------------------------------------------------- + +This will do a regular lookup first. Then does another lookup with DN taken +from mailDN's value. The *@mail attributes are assigned from the second +lookup's results. + +---%<------------------------------------------------------------------------- +user_attrs = \ + =user=%{ldap:uid}, \ + =home=%{ldap_ptr:activePath}, \ + !primaryPath, !secondaryPath +---%<------------------------------------------------------------------------- + +The activePath's value can be either "primaryPath" or "secondaryPath". The +home's value will be the contents of that field. The !field tells Dovecot to +fetch the field's value but not to do anything with it otherwise. + +Multiple queries via userdbs (v2.2+) +------------------------------------ + +Example: Give the user a class attribute, which defines the default quota: + +dovecot.conf: + +---%<------------------------------------------------------------------------- +userdb { + driver = ldap + args = /etc/dovecot/dovecot-users-ldap.conf.ext + result_success = continue-ok +} +userdb { + driver = ldap + args = /etc/dovecot/dovecot-class-ldap.conf.ext + skip = notfound +} +---%<------------------------------------------------------------------------- + +/etc/dovecot/dovecot-users-ldap.conf.ext: + +---%<------------------------------------------------------------------------- +# If user has overridden quota, quota_rule is set below. Otherwise it's still +unset. +user_attrs = \ + =class=%{ldap:userClass} + quotaBytes=quota_rule=*:bytes=%{ldap:quotaBytes} +---%<------------------------------------------------------------------------- + +/etc/dovecot/dovecot-class-ldap.conf.ext: + +---%<------------------------------------------------------------------------- +# Do the lookup using the user's class: +user_filter = (&(objectClass=userClass)(class=%{userdb:class})) +# With :protected suffix the quota_rule isn't overridden if it's already set. +user_attrs = \ + classQuotaBytes=quota_rule:protected=*:bytes=%{ldap:classQuotaBytes} +---%<------------------------------------------------------------------------- + +Variables and domains +--------------------- + +User names and domains may be distinguished using the <Variables.txt> %n and +%d. They split the /previous username/ at the "@" character. The /previous +username/ is: + + * For LMTP, it will be user@hostname, where hostname depends on e.g. the + Postfix configuration. + * For IMAP, it will be whatever the password database has designated as the + username. If the (LDAP) password database has "user_attrs = =user=%n", then + the domain part of the login name will be stripped by the password database. + The UserDB will not see any domain part, i.e. %n and %u are the same thing + for the UserDB. + +The UserDB may set a new username, too, using "user_attrs = =user=...". This +will be used for + + * Logging + * %u and %d variables in other parts of the configuration (e.g. quota file + names) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.LDAP.txt b/doc/wiki/AuthDatabase.LDAP.txt new file mode 100644 index 0000000..3ad2348 --- /dev/null +++ b/doc/wiki/AuthDatabase.LDAP.txt @@ -0,0 +1,79 @@ +LDAP +==== + +There are two ways to do LDAP authentication: + + * <Password lookups> [AuthDatabase.LDAP.PasswordLookups.txt] + * <Authentication binds> [AuthDatabase.LDAP.AuthBinds.txt] + +Both of these have their own advantages and disadvantages. + + * <LDAP as userdb> [AuthDatabase.LDAP.Userdb.txt] and other common LDAP query + settings. + +Configuration common to LDAP passdb and userdb +---------------------------------------------- + +Connecting +---------- + +There are two alternative ways to specify what LDAP server(s) to connect to: + + * 'hosts': A space separated list of LDAP hosts to connect to. You can also + use host:port syntax to use different ports. + * 'uris': A space separated list of LDAP URIs to connect to. This isn't + supported by all LDAP libraries. The URIs are in syntax + 'protocol://host:port'. For example 'ldap://localhost' or + 'ldaps://secure.domain.org' + +If multiple LDAP servers are specified, it's decided by the LDAP library how +the server connections are handled. Typically the first working server is used, +and it's never disconnected from. So there is no load balancing or automatic +reconnecting to the "primary" server. + +SSL/TLS +------- + +You can enable TLS in two alternative ways: + + * Connect to ldaps port (636) by using "ldaps" protocol, e.g. 'uris = + ldaps://secure.domain.org' + * Connect to ldap port (389) and use STARTTLS command. Use 'tls=yes' to enable + this. + +See the tls_* settings in 'dovecot-ldap-example.conf' for how to configure TLS. +(I think they apply to ldaps too?) + +Getting Dovecot to talk to a LDAPS signed against a custom certificate of +authority +----------------------------------------------------------------------------------- + +If you need to connect to ldaps secured against a custom certificate of +authority (CA), you will need to install the custom CA on your system.On Red +Hat Enterprise Linux 6, Dovecot uses the OpenLDAP library. By default, the CA +must be installed under the directory specified in the TLS_CACERTDIR option +found under /etc/openldap/ldap.conf (default value is /etc/openldap/certs). +After copying the CA, you'll need to run "c_rehash ." inside the directory, +this will create a symlink pointing to the CA. + +You can test the CA installation with this: openssl s_client -connect +yourldap.example.org:636 -CApath /etc/openldap/certs -showcerts + +This should report "Verify return code: 0 (ok)". + +SASL binds +---------- + +It's possible to use SASL binds instead of the regular plaintext binds if your +LDAP library supports them. See the sasl_* settings in +'dovecot-ldap-example.conf'. Note that SASL binds are currently incompatible +with authentication binds. + +Active Directory +---------------- + +When connecting to AD, you may need to use port 3268. Then again, not all LDAP +fields are available in port 3268. Use whatever +works.http://technet.microsoft.com/en-us/library/cc978012.aspx + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.Lua.txt b/doc/wiki/AuthDatabase.Lua.txt new file mode 100644 index 0000000..41caf61 --- /dev/null +++ b/doc/wiki/AuthDatabase.Lua.txt @@ -0,0 +1,293 @@ +Lua based authentication +======================== + +Since v2.3.0 you can implement passdb and userdb using Lua +[https://www.lua.org/] script. + +Contents + + + 1. Lua based authentication + + 1. Known bugs + + 2. Lua interface + + 3. Auth request methods + + 4. Password database + + 5. User database + + 6. Examples + +Known bugs +---------- + + * Before 2.3.4 when returning a table with values, the table values are + mistakenly converted into a number if they seem like a number. So if you are + using values like '012345', this would get converted into '12345' + * Before 2.3.4 returning password without scheme would cause a crash. + +Lua interface +------------- + +For details about Dovecot Lua, see <Design.Lua.txt>. + +When used in authentication, additional module *dovecot.auth* is added, which +contains constants for passdb and userdb. + +List of constants +----------------- + + * dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE + * dovecot.auth.PASSDB_RESULT_SCHEME_NOT_AVAILABLE - indicates password scheme + that cannot be understood + * dovecot.auth.PASSDB_RESULT_USER_UNKNOWN + * dovecot.auth.PASSDB_RESULT_USER_DISABLED + * dovecot.auth.PASSDB_RESULT_PASS_EXPIRED + * dovecot.auth.PASSDB_RESULT_NEXT - indicates that this passdb did not + authenticate user, next passdb should do it + * dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH + * dovecot.auth.PASSDB_RESULT_OK + * dovecot.auth.USERDB_RESULT_INTERNAL_FAILURE + * dovecot.auth.USERDB_RESULT_USER_UNKNOWN + * dovecot.auth.USERDB_RESULT_OK + +Also, it registers object *struct auth_request** which lets access various +parts of the auth request. You should use the loggers associated with +auth_request when possible. + +Auth request methods +-------------------- + +Functions: + + * auth_request#log_debug(text) - logs debug message (if debug is enabled, noop + otherwise) + * auth_request#log_error(text) - logs error message + * auth_request#log_info(text) - logs informational message + * auth_request#log_warning(text) - logs warning message + * auth_request#response_from_template(template) - takes in key=value template + and expands it using var_expand and produces table suitable for passdb + result + * auth_request#var_expand(template) - performs var expansion on the template + using <Variables.txt> + * auth_request#password_verify(crypted_password, plain_password) - checks if + the plain password matches the crypted or hashed password + * auth_request#event() - Returns child event for the auth request, can be used + for logging and other events. Comes with a prefix. (Since v2.3.6+) + +Subtables: + + * auth_request#passdb + * auth_request#userdb + +Members: + +See <Variables.txt> for details + + * auth_request#auth_domain + * auth_request#auth_user + * auth_request#auth_username + * auth_request#cert + * auth_request#client_id + * auth_request#domain + * auth_request#domain_first + * auth_request#domain_last + * auth_request#home + * auth_request#lip + * auth_request#local_name + * auth_request#login_domain + * auth_request#login_user + * auth_request#login_username + * auth_request#lport + * auth_request#master_user + * auth_request#mech + * auth_request#orig_domain + * auth_request#orig_user + * auth_request#orig_username + * auth_request#password + * auth_request#pid + * auth_request#real_lip + * auth_request#real_lport + * auth_request#real_rip + * auth_request#real_rport + * auth_request#rip + * auth_request#rport + * auth_request#secured + * auth_request#service + * auth_request#session + * auth_request#session_pid + * auth_request#user + * auth_request#username + +Additionally you can access + + * skip_password_check - Set if the password has already been validated by + another passdb + * passdbs_seen_user_unknown - If some previous passdb has not found this user + * passdbs_seen_internal_failure - If some previous passdb has had internal + failure + * userdbs_seen_internal_failure - If some previous userdb has had internal + failure + +Password database +----------------- + +Lua passdb supports two modes of function. It can behave as lookup database, or +password verification database. + +Lookup function signature is *auth_passdb_lookup(request)* and the password +verification signature is *auth_password_verify(request, password)* + +Both functions must return a tuple, which contains a return code, and also +additionally string or table. Table must be in key-value format, it will be +imported into auth request. The string must be in key=value format, except if +return code indicates internal error, the second parameter can be used as error +string. + +If *auth_verify_password* is found, it's always used. + +To configure passdb in dovecot, use + +---%<------------------------------------------------------------------------- +passdb { + driver = lua + args = file=/path/to/lua blocking=yes # default is yes +} +---%<------------------------------------------------------------------------- + +By default, dovecot runs Lua scripts in auth-worker processes. If you do not +want this, you can disable blocking, and Lua script will be ran in auth +process. This can degrade performance if your script is slow or makes external +lookups. + +User database +------------- + +Lua userdb supports both single user lookup and iteration. Note that iteration +will hold the whole user database in memory during iteration. + +User lookup function signature is *auth_userdb_lookup(request)*. The function +must return a tuple, which contains a return code, and also additionally string +or table. Table must be in key-value format, it will be imported into auth +request. The string must be in key=value format, except if return code +indicates internal error, the second parameter can be used as error string. + +User iteration function signature is *auth_userdb_iterate*, which is expected +to return table of usernames. Key names are ignored. + +To configure userdb in dovecot, use + +---%<------------------------------------------------------------------------- +userdb { + driver = lua + args = file=/path/to/lua blocking=yes # default is yes +} +---%<------------------------------------------------------------------------- + +Examples +-------- + +Skeleton +-------- + +---%<------------------------------------------------------------------------- +function auth_passdb_lookup(req) + if req.user == "testuser1" then + return dovecot.auth.PASSDB_RESULT_OK, "password=pass" + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "no such user" +end + +function auth_userdb_lookup(req) + if req.user == "testuser1" then + return dovecot.auth.USERDB_RESULT_OK, "uid=vmail gid=vmail" + end + return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "no such user" +end + +function script_init() + return 0 +end + +function script_deinit() +end + +function auth_userdb_iterate() + return {"testuser1"} +end +---%<------------------------------------------------------------------------- + +Simple username password database (such as opensmtpd) +----------------------------------------------------- + +The example uses whitespace separated username and password. As a special +caution, the way Lua is used here means you can have multiple user password per +line, instead of just one.This can be extended to more complicated separators +or multiple fields per user. + +If you only want to autenticate users, and don't care about user listing, you +can use + +---%<------------------------------------------------------------------------- +function auth_passdb_lookup(req) + for line in io.lines("/path/to/file") do + for user, pass in string.gmatch(line, "(%w+)%s(.+)") do + if (user == req.username) then + -- you can add additional information here, like userdb_uid + return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass + end + end + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "" +end +---%<------------------------------------------------------------------------- + +If you also want to be able to list users, so that you could use doveadm cmd -A + +---%<------------------------------------------------------------------------- +local database = "/path/to/file" + +function db_lookup(username) + for line in io.lines(database) do + for user, pass in string.gmatch(line, "(%w+)%s(.+)") do + if (user == username) then + return {result=0, password=pass} + end + end + end + return {result=-1} +end + +function auth_passdb_lookup(req) + res = db_lookup(req.username) + if res.result == 0 then + -- you can add additional information here for passdb + return dovecot.auth.PASSDB_RESULT_OK, "password=" .. res.password + end + return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "" +end + +function auth_userdb_lookup(req) + res = db_lookup(req.username) + if res.result == 0 then + -- you can add additional information here for userdb, like uid or home + return dovecot.auth.USERDB_RESULT_OK, "uid=vmail gid=vmail" + end + return dovecot.auth.USERDB_RESULT_USER_UNKNOWN, "" +end + +function auth_userdb_iterate() + users = {} + for line in io.lines(database) do + for user in string.gmatch(line, "(%w+)%s.+") do + table.insert(users, user) + end + end + return users +end +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.Passwd.txt b/doc/wiki/AuthDatabase.Passwd.txt new file mode 100644 index 0000000..d9e1071 --- /dev/null +++ b/doc/wiki/AuthDatabase.Passwd.txt @@ -0,0 +1,53 @@ +Passwd +====== + +User is looked up using 'getpwnam()' call, which usually looks into +'/etc/passwd' file, but depending on NSS +[http://en.wikipedia.org/wiki/Name_Service_Switch] configuration it may also +look up the user from eg. LDAP database. + +Most commonly used as a user database. + +The lookup is by default done in the auth worker processes. If you have only a +small local passwd file, you can avoid having extra auth worker processes by +disabling it: + +---%<------------------------------------------------------------------------- +userdb { + driver = passwd + args = blocking=no +} +---%<------------------------------------------------------------------------- + +Field overriding and extra fields (obsolete in v2.1+) +----------------------------------------------------- + +It's possible to override fields from passwd and add <extra fields> +[UserDatabase.ExtraFields.txt] with templates, but in v2.1+ it's done in a +better way by using override_fields. For example: + +---%<------------------------------------------------------------------------- +userdb { + driver = passwd + # Pre-v2.1: + #args = home=/var/mail/%u mail=maildir:/var/mail/%u/Maildir + # v2.1+: + override_fields = home=/var/mail/%u mail=maildir:/var/mail/%u/Maildir +} +---%<------------------------------------------------------------------------- + +This uses the UID and GID fields from passwd, but home directory is overridden. +Also the default <mail_location> [MailLocation.txt] setting is overridden. + +Passwd as a password database +----------------------------- + +Many systems use shadow passwords nowadays so passwd doesn't usually work as a +password database. BSDs are an exception to this, they still set the password +field even with shadow passwords. + +With FreeBSD, passwd doesn't work as a password database because the password +field is replaced by a '*'. But you can use <Passwd-file> +[AuthDatabase.PasswdFile.txt]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.PasswdFile.txt b/doc/wiki/AuthDatabase.PasswdFile.txt new file mode 100644 index 0000000..aa25b6d --- /dev/null +++ b/doc/wiki/AuthDatabase.PasswdFile.txt @@ -0,0 +1,150 @@ +Passwd-file +=========== + +This file is compatible with a normal '/etc/passwd' file, and a password file +used by libpam-pwdfile <PAM> [PasswordDatabase.PAM.txt] plugin. It's in the +following format: + +---%<------------------------------------------------------------------------- +user:password:uid:gid:(gecos):home:(shell):extra_fields +---%<------------------------------------------------------------------------- + +For a password database it's enough to have only the user and password fields. +For a user database, you need to set also uid, gid and preferably also home +(see <VirtualUsers.txt>). (gecos) and (shell) fields are unused by Dovecot. + +The password field can be in four formats: + + * 'password': Assume CRYPT <password scheme> + [Authentication.PasswordSchemes.txt]. + * '{SCHEME}password': The password is in the given <scheme> + [Authentication.PasswordSchemes.txt]. + * 'password[13]': libpam-passwd file compatible format for CRYPT <scheme> + [Authentication.PasswordSchemes.txt]. + * 'password[34]': libpam-passwd file compatible format for MD5 <scheme> + [Authentication.PasswordSchemes.txt]. + +extra_fields is a space-separated list of key=value pairs which can be used to +set various <passdb settings> [PasswordDatabase.ExtraFields.txt] and <userdb +settings> [UserDatabase.ExtraFields.txt]. Keys which begin with a 'userdb_' +prefix are used for userdb, others are used for passdb. So for example if you +wish to override <mail_location> [MailLocation.txt] setting for one user, use +'userdb_mail=mbox:~/mail'. <Variable> [Variables.txt] expansion is done for +extra_fields. + +Empty lines and lines beginning with '#' character are ignored. + +Multiple passwd files +--------------------- + +You can use all the <variables> [Variables.txt] in the passwd-file filenames, +for example: + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + # Each domain has a separate passwd-file: + args = /etc/auth/%d/passwd +} +---%<------------------------------------------------------------------------- + +Passwd-file args +---------------- + + * *scheme=<s>*: Allows you to specify the default <password scheme> + [Authentication.PasswordSchemes.txt]. The default is CRYPT. This is + available only for passdb. + * *username_format=<s>*: Look up usernames using this format instead of the + full username ('%u'). If you want to enable user@domain logins but have only + "user" in the file, set this to '%n'. + +Examples +-------- + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = scheme=plain-md5 username_format=%n /etc/imap.passwd +} +userdb { + driver = passwd-file + args = username_format=%n /etc/imap.passwd + default_fields = uid=vmail gid=vmail home=/home/vmail/%u +} +---%<------------------------------------------------------------------------- + + * The default_fields is explained in <UserDatabase#Userdb_settings.> + [UserDatabase.txt] They can be used to provide default userdb fields based + on templates in case they're not specified for everyone in the passwd file. + If you leave any of the standard userdb fields (uid, gid, home) empty, these + defaults will be used. + +This file can be used as a passdb: + +---%<------------------------------------------------------------------------- +user:{plain}password +user2:{plain}password2 +---%<------------------------------------------------------------------------- + +passdb with extra fields: + +---%<------------------------------------------------------------------------- +user:{plain}password::::::allow_nets=192.168.0.0/24 +---%<------------------------------------------------------------------------- + +This file can be used as both a passwd and a userdb: + +---%<------------------------------------------------------------------------- +user:{plain}pass:1000:1000::/home/user::userdb_mail=maildir:~/Maildir +allow_nets=192.168.0.0/24 +user2:{plain}pass2:1001:1001::/home/user2 +---%<------------------------------------------------------------------------- + +FreeBSD /etc/master.passwd as passdb and userdb +----------------------------------------------- + +On FreeBSD, '/etc/passwd' doesn't work as a password database because the +password field is replaced by a '*'. '/etc/master.passwd' can be converted into +a format usable by passwd-file. As <PasswordDatabase.PAM.txt> can access the +system-wide credentials on FreeBSD, what follows is generally needed only if +the mail accounts are different from the system accounts. + +If only using the result for 'name:password:uid:gid' and not using +<PasswordDatabase.ExtraFields.txt> you may be able to use the extract directly. +However, the Linux-style passwd file has fewer fields than that used by FreeBSD +and it will need to be edited if any fields past the first four are needed. In +particular, it will fail if used directly as a 'userdb' as the field used for +'home' is not in the same place as expected by the Dovecot parser. The +':class:change:expire' stanza in each line should be removed to be consistent +with the Linux-style format. While that stanza often is '::0:0' use of 'cut' is +likely much safer than 'sed' or other blind substitution. + +In '/etc/master.passwd', a password of '*' indicates that password +authentication is disabled for that user and the token '*LOCKED*' prevents all +login authentication, so you might as well exclude those: + +---%<------------------------------------------------------------------------- +# fgrep -v '*' /etc/master.passwd | cut -d : -f 1-4,8-10 > +/path/to/file-with-encrypted-passwords +# chmod 640 /path/to/file-with-encrypted-passwords +# chown root:dovecot /path/to/file-with-encrypted-passwords +---%<------------------------------------------------------------------------- + +or permissions and ownership that may be more appropriate for your install and +security needs. + +The following will work in many situations, after disabling the inclusion of +other 'userdb' and 'passdb' sections + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = username_format=%n /path/to/file-with-encrypted-passwords +} +userdb { + driver = passwd-file + args = username_format=%n /path/to/file-with-encrypted-passwords +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.SQL.txt b/doc/wiki/AuthDatabase.SQL.txt new file mode 100644 index 0000000..6176be7 --- /dev/null +++ b/doc/wiki/AuthDatabase.SQL.txt @@ -0,0 +1,243 @@ +SQL +=== + +SQL can be used for both passdb and userdb lookups. If the args parameter in +passdb sql and userdb sql contain the exact same filename, only one SQL +connection is used for both passdb and userdb lookups. + +Contents + + + 1. SQL + + 1. Dovecot configuration + + 2. Password database lookups + + 3. Password verification by SQL server + + 4. User database lookups + + 5. User iteration + + 6. Prefetching + + 7. High availability + + 8. Examples + +Dovecot configuration +--------------------- + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +Password database lookups +------------------------- + +'password_query' setting contains the SQL query to look up the password. It +must return a field named "password". If you have it by any other name in the +database, you can use the SQL's "AS" keyword ('SELECT pw AS password ..'). You +can use all the normal <variables> [Variables.txt] such as '%u' in the SQL +query. + +If all the passwords are in same format, you can use 'default_pass_scheme' to +specify it. Otherwise each password needs to be prefixed with +"{password-scheme}", for example "{plain}plaintext-password". See +<Authentication.PasswordSchemes.txt> for a list of supported password schemes. + +By default MySQL does case-insensitive string comparisons, so you may have a +problem if your users are logging with different as "user", "User" and "uSer". +To fix this, you can make the SQL database return a <"user" field> +[PasswordDatabase.ExtraFields.User.txt], which makes Dovecot modify the +username to the returned value. Note that if you're using separate user and +domain fields, a common problem is that you're returning only the "user" field +from the database.*This drops out the domain from the username*. So make sure +you're returning a concatenated user@domain string or username/domain fields +separately. See the examples below. + +The query can also return other <extra fields> +[PasswordDatabase.ExtraFields.txt] which have special meaning. + +You can't use multiple statements in one query, but you could use a stored +procedure. If you want something like a last login update, use +<PostLoginScripting.txt> instead. + +Password verification by SQL server +----------------------------------- + +If the passwords are in some special format in the SQL server that Dovecot +doesn't recognize, it's still possible to use them. Change the SQL query to +return NULL as the password and return the row only if the password matches. +You'll also need to return a non-NULL "nopassword" field. The password is in +'%w' variable. For example: + +---%<------------------------------------------------------------------------- +password_query = SELECT NULL AS password, 'Y' as nopassword, userid AS user \ + FROM users WHERE userid = '%u' AND mysql_pass = password('%w') +---%<------------------------------------------------------------------------- + +This of course makes the verbose logging a bit wrong, since password mismatches +are also logged as "unknown user". + +User database lookups +--------------------- + +Usually your SQL database contains also the userdb information. This means +user's UID, GID and home directory. If you're using only static UID and GID, +and your home directory can be specified with a template, you could use <static +userdb> [UserDatabase.Static.txt] instead. It is also a bit faster since it +avoids doing the userdb SQL query. + +'user_query' setting contains the SQL query to look up the userdb information. +The commonly returned userdb fields are uid, gid, home and mail. See +<UserDatabase.ExtraFields.txt> for more information about these and other +fields that can be returned. + +If you're using a single UID and GID for all users, you can set them in +dovecot.conf with: + +---%<------------------------------------------------------------------------- +mail_uid = vmail +mail_gid = vmail +---%<------------------------------------------------------------------------- + +User iteration +-------------- + +Some commands, such as 'doveadm -A' need to get a list of users. With SQL +userdb this is done with 'iterate_query' setting. You can either return + + * "user" field containing either user or user@domain style usernames, or + * "username" and "domain" fields + +Any other fields are ignored. + +Prefetching +----------- + +If you want to avoid doing two SQL queries when logging in with IMAP/POP3, you +can make the 'password_query' return all the necessary userdb fields and use +prefetch userdb to use those fields. If you're using Dovecot's deliver you'll +still need to have the 'user_query' working. + +See <UserDatabase.Prefetch.txt> for example configuration + +High availability +----------------- + +You can add multiple "host" parameters to the SQL connect string. Dovecot will +do round robin load balancing between them. If one of them goes down, the +others will handle the traffic. + +Examples +-------- + +Note that "user" can have a special meaning in some SQL databases, so we're +using "userid" instead. + +SQL table creation command: + +---%<------------------------------------------------------------------------- +CREATE TABLE users ( + userid VARCHAR(128) NOT NULL, + domain VARCHAR(128) NOT NULL, + password VARCHAR(64) NOT NULL, + home VARCHAR(255) NOT NULL, + uid INTEGER NOT NULL, + gid INTEGER NOT NULL +); +---%<------------------------------------------------------------------------- + +MySQL +----- + +Add to your 'dovecot-sql.conf' file: + +---%<------------------------------------------------------------------------- +driver = mysql +# The mysqld.sock socket may be in different locations in different systems. +# Use "host= ... pass=foo#bar" with double-quotes if your password has '#' +character. +# If you need SSL connection, you can add ssl_ca or ssl_ca_path +# You can also use ssl_cert/ssl_key, ssl_cipher, ssl_verify_server_cert +# or provide option_file and option_group +connect = host=/var/run/mysqld/mysqld.sock dbname=mails user=admin +password=pass +# Alternatively you can connect to localhost as well: +#connect = host=localhost dbname=mails user=admin password=pass # port=3306 + +password_query = SELECT userid AS username, domain, password \ + FROM users WHERE userid = '%n' AND domain = '%d' +user_query = SELECT home, uid, gid FROM users WHERE userid = '%n' AND domain = +'%d' + +# For using doveadm -A: +iterate_query = SELECT userid AS username, domain FROM users +---%<------------------------------------------------------------------------- + +PostgreSQL +---------- + +Add to your 'dovecot-sql.conf' file: + +---%<------------------------------------------------------------------------- +# You can also set up non-password authentication by modifying PostgreSQL's +pg_hba.conf +driver = pgsql +# Use "host= ... pass=foo#bar" if your password has '#' character +connect = host=localhost dbname=mails user=admin password=pass + +password_query = SELECT userid AS username, domain, password \ + FROM users WHERE userid = '%n' AND domain = '%d' +user_query = SELECT home, uid, gid FROM users WHERE userid = '%n' AND domain = +'%d' + +# For using doveadm -A: +iterate_query = SELECT userid AS username, domain FROM users +---%<------------------------------------------------------------------------- + +SQLite +------ + +Add to your 'dovecot-sql.conf' file: + +---%<------------------------------------------------------------------------- +driver = sqlite +connect = /path/to/sqlite.db + +password_query = SELECT userid AS username, domain, password \ + FROM users WHERE userid = '%n' AND domain = '%d' +user_query = SELECT home, uid, gid FROM users WHERE userid = '%n' AND domain = +'%d' + +# For using doveadm -A: +iterate_query = SELECT userid AS username, domain FROM users +---%<------------------------------------------------------------------------- + +PostgreSQL/Horde +---------------- + +I used the following in devocot-sql.conf file to authenticate directly against +the Horde user/password database (with static userdb) on PostgreSQL: + +---%<------------------------------------------------------------------------- +driver = pgsql +connect = host=localhost dbname=horde user=dovecot password= +default_pass_scheme = MD5-CRYPT +password_query = SELECT user_uid AS username, user_pass AS password \ + FROM horde_users WHERE user_uid = '%u' +iterate_query = SELECT user_uid AS username FROM users +---%<------------------------------------------------------------------------- + +Note that you will have to change the password encryption in Horde to +MD5-CRYPT. Also, the example above requires a 'dovecot' user in PostgreSQL with +read (SELECT) privileges on the 'horde_users' table. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.VPopMail.txt b/doc/wiki/AuthDatabase.VPopMail.txt new file mode 100644 index 0000000..30e7144 --- /dev/null +++ b/doc/wiki/AuthDatabase.VPopMail.txt @@ -0,0 +1,167 @@ +VPopMail +======== + +Dovecot supports authenticating against external VPopMail +[http://www.inter7.com/index.php?page=vpopmail] virtual domain manager. Dovecot +must have been configured with '--with-vpopmail' to enable this. You can check +this with 'dovecot --build-options'. See also <VMailMgr> [HowTo.VMailMgr.txt] +for another similar virtual domain manager. + +If the vpopmail database contains plaintext passwords, it can be used for +non-plaintext authentication as well. + +passdb parameters: + + * cache_key: If set, you can use 'auth_cache' with VPopMail. See <PAM> + [PasswordDatabase.PAM.txt] for more information about it. + * webmail=IP: If IP address is specified, connections from it are assumed to + come from webmail and VPopMail's webmail usage restrictions apply. + +userdb parameters: + + * cache_key: Like in passdb. + * quota_template=TEMPLATE: Template to specify quota rule, %q in value expands + to Maildir++ quota. + +Example +------- + +---%<------------------------------------------------------------------------- +passdb { + driver = vpopmail + args = webmail=127.0.0.1 +} +userdb { + driver = vpopmail + args = quota_template=quota_rule=*:backend=%q +} +---%<------------------------------------------------------------------------- + +VPopMail + MySQL +================ + +Alternatively, you can use the SQL backend with the following configuration: + +---%<------------------------------------------------------------------------- +driver = mysql +connect = host=/var/run/mysqld/mysqld.sock user=vpopmail +password=YOURPASSWORDHERE dbname=vpopmail + +default_pass_scheme = PLAIN +password_query = SELECT CONCAT(pw_name, '@', pw_domain) AS user, \ + pw_clear_passwd AS password \ + FROM vpopmail \ + WHERE pw_name = '%n' AND pw_domain = '%d' +user_query = SELECT pw_dir as home, \ + 89 AS uid, 89 AS gid \ + FROM vpopmail \ + WHERE pw_name = '%n' AND pw_domain = '%d' +---%<------------------------------------------------------------------------- + +VPopMail + MySQL + pw_gid (disable_imap, disable_webmail) and vlimits support +============================================================================= + +The above example doesn't support vpopmail's abilities to disable access to +services like IMAP, webmail etc. which is controlled by vmoduser and +vmoddomlimits. + +VPopMail uses pw_gid column in the database to store this information. It has a +binary format and every bit of the number stored in this column is responsible +for a different access limit. + +As defined in the vpopmail.h: + +---%<------------------------------------------------------------------------- +/* gid flags */ +#define NO_PASSWD_CHNG 0x01 +#define NO_POP 0x02 +#define NO_WEBMAIL 0x04 +#define NO_IMAP 0x08 +#define BOUNCE_MAIL 0x10 +#define NO_RELAY 0x20 +#define NO_DIALUP 0x40 +#define V_USER0 0x080 +#define V_USER1 0x100 +#define V_USER2 0x200 +#define V_USER3 0x400 +#define NO_SMTP 0x800 +#define QA_ADMIN 0x1000 +#define V_OVERRIDE 0x2000 +---%<------------------------------------------------------------------------- + ++ if vpopmail has been compiled with domain limits (--enable-mysql-limits) +domain wise limits will be defined in a table called "limits" where there are +fields like disable_imap and disable_webmail which values by default are NULL +and 1 if option is set. The use of NULLs in limits table is a bit problematic +because in order to properly handle this situation we're going to have replace +NULL with a numeric value. Of course we're going to join vpopmail table (the +table holding users) with limits table using LEFT JOIN. + +Here's the config taken directly from my install: + +---%<------------------------------------------------------------------------- +# +user_query = SELECT pw_name,89 as uid, 89 as gid, pw_dir as home FROM vpopmail +WHERE pw_name = '%n' AND pw_domain = '%d' +#The below passes all users and doesn't care for vpopmail limits (pw_gid column +or vlimits table) +#password_query = SELECT pw_passwd as password FROM vpopmail WHERE pw_name = +'%n' AND pw_domain = '%d' +# +#A little bit more complicated query to support vpopmail pw_gid flags and +vlimits for domain +#explanation: +#We're using bitwise operations on pw_gid. +#as defined in vpopmail.h: +#- 0x04 - disable webmail flag +#- 0x08 - disable imap flag +# +# !(pw_gid & 8) means - if 8th bit of pw_gid is not set +# !(pw_gid & 4) means - if 4th bit of pw_gid is not set +# (pw_gid & 8192) means - if 14th bit of pw_gid is set (ignore vlimits) +# +# additionally because we're using LEFT JOIN we have to take care of NULLs for +rows that don't return any records from the right table hence the use of +COALESCE() function +# !(pw_gid & 4) (disable webmail flag) is used in conjuntion with +'%r'!="127.0.0.1" which means that it will only apply to connections +originating from hosts other than localhost +# +# So the below query supports pw_gid and vlimits settings for user account and +domains but no domain limit overrides +# +#password_query = select pw_passwd as password FROM vpopmail LEFT JOIN limits +ON vpopmail.pw_domain=limits.domain WHERE pw_name='%n' and pw_domain='%d' and ( +!(pw_gid & 8) and ('%r'!='127.0.0.1' or !(pw_gid & 4)) and ( '%r'!='127.0.0.1' +or COALESCE(disable_webmail,0)!=1) and COALESCE(disable_imap,0)!=1); +# +# The below adds support for vlimits override on user account (vmoduser -o) +# +#logically this means: show password for user=%n at domain=%d when imap on the +account is not disabled and connection is not comming from localhost when +webmail access on the account is not disabled and if imap for the domain is not +disabled and (connection is not comming from localhost when webmail access for +the domain is not disabled) when vlimits are not overriden on the account +# +password_query = select pw_passwd as password FROM vpopmail LEFT JOIN limits ON +vpopmail.pw_domain=limits.domain WHERE pw_name='%n' and pw_domain='%d' and +!(pw_gid & 8) and ('%r'!='127.0.0.1' or !(pw_gid & 4)) and ( ('%r'!='127.0.0.1' +or COALESCE(disable_webmail,0)!=1) and COALESCE(disable_imap,0)!=1 or (pw_gid & +8192) ); +---%<------------------------------------------------------------------------- + +Please be aware that disable_webmail is strictly binded to the IP address hard +coded in the query. In this example webmail connections come from the same +machine that the IMAP server is running on using 127.0.0.1 IP address. So the +webmail client is configured with something like eg. $IMAP_SERVER="127.0.0.1". +If your webmail client is on a different machine you need to change 127.0.0.1 +to your webmail's server IP. + +Also - be aware that dovecot caches SQL results (configurable) so if you're +testing the above config on an account that has logged on succesfully within +the cache timeout period and you changed the settings on it using eg. vmoduser +-i test@example.com account which effectively disabled IMAP access for this +account dovecot can still log this user on because the result of the password +query has been stored in cache and used. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/AuthDatabase.txt b/doc/wiki/AuthDatabase.txt new file mode 100644 index 0000000..ccfc896 --- /dev/null +++ b/doc/wiki/AuthDatabase.txt @@ -0,0 +1,19 @@ +Authentication Databases +======================== + +These databases can be used as both <password databases> [PasswordDatabase.txt] +and <user databases> [UserDatabase.txt]: + + * <Passwd> [AuthDatabase.Passwd.txt]: System users (NSS, '/etc/passwd', or + similiar) + * <Passwd-file> [AuthDatabase.PasswdFile.txt]: '/etc/passwd'-like file in + specified location + * <LDAP> [AuthDatabase.LDAP.txt]: Lightweight Directory Access Protocol + * <SQL> [AuthDatabase.SQL.txt]: SQL database (PostgreSQL, MySQL, SQLite) + * <Dict> [AuthDatabase.Dict.txt]: Dict key-value database (Redis, memcached, + etc.) + * <VPopMail> [AuthDatabase.VPopMail.txt]: External software used to handle + virtual domains + * <Lua> [AuthDatabase.Lua.txt]: Lua script for authentication (v2.3.0+) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Caching.txt b/doc/wiki/Authentication.Caching.txt new file mode 100644 index 0000000..4f696d3 --- /dev/null +++ b/doc/wiki/Authentication.Caching.txt @@ -0,0 +1,107 @@ +Caching of authentication results +================================= + +Dovecot supports caching the results of password and user database lookups. The +following rules apply to using the authentication cache: + + * Data is used from the cache if it's not expired ('auth_cache_ttl' setting) + * If authentication fails this time, but it didn't fail last time, it's + assumed that the password has changed and a database lookup is done. + * If a database lookup fails because of some internal error, but data still + exists in the cache (even if expired), the cached data is used. This allows + Dovecot to log in some users even if the database is temporarily down. + +The authentication cache can be flushed by sending a SIGHUP to dovecot-auth. + +Sending SIGUSR2 to dovecot-auth makes it log the number of cache hits and +misses. You can use that information for tuning the cache size and TTL. + +Settings +-------- + +The settings related to the authentication cache are: + + * 'auth_cache_size': Authentication cache size, 0 disables caching (default). + A typical passdb cache entry is around 50 bytes and a typical userdb cache + entry is around 100-200 bytes, depending on the amount of information your + user and password database lookups return. + * 'auth_cache_ttl': Time to live in seconds for cache entries. A cache entry + is no longer used (except for internal failures) if it was created more than + this many seconds ago. Entries are removed from the cache only when the + cache is full and a new entry is to be added. + * 'auth_cache_negative_ttl': If a passdb or userdb lookup didn't return any + data (i.e. the user doesn't exist), it's also stored in the cache as a + negative entry. This setting allows you to give negative entries a different + TTL. 0 disables negative caching completely. + * 'auth_cache_verify_password_with_worker': Password hash verifications are + done by the auth master process by default. Setting this to "yes" moves the + verification to auth-worker processes. This allows distributing the hash + calculations to multiple CPU cores, which could make sense if strong hashes + are used. (v2.2.34+) + +It should be pretty safe to set very high TTLs, because the only field that +usually can change is the user's password, and Dovecot attempts to catch those +cases (see the rules above). + +Cache keys +---------- + +Usually only the username uniquely identifies a user, but in some setups you +may need something more, for example the remote IP address. For SQL and LDAP +lookups Dovecot figures this out automatically by using all the used +<%variables> [Variables.txt] as the cache key. For example if your SQL query +contains %s, %u and %r the cache entry is used only if all of them (service +name, username and remote IP) match for the new lookup. + +With other databases Dovecot doesn't know what could affect caching, so you +have to tell Dovecot manually. The following databases require specifying the +cache key: + + * vpopmail + * pam + * bsdauth + +For example if the PAM lookup depends on username and service, you can use: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = cache_key=%s%u * +} +---%<------------------------------------------------------------------------- + +Password changing scenarios +--------------------------- + +Normal scenario: + + 1. User logs in with password X. The password X is added to cache and login + succeeds. + 2. Password is changed to Y. + 3. User logs in with password Y. The cached password X doesn't match Y, but + since the previous authentication was successful Dovecot does another + backend passdb lookup to see if the password changed. It did, so the + password Y is cached and login succeeds. + +Using old cached password scenario: + + 1. User logs in with password X. The password X is added to cache and login + succeeds. + 2. Password is changed to Y. + 3. User logs in with password X. The cached password X matches X, so login + succeeds. + +Early change scenario: + + 1. User logs in with password X. The password X is added to cache and login + succeeds. + 2. User logs in with password Y. The cached password X doesn't match Y, but + since the previous authentication was successful Dovecot does another + backend passdb lookup to see if the password changed. It didn't, so the + login fails. + 3. Password is changed to Y. + 4. User logs in with password Y. The cached password X doesn't match Y and the + previous authentication was unsuccessful, so Dovecot doesn't bother doing + another backend passdb lookup (until cache TTL expires). The login fails. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Kerberos.txt b/doc/wiki/Authentication.Kerberos.txt new file mode 100644 index 0000000..d37dc3c --- /dev/null +++ b/doc/wiki/Authentication.Kerberos.txt @@ -0,0 +1,229 @@ +Kerberos +======== + +Dovecot supports Kerberos 5 using GSSAPI. The Kerberos authentication mechanism +doesn't require having a <passdb> [PasswordDatabase.txt], but you do need a +<userdb> [UserDatabase.txt] so Dovecot can lookup user-specific information, +such as where their mailboxes are stored. With centralized systems, such as +Microsoft Active Directory, LDAP is pretty good choice. + +*Note:* If you only wish to authenticate clients using their Kerberos +/passphrase/ (as opposed to ticket authentication), you will probably want to +use <PAM> [PasswordDatabase.PAM.txt] authentication with 'pam_krb5.so' instead. + +Pre-requisites +-------------- + +This document assumes that you already have a Kerberos Realm up and functioning +correctly at your site, and that each host in your realm also has a host +/keytab/ installed in the appropriate location. + +For Dovecot, you will need to install the appropriate /service/ keys on your +server. By default, Dovecot will look for these in the host's keytab file, +typically '/etc/krb5.keytab', but you can specify an alternate path using the +'auth_krb5_keytab' configuration entry in dovecot.conf. Anyway specified +keytab file should be readable by user "dovecot" (or whatever user the auth +process is running as). If you wish to provide an IMAP service, you will need +to install a service ticket of the form 'imap/hostname@REALM'. For POP3, you +will need a service ticket of the form 'pop/hostname@REALM'. When using +Dovecot's <SASL> [Sasl.txt] with MTA, you will need to install service ticket +of the form 'smtp/hostname@REALM'. + +Setting up (samba) +------------------ + +Create symlink for krb5.conf, if you do not have krb5.conf ready + +---%<------------------------------------------------------------------------- +ln -sf /usr/local/samba/private/krb5.conf /etc/krb5.conf +---%<------------------------------------------------------------------------- + +Create dovecot user to your samba instance (choose random password) + +---%<------------------------------------------------------------------------- +$ samba-tool user create dovecot +New Password: +Retype Password: +User 'dovecot' created successfully +---%<------------------------------------------------------------------------- + +Add Service Principal Names (SPNs) and create keytab + +---%<------------------------------------------------------------------------- +$ samba-tool spn add imap/host.domain.com dovecot +$ samba-tool domain exportkeytab --principal imap/host.domain.com +/etc/dovecot/dovecot.keytab +---%<------------------------------------------------------------------------- + +Dovecot needs to be able to read the keytab + +---%<------------------------------------------------------------------------- +$ chgrp dovecot /etc/dovecot/dovecot.keytab +$ chmod g+r /etc/dovecot/dovecot.keytab +---%<------------------------------------------------------------------------- + +Make sure your keytab has entry for imap/host.domain.name@REALM. + +---%<------------------------------------------------------------------------- +$ klist -Kek /etc/dovecot/dovecot.keytab +Keytab name: FILE:/etc/dovecot/dovecot.keytab +KVNO Principal +---- -------------------------------------------------------------------------- + 1 imap/host.domain.name@REALM (des-cbc-crc) + 1 imap/host.domain.name@REALM (des-cbc-md5) + 1 imap/host.domain.name@REALM (arcfour-hmac) +---%<------------------------------------------------------------------------- + +Example dovecot.conf configurations +----------------------------------- + +If you only want to use Kerberos ticket-based authentication: + +---%<------------------------------------------------------------------------- +auth_gssapi_hostname = "$ALL" +auth_mechanisms = gssapi +auth_krb5_keytab = /etc/dovecot/dovecot.keytab + +userdb { + driver = static + args = uid=vmail gid=vmail home=/var/vmail/%u +} +---%<------------------------------------------------------------------------- + +(In this virtual-hosting example, all mail is stored in /var/vmail/$username +with uid and gid set to 'vmail') + +If you also want to support plaintext authentication in addition to +ticket-based authentication, you will need something like: + +---%<------------------------------------------------------------------------- +auth_mechanisms = plain login gssapi +auth_gssapi_hostname = "$ALL" +auth_mechanisms = gssapi +auth_krb5_keytab = /etc/dovecot/dovecot.keytab +passdb { + driver = pam +} +userdb { + driver = passwd +} +---%<------------------------------------------------------------------------- + +(Note that in this example, you will also need to configure PAM to use +whichever authentication backends are appropriate for your site.) + +Enable plaintext authentication to use Kerberos +----------------------------------------------- + +This is needed when some of your clients don't support GSSAPI and you still +want them to authenticate against Kerberos. + +Install pam_krb5 module for PAM, and create '/etc/pam.d/dovecot': + +---%<------------------------------------------------------------------------- +auth sufficient pam_krb5.so +account sufficient pam_krb5.so +---%<------------------------------------------------------------------------- + +Then enable PAM passdb: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam +} +---%<------------------------------------------------------------------------- + +Check '/var/log/auth.log' if you have any problems logging in. The problem +could be that PAM is still trying to use pam_unix.so rather than pam_krb5.so. +Make sure pam_krb5.so is the first module for account or just change +pam_unix.so to sufficient. + +Cross-realm authentication +-------------------------- + +This seems to have all kinds of trouble. Search Dovecot mailing list for +previous threads about it. Some points about it: + + * krb5_kuserok() is used to check if access is allowed. It may try to do the + check by reading ~user/.k5login (good!) or ~dovecot/.k5login (bad!) + * Solaris uses _gss_userok() instead of krb5_kuserok() + * v2.2+ has "k5principals" <passdb extra field> + [PasswordDatabase.ExtraFields.txt], which is a comma separated list of + usernames that are allowed to log in. If it's set, it bypasses the + krb5_kuserok() check.*NOTE*: for this to work, you need a password database + which supports *credential lookups*. + * With 2.2.13, this excludes LDAP databases using authentication binds + (auth_bind = yes). However, a second LDAP passdb entry without "auth_bind + = yes" may be added for the sole purpose of Kerberos principals mapping. + This passdb doesn't need to return a password attribute (and usually + should'nt). + * UPDATE: code seems to have been reworked in later versions. With 2.2.24, + authentication-bind LDAP databases are able to provide k5principals + lookups if configured with "pass_filter". + +Client support +-------------- + +Mail clients that support Kerberos GSSAPI authentication include: + + * Evolution + * Mozilla Thunderbird + * SeaMonkey + * Mutt + * UW Pine + * Apple Mail + +Test that the server can access the keytab +------------------------------------------ + +This test demonstrates that the server can acquire its private credentials. +First telnet directly to the server + +---%<------------------------------------------------------------------------- +$ telnet localhost 143 +* OK Dovecot ready. +---%<------------------------------------------------------------------------- + +or, if you are using IMAPS then use openssl instead of telnet to connect: + +---%<------------------------------------------------------------------------- +$ openssl s_client -connect localhost:993 +CONNECTED(00000003) +... +* OK Dovecot ready. +---%<------------------------------------------------------------------------- + +Check that GSSAPI appears in the authentication capabilities: + +---%<------------------------------------------------------------------------- +a capability +* CAPABILITY ... AUTH=GSSAPI +---%<------------------------------------------------------------------------- + +Attempt the first round of GSS communication. The '+' indicates that the server +is ready + +---%<------------------------------------------------------------------------- +a authenticate GSSAPI ++ +---%<------------------------------------------------------------------------- + +Abort the telnet session by typing control-] and then 'close' + +---%<------------------------------------------------------------------------- +^] +telnet> close +---%<------------------------------------------------------------------------- + +The test: + + * Setup mutt in /etc/Muttrc to use kerberos using gssapi and imap + configuration + * this is done with 'set imap_authenticators="gssapi"' + * run kinit (type in password for kerb) + * run command mutt + * If you get error No Authentication Method + * run command klist (list all kerberos keys) should show imap/HOSTNAME + * DNS has to function correctly so that kerberos works. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.MasterUsers.txt b/doc/wiki/Authentication.MasterUsers.txt new file mode 100644 index 0000000..2374cf7 --- /dev/null +++ b/doc/wiki/Authentication.MasterUsers.txt @@ -0,0 +1,294 @@ +Master users/passwords +====================== + +It's possible to configure master users who are able to log in as other users. +It's also possible to directly log in as any user using a master password. + +Master users +------------ + +There are two ways for master users to log in as other users: + + 1. Give the login username in the <SASL mechanism's> + [Authentication.Mechanisms.txt] authorization ID field. + 2. Specify both the master username and the login username in the same + username field. The usernames are separated by a string configured by the + 'auth_master_user_separator' setting. UW-IMAP uses "*" as the separator, so + that could be a good choice. Using "*" as the separator, the master user + would log in as "login_user*master_user". + +Master users are configured by adding a new <passdb> [PasswordDatabase.txt] +with 'master=yes' setting. The users in the master passdb cannot log in as +themselves, only as other people. That means they don't need to exist in the +<userdb> [UserDatabase.txt], because the userdb lookup is done only for the +user they're logging in as. + +You should also add the 'pass=yes' setting to the master passdb if possible. It +means that Dovecot verifies that the login user really exists before allowing +the master user to log in. Without the setting if a nonexistent login username +is given, depending on the configuration, it could either return an internal +login error (the userdb lookup failed) or create a whole new user (with eg. +<static userdb> [UserDatabase.Static.txt]). 'pass=yes' doesn't work with PAM or +LDAP with 'auth_bind=yes', because both of them require knowing the user's +password. + +'pass=yes' is especially useful with a <Checkpassword> +[PasswordDatabase.CheckPassword.txt] passdb because the script gets both the +login and the master username as environment variables. Other passdbs see only +the login username in '%u'. In the future there will probably be another +setting to make the user verification to be done from userdb. + +If you want master users to be able to log in as themselves, you'll need to +either add the user to the normal passdb or add the passdb to 'dovecot.conf' +twice, with and without 'master=yes'. Note that if the passdbs point to +different locations, the user can have a different password when logging in as +other users than when logging in as himself. This is a good idea since it can +avoid accidentally logging in as someone else. + +Usually it's better to have only a few special master users that are used +*only* to log in as other people. One example could be a special "spam" master +user that trains the users' spam filters by reading the messages from the +user's spam mailbox. + +ACLs +---- + +If <ACL.txt> plugin is enabled, the Master user is still subject to ACLs just +like any other user, which means that by default the master user has no access +to any mailboxes of the user. The options for handling this are: + + 1. Adding a global <ACL.txt> for the master user. You can create a "default + ACL", that applies to all mailboxes. See example below. + 2. Set 'plugin { acl_user=%u } ' This preserves the master_user for other + purposes (e.g. %{master_user} variable). + 3. Set 'plugin { master_user=%u } ' This fully hides that master user login is + being used. + +Example configuration +--------------------- + +---%<------------------------------------------------------------------------- +auth_master_user_separator = * +passdb { + driver = passwd-file + args = /etc/dovecot/passwd.masterusers + master = yes + pass = yes +} +passdb { + driver = shadow +} +userdb { + driver = passwd +} +---%<------------------------------------------------------------------------- + +To grant the masteruser access to all Mailboxes, the 'dovecot-acl' file can +contain: + +---%<------------------------------------------------------------------------- +* user=masteruser lr +---%<------------------------------------------------------------------------- + +Where the 'passwd.masterusers' file would contain the master usernames and +passwords: + +---%<------------------------------------------------------------------------- +admin:{SHA1}nU4eI71bcnBGqeO0t9tXvY1u5oQ= +admin2:{SHA1}i+UhJqb95FCnFio2UdWJu1HpV50= +---%<------------------------------------------------------------------------- + +One way to create this master file is to use the htaccess program as follows: + +---%<------------------------------------------------------------------------- +htpasswd -b -c -s passwd.masterusers user password +---%<------------------------------------------------------------------------- + +SQL Example +----------- + +The master passdb doesn't have to be passwd-file, it could be an SQL query as +well: + +---%<------------------------------------------------------------------------- +auth_master_user_separator = * +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql-master.conf.ext + master = yes + pass = yes +} +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +} +---%<------------------------------------------------------------------------- + +'dovecot-sql-master.conf.ext' would contain all the normal connection settings +and a 'password_query': + +---%<------------------------------------------------------------------------- +password_query = SELECT password FROM users WHERE userid = '%u' and master_user += true +---%<------------------------------------------------------------------------- + +Testing +------- + +---%<------------------------------------------------------------------------- +# telnet localhost 143 +* OK Dovecot ready. +1 login loginuser*masteruser masterpass +1 OK Logged in. +---%<------------------------------------------------------------------------- + +If you had any problems, set 'auth_debug=yes' and look at the logs. + +Master passwords +---------------- + +You can configure a passdb which first performs authentication using the master +password. Then it continues to the primary passdb to verify that the user +exists and get other extra fields. + +---%<------------------------------------------------------------------------- +# master password passdb +passdb { + driver = static + default_fields = password=master-password + result_success = continue +} +# primary passdb +passdb { + driver = pam +} +---%<------------------------------------------------------------------------- + +Advanced SQL Examples +--------------------- + +In these example we will create 3 kinds of master users. The first will be +users who can read all email for all domains. The next example will be users +who can read all email for their domain only. The third example will be users +who can read email of domains listed in a separate ownership table. We will use +MySQL and create 2 tables with the following structure. + +---%<------------------------------------------------------------------------- +CREATE TABLE `users` ( + `uid` int(4) NOT NULL AUTO_INCREMENT, + `user_name` varchar(80) NOT NULL, + `domain_name` varchar(80) NOT NULL, + `password` varchar(60) DEFAULT NULL, + `last_login` datetime DEFAULT NULL, + `masteradmin` tinyint(1) NOT NULL DEFAULT '0', + `owns_domain` tinyint(1) NOT NULL DEFAULT '0', + UNIQUE KEY `emaillookup` (`domain_name`,`user_name`), + UNIQUE KEY `uid` (`uid`) +) ENGINE=MyISAM AUTO_INCREMENT=995 DEFAULT CHARSET=latin + +CREATE TABLE `ownership` ( + `login_id` varchar(128) NOT NULL, + `owned_object` varchar(128) NOT NULL, + UNIQUE KEY `login_id_full` (`login_id`,`owned_object`), + KEY `login_id` (`login_id`), + KEY `owned_object` (`owned_object`), + KEY `login_id_index` (`login_id`), + KEY `owned_object_index` (`owned_object`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +---%<------------------------------------------------------------------------- + +The dovecot.conf file for all 3 master user configurations will be as follows: + +---%<------------------------------------------------------------------------- +passdb { + driver = sql + args = /etc/dovecot/ownership-sql.conf + master = yes + pass = yes +} + +passdb { + driver = sql + args = /etc/dovecot/domain-owner-sql.conf + master = yes + pass = yes +} + +passdb { + driver = sql + args = /etc/dovecot/masteradmin-sql.conf + master = yes + pass = yes +} +passdb { + args = /etc/dovecot/sql.conf + driver = sql +} +---%<------------------------------------------------------------------------- + +Before we get into the master user tricks, we start with normal email +authentication. The query for that is as follows: + +---%<------------------------------------------------------------------------- +password_query = SELECT user_name, domain_name, password FROM users WHERE +user_name = '%n' AND domain_name = '%d' +---%<------------------------------------------------------------------------- + +In this first example master admin suppose you want to allow a few people to be +master users over all domains. These users will have the "masteradmin" field +set to 1. The query would be: + +---%<------------------------------------------------------------------------- +password_query = SELECT user_name, domain_name, password FROM users WHERE +user_name = '%n' AND domain_name = '%d' AND masteradmin='1' +---%<------------------------------------------------------------------------- + +In the second example suppose you are hosting multiple domains and you want to +allow a few users to become master users of their domain only. + +Your query would be as follows: + +---%<------------------------------------------------------------------------- +password_query = SELECT user_name, domain_name, password FROM users WHERE +user_name = '%n' \ +AND domain_name = '%d' AND owns_domain='1' AND '%d'='%{login_domain}' +---%<------------------------------------------------------------------------- + +This will allow you to log in using the following to read Joe's email if +master@dovecot.org is flagged as the domain_owner. + +---%<------------------------------------------------------------------------- +joe@dovecot.org*master@dovecot.org +---%<------------------------------------------------------------------------- + +In this third example we have a table of owners. There are a list of pairs +between owner email addresses and domains that are owned. That way if a person +controls a lot of domains then they can view all the users in all the domains +they control. The query would be as follows: + +---%<------------------------------------------------------------------------- +password_query = SELECT user_name, domain_name, password FROM users, ownership +WHERE \ +user_name = '%n' AND domain_name = '%d' AND login_id='%u' AND +owned_object='%{login_domain}' +---%<------------------------------------------------------------------------- + +If you really want to get tricky and efficient you can combine all 3 queries +into one giant query that does everything. + +---%<------------------------------------------------------------------------- +password_query = SELECT user_name, domain_name, password FROM users, ownership +WHERE \ +user_name = '%n' AND domain_name = '%d' AND ( \ +(masteradmin='1') OR \ +(owns_domain='1' AND '%d'='%{login_domain}') OR \ +(login_id='%u' and owned_object='%{login_domain}')) \ +group by uid +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Mechanisms.DigestMD5.txt b/doc/wiki/Authentication.Mechanisms.DigestMD5.txt new file mode 100644 index 0000000..eda617e --- /dev/null +++ b/doc/wiki/Authentication.Mechanisms.DigestMD5.txt @@ -0,0 +1,80 @@ +Digest-MD5 Authentication Mechanism +=================================== + +Digest-MD5 has two things that make it special and which can cause problems: + + * Instead of using user@domain usernames, it supports *realms*. + * User name and realm are part of the MD5 hash that's used for authentication. + +For these and other reasons Digest-MD5 has been obsoleted +[http://tools.ietf.org/html/rfc6331] by SCRAM +[http://tools.ietf.org/html/rfc5802]. + +Realms +------ + +Dovecot v1.0 has problems handling user@domain style usernames with Digest-MD5 +and with passwords stored in plaintext in the password database. + +Instead, user@realm is used. Realms are an integral part of Digest-MD5. You +will need to specify realms you want to advertise to the client in the config +file: + +---%<------------------------------------------------------------------------- +auth_realms = example.com another.example.com foo +---%<------------------------------------------------------------------------- + +The realms don't have to be domains. All listed realms are presented to the +client and it can select to use one of them. Some clients always use the first +realm. Some clients use your domain name, whenever given more than one realm to +choose from. Even if this was NOT one of the choices you provided (KMail, +others?). In both cases the user never sees the advertised realms. + +You can also set an 'auth_default_realm' to use when a client gives an empty +realm. However the client is supposed to use the same realm it tells the server +for the calculation. So when this option helps, it is only for broken clients. + +DIGEST-MD5 scheme +----------------- + +Password must be stored in either plaintext or with DIGEST-MD5 scheme. See +<Authentication.PasswordSchemes.txt>. + +The Digest is the MD5 sum of the string "user:realm:password". So for example +if you want to log in as 'user' with password 'pass' and the realm should be +'example.com' (usually not provided by the user, see above), create the digest +with: + +---%<------------------------------------------------------------------------- +% echo -n "user:example.com:pass" | md5sum +c19c4c6e32f9d8026b26ba77c21fb8eb - +---%<------------------------------------------------------------------------- + +And save it as + +---%<------------------------------------------------------------------------- +user@example.com:c19c4c6e32f9d8026b26ba77c21fb8eb +---%<------------------------------------------------------------------------- + +Note that if you're using DIGEST-MD5 scheme to store the passwords, you can't +change the users' names or realms in any way or the authentication will fail +because the MD5 sums don't match. Also not that this is different from what +Apache does with HTTP AUTH Digest. There it would be +'user:example.com:c19c4c6e32f9d8026b26ba77c21fb8eb' and is created with +'htdigest'. + +Testing +------- + +You can use 'imtest' from Cyrus SASL +[http://asg.web.cmu.edu/sasl/sasl-library.html] library to test an IMAP +connection: + +---%<------------------------------------------------------------------------- +# With realm: +imtest -a user -r example.com +# Without realm: +imtest -a user@example.com +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Mechanisms.NTLM.txt b/doc/wiki/Authentication.Mechanisms.NTLM.txt new file mode 100644 index 0000000..46b5750 --- /dev/null +++ b/doc/wiki/Authentication.Mechanisms.NTLM.txt @@ -0,0 +1,34 @@ +NTLM +==== + +There are four authentication submethods inside the NTLM: + + 1. LM: server nonce only, highly vulnerable to MITM and rogue server attacks. + 2. NTLM: different algorithm, almost equally vulnerable as LM today. + 3. NTLM2: server and client nonce, but MITM can force downgrade to NTLM/LM. + 4. NTLMv2: server and client nonce, MITM can't force downgrade. + +NTLM <password scheme> [Authentication.PasswordSchemes.txt] is required for +NTLM, NTLM2 and NTLMv2. + +NTLMv2 can not be negotiated. It must be explicitly enabled on the client side +by setting registry key below to at least 3: + + * Win9x: + 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA\LMCompatibility' + * WinNT: + 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA\LMCompatibilityLevel' + +Dovecot's NTLM logic is: + + 1. If we have only LM password scheme, try LM authentication; + 2. If client sends LM response only (some very old clients do it), try LM too; + + 3. If NTLMv2 is guessed (using client response length), try NTLMv2; + 4. If NTLM2 was negotiated, try it; + 5. Otherwise try NTLM. + +For more information about NTLM internals, see http://ubiqx.org/cifs/ and +http://davenport.sourceforge.net/ntlm.html + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Mechanisms.Winbind.txt b/doc/wiki/Authentication.Mechanisms.Winbind.txt new file mode 100644 index 0000000..256a54d --- /dev/null +++ b/doc/wiki/Authentication.Mechanisms.Winbind.txt @@ -0,0 +1,35 @@ +Winbind mechanisms +================== + +Dovecot supports NTLM and GSS-SPNEGO authentication mechanisms using Samba +[http://www.samba.org]'s winbind daemon. It is useful when you need to +authenticate users against a Windows domain (either AD or NT). + +By default NTLM mechanism is handled internally. You can use winbind instead by +setting: + +---%<------------------------------------------------------------------------- +auth_use_winbind = yes +---%<------------------------------------------------------------------------- + +The usernames, returned by winbind, can contain some domain part (either +"DOMAIN\user" or "user@example.com"). Such usernames are always transformed to +the form of "user@domain". To strip domain part (to obtain corresponding local +username, for example), set: + +---%<------------------------------------------------------------------------- +auth_username_format = %n +---%<------------------------------------------------------------------------- + +Dovecot needs path to Samba's 'ntlm_auth' binary to perform the authentication. +You can change the path with: + +---%<------------------------------------------------------------------------- +auth_winbind_helper_path = /usr/bin/ntlm_auth +---%<------------------------------------------------------------------------- + +Dovecot currently does blocking lookups, so if 'ntlm_auth' is slow on +responding (e.g. network problems), Dovecot blocks all other authentication +requests until it's finished. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Mechanisms.txt b/doc/wiki/Authentication.Mechanisms.txt new file mode 100644 index 0000000..ed36580 --- /dev/null +++ b/doc/wiki/Authentication.Mechanisms.txt @@ -0,0 +1,82 @@ +Authentication Mechanisms +========================= + +Plaintext authentication +------------------------ + +The simplest authentication mechanism is PLAIN. The client simply sends the +password unencrypted to Dovecot. All clients support the PLAIN mechanism, but +obviously there's the problem that anyone listening on the network can steal +the password. For that reason (and some others) other mechanisms were +implemented. + +Today however many people use <SSL/TLS> [SSL.txt], and there's no problem with +sending unencrypted password inside SSL secured connections. So if you're using +SSL, you probably don't need to bother worrying about anything else than the +PLAIN mechanism. + +Another plaintext mechanism is LOGIN. It's typically used only by SMTP servers +to let Outlook clients perform SMTP authentication. Note that LOGIN mechanism +is not the same as IMAP's LOGIN command. The LOGIN command is internally +handled using PLAIN mechanism. + +Non-plaintext authentication +---------------------------- + +Non-plaintext mechanisms have been designed to be safe to use even without +<SSL/TLS> [SSL.txt] encryption. Because of how they have been designed, they +require access to the plaintext password or their own special hashed version of +it. This means that it's impossible to use non-plaintext mechanisms with +commonly used DES or MD5 password hashes. + +If you want to use more than one non-plaintext mechanism, the passwords must be +stored as plaintext so that Dovecot is able to generate the required special +hashes for all the different mechanisms. If you want to use only one +non-plaintext mechanism, you can store the passwords using the mechanism's own +<password scheme> [Authentication.PasswordSchemes.txt]. + +With <success/failure password databases> [PasswordDatabase.txt] (e.g. PAM) +it's not possible to use non-plaintext mechanisms at all, because they only +support verifying a known plaintext password. + +Dovecot supports the following non-plaintext mechanisms: + + * <CRAM-MD5.txt>: Protects the password in transit against eavesdroppers. + Somewhat good support in clients. + * <DIGEST-MD5> [Authentication.Mechanisms.DigestMD5.txt]: Somewhat stronger + cryptographically than CRAM-MD5, but clients rarely support it. + * SCRAM-SHA-1: Salted Challenge Response Authentication Mechanism (SCRAM) SASL + and GSS-API Mechanisms. Intended as DIGEST-MD5 replacement. + * APOP: This is a POP3-specific authentication. Similar to CRAM-MD5, but + requires storing password in plaintext. + * <NTLM> [Authentication.Mechanisms.NTLM.txt]: Mechanism created by Microsoft + and supported by their clients. + * Optionally supported <using Samba's winbind> + [Authentication.Mechanisms.Winbind.txt]. + * GSS-SPNEGO: A wrapper mechanism defined by RFC 4178 + [http://tools.ietf.org/html/rfc4178]. Can be accessed via either GSSAPI or + <Winbind> [Authentication.Mechanisms.Winbind.txt]. + * <GSSAPI> [Authentication.Kerberos.txt]: Kerberos v5 support. + * RPA: Compuserve RPA authentication mechanism. Similar to DIGEST-MD5, but + client support is rare. + * ANONYMOUS: Support for logging in anonymously. This may be useful if you're + intending to provide publicly accessible IMAP archive. + * OTP and SKEY: One time password mechanisms. + * EXTERNAL: EXTERNAL SASL mechanism. + * OAUTBEARER: OAuth2 bearer authentication + https://tools.ietf.org/html/rfc7628. See <OAuth2 password database> + [PasswordDatabase.oauth2.txt] (v2.2.29+) + * XOAUTH2: Google flavor OAUTHBEARER + [https://developers.google.com/gmail/xoauth2_protocol] (v2.2.29+) + +Configuration +------------- + +By default only PLAIN mechanism is enabled. To use more, edit your +'/etc/dovecot/conf.d/10-auth.conf' and set: + +---%<------------------------------------------------------------------------- +auth_mechanisms = plain login cram-md5 +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.MultipleDatabases.txt b/doc/wiki/Authentication.MultipleDatabases.txt new file mode 100644 index 0000000..8a98692 --- /dev/null +++ b/doc/wiki/Authentication.MultipleDatabases.txt @@ -0,0 +1,112 @@ +Multiple Authentication Databases +================================= + +Dovecot supports defining multiple authentication databases, so that if the +password doesn't match in the first database, it checks the next one. This can +be useful if you want to easily support having both local system users in +'/etc/passwd' and virtual users. + +Currently the fallback works only with the PLAIN authentication mechanism. + +Often you also want a different mail location for system and virtual users. The +best way to do this would be to always have mails stored below the home +directory ( <virtual users should have a home directory too> +[VirtualUsers.Home.txt]): + + * System users' mails: /home/user/Maildir + * Virtual users' mails: /var/vmail/domain/user/Maildir + +This can be done by simply having both system and virtual userdbs return home +directory properly (i.e. virtual users''home=/var/vmail/%d/%n') and then set +'mail_location = maildir:~/Maildir'. + +If it's not possible to have a home directory for virtual users (avoid that if +possible), you can do this by pointing <mail_location> [MailLocation.txt] to +system users' mail location and have the virtual userdb override it by +returning 'mail' <extra field> [UserDatabase.ExtraFields.txt]. + +Example with home dirs +---------------------- + + * System users' mails: /home/user/Maildir + * Virtual users' mails: /var/vmail/domain/user/Maildir + +dovecot.conf: + +---%<------------------------------------------------------------------------- +# Mail location for both system and virtual users: +mail_location = maildir:~/Maildir + +# try to authenticate using SQL database first +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +# fallback to PAM +passdb { + driver = pam +} + +# look up users from SQL first (even if authentication was done using PAM!) +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +# if not found, fallback to /etc/passwd +userdb { + driver = passwd +} +---%<------------------------------------------------------------------------- + +dovecot-sql.conf.ext: + +---%<------------------------------------------------------------------------- +password_query = SELECT userid as user, password FROM users WHERE userid = '%u' +user_query = SELECT uid, gid, '/var/vmail/%d/%n' as home FROM users WHERE +userid = '%u' +---%<------------------------------------------------------------------------- + +Example with overriding mail location +------------------------------------- + + * System users' mails: /home/user/Maildir + * Virtual users' mails: /var/vmail/domain/user + +dovecot.conf: + +---%<------------------------------------------------------------------------- +# the default mail location for system users, this will be overridden in userdb +sql. +mail_location = maildir:~/Maildir + +# try to authenticate using SQL database first +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +# fallback to PAM +passdb { + driver = pam +} + +# look up users from SQL first (even if authentication was done using PAM!) +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +# if not found, fallback to /etc/passwd +userdb { + driver = passwd +} +---%<------------------------------------------------------------------------- + +dovecot-sql.conf.ext: + +---%<------------------------------------------------------------------------- +password_query = SELECT userid as user, password FROM users WHERE userid = '%u' +# returning mail overrides mail_location setting for SQL users. +user_query = SELECT uid, gid, 'maildir:/var/vmail/%u' as mail FROM users WHERE +userid = '%u' +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.PasswordSchemes.txt b/doc/wiki/Authentication.PasswordSchemes.txt new file mode 100644 index 0000000..c8516ac --- /dev/null +++ b/doc/wiki/Authentication.PasswordSchemes.txt @@ -0,0 +1,248 @@ +Password Schemes +================ + +Password scheme means the format in which the password is stored in <password +databases> [PasswordDatabase.txt]. The main reason for choosing a scheme other +than *PLAIN* is to prevent someone with access to the password database (such +as a hacker) from stealing users' passwords and using them to access other +services. + +What scheme to use? +------------------- + +You should choose the strongest crypt scheme that's supported by your system. +From strongest to weakest: + + * *ARGON2I/ARGON2ID*: Argon2 [https://en.wikipedia.org/wiki/Argon2] is the + winner of password hashing competition held at July 2015. The password will + start with $argon2i$ or $argon2id$. You can use -r to tune computational + complexity, minimum is 3. ARGON2ID is only available if your libsodium is + recent enough. ARGON2 can require quite a hefty amount of virtual memory, so + we recommend that you set 'service auth { vsz_limit = 2G }' at least, or + more. + * *BLF-CRYPT*: This is the Blowfish crypt (bcrypt) scheme. It is generally + considered to be very secure. The encrypted password will start with '$2y$' + (other generators can generate passwords that have other letters after ' $2 + ', those should work too.) (Note v2.2: bcrypt is not available on most Linux + distributions). Since v2.3.0 this is provided by dovecot. You can tune the + computational cost using -r parameter for doveadm. + * *SHA512-CRYPT*: A strong scheme. The encrypted password will start with + '$6$' + * *SHA256-CRYPT*: A strong scheme. The encrypted password will start with + '$5$' + * *MD5-CRYPT*: A weak but common scheme often used in '/etc/shadow'. The + encrypted password will start with '$1$' + +Note that the above schemes are implemented by the libc's 'crypt()' function. +Using them is especially useful when sharing the same passwords with other +software, because most of them support using 'crypt()' to verify the password. +However, not all libcs (especially older ones) implement all of the above +schemes. See below for other password schemes that are implemented by Dovecot +internally (instead of libc). + +A few articles about why choosing a good password scheme is important: + + * How To Safely Store A Password + [http://codahale.com/how-to-safely-store-a-password/] + * Speed Hashing [http://www.codinghorror.com/blog/2012/04/speed-hashing.html] + +It's not possible to easily switch from one password scheme to another. The +only practical way to do this is to wait until user logs in and change the +password during the login. <This HOWTO> [HowTo.ConvertPasswordSchemes.txt] +shows one way to do this. + +Generating encrypted passwords +------------------------------ + +You can generate passwords for a particular scheme easily with "doveadm pw" +utility. For example: + +---%<------------------------------------------------------------------------- +doveadm pw +---%<------------------------------------------------------------------------- + +Since v2.3.0+ the scheme defaults to BCRYPT, but you can use -s to override + +---%<------------------------------------------------------------------------- +doveadm pw -s SHA512-CRYPT +---%<------------------------------------------------------------------------- + +To provide password, for scripting purposes, you can use either + +---%<------------------------------------------------------------------------- +doveadm pw -p password +---%<------------------------------------------------------------------------- + +or + +---%<------------------------------------------------------------------------- +printf 'password\npassword\n' | doveadm pw +---%<------------------------------------------------------------------------- + +Default password schemes +------------------------ + +Password databases have a default password scheme: + + * <SQL> [AuthDatabase.SQL.txt]: See 'default_pass_scheme' setting in + 'dovecot-sql.conf.ext' + * <LDAP> [AuthDatabase.LDAP.txt]: See 'default_pass_scheme' setting in + 'dovecot-ldap.conf.ext' + * <PasswdFile> [AuthDatabase.PasswdFile.txt]: CRYPT is used by default, but + can be changed with 'scheme' parameter in passdb args. + * <Passwd> [AuthDatabase.Passwd.txt], <Shadow> [PasswordDatabase.Shadow.txt], + <VPopMail> [AuthDatabase.VPopMail.txt]: CRYPT is used by default and can't + be changed currently. + * <PAM> [PasswordDatabase.PAM.txt], <BSDAuth> [PasswordDatabase.BSDAuth.txt], + <CheckPassword> [PasswordDatabase.CheckPassword.txt]: Dovecot never even + sees the password with these databases, so Dovecot has nothing to do with + what password scheme is used. + +The password scheme can be overridden for each password by prefixing it with +{SCHEME}, for example:'{PLAIN}pass'. + +Non-plaintext authentication mechanisms +--------------------------------------- + +See <Authentication.Mechanisms.txt> for explanation of auth mechanisms. Most +installations use only plaintext mechanisms, so you can skip this section +unless you know you want to use them. + +The problem with non-plaintext auth mechanisms is that the password must be +stored either in plaintext, or using a mechanism-specific scheme that's +incompatible with all other non-plaintext mechanisms. In addition, the +mechanism-specific schemes often offer very little protection. This isn't a +limitation of Dovecot, it's a requirement for the algorithms to even work. + +For example if you're going to use CRAM-MD5 authentication, the password needs +to be stored in either PLAIN or CRAM-MD5 scheme. If you want to allow both +CRAM-MD5 and DIGEST-MD5, the password must be stored in plaintext. + +In future it's possible that Dovecot could support multiple passwords in +different schemes for a single user. + + * *LANMAN*: DES-based encryption. Used sometimes with NTLM mechanism. + * *NTLM*: MD4 sum of the password stored in hex. Used with NTLM mechanism. + * *RPA*: Used with RPA mechanism. + * *CRAM-MD5*: Used with CRAM-MD5 mechanism. + * *DIGEST-MD5*: Used with <DIGEST-MD5 mechanism> + [Authentication.Mechanisms.DigestMD5.txt]. The username is included in the + hash, so it's not possible to use the hash for different usernames. + * *SCRAM-SHA-1*: Used with SCRAM-SHA-1 mechanism. (v2.2+) + +Other supported password schemes +-------------------------------- + +Strong schemes and mechanism-specific schemes are listed above. + + * *PLAIN*: Password is in plaintext. + * *CRYPT*: Traditional DES-crypted password in '/etc/passwd' (e.g. "pass" = + 'vpvKh.SaNbR6s') + * Dovecot uses libc's 'crypt()' function, which means that CRYPT is usually + able to recognize MD5-CRYPT and possibly also other password schemes. See + all of the *-CRYPT schemes at the top of this page. + * The traditional DES-crypt scheme only uses the first 8 characters of the + password, the rest are ignored. Other schemes may have other password + length limitations (if they limit the password length at all). + +MD5 based schemes: + + * *PLAIN-MD5*: MD5 sum of the password stored in hex. + * *LDAP-MD5*: MD5 sum of the password stored in base64. + * *SMD5*: Salted MD5 sum of the password stored in base64. + +SHA based schemes (also see below for libc's SHA* support): + + * *SHA*: SHA1 sum of the password stored in base64. + * *SSHA*: Salted SHA1 sum of the password stored in base64. + * *SHA256*: SHA256 sum of the password stored in base64. (v1.1 and later). + * *SSHA256*: Salted SHA256 sum of the password stored in base64. (v1.2 and + later). + * *SHA512*: SHA512 sum of the password stored in base64. (v2.0 and later). + * *SSHA512*: Salted SHA512 sum of the password stored in base64. (v2.0 and + later). + +Other schemes + + * *ARGON2I*: ARGON2i password scheme (v2.3.0+), needs libsodium + * *ARGON2ID*: ARGON2id password scheme (v2.3.0+), needs libsodium + * *PBKDF2*: PKCS5 Password hashing algortihm + +For some schemes (e.g. PLAIN-MD5, SHA) Dovecot is able to detect if the +password hash is base64 or hex encoded, so both can be used.'doveadm pw' anyway +generates the passwords using the encoding mentioned above. + +3rd party password schemes +-------------------------- + +These plugins are provided by community members, we do not provide support or +help with them, please contact the developer(s) directly. Use at your own +discretion. Since v2.3.0 ARGON2 is provided by dovecot itself. + + * *SCRYPT* and *ARGON2*: See + https://github.com/LuckyFellow/dovecot-libsodium-plugin/ + +Encoding +-------- + +The base64 vs. hex encoding that is mentioned above is simply the default +encoding that is used. You can override it for any scheme by adding a ".hex", +".b64" or ".base64" suffix. For example: + + * '{SSHA.b64}986H5cS9JcDYQeJd6wKaITMho4M9CrXM' contains the password encoded + to base64 (just like {SSHA}) + * '{SSHA.HEX}3f5ca6203f8cdaa44d9160575c1ee1d77abcf59ca5f852d1' contains the + password encoded to hex + +This can be especially useful with plaintext passwords to encode characters +that would otherwise be illegal. For example in passwd-file you couldn't use a +":" character in the password without encoding it to base64 or hex. For +example:'{PLAIN}{\}:!"' is the same as '{PLAIN.b64}e1x9OiEiCg=='. + +You can also specify the encoding with doveadm pw. For example: 'doveadm pw -s +plain.b64' + +Salting +------- + +For the SHA512-CRYPT, SHA256-CRYPT and MD5-CRYPT schemes, the salt is stored +before the hash, e.g.:'$6$salt$hash'. For the BLF-CRYPT scheme, bcrypt stores +the salt as part of the hash. + +For most of the other salted password schemes (SMD5, SSHA*) the salt is stored +after the password hash and its length can vary. When hashing the password, +append the salt after the plaintext password, e.g.: SSHA256(pass, salt) = +SHA256(pass + salt) + salt. + +For example with SSHA256 you know that the hash itself is 32 bytes (256 bits/8 +bits per byte). Everything after that 32 bytes is the salt. For example if you +have a password: + +---%<------------------------------------------------------------------------- +{SSHA256}SoR/78T5q0UPFng8UCXWQxOUKhzrJZlwfNtllAupAeUT+kQv +---%<------------------------------------------------------------------------- + +After base64 decoding it you'll see that its length is 36 bytes, so the first +32 bytes are the hash and the following 4 bytes are the salt: + + * length: 'echo SoR/78T5q0UPFng8UCXWQxOUKhzrJZlwfNtllAupAeUT+kQv|base64 -d|wc + -c' -> 36 + * hash: 'echo SoR/78T5q0UPFng8UCXWQxOUKhzrJZlwfNtllAupAeUT+kQv|base64 -d|dd + bs=1 count=32|hexdump -C' -> 4a 84 7f ef c4 f9 ab 45 0f 16 78 3c 50 25 d6 + 43 13 94 2a 1c eb 25 99 70 7c db 65 94 0b a9 01 e5 + * salt: 'echo SoR/78T5q0UPFng8UCXWQxOUKhzrJZlwfNtllAupAeUT+kQv|base64 -d|dd + bs=1 skip=32|hexdump -C' -> 13 fa 44 2f + +Other common hash sizes are: + + * MD5: 16 bytes + * SHA: 20 bytes + * SHA256: 32 bytes + * SHA512: 64 bytes + +The web management gui VBoxAdm [http://developer.gauner.org/vboxadm/] has some +code dealing with creation and verification of salted hashes in Perl. However +not all password schemes provided by dovecotpw are supported. Have a look at +the module VBoxAdm::DovecotPW for more details. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Penalty.txt b/doc/wiki/Authentication.Penalty.txt new file mode 100644 index 0000000..dcbb3ea --- /dev/null +++ b/doc/wiki/Authentication.Penalty.txt @@ -0,0 +1,45 @@ +Authentication Penalty +====================== + +Dovecot anvil process tracks authentication penalties for different IPs to slow +down brute force login attempts. The algorithm works by: + + * First auth failure reply will be delayed for 2 seconds (this happens even + without auth penalty) + * 'AUTH_PENALTY_INIT_SECS' in 'src/auth/auth-penalty.h' + * The delay will be doubled for 4 -> 8 seconds, and then the upper limit of 15 + seconds is reached. + * 'AUTH_PENALTY_MAX_SECS' and AUTH_PENALTY_MAX_PENALTY in + 'src/auth/auth-penalty.h' + * If the IP is in login_trusted_networks (e.g. webmail), skip any + authentication penalties + * If the username+password combination is the same as one of the last 10 login + attempts, skip increasing authentication penalty. + * 'CHECKSUM_VALUE_PTR_COUNT' in 'src/anvil/penalty.c' + * The idea is that if a user has simply configured the password wrong, it + shouldn't keep increasing the delay. + * The username+password is tracked as the CRC32 of them, so there is a + small possibility of hash collisions + +Problems: + + * It is still possible to do multiple auth lookups from the same IP in + parallel. + * For IPv6 it currently blocks the entire /48 block, which may or may not be + what is wanted. + * PENALTY_IPV6_MASK_BITS in auth-penalty.c + +Authentication penalty tracking can be disabled completely with: + +---%<------------------------------------------------------------------------- +service anvil { + unix_listener anvil-auth-penalty { + mode = 0 + } +} +---%<------------------------------------------------------------------------- + +Also you can have similar functionality with fail2ban +[http://wiki2.dovecot.org/HowTo/Fail2Ban]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.Policy.txt b/doc/wiki/Authentication.Policy.txt new file mode 100644 index 0000000..b902e48 --- /dev/null +++ b/doc/wiki/Authentication.Policy.txt @@ -0,0 +1,240 @@ +Authentication policy support +============================= + +Dovecot supports (v2.2.25+) external authentication policy server. This server +can be used to decide whether the connecting user is permitted, tarpitted or +outright rejected. While dovecot can do tarpitting and refusal on its own, this +adds support for making cluster-wide decisions to make it easier to deter and +defeat bruteforce attacks. + +Known issues +------------ + +Prior v2.2.27 request policy was mostly broken. + +Prior v2.2.34, the request attributes contained *orig_username* which was not +correct in all cases, especially with master login. + +Prior v2.3.5.2 / 2.2.36.3, invalid UTF-8 would crash auth server if auth policy +is used. + +Configuration +------------- + +The auth-policy server is a core feature and does not require plugin(s) to +work. To activate this feature, you need to configure it. + + * *auth_policy_server_url*: URL of the policy server, url is appended with + ?command=allow/report unless it ends with '&', at which just + command=allow/report is added. + * /Default/: None (*REQUIRED* configuration) + * Example: 'auth_policy_server_url = http://example.com:4001/' + * *auth_policy_server_api_header*: Header and value to add to request (for API + authentication) + * /Default/: None (No authentication is done) + * See https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side + + * Example: 'Authorization: Basic <base64-encoded value>' + * *auth_policy_server_timeout_msecs*: Request timeout in milliseconds + * /Default/: 'auth_policy_server_timeout_msecs = 2000' + * *auth_policy_hash_mech*: Hash mechanism to use for password, you can use any + hash mechanism supported by Dovecot (md4,md5,sha1,sha256,sha512) + * /Default/: 'auth_policy_hash_mech = sha256' + * *auth_policy_hash_nonce*: Cluster-wide nonce to add to hash + * /Default/: None (*REQUIRED* configuration) + * Example: 'auth_policy_hash_nonce = localized_random_string' + * *auth_policy_request_attributes*: Request attributes specification (see + attributes section below) + * /Default/: 'auth_policy_request_attributes = login=%{requested_username} + pwhash=%{hashed_password} remote=%{rip} device_id=%{client_id} + protocol=%s' + * *auth_policy_reject_on_fail*: If policy request fails for some reason should + users be rejected + * /Default/: 'auth_policy_reject_on_fail = no' + * *auth_policy_hash_truncate*: How many *bits* to use from password hash. + * /Default/: 'auth_policy_hash_truncate = 12' + * *auth_policy_check_before_auth*: Whether to do policy lookup before + authentication is started + * /Default/: 'auth_policy_check_before_auth = yes' + * *auth_policy_check_after_auth*: Whether to do policy lookup after + authentication is completed + * /Default/: 'auth_policy_check_after_auth = yes' + * *auth_policy_report_after_auth*: Whether to report authentication result + * /Default/: 'auth_policy_report_after_auth = yes' + +Required Minimum Configuration +------------------------------ + +---%<------------------------------------------------------------------------- +auth_policy_server_url = http://example.com:4001/ +auth_policy_hash_nonce = localized_random_string +#auth_policy_server_api_header = Authorization: Basic <base64-encoded value> +#auth_policy_server_timeout_msecs = 2000 +#auth_policy_hash_mech = sha256 +#auth_policy_request_attributes = login=%{requested_username} +pwhash=%{hashed_password} remote=%{rip} device_id=%{client_id} protocol=%s +#auth_policy_reject_on_fail = no +#auth_policy_hash_truncate = 12 +#auth_policy_check_before_auth = yes +#auth_policy_check_after_auth = yes +#auth_policy_report_after_auth = yes +---%<------------------------------------------------------------------------- + +Password hash algorithm +----------------------- + +To generate the hash, you concatenate nonce, login name, nil byte, password and +run it through the hash algorithm once. The hash is truncated when truncation +is set to non-zero. The hash is truncated by first choosing bits from MSB to +byte boundary (rounding up), then right-shifting the remainding bits. + +---%<------------------------------------------------------------------------- +hash = H(nonce||user||'\x00'||password) +bytes = round8(bits*8) +hash = HEX(hash[0:bytes] >> (bytes-bits*8)) +---%<------------------------------------------------------------------------- + +Request attributes +------------------ + +Auth policy server requests are JSON requests. The JSON format can be specified +with auth_policy_request_attributes. The syntax is key=value pairs, and key can +contain one or more / to designate that a JSON object should be made. For +example: + +---%<------------------------------------------------------------------------- +login=%{orig_username} pwhash=%{hashed_password} remote=%{real_rip} +---%<------------------------------------------------------------------------- + +produces + +---%<------------------------------------------------------------------------- +{"login":"john.doe","pwhash":"1234","remote":"127.0.0.1"} +---%<------------------------------------------------------------------------- + +And + +---%<------------------------------------------------------------------------- +login=%{orig_username} pwhash=%{hashed_password} remote=%{real_rip} +attrs/cos=%{userdb:cos} +---%<------------------------------------------------------------------------- + +produces + +---%<------------------------------------------------------------------------- +{"login":"john.doe","pwhash":"1234","remote":"127.0.0.1", +"attrs":{"cos":"premium"}} +---%<------------------------------------------------------------------------- + +Since v2.2.29/v2.3 you can include IMAP ID command result in auth policy +requests, this is achieved with using %{client_id}, which will expand to IMAP +ID command arglist. You must set + +---%<------------------------------------------------------------------------- +imap_id_retain=yes +---%<------------------------------------------------------------------------- + +for this to work. + +Default values for auth_policy_request_attributes +------------------------------------------------- + +Since v2.2.25 + +---%<------------------------------------------------------------------------- +login=%{orig_username} pwhash=%{hashed_password} remote=%{real_rip} +---%<------------------------------------------------------------------------- + +Since v2.2.30 + +---%<------------------------------------------------------------------------- +login=%{orig_username} pwhash=%{hashed_password} remote=%{real_rip} +device_id=%{client_id} protocol=%s +---%<------------------------------------------------------------------------- + +Since v2.2.34 + +---%<------------------------------------------------------------------------- +login=%{requested_username} pwhash=%{hashed_password} remote=%{rip} +device_id=%{client_id} protocol=%s +---%<------------------------------------------------------------------------- + +Since v2.3.0 (note that 2.2 and 2.3 branches have been developed in parallel +for a while) + +---%<------------------------------------------------------------------------- +login=%{orig_username} pwhash=%{hashed_password} remote=%{real_rip} +device_id=%{client_id} protocol=%s +---%<------------------------------------------------------------------------- + +Since v2.3.1 + +---%<------------------------------------------------------------------------- +login=%{requested_username} pwhash=%{hashed_password} remote=%{rip} +device_id=%{client_id} protocol=%s +---%<------------------------------------------------------------------------- + +Since v2.3.2 the request contains 'tls' attribute when TLS has been used. TLS +is also detected if it's offloaded by a load balancer that can provide this +information using HAProxy v2 protocol to dovecot. + +Response +-------- + +---%<------------------------------------------------------------------------- +{"status":-1,"msg":"go away"} +---%<------------------------------------------------------------------------- + +'status' values: see below + +Mode of operation +----------------- + +Auth policy check: Authentication ''before'' userdb/passdb +---------------------------------------------------------- + +First query is done *before* password and user databases are consulted. This +means that any userdb/passdb attributes are left empty. + +The command used here is 'allow' and will appear on the URL as command=allow. + +'status' result values: + + * *-1*: Reject + * *0*: Accept + * *(Any other positive value)*: Tarpit for this number of seconds. + +Auth policy check: Authentication ''after'' successful userdb/passdb lookup +--------------------------------------------------------------------------- + +Second lookup is done *after* authentication succeeds. + +The command used here is 'allow' and will appear on the URL as command=allow. + +'status' result values: + + * *-1*: Authentication fail + * *>= 0*: Authentication succeed + +Auth policy check: Reporting after authentication succeeds +---------------------------------------------------------- + +A report request is sent at end of authentication. + +The command used here is 'report' and will appear on the URL as command=report. + +The JSON request is sent with two additional attributes: + + * *success*: boolean true/false depending on whether the overall + authentication succeeded + * *policy_reject*: boolean true/false whether the failure was due to policy + server + +'status' result value is ignored. + +External Auth Policy Servers +---------------------------- + + * http://oxpedia.org/wiki/index.php?title=AppSuite:Dovecot_Antiabuse_Shield + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.RestrictAccess.txt b/doc/wiki/Authentication.RestrictAccess.txt new file mode 100644 index 0000000..b24be44 --- /dev/null +++ b/doc/wiki/Authentication.RestrictAccess.txt @@ -0,0 +1,85 @@ +Restricting Access +================== + +Restricting IMAP/POP3 access +---------------------------- + +Below examples show how you can give POP3 access to everyone, but IMAP access +only for some people. The exact solution you want depends on what passdb you +use. The solutions can also be modified for other types of IMAP/POP3/SMTP/etc. +access checks. + +PAM +--- + +Set PAM service name to '%s', ie.: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = %s +} +---%<------------------------------------------------------------------------- + +That way PAM uses '/etc/pam.d/imap' for IMAP, and '/etc/pam.d/pop3' for POP3. + +In '/etc/pam.d/imap' you could then use eg. the pam_listfile.so module: + +---%<------------------------------------------------------------------------- +# allow IMAP access only for users in /etc/imapusers file +auth required pam_listfile.so item=user sense=allow +file=/etc/imapusers onerr=fail +---%<------------------------------------------------------------------------- + +SQL +--- + +You can use the '%s' variable which expands to 'imap' or 'pop3' in +'password_query', eg: + +---%<------------------------------------------------------------------------- +password_query = SELECT password FROM users WHERE userid = '%u' and not +(imap_allowed = false and '%s' = 'imap') +---%<------------------------------------------------------------------------- + +LDAP +---- + +Just like with SQL, you can use '%s' in pass_filter, eg.: + +---%<------------------------------------------------------------------------- +pass_filter = (&(objectClass=posixAccount)(uid=%u)(service=%s)) +---%<------------------------------------------------------------------------- + +That would require setting both service=pop3 and service=imap attributes to the +user objects. + +passwd-file +----------- + +You can create a deny passwd-file based on the service: + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = /etc/dovecot/deny.%s + deny = yes +} +---%<------------------------------------------------------------------------- + +This makes Dovecot look for '/etc/dovecot/deny.imap' and +'/etc/dovecot/deny.pop3' files. If the user exists in it, the access is denied. +The files don't need to have anything else than one username per line. + +Note that this deny passdb must be before other passdbs. It also means that it +can be used with any other passdb, not just with passwd-file passdbs. + +Restricting IP Access +--------------------- + +It's possible to allow a user to authenticate only from a specific IP or +network. This is especially useful for master users. This can be done by +returning <allow_nets> [PasswordDatabase.ExtraFields.AllowNets.txt] extra field +in passdb. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Authentication.txt b/doc/wiki/Authentication.txt new file mode 100644 index 0000000..d72c5d7 --- /dev/null +++ b/doc/wiki/Authentication.txt @@ -0,0 +1,37 @@ +Authentication +============== + +Authentication is split into four parts: + + 1. <Authentication mechanisms> [Authentication.Mechanisms.txt] + 2. <Password schemes> [Authentication.PasswordSchemes.txt] + 3. <Password databases> [PasswordDatabase.txt] + 4. <User databases> [UserDatabase.txt] + +See also <authentication penalty> [Authentication.Penalty.txt] handling for IP +addresses. See also <authentication policy support> [Authentication.Policy.txt] +for making policy based decisions. + +Authentication mechanisms vs. password schemes +---------------------------------------------- + +Authentication mechanisms and password schemes are often confused, because they +have somewhat similar values. For example there is a PLAIN auth mechanism and +PLAIN password scheme. But they mean completely different things. + + * *Authentication mechanism is a client/server protocol*. It's about how the + client and server talk to each others in order to perform the + authentication. Most people use only PLAIN authentication, which basically + means that the user and password are sent without any kind of encryption to + the server. SSL/TLS can then be used to provide the encryption to make PLAIN + authentication secure. + * *Password scheme is about how the password is hashed in your password + database*. If you use a PLAIN scheme, your passwords are stored in cleartext + without any hashing in the password database. A popular password scheme + MD5-CRYPT (also commonly used in '/etc/shadow') where passwords looks like + "$1$oDMXOrCA$plmv4yuMdGhL9xekM.q.I/". + * Plaintext authentication mechanisms work with ALL password schemes. + * Non-plaintext authentication mechanisms require either PLAIN password scheme + or a mechanism-specific password scheme. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/BasicConfiguration.txt b/doc/wiki/BasicConfiguration.txt new file mode 100644 index 0000000..a03590b --- /dev/null +++ b/doc/wiki/BasicConfiguration.txt @@ -0,0 +1,157 @@ +Basic Configuration +=================== + +This page tells you the basics that you'll need to get a working Dovecot +installation. + +Find Dovecot configuration file location using: + +---%<------------------------------------------------------------------------- +doveconf -n | head -n1 +---%<------------------------------------------------------------------------- + +Your configuration file doesn't exist if you installed Dovecot from sources. +The config directory should contain a 'README' file pointing to an example +configuration, which you can use as your basic configuration. For example: + +---%<------------------------------------------------------------------------- +cp -r /usr/share/doc/dovecot/example-config/* /etc/dovecot/ +---%<------------------------------------------------------------------------- + +The default configuration starts from 'dovecot.conf', which contains an +'!include conf.d/*.conf' statement to read the rest of the configuration. This +split of configuration files isn't a requirement to use, and it doesn't really +matter which .conf file you add any particular setting, just as long as it +isn't overridden in another file. You can verify with 'doveconf -n' that +everything looks as you intended. + +Authentication +-------------- + +By default Dovecot is set up to use system user authentication. If you're +planning on using system users, you can simply skip this section and read <PAM> +[PasswordDatabase.PAM.txt] (or <bsdauth> [PasswordDatabase.BSDAuth.txt]) for +configuring it. + +If you're planning on using virtual users, it's easier to first create a simple +passwd-like file to make sure that the authentication will work. Later when you +know Dovecot is working, you can do it differently (see <VirtualUsers.txt>). + +Run as your own non-root user: + +---%<------------------------------------------------------------------------- +echo "$USER:{PLAIN}password:$UID:$GID::$HOME" > users +sudo mv users /etc/dovecot/ + +# If SELinux is enabled: +restorecon -v /etc/dovecot/users +---%<------------------------------------------------------------------------- + +You can (and should) replace the "password" with whatever password you wish to +use, but don't use any important password here as we'll be logging in with +insecure plaintext authentication until <SSL.txt> is configured. + +(Remark: $GID is not set per default on <OpenSuse.txt> systems, replace by 'id +-g') + +If you used the example configuration files, switch to passwd-file by modifying +'conf.d/10-auth.conf': + +---%<------------------------------------------------------------------------- +# Add '#' to comment out the system user login for now: + +# Remove '#' to use passwd-file: +!include auth-passwdfile.conf.ext +---%<------------------------------------------------------------------------- + +In 'conf.d/auth-passwdfile.conf.ext' you should have: + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = scheme=CRYPT username_format=%u /etc/dovecot/users +} +userdb { + driver = passwd-file + args = username_format=%u /etc/dovecot/users +} +---%<------------------------------------------------------------------------- + +Verify with 'doveconf -n passdb userdb' that the output looks like above (and +there are no other passdbs or userdbs). + +Plaintext Authentication +------------------------ + +To allow any Authentication without SSL, disable SSL in the +'conf.d/10-ssl.conf' file. This has to be done because Dovecot (now) uses SSL +as default. You probably want to switch this back to "yes" or other options +afterward. + +---%<------------------------------------------------------------------------- +ssl = no +---%<------------------------------------------------------------------------- + +Until SSL is configured, allow plaintext authentication in the +'conf.d/10-auth.conf' file. You probably want to switch this back to "yes" +afterward. + +---%<------------------------------------------------------------------------- +disable_plaintext_auth = no +---%<------------------------------------------------------------------------- + +If you didn't use the temporary passwd-file created above, don't do this if you +don't want your password to be sent in clear to network. Instead get SSL +configuration working and connect to Dovecot only using SSL. + +Mail Location +------------- + +Set the 'mail_location' in 'conf.d/10-mail.conf' as determined by the +instructions in <FindMailLocation.txt>. + +mbox +---- + +If you're using mboxes, it's important to have locking configuration correct. +See <MboxLocking.txt> for more information. + +If you're using '/var/mail/' or '/var/spool/mail/' directory for INBOXes, you +may need to give Dovecot additional permissions so it can create dotlock files +there. A failure to do so will result in errors like these: + +---%<------------------------------------------------------------------------- +open(/var/mail/.temp.host.1234.abcdefg) failed: Permission denied +file_lock_dotlock() failed with mbox file /var/mail/user: Permission denied +---%<------------------------------------------------------------------------- + +From here on I'm assuming the INBOX directory is '/var/mail'. + +First check what the permissions of '/var/mail' are: + +---%<------------------------------------------------------------------------- +# ls -ld /var/mail +drwxrwxrwt 2 root mail 47 2006-01-07 20:44 /var/mail/ +---%<------------------------------------------------------------------------- + +In this case everyone has write access there and the directory is marked +sticky. This allows Dovecot to create the dotlock files, so you don't need to +do anything. + +---%<------------------------------------------------------------------------- +# ls -ld /var/mail +drwxrwxr-- 2 root mail 47 2006-01-07 20:44 /var/mail/ +---%<------------------------------------------------------------------------- + +In this case only the root and the 'mail' group has write permission to the +directory. You'll need to give Dovecot's mail processes ability to use this +group by changing 'conf.d/10-mail.conf': + +---%<------------------------------------------------------------------------- +mail_privileged_group = mail +---%<------------------------------------------------------------------------- + +Note: Specifying the privileged user must be done as shown. Simply adding +'dovecot' user to the 'mail' group does /*not*/ grant write permission. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Chrooting.txt b/doc/wiki/Chrooting.txt new file mode 100644 index 0000000..8284dc3 --- /dev/null +++ b/doc/wiki/Chrooting.txt @@ -0,0 +1,65 @@ +Chrooting +========= + +Traditionally chrooting has been done to run the whole server within a single +chroot. This is also possible with Dovecot, but it requires manually setting up +the chroot and it can be a bit tricky. Dovecot however supports internally +running different parts of it in different chroots: + + * Login processes (imap-login, pop3-login) are chrooted by default into an + empty non-writable directory. + * Authentication process (dovecot-auth) can be chrooted by setting + 'chroot=<path>' inside 'service auth' and/or 'service auth-worker' sections. + This could be a good idea to change if you're not using a passdb or userdb + that needs to access files outside of the chroot. Also make sure not to run + the auth process as root then. + * Mail processes (imap, pop3) can be made to chroot in different ways. See + below. + +Security problems +----------------- + +If chrooting is used incorrectly, it allows local users to gain root +privileges. This is possible by hardlinking setuid binaries inside the chroot +jail and tricking them. There are at least two possibilities: + + 1. Hardlink '/bin/su' inside the chroot and create your own + '<chroot>/etc/passwd'. Then simply run 'su root'. + 2. Create your own '<chroot>/lib/libc.so' and run any setuid binary. + +Of course both of these require that the setuid binary can be run inside the +chroot. This isn't possible by default. Either user would have to find a +security hole from Dovecot, or the administrator would have had to set up +something special that allows running binaries. + +In any case it's a good idea not to allow users to hardlink setuid binaries +inside the chroots. The safest way to do this is to mount the filesystem with +"nosuid" option. + +Mail process chrooting +---------------------- + +Due to the potential security problem described above, Dovecot won't chroot +mail processes to directories which aren't listed in 'valid_chroot_dirs' +setting. For example if your users may be chrooting under '/var/mail/<user>/' +and '/home/<user>/', use: + +---%<------------------------------------------------------------------------- +valid_chroot_dirs = /var/mail:/home +---%<------------------------------------------------------------------------- + +You can chroot all users globally into the same directory by using +'mail_chroot' setting. For example: + +---%<------------------------------------------------------------------------- +mail_chroot = /home +---%<------------------------------------------------------------------------- + +You can also make userdb return a chroot. There are two ways to do that: + + 1. Make userdb return 'chroot=<path>' field. + 2. Insert "/./" inside the returned home directory, eg.: 'home=/home/./user' + to chroot into '/home', or 'home=/home/user/./' to chroot into + '/home/user'. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Clients.NegativeUIDs.txt b/doc/wiki/Clients.NegativeUIDs.txt new file mode 100644 index 0000000..28fc164 --- /dev/null +++ b/doc/wiki/Clients.NegativeUIDs.txt @@ -0,0 +1,53 @@ +Negative UIDs +============= + +---%<------------------------------------------------------------------------- +Invalid messageset: 1181461470:-1181461446. +---%<------------------------------------------------------------------------- + +IMAP uses unsigned 32bit integers for unique message identifiers. Unfortunately +a lot of IMAP clients use 32bit signed integers, which means that if the UIDs +go higher than 2147483647, they'll wrap to negative integers. This causes +errors such as above. + +However normally the UIDs should never go that high, so it's possible to avoid +this problem. + +mbox +---- + +Earlier Dovecot versions had bugs which could cause X-UID: headers in incoming +messages to grow the UIDs too high. Some spam messages especially contained +these intentionally broken X-UID: headers. + +With newer Dovecot versions these broken X-UID: headers aren't practically ever +used. It happens only if the mail has a valid X-IMAPbase: header, X-UID: header +and the mail is written to an empty mbox file. Note that this can happen only +new mboxes, because expunging all messages in a mailbox causes Dovecot to +create a metadata message at the beginning of the mbox file. + +In any case it's still a good idea to filter out X-UID: and other metadata +headers in your MDA. <Dovecot's deliver> [LDA.txt] does this internally. See +<MboxProblems.txt> for a list of headers to filter out. + +Fixing +------ + +Fixing is done by letting Dovecot update UIDVALIDITY value and recreate the +UIDs beginning from one. This means that client's local cache will be +invalidated and the client will be required to download all the messages again. + +mbox +---- + +Delete Dovecot's index files (eg. '.imap/INBOX/') and X-IMAP: and X-IMAPbase: +headers from the mbox file. + +Maildir +------- + +This should really never be a problem with Maildir. If however you have managed +to cause it somehow (by receiving 2 billion mails?), you can recreate the UIDs +by deleting 'dovecot-uidlist' file. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Clients.txt b/doc/wiki/Clients.txt new file mode 100644 index 0000000..f79d377 --- /dev/null +++ b/doc/wiki/Clients.txt @@ -0,0 +1,186 @@ +Client issues and configuration +=============================== + +It seems to be quite difficult to implement a working IMAP client. Best +Practices for Implementing an IMAP Client +[http://www.imapwiki.org/ClientImplementation] tries to help you with it. + +Contents + + + 1. Client issues and configuration + + 1. Apple Mail.app + + 2. Outlook + + 3. Outlook Express 6 + + 4. Netscape Mail + + 5. Evolution + + 6. Mulberry + + 7. Claws-mail + + 8. Thunderbird + + 9. Mutt + + 10. Pine + + 11. SquirrelMail + + 12. Horde IMP + + 13. RoundCube Webmail + + 14. @Mail Webmail + + 15. RainLoop Webmail + +Apple Mail.app +-------------- + +On Mac OS X Leopard 10.5 Mail.app appears to support subscribe/unsubscribe by +right clicking on a mailbox, selecting 'Get Account Info' and selecting +'Subscription List' from tabs. This however doesn't really work with any IMAP +server. + +Apple Mail 3.6 (that comes with OS X 10.5 Leopard) supports +subscribing/unsubscribing to folders in the public namespace. + +Outlook +------- + + * You should enable 'outlook-no-nuls' workaround with POP3. + * Outlook 2003 has problems with older Dovecot's default POP3 UIDL format, + which causes it to download the same mails over and over again if "leave + mails to server" option is enabled. See 'pop3_uidl_format' setting. + * Outlook might not hide or purge deleted items by default. Microsoft has a + how-to that shows how to fix this + [http://office.microsoft.com/en-us/outlook/HP100804201033.aspx] (Outlook + 2007, not Outlook 2003). + * If some Outlook users don't see new or sent mails in the appropriate folders + after a migration from UW IMAPd even if they are visible in other clients + (e.g. Roundcube, Thunderbird, or on the disk itself), and you get the error + message "BAD Error in IMAP command UID: Invalid UID messageset" in the log + or rawlog: It helps to remove the problematic IMAP account completely from + Outlook and recreating it again there. It speaks a different IMAP + afterwards, so there are reasons to believe it caches the details of some + server on the first connect and doesn't refresh them even if you change the + server's hostname in the account settings. + +Outlook Express 6 +----------------- + + * Using "Headers only" synchronization is buggy and can cause "Message is no + longer available on this server" error when opening a mail. This isn't + Dovecot specific problem, and I'm not aware of any possible workarounds at + the moment for this in server side. + * You should enable 'delay-newmail' workarounds for IMAP. + * You should enable 'outlook-no-nuls' and 'oe-ns-eoh' workarounds for POP3. + +Netscape Mail +------------- + +I'm not actually sure what version exactly this refers to. + + * You should enable 'oe-ns-eoh' workaround for POP3. + +Evolution +--------- + + * Some versions don't support creating subfolders with mbox format. Evolution + in Ubuntu Gutsy, 2.12.0-0ubuntu5, does support creating subfolders, at least + when the parent folder is empty. + +Mulberry +-------- + +Seems to be OK. + +Claws-mail +---------- + +Everything works perfectly with Dovecot. + +Thunderbird +----------- + + * If you're using <mbox> [MailboxFormat.mbox.txt], <dbox> + [MailboxFormat.dbox.txt] or <Maildir> [MailLocation.Maildir.txt] with + ':LAYOUT=fs' , + * You should enable 'tb-extra-mailbox-sep' workaround for IMAP. Bug report + [https://bugzilla.mozilla.org/show_bug.cgi?id=29926]. + * If you're using <mbox> [MailboxFormat.mbox.txt]: + * If you are not using a technique to allow folders that contain both + sub-folders and messages (e.g. see <MboxChildFolders.txt>) then you will + have to disable "Server supports folders that contain sub-folders and + messages" setting from Thunderbird.Enhancement request + [https://bugzilla.mozilla.org/show_bug.cgi?id=284933]. + * Versions of Thunderbird from at least 17 (possibly earlier) up to 24.0 + display incorrect new mail counts in the New Mail notification box. This is + due to a bug in Thunderbird's handling of the CONDSTORE extension. See Bug + Report [https://bugzilla.mozilla.org/show_bug.cgi?id=885220] for details and + a client-side workaround. + +Mutt +---- + + * New mutt versions supporting IDLE command will hang with Dovecot versions + earlier than v1.0beta3. Upgrade Dovecot or disable IDLE by setting + imap_idle=no in .muttrc. + * <Using mutt with IMAP> [mutt.txt] + +Pine +---- + +Seems to be OK. + +SquirrelMail +------------ + + * Configuration asks IMAP server name for some workarounds. There has been a + Dovecot option since 1.4.6 and 1.5.1. For olderSquirrelMail versions, select + the "other" option and remove the default INBOX-prefix. + +Horde IMP +--------- + +Dovecot namespace detection works automatically with any recent version of IMP +(4.1+). + +Quota support is now integrated into the 'imap' driver (as of horde-groupware +V1.2), an example config of /imp/config/servers.php is: + +---%<------------------------------------------------------------------------- +$servers['imap'] = array( + 'name' => 'IMAP Server', + 'server' => 'localhost', + 'hordeauth' => false, + 'protocol' => 'imap/notls', + 'port' => 143, + 'quota' => array('driver'=>'imap'), +); +---%<------------------------------------------------------------------------- + +RoundCube Webmail +----------------- + +Works fine. + +@Mail Webmail +------------- + +Uses the namespace returned via Dovecot, full support via IMAP/POP3 using @Mail +[http://atmail.com/]. Can also read mailbox quota via the getquotaroot IMAP +command. + +RainLoop Webmail +---------------- + +Works fine. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/CompilingSource.txt b/doc/wiki/CompilingSource.txt new file mode 100644 index 0000000..49555a3 --- /dev/null +++ b/doc/wiki/CompilingSource.txt @@ -0,0 +1,369 @@ +Contents + + + 1. Compiling Dovecot From Sources + + 2. Compiling Dovecot From Git + + 3. Compiling Dovecot with rpmbuild (Mandriva, RedHat, etc.) + + 4. SSL/TLS Support + + 1. Solaris and OpenSSL problems + + 5. Notify method + + 1. Linux + + 6. Optional Configure Options + + 1. SQL Driver Options + + 2. Authentication Backend Options + + 7. Dynamic IMAP and POP3 Modules + +Compiling Dovecot From Sources +============================== + +For most people it is enough to do: + +---%<------------------------------------------------------------------------- +./configure +make +sudo make install +---%<------------------------------------------------------------------------- + +That installs Dovecot under the '/usr/local' directory. The configuration file +is in '/usr/local/etc/dovecot.conf'. Logging goes to syslog's mail facility by +default, which typically goes to '/var/log/mail.log' or something similar. If +you are in a hurry, you can then jump to <QuickConfiguration.txt>. + + If you have installed some libraries into locations which require special +include or library paths, you can pass them in the 'CPPFLAGS' and 'LDFLAGS' +environment variables. For example: + +---%<------------------------------------------------------------------------- +CPPFLAGS="-I/opt/openssl/include" LDFLAGS="-L/opt/openssl/lib" ./configure +---%<------------------------------------------------------------------------- + +You'll need to create two users for Dovecot's internal use: + + * *dovenull*: Used by untrusted imap-login and pop3-login processes + (default_login_user setting). + * *dovecot*: Used by slightly more trusted Dovecot processes + (default_internal_user setting). + +Both of them should also have their own *dovenull* and *dovecot* groups. See +<UserIds.txt> for more information. + +Compiling Dovecot From Git +========================== + +If you got Dovecot from Git, for instance with + +---%<------------------------------------------------------------------------- +git clone https://github.com/dovecot/core.git dovecot +---%<------------------------------------------------------------------------- + +you will first need to run './autogen.sh' to generate the 'configure' script +and some other files. This requires that you have the following +software/packages installed: + + * 'autoconf' + * 'automake' + * 'libtool' + * 'pkg-config' + * 'gettext' + * 'pandoc' (not strictly required - you can avoid it by using: 'PANDOC=false + ./configure') + * GNU make. + +It is advisable to add '--enable-maintainer-mode' to the 'configure' script. +Thus: + +---%<------------------------------------------------------------------------- +./autogen.sh +./configure --enable-maintainer-mode +make +sudo make install +---%<------------------------------------------------------------------------- + +For later updates, you can use: + +---%<------------------------------------------------------------------------- +git pull +make +sudo make install +---%<------------------------------------------------------------------------- + +Compiling Dovecot with rpmbuild (Mandriva, RedHat, etc.) +======================================================== + +Fetch the source rpm from ftp://ftp.surfnet.nl/ +[ftp://ftp.surfnet.nl/vol/5/mandrakelinux/official/2007.0/SRPMS/contrib/release/] +or any other mirror. At the moment of this writing dovecot-10.rc26.src.rpm can +be found in the cooker subtree. If the current release is newer; updating the +source rpm is not difficult. Unpack the source rpm with 'rpm -ivh +dovecot-10.rc26.src.rpm' to a build environment (/usr/src/rpm...) Copy the +newer tarball from the dovecot site to the SOURCES directory of the build +environment. Change the dovecot.spec file in the SPECS directory to reflect the +new release and the new name of the tarball. The maintainer seems to work with +a bz2 tarball; a tar.gz tarball makes no difference Issue a rpmbuild -ba +dovecot.spec. The resulting rpm will be placed in RPMS/i586 Install with rpm or +urpmi. + +---%<------------------------------------------------------------------------- +rpm -ivh dovecot-1.0.rc26.src.rpm +cd /usr/src/rpm +mv ~/downloads/dovecot-1.0.rc28.tar.gz ./SOURCES +cd SPECS +vi dovecot.spec +...edit release and tarball name. Change default options if needed... +rpmbuild -ba dovecot.spec +cd ../RPMS/i586 +urpmi ./dovecot-1.0.rc28-1mdv2007.0.i586.rpm +---%<------------------------------------------------------------------------- + +During this process missing prerequisites may be detected. Install them and +rerun the build process. The spec file also need updating for the new add-ons +(idxview and logview). + +SSL/TLS Support +=============== + +Dovecot was initially built to support both OpenSSL and GNUTLS. GNUTLS has +however had some problems and nowadays it does not work any more. Patches to +fix it are welcome. + +OpenSSL is used by default now, and it should be automatically detected. If it +is not, you are missing some header files or libraries, or they are just in a +non-standard path. Make sure you have the 'openssl-dev' or a similar package +installed, and if it is not in the standard location, set 'CPPFLAGS' and +'LDFLAGS' as shown in <the first section above.> [CompilingSource.txt] + +By default the SSL certificate is read from '/etc/ssl/certs/dovecot.pem' and +the private key from '/etc/ssl/private/dovecot.pem'. The '/etc/ssl' directory +can be changed using the '--with-ssldir=DIR' configure option. Both can of +course be overridden from the configuration file. + +Solaris and OpenSSL problems +---------------------------- + +Solaris 10 includes a bundled OpenSSL that does not function correctly with +Dovecot when attempting to use SSL/TLS with the default dovecot config. This is +because the default setting of ssl_cipher_list in 'dovecot.conf' is HIGH:!ALL; +due to import restrictions in some countries (now apparently relaxed) the high +level routines are part of the unbundled SUNWcry package and are not available +if you don't have this package installed. This confuses the client as dovecot +announces support for high level crypto and then cannot deliver. In any case, +to resolve this you can alternatively (in decreasing order of simplicity): + + 1. Set 'ssl_cipher_list = MEDIUM:!LOW' in 'dovecot.conf' + 2. Find and install the missing SUNWcry package. + 3. Provide an alternate version of the openssl libraries that doesn't have the + high grade routines removed for your protection (sigh). The bundled version + of OpenSSL cannot be removed. Installing a newer OpenSSL from source or + package (for instance, from http://sunfreeware.com/) will enable Dovecot to + work correctly as long as you link against the new OpenSSL. Assuming you + are building with the built-in ld, make and gcc, then your build should go + something like this (notice the -R required by Sun's linker that sets the + runtime linking path in the resulting programs so the OpenSSL libraries + load from '/usr/local/ssl/lib'): + +---%<------------------------------------------------------------------------- +PATH=$PATH:/usr/sfw/bin:/usr/ccs/bin +export PATH +mv /usr/lib/pkgconfig/openssl.pc /usr/lib/pkgconfig/openssl.pc.orig +CPPFLAGS=-I/usr/local/ssl/include \ + LDFLAGS='-L/usr/local/ssl/lib -R/usr/local/ssl/lib' \ + ./configure --with-ssl=openssl +make +make install +---%<------------------------------------------------------------------------- + +Notify method +============= + +Linux +----- + +Note that current 'inotify' is in the Linux kernel since version 2.6.13 and it +is preferred over 'dnotify'. If your distribution does not have the required +'inotify' header file, you can get it from the inotify maintainer (this example +requires cURL [http://curl.haxx.se/]): + +---%<------------------------------------------------------------------------- +mkdir -p /usr/local/include/sys +cd /usr/local/include/sys +curl ftp://ftp.kernel.org/pub/linux/kernel/people/rml/inotify/headers/inotify.h +-O +curl +ftp://ftp.kernel.org/pub/linux/kernel/people/rml/inotify/headers/inotify-syscalls.h +>> inotify.h +---%<------------------------------------------------------------------------- + +/usr/local/include isn't in standard include lookup path, so you'll need to +specify that to configure: + +---%<------------------------------------------------------------------------- +CPPFLAGS=-I/usr/local/include ./configure --with-notify=inotify +---%<------------------------------------------------------------------------- + +Debian Etch ships 'sys/inotify.h' wrapped in the 'inotify-tools' package and +installs the header file into '/usr/include/inotifytools/'. To use the header +file use: + +---%<------------------------------------------------------------------------- +if ! test -e /usr/include/sys/inotify.h; then + aptitude install inotify-tools + ln -sf /usr/include/inotifytools/inotify.h /usr/include/sys/inotify.h +fi +---%<------------------------------------------------------------------------- + +Then pass 'CPPFLAGS' as in the example above: + +---%<------------------------------------------------------------------------- +CPPFLAGS=-I/usr/include/inotifytools ./configure --with-notify=inotify +---%<------------------------------------------------------------------------- + +Optional Configure Options +========================== + +--help: + gives a full list of available options + +--help=short: + just lists the options added by the particular package (= Dovecot) + +Options are usually listed as '--with-something' or '--enable-something'. If +you want to disable them, do it as '--without-something' or +'--disable-something'. There are many default options that come from autoconf, +automake or libtool. They are explained elsewhere. + +Here is a list of options that Dovecot adds. You should not usually have to +change these, but they are described here just for completeness: + +--enable-devel-checks: + Enables some extra sanity checks. This is mainly useful for developers. It + does quite a lot of unnecessary work but should catch some programming + mistakes more quickly. + +--enable-asserts: + Enable assertion checks, enabled by default. Disabling them may slightly save + some CPU, but if there are bugs they can cause more problems since they are + not detected as early. + +--without-shared-libs: + Link Dovecot binaries with static libraries instead of dynamic libraries. + +--disable-largefile: + Specifies if we use 32bit or 64bit file offsets in 32bit CPUs. 64bit is the + default if the system supports it (Linux and Solaris do). Dropping this to + 32bit may save some memory, but it prevents accessing any file larger than 2 + GB. + +--with-mem-align=BYTES: + Specifies memory alignment used for memory allocations. It is needed with + many non-x86 systems and it should speed up x86 systems too. Default is 8, to + make sure 64bit memory accessing works. + +--with-ioloop=IOLOOP: + Specifies what I/O loop method to use. Possibilities are 'select', 'poll', + 'epoll' and 'kqueue'. The default is to use the best method available on your + system. + +--with-notify=NOTIFY: + Specifies what file system notification method to use. Possibilities are + 'dnotify', 'inotify' (both on Linux), 'kqueue' (FreeBSD) and 'none'. The + default is to use the best method available on your system. See <Notify + method> [CompilingSource.txt] above for more information. + +--with-storages=FORMATS: + Specifies what mailbox formats to support. Note: Independent of this option, + the formats /raw/ and /shared/ will be always built. + +--with-solr: + Build with Solr full text search support + +--with-zlib: + Build with zlib compression support (default if detected) + +--with-bzlib: + Build with bzip2 compression support (default if detected) + +SQL Driver Options +------------------ + +SQL drivers are typically used only for authentication, but they may be used as +a lib-dict backend too, which can be used by plugins for different purposes. + +--with-sql-drivers: + Build with specified SQL drivers. Defaults to all that were found with + autodetection. + +--with-pgsql: + Build with PostgreSQL support (requires pgsql-devel, libpq-dev or similar + package) + +--with-mysql: + Build with MySQL support (requires mysql-devel, libmysqlclient15-dev or + similar package) + +--with-sqlite: + Build with SQLite3 driver support (requires sqlite-devel, libsqlite3-dev or + similar package) + +Authentication Backend Options +------------------------------ + +The basic backends are built if the system is detected to support them: + +--with-shadow: + Build with <shadow> [PasswordDatabase.Shadow.txt] password support + +--with-pam: + Build with <PAM> [PasswordDatabase.PAM.txt] support + +--with-nss: + Build with <NSS> [UserDatabase.NSS.txt] support + +--with-sia: + Build with Tru64 SIA support + +--with-bsdauth: + Build with <BSD authentication> [PasswordDatabase.BSDAuth.txt] support (if + supported by your OS) + +Some backends require extra libraries and are not necessarily wanted, so they +are built only if specifically enabled: + +--with-sql: + Build with generic SQL support (drivers are enabled separately) + +--with-ldap: + Build with LDAP support (requires openldap-devel, libldap2-dev or similar + package) + +--with-gssapi: + Build with GSSAPI authentication support (requires krb5-devel, libkrb5-dev or + similar package) + +--with-vpopmail: + Build with vpopmail support (requires vpopmail sources or a devel package) + +It's also possible to build these as plugins by giving e.g. --with-sql=plugin. + +Dynamic IMAP and POP3 Modules +============================= + +The 'mail_plugins' setting lists all plugins that Dovecot is supposed to load +from the 'mail_plugin_dir' directory at program start. These plugins can do +anything they want. They are only expected to contain the '<plugin name>_init' +and '<plugin name>_deinit' functions which are called at startup and at exit. + +The plugin filename is prefixed with a number which specifies the order in +which the plugins are loaded. This is important if one plugin depends on +another. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/ConfigFile.txt b/doc/wiki/ConfigFile.txt new file mode 100644 index 0000000..0f7ab52 --- /dev/null +++ b/doc/wiki/ConfigFile.txt @@ -0,0 +1,312 @@ +Dovecot Configuration File +========================== + +Contents + + + 1. Dovecot Configuration File + + 1. Basic syntax + + 2. Sections + + 3. Filters + + 4. Including config files + + 5. External config files + + 6. Long lines + + 7. Reading value from file + + 8. Variable expansion + +Basic syntax +------------ + +The syntax generally looks like this: + +---%<------------------------------------------------------------------------- +# this is a comment + +settings_key = settings_value +---%<------------------------------------------------------------------------- + +If Dovecot doesn't seem to be reading your configuration correctly, use +'doveconf -n' to check how Dovecot actually parses it. You can also check more +complex configurations by providing filters, for example:'doveconf -n -f +service=imap -f local=10.0.0.1 -f remote=1.2.3.4' + +Sections +-------- + +Sections look like this: + +---%<------------------------------------------------------------------------- +section optional_name { + section_setting_key = section_setting_value + subsection optional_subname { + subkey = subvalue + } +} +---%<------------------------------------------------------------------------- + +Note that sections must be currently written with the linefeeds as shown above. +So for example this doesn't work: + +---%<------------------------------------------------------------------------- +section optional_name { key = value } # DOES NOT WORK +---%<------------------------------------------------------------------------- + +The sections can be optionally named. This is especially useful if you want to +update the same section later on in the config. For example: + +---%<------------------------------------------------------------------------- +namespace inbox { + inbox = yes +} +# ... +# possibly included from another file: +namespace inbox { + mailbox Trash { + special_use = \Trash + } +} +# The namespaces get merged into the same inbox namespace. +---%<------------------------------------------------------------------------- + +Without naming the namespace it would have created a new namespace. The section +name may also sometimes be used as part of the settings instead of simply a +name. For example: + +---%<------------------------------------------------------------------------- +service auth { + unix_listener auth-master { + # .. + } +} +---%<------------------------------------------------------------------------- + +Above the "auth-master" both uniquely identifies the section name, but also it +names the UNIX socket path. + +Filters +------- + +There are a few different filters that can be used to apply settings +conditionally. The filters look exactly like sections, which may be a bit +confusing. The currently supported filters are: + + * protocol <name>: Name of the service/protocol that is reading the settings. + For example: imap, pop3, doveadm, lmtp, lda + * remote <ip/network>: Remote client's IP/network. For non-TCP connections + this will never match. For example 10.0.0.1 or 10.0.0.0/16. + * local_name <name>: Matches TLS connection's SNI + [https://en.wikipedia.org/wiki/Server_Name_Indication] name, if it's sent by + the client. Commonly used to <configure multiple TLS certificates> + [SSL.DovecotConfiguration.txt]. + * local <ip/range>: Locally connected IP/network. For non-TCP connections this + will never match. For example 127.0.0.1 or 10.0.0.0/16. + +These filters work for most of the settings, but most importantly auth settings +currently only support the protocol filter. Some of the other settings are also +global and can't be filtered, such as log_path. + +An example, which uses all of the filters: + +---%<------------------------------------------------------------------------- +local 127.0.0.1 { + local_name imap.example.com { + remote 10.0.0.0/24 { + protocol imap { + # ... + } + } + } +} +---%<------------------------------------------------------------------------- + +The nesting of the filters must be exactly in that order or the config parsing +will fail. + +When applying the settings, the settings within the most-specific filters +override the less-specific filter's settings, so the order of the filters in +config file doesn't matter. For example: + +---%<------------------------------------------------------------------------- +local 127.0.0.2 { + key = 127.0.0.2 +} +local 127.0.0.0/24 { + key = 127.0.0.0/24 +} +local 127.0.0.1 { + key = 127.0.0.1 +} +# The order of the above blocks doesn't matter: +# If local IP=127.0.0.1, key=127.0.0.1 +# If local IP=127.0.0.2, key=127.0.0.2 +# If local IP=127.0.0.3, key=127.0.0.0/24 +---%<------------------------------------------------------------------------- + +Similarly remote local filters override remote filters, which override +local_name filters, which override protocol filters. In some situations Dovecot +may also return an error if it detects that the same setting is being +ambiguously set by multiple matching filters. + +Including config files +---------------------- + +The main dovecot.conf file can also include other config files: + +---%<------------------------------------------------------------------------- +!include local.conf +!include /path/to/another.conf +!include conf.d/*.conf +---%<------------------------------------------------------------------------- + +The paths are relative to the currently parsed config file's directory. For +example: + +---%<------------------------------------------------------------------------- +# /etc/dovecot/dovecot.conf: +!include conf.d/imap.conf +# /etc/dovecot/conf.d/imap.conf: +!include imap2.conf +# /etc/dovecot/conf.d/imap2.conf is being included +---%<------------------------------------------------------------------------- + +If any of the includes fail (e.g. file doesn't exist or permission denied), it +results in an error. It's not an error if wildcards don't result in any +matching files. To avoid these errors, you can use !include_try instead: + +---%<------------------------------------------------------------------------- +!include_try passwords.conf +---%<------------------------------------------------------------------------- + +Including a file preserves the context where it's included from. For example: + +---%<------------------------------------------------------------------------- +protocol imap { + plugin { +!include imap-plugin-settings.conf + } +} +---%<------------------------------------------------------------------------- + +External config files +--------------------- + +Due to historical reasons there are still some config files that are external +to the main dovecot.conf, which are typically named '*.conf.ext'. For example: + + * passdb/userdb { args } for ldap/sql points to a dovecot-ldap.conf.ext and + dovecot-sql.conf.ext. + * dict { .. } points to dovecot-dict-*.conf.ext + +Although these external config files look similar to the main dovecot.conf +file, they have quite a lot of differences in details. Their parsing is done +with a completely different config parser, so things like filters, $variables, +!includes and<files don't work. + +The external config files are also not loaded by the config process at startup, +but instead they're parsed whenever the value is being used. So the external +passdb/userdb files are loaded by auth process at startup, while the dict +config is loaded by dict process at startup. + +Eventually these external config files will hopefully be removed. + +Long lines +---------- + +It's possible to split the setting values into multiple lines. Unfortunately +this was broken for a long time, so outside *.conf.ext files this works only in +v2.2.22+: + +---%<------------------------------------------------------------------------- +# This works in *.conf.ext files, but in the main dovecot.conf only with +v2.2.22+: +setting_key = \ + long \ + value +# equivalent to: "long value" +---%<------------------------------------------------------------------------- + +All the whitespace between lines is converted to a single space regardless of +how many spaces or tabs are at the beginning of the line or before the '\'. +Even if there is zero whitespace a single space is added. + +Reading value from file +----------------------- + +It's possible to read the value for a setting from a file: + +---%<------------------------------------------------------------------------- +key = </path/to/file +---%<------------------------------------------------------------------------- + +The value is read exactly as the entire contents of the file. This includes all +the whitespace and newlines. The paths are relative to the currently parsed +config file's directory, similar to how !include works. The file is read +immediately whenever parsing the configuration file, so if it changes +afterwards it requires a configuration reload to see the changes. This +functionality is especially useful for reading SSL certificates and keys. + +Variable expansion +------------------ + +It's possible to refer to other earlier settings as $name. For example: + +---%<------------------------------------------------------------------------- +key = value1 +key2 = $key value2 +# Equivalent to key2 = value1 value2 +---%<------------------------------------------------------------------------- + +This is commonly used with mail_plugins settings to easily add more plugins +e.g. inside imap protocol: + +---%<------------------------------------------------------------------------- +mail_plugins = acl quota +protocol imap { + mail_plugins = $mail_plugins imap_acl imap_quota +} +---%<------------------------------------------------------------------------- + +However, you must be careful with the ordering of these in the configuration +file, because the $variables are expanded immediately while parsing the config +file and they're not updated later. For example this is a common problem: + +---%<------------------------------------------------------------------------- +# NON-WORKING EXAMPLE +# Enable ACL plugin: +mail_plugins = $mail_plugins acl +protocol imap { + mail_plugins = $mail_plugins imap_acl +} +# Enable quota plugin: +mail_plugins = $mail_plugins quota +protocol imap { + mail_plugins = $mail_plugins imap_quota +} +# The end result is: +# mail_plugins = " acl quota" - OK +# protocol imap { +# mail_plugins = " acl imap_acl imap_quota" - NOT OK +# } +# v2.2.24+ also gives a warning about this: +# doveconf: Warning: /etc/dovecot/dovecot.conf line 8: Global setting +mail_plugins won't change the setting inside an earlier filter at +/etc/dovecot/dovecot.conf line 5 (if this is intentional, avoid this warning by +moving the global setting before /etc/dovecot/dovecot.conf line 5) +---%<------------------------------------------------------------------------- + +This is because the second mail_plugins change that added "quota" globally +didn't update anything inside the existing 'protocol { .. }' or other filters. + +Some variables exist in the plugin section only, such as sieve_extensions. +Those variables *cannot* be referred to, that is '$sieve_extensions' won't +work. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Debugging.Authentication.txt b/doc/wiki/Debugging.Authentication.txt new file mode 100644 index 0000000..6189f4d --- /dev/null +++ b/doc/wiki/Debugging.Authentication.txt @@ -0,0 +1,91 @@ +Debugging Authentication +======================== + +The most important thing to do is to set 'auth_debug=yes', and preferrably also +'auth_debug_passwords=yes'. After that you'll see in the logs exactly what +dovecot-auth is doing, and that should help you to fix the problem. + +PLAIN SASL mechanism +-------------------- + +With IMAP and POP3 it's easy to log in manually using the IMAP's LOGIN command +or POP3's USER and PASS commands (see <TestInstallation.txt> and +<TestPop3Installation.txt> for details), but with SMTP AUTH you'll need to use +PLAIN authentication mechanism, which requires you to build a base64-encoded +string in the correct format. The PLAIN authentication is also used internally +by both IMAP and POP3 to authenticate to dovecot-auth, so you see it in the +debug logs. + +The PLAIN mechanism's authentication format is: <authorization ID> NUL +<authentication ID> NUL <password>. Authorization ID is the username who you +want to log in as, and authentication ID is the username whose password you're +giving. If you're not planning on doing a <master user login> +[Authentication.MasterUsers.txt], you can either set both of these fields to +the same username, or leave the authorization ID empty. + +Encoding with mmencode +---------------------- + +printf(1) and mmencode(1) should be available on most Unix or GNU/Linux +systems. (If not, check with your distribution. GNU coreutils includes +printf(1), and metamail includes mmencode(1). In Debian, mmencode is called +mimencode(1).) + +---%<------------------------------------------------------------------------- +$ printf 'username\0username\0password' | mmencode +dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ= +---%<------------------------------------------------------------------------- + +This string is what a client would use to attempt PLAIN authentication as user +"username" with password "password." With ''auth_debug_passwords=yes', it would +appear in your logs. + +Decoding with mmencode +---------------------- + +You can use mmencode -u to interpret the encoded string pasted into stdin as +follows: + +---%<------------------------------------------------------------------------- +# mmencode -u +bXl1c2VybmFtZUBkb21haW4udGxkAG15dXNlcm5hbWVAZG9tYWluLnRsZABteXBhc3N3b3Jk<CR> +myusername@domain.tldmyusername@domain.tldmypassword<CTRL-D> +# +---%<------------------------------------------------------------------------- + +You should see the correct user address (twice) and password. The null bytes +won't display. + +Encoding with Perl +------------------ + +Unfortunately, mmencode on FreeBSD chokes on "\0". As an alternate, if you +have MIME::Base64 on your system, you can use a perl statement to do the same +thing: + +---%<------------------------------------------------------------------------- +perl -MMIME::Base64 -e 'print +encode_base64("myusername\@domain.tld\0myusername\@domain.tld\0mypassword");' +---%<------------------------------------------------------------------------- + +As mmencode -u doesn't encounter any "\0" you can still do: + +---%<------------------------------------------------------------------------- +perl -MMIME::Base64 -e 'print +encode_base64("myusername\@domain.tld\0myusername\@domain.tld\0mypassword");' | +mmencode -u +---%<------------------------------------------------------------------------- + +to check that you have encoded correctly. + +Encoding with Python +-------------------- + +With python you can do: + +---%<------------------------------------------------------------------------- +python -c "import base64; +print(base64.encodestring('myusername@domain.tld\0myusername@domain.tld\0mypassword'));" +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Debugging.ProcessTracing.txt b/doc/wiki/Debugging.ProcessTracing.txt new file mode 100644 index 0000000..89ea41a --- /dev/null +++ b/doc/wiki/Debugging.ProcessTracing.txt @@ -0,0 +1,44 @@ +Process Tracing +=============== + +If a Dovecot's process hangs or is just really slow, the best way to debug it +is to see what it's really doing. Typically you'd be looking into imap or pop3 +processes. + +Linux +----- + +---%<------------------------------------------------------------------------- +strace -tt -o log -p <process pid> +---%<------------------------------------------------------------------------- + +BSDs, OS X <= 10.4 +------------------ + +---%<------------------------------------------------------------------------- +# enable process tracing +ktrace -f log -p <process pid> +# do whatever makes it break, then stop the process tracing: +ktrace -C +# and see what it's done: +kdump -T -f log +---%<------------------------------------------------------------------------- + +OS X >= 10.5 +------------ + +---%<------------------------------------------------------------------------- +dtruss -p <process id> +---%<------------------------------------------------------------------------- + +Solaris +------- + +---%<------------------------------------------------------------------------- +truss -d -r0 -w1 -o log -p <process pid> +---%<------------------------------------------------------------------------- + +'-r0' and '-w1' cause all IMAP input/output to be logged. '-d' adds timestamps +to the log. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Debugging.Rawlog.txt b/doc/wiki/Debugging.Rawlog.txt new file mode 100644 index 0000000..fc1ffdc --- /dev/null +++ b/doc/wiki/Debugging.Rawlog.txt @@ -0,0 +1,148 @@ +Rawlog +====== + +Dovecot supports logging IMAP/POP3/LMTP/SMTP(submission) traffic (also TLS/SSL +encrypted). There are several possibilities for this: + + 1. rawlog_dir setting (v2.2.26+) + 2. Using 'rawlog' binary, which is executed as post-login script. + 3. Pre-login imap/pop3-login process via -R parameter. + 4. For <lmtp> [LMTP.txt], you need to use lmtp_rawlog_dir and + lmtp_proxy_rawlog_dir settings (since v2.3.2) + 5. For <submission> [Submission.txt], you can use rawlog_dir setting and + submission_relay_rawlog_dir (since v2.3.2) + +rawlog_dir setting (v2.2.26+) +----------------------------- + +Dovecot creates *.in and *.out rawlogs to the specified directory if it exists. +For example: + +---%<------------------------------------------------------------------------- +protocol imap { + rawlog_dir = /tmp/rawlog/%u + # if you want to put files into user's homedir, use this, do not use ~ + #rawlog_dir = %h/rawlog +} +---%<------------------------------------------------------------------------- + +lmtp_rawlog_dir (v2.3.2+) +------------------------- + +You can use lmtp_rawlog_dir to generate rawlogs on lmtp backend server. Unlike +the rawlog_dir setting, this does not accept variables. + +lmtp_proxy_rawlog_dir (v2.3.2+) +------------------------------- + +You can use lmtp_proxy_rawlog_dir to generate rawlogs on lmtp proxy server. +Unlike the rawlog_dir setting, this does not accept variables. + +submission_relay_rawlog_dir (v2.3.2+) +------------------------------------- + +You can use submission_relay_rawlog_dir to generate relay rawlogs on the +dovecot submission server. + +rawlog binary +------------- + +It works by checking if 'dovecot.rawlog/' directory exists in the logged in +user's home directory, and writing the traffic to 'yyyymmdd-HHMMSS-pid.in' and +'.out' files. Each connection gets their own in/out files. Rawlog will simply +skip users who don't have the 'dovecot.rawlog/' directory and the performance +impact for those users is minimal. + +Home directory +-------------- + +Note that for rawlog to work, your <userdb> [UserDatabase.txt] must have +returned a home directory for the user.*IMPORTANT: The home directory must be +returned by userdb, mail_home setting won't work.* Verify that 'doveadm user -u +user@example.com' (with -u parameter) returns the home directory, for example: + +---%<------------------------------------------------------------------------- +% doveadm user -u user@example.com +userdb: user@example.com + user : user@example.com + uid : 1000 + gid : 1000 + home : /home/user@example.com +---%<------------------------------------------------------------------------- + +In above configuration rawlog would expect to find +'/home/user@example.com/dovecot.rawlog/' directory writable by uid 1000. + +If your userdb can't return a home directory directly, with v2.1+ you can add: + +---%<------------------------------------------------------------------------- +userdb { + # ... + default_fields = home=/home/%u + # or temporarily even e.g. default_fields = home=/tmp/temp-home +} +---%<------------------------------------------------------------------------- + +You can also set DEBUG environment to have rawlog log an info message why it's +not doing anything: + +---%<------------------------------------------------------------------------- +import_environment = $import_environment DEBUG=1 +---%<------------------------------------------------------------------------- + +Configuration +------------- + +To enable rawlog, you must use rawlog as a <post-login script> +[PostLoginScripting.txt]: + +---%<------------------------------------------------------------------------- +service imap { + executable = imap postlogin +} +service pop3 { + executable = pop3 postlogin +} + +service postlogin { + executable = script-login -d rawlog + unix_listener postlogin { + } +} +---%<------------------------------------------------------------------------- + +You can also give parameters to rawlog: + + * -b: Write IP packet boundaries (or whatever read() sees anyway) to the log + files. The packet is written between<<< and >>>. + * -t: Log a microsecond resolution timestamp at the beginning of each line. + * -I: Include IP address in the filename (v2.2.16+) + * v2.1 and newer: + * -f in: Log only to *.in files + * -f out: Log only to *.out files + * v2.0 and older: + * -i: Log only to *.in files + * -o: Log only to *.out files + +Pre-login rawlog (v2.1+) +------------------------ + +You can enable pre-login rawlog for all users by telling the login processes to +log to a rawlog directory, for example: + +---%<------------------------------------------------------------------------- +service imap-login { + executable = imap-login -R rawlogs +} +---%<------------------------------------------------------------------------- + +This tries to write the rawlogs under $base_dir/login/rawlogs directory. You +need to create it first with enough write permissions, e.g.: + +---%<------------------------------------------------------------------------- +mkdir /var/run/dovecot/login/rawlogs +chown dovenull /var/run/dovecot/login/rawlogs +chmod 0700 /var/run/dovecot/login/rawlogs +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Debugging.Thunderbird.txt b/doc/wiki/Debugging.Thunderbird.txt new file mode 100644 index 0000000..db82307 --- /dev/null +++ b/doc/wiki/Debugging.Thunderbird.txt @@ -0,0 +1,58 @@ +Debugging using Thunderbird's logging +------------------------------------- + +Thunderbird has the ability to log its client actions based on protocol; this +can be useful when you're experiencing a problem with Dovecot and want to trap +the commands that the client is sending. + +Windows batch file +------------------ + +Save the below as 'runtbird.bat' and place it on the desktop, then run this +instead of the Thunderbird icon. + +---%<------------------------------------------------------------------------- +set mydate=%date:~-4,4%%date:~-7,2%%date:~-10,2% +set mytime=%time:~0,2%%time:~+3,2% + +set NSPR_LOG_MODULES=IMAP:5 +set NSPR_LOG_FILE=%USERPROFILE%\thunderbird_%mydate%_%mytime%.log + +start /d "c:\program files\mozilla thunderbird" thunderbird.exe +---%<------------------------------------------------------------------------- + +Adjust the log location and Thunderbird install folder as appropriate. If you +want to log all modules instead of just IMAP (SMTP, e.g.) then replace "IMAP" +above with "all". The above will create a date/time stamped logfile for each +run, so you won't lose the previous logs. + +Linux/BSD/etc. shell script +--------------------------- + +Save the below as 'runtbird.sh', chmod it 0755, then run this instead of the +Thunderbird icon. + +---%<------------------------------------------------------------------------- +#!/bin/sh + +TB_PATH=`which thunderbird` +# or for MacOSX: +#TB_PATH="/Applications/Thunderbird.app/Contents/MacOS/thunderbird-bin" + +MYDATE=`date "+%Y%m%d_%H%M%S"` +NSPR_LOG_MODULES=IMAP:5 +NSPR_LOG_FILE=/tmp/thunderbird_${MYDATE}.log +export NSPR_LOG_MODULES NSPR_LOG_FILE + +$TB_PATH & +exit $? +---%<------------------------------------------------------------------------- + +Adjust the log location and Thunderbird launch binary as appropriate. If you +want to log all modules instead of just IMAP (SMTP, e.g.) then replace "IMAP" +above with "all". You can also get a timestamp at the begining of all the log +lines, if you add ",timestamp" after "NSPR_LOG_MODULES=IMAP:5" for example. The +above will create a date/time stamped logfile for each run, so you won't lose +the previous logs. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Arrays.txt b/doc/wiki/Design.Arrays.txt new file mode 100644 index 0000000..2ecb787 --- /dev/null +++ b/doc/wiki/Design.Arrays.txt @@ -0,0 +1,109 @@ +Dynamic Arrays +============== + +'lib/array.h' and 'lib/array-decl.h' describes Dovecot's type-safe dynamic +arrays. Trying to add wrong typed elements gives a compiler warning. + +Declaring +--------- + +Arrays can be declared in two ways: + + 1. Directly: 'ARRAY_DEFINE(array_name, array_type);'. For example: + 'ARRAY_DEFINE(numbers, int);' or 'ARRAY_DEFINE(foos, struct foo);' + 2. Via predefined type: 'ARRAY_DEFINE_TYPE(foo, struct foo); ... + ARRAY_TYPE(foo) foos;' + +The main reason to define a type for an array is to be able to pass the array +as a function parameter, like: + +---%<------------------------------------------------------------------------- +void func(ARRAY_TYPE(foo) *foos) { .. } +---%<------------------------------------------------------------------------- + +Trying to do the same with 'ARRAY_DEFINE()' will generate a compiler warning. +'lib/array-decl.h' defines several commonly used types. + +Initializing +------------ + +Arrays are typically initialized by calling 'i_array_init()', 'p_array_init()' +or 't_array_init()' depending on where you want to allocate the memory from. +Arrays are internally handled as <buffers> [Design.Buffers.txt], so the initial +size is just multiplied by element size and passed to +'buffer_create_dynamic()'. + +Example: + +---%<------------------------------------------------------------------------- +ARRAY_DEFINE(foo, struct foo *); + +i_array_init(&foo, 32); /* initialize array with 32 elements until it needs to +be grown */ +---%<------------------------------------------------------------------------- + +Arrays can be freed with 'array_free()', but this isn't necessary if the memory +gets freed by other means (i.e. it was allocated from alloconly-pool or data +stack). + +Writing +------- + + * 'array_append(array, data, count)' is the most common way to add data to + arrays + * 'array_append_array(dest, src)' + * 'array_insert(array, idx, data, count)' + * 'array_delete(array, idx, count)' + * 'array_idx_set(array, idx, data)' replaces (or adds) data to given index + * 'array_idx_clear(array, idx)' clears given index by writing NULs to it + * 'array_append_space(array, count)' + +Reading +------- + +'array_idx(array, idx)' returns pointer to given index in array. The index must +already exist, otherwise the call assert-crashes. This call adds extra overhead +for accessing arrays though, so usually it's better to just get list of all +elements and access them directly: + +---%<------------------------------------------------------------------------- +data = array_get(&array, &count); +---%<------------------------------------------------------------------------- + +You can also iterate through the whole array easily: + +---%<------------------------------------------------------------------------- +const char *str; + +array_foreach(&string_array, str) { + /* str changes in each iteration */ +} +---%<------------------------------------------------------------------------- + +There's also 'array_foreach_modifiable()' to get the data without const. + +Unsafe Read/Write +----------------- + +Functions below have similar problems to [[Design/Buffer|buffer]'s '*_unsafe()' +functions. Memory returned by them must not be accessed after calls to other +'array_*()' modifying functions, because they may reallocate the array +elsewhere in memory. + + * 'array_append_space(array)' + * 'array_insert_space(array, idx)' + * 'array_get_modifiable(array, &count)' + * 'array_idx_modifiable(array, idx)' + +Others +------ + + * 'array_cmp(array1, array2)' compares two arrays + * 'array_reverse(array)' reverses all elements in an array + * 'array_sort(array, cmp_func)' is a wrapper for 'qsort()' adding also type + safety. The parameters in cmp_func should be the same type as the array, + instead of 'const void *'. + * 'array_bsearch(array, key, cmp_func)' is a wrapper for 'bsearch()' also + adding type safety, just like 'array_sort()'. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.AuthProcess.txt b/doc/wiki/Design.AuthProcess.txt new file mode 100644 index 0000000..dd4fc89 --- /dev/null +++ b/doc/wiki/Design.AuthProcess.txt @@ -0,0 +1,365 @@ +Authentication process design +============================= + +See <Design.Processes.txt> for an overview of how the authentication process +works. + +There are four major classes in the code: + + * 'struct mech_module': Authentication mechanism + * 'struct password_scheme': Password scheme + * 'struct passdb_module': Password database + * 'struct userdb_module': User database + +There are many implementations for each of these, and it's simple to add more +of them. They can also be added as plugins, although the current plugin loading +code doesn't allow loading authentication mechanisms cleanly, and it's not +possible to add new credentials (see below). + +The code flow usually goes like: + + * Dovecot-auth listens for new authentication client connections (the listener + socket is created by master process and passed in MASTER_SOCKET_FD -> + 'main.c:main_init()' -> + 'auth-master-connection.c:auth_master_listener_add()') + * A new authentication client connects via UNIX socket + ('auth-master-connection.c:auth_master_listener_accept()' -> + 'auth-client-connection.c:auth_client_connection_create()') + * Authentication client begins an authentication + ('auth-client-connection.c:auth_client_input()' -> + 'auth_client_handle_line()' -> + 'auth-request-handler.c:auth_request_handler_auth_begin()' [ -> + 'auth-request.c:auth_request_new()']) + * Authentication mechanism backend handles it ('mech->auth_initial()' and + 'mech->auth_continue()' in 'mech-*.c') + * The mechanism looks up the password from passdb + ('auth-request.c:auth_request_verify_plain()' and + 'auth_request_lookup_credentials()') and the password scheme code to + verifies it ('password-scheme.c:password_verify()' and + 'password_generate()') + * If user is logging in, the user information is looked up from the userdb + ('auth-master-connection.c:master_input()' -> 'master_input_request()' -> + 'auth-request-handler.c:auth_request_handler_master_request()' -> + 'auth-request.c:auth_request_lookup_user()') + * The authentication may begin new authentication requests even before the + existing ones are finished. + +It's also possible to request a userdb lookup directly, for example Dovecot's +<deliver> [LDA.txt] needs that. The code path for that goes +'auth-master-connection.c:master_input()' -> 'master_input_user()' -> +'auth-request.c:auth_request_lookup_user()'. + +Authentication mechanisms +------------------------- + +These are <SASL> [Sasl.txt] authentication mechanism implementations. See +<Authentication.Mechanisms.txt> for a list of mechanisms supported by Dovecot. + +A new mechanism is created by filling a 'struct mech_module' (in 'mech.h') and +passing it to 'mech_register_module()'. The struct fields are: + +mech_name: + The public name of the mechanism. This is shown to clients in the IMAP, POP3 + and SMTP capability lists. If you create a new non-standard mechanism, please + prefix it with "X-". + +flags: + Describes how secure the mechanism is. Also 'MECH_SEC_PRIVATE' flag specifies + that the mechanism shouldn't be advertised in the capability list. This is + currently used only for APOP mechanism, which is defined by the POP3 protocol + itself. + +passdb_need_plain: + This mechanism uses passdb's 'verify_plain()' function to verify the + password's validity. This means that the mechanism has access to the + plaintext password. This is true only for plaintext mechanisms such as PLAIN + and LOGIN. The main purpose of this flag is to make dovecot-auth complain at + startup if there are no passdbs defined in the configuration file. Note that + a configuration without any passdbs is valid with eg. GSSAPI mechanism which + doesn't need a passdb at all. + +passdb_need_credentials: + This mechanism uses passdb's 'lookup_credentials()' function. See below for + description of the credentials. + +auth_new(): + Allocates a new 'struct auth_request'. Typically with more complex mechanisms + it really allocates a 'struct <mech>_auth_request' which contains 'struct + auth_request' as the first field, followed by mechanism-specific fields. + +auth_initial(request, data, data_size): + This begins the authentication, data and data_size containing the initial + response sent by the client (decoded, not in base64). Call + 'request->callback()' once you're done (see below). + +auth_continue(request, data, data_size): + Continues the authentication. Works the same as 'auth_initial()'. + +auth_free(): + Free the request. Usually all the memory allocations for the request should + be allocated from 'request->pool', so you can use 'mech_generic_auth_free()' + which simply frees the pool. + +'auth_initial()' and 'auth_continue()' continue or finish the authentication by +calling 'request->callback()': + +---%<------------------------------------------------------------------------- +typedef void mech_callback_t(struct auth_request *request, + enum auth_client_result result, + const void *reply, size_t reply_size); +---%<------------------------------------------------------------------------- + +The 'reply' and 'reply_size' contain the server's mechanism-specific reply to +the client. If there is no need to return anything (which is usually the case +with the "success" reply), the 'reply_size' can be 0. The 'result' parameter is +one of: + + * AUTH_CLIENT_RESULT_CONTINUE: Client can continue the authentication. The + reply contains the mechanism-specific reply sent to the client. + * AUTH_CLIENT_RESULT_SUCCESS: Authentication successful. The reply is usually + empty. + * AUTH_CLIENT_RESULT_FAILURE: Authentication failed. The reply is always + ignored. + +The 'request->callback()' should actually be called directly only for +continuation requests (a new function should probably be added for this as +well). For success and failure replies, you should instead use one of these +functions: + + * 'auth_request_success()' + * 'auth_request_fail()' + * 'auth_request_internal_failure()': Use this if you couldn't figure out if + the authentication succeeded or failed, for example because passdb lookup + returned internal failure. + +SASL authentication in general works like: + + 1. Client begins the authentication, optionally sending an "initial response", + meaning some data that the mechanism sees in 'auth_initial()'. + * Note that not all protocols support the initial response. For example + IMAP supports it only if the server implements SASL-IR extension. + Because of this mechanisms, such as PLAIN, support doing the + authentication either in 'auth_initial()' or in 'auth_continue()'. + * If the client initiates the authentication (ie. server's initial reply + is empty, such as with PLAIN mechanism) you can use + 'mech_generic_auth_initial()' instead of implementing your own. + 2. Server processes the authentication request and replies back with + 'request->callback()'. + * If the authentication failed, it's placed into 'auth_failures_buf' + unless 'request->no_failure_delay=TRUE'. The failures are flushed from + the buffer once every 2 seconds to clients and 'mechanism->auth_free()' + is called. + * If the authentication succeeded and + * there is a master connection associated with the request (IMAP/POP3 + login), the authentication now waits for master connection to do a + verification request. If this for some reason doesn't happen in + 'AUTH_REQUEST_TIMEOUT' seconds (3,5 mins), it's freed. + * there isn't a master connection (SMTP AUTH), the authentication is + freed immediately. + 3. Client processes the reply: + * If the authentication continues, it sends back more data which is + processed in 'auth_continue()'. Goto 2. + * If the authentication failed, it's done. + 4. If the authentication succeeded, the client requests a login from the + master process, which in turn requests verification from the auth process. + * Besides verifying the authentication, dovecot-auth also does a userdb + lookup to return the userdb information to master. + * If the verification fails (normally because userdb lookup fails), the + client gets "internal authentication failure" + * If the verification succeeds, the user is now logged in + * In either case, 'mechanism->auth_free()' is called now. + +Credentials +----------- + +Most of the non-plaintext mechanisms need to verify the authentication by using +a special hash of the user's password. So either the passdb credentials lookup +returns a plaintext password from which the hash can be created, or the hash +directly. The plaintext to hash conversion is done by calling +'password_generate' function of the password scheme. + +Unfortunately the list of allowed credentials is currently hardcoded in 'enum +passdb_credentials'. The enum values are mapped to password scheme strings in +'passdb_credentials_to_str()'. Some day the enum will be removed so plugins can +add new mechanisms. Besides the mechanism-specific credentials, the enum +contains: + +_PASSDB_CREDENTIALS_INTERNAL: + I don't remember why this really exists. It should probably be called + _PASSDB_CREDENTIALS_INVALID or something and used only by some asserts.. + +PASSDB_CREDENTIALS_PLAINTEXT: + Request a plaintext password. + +PASSDB_CREDENTIALS_CRYPT: + Request the password in any scheme. This is especially useful if you only + want to verify a user's existence in a passdb. Used by <static userdb> + [UserDatabase.Static.txt] in userdb lookups. + +Password schemes +---------------- + +'struct password_scheme' has fields: + +name: + Name of the scheme. This only shows up in configuration files and maybe in + the passwords stored in passdb ("{scheme_name}password_hash"). + +password_verify(plaintext, password, user): + Returns TRUE if 'password' hash matches the plaintext password given in + 'plaintext' parameter. If the password hash depends on the username (eg. with + DIGEST-MD5), the 'user' parameter can also be used. + +password_generate(plaintext, user): + Returns the password hash for given plaintext password and username. + +You can create a new password scheme by simply creating a 'struct +password_scheme' named '<module_name>_scheme', compiling a shared object and +placing it to '$moduledir/auth/' directory. + +Password databases +------------------ + +See <PasswordDatabase.txt> for a description of passdbs and a list of already +implemented ones. + +'struct passdb_module' contains fields: + +cache_key: + A string containing <variables> [Variables.txt]. When expanded, it uniquely + identifies a passdb lookup. This is '%u' when the passdb lookup validity + depends only on the username. With more complex databases such as SQL and + LDAP this is created dynamically based on the password query in the + configuration file. If there are multiple variables, they should be separated + so that their contents don't get mixed, for example '%u<TAB>%r<TAB>%l'. + 'auth_cache_parse_key()' can be used to easily create a cache key from a + query string. + +default_pass_scheme: + The default scheme to use when it's not explicitly specified with a + "{scheme}" prefix. + +blocking: + If TRUE, the lookup is done in dovecot-auth worker process. This should be + used if the lookup may block. + +iface.preinit(auth_passdb, args): + Allocate 'struct passdb_module' and return it. This function is called before + chrooting and before privileges are dropped from dovecot-auth process, so if + should do things like read the configuration file.'auth_passdb' is typically + used for getting a memory pool and looking up some global settings such as + 'auth_passdb->auth->verbose_debug'. 'args' contains the args parameter in + configuration file. + +iface.init(module, args): + The privileges have been dropped before calling this. 'module' contains the + structure returned by 'preinit()'. 'args' is the same as in 'preinit()'. + Typically this function will do things like connect to the database. + +iface.deinit(module): + Close the connection to the password database and free all the memory you + used. + +iface.verify_plain(auth_request, password, callback): + Check if the given plaintext password matches. 'auth_request->credentials = + -1' always. When the verification is done, call the given callback with the + result in 'result' parameter. + +iface.lookup_credentials(auth_request, callback): + Look up the password credentials. 'auth_request->credentials' contains the + credentials that the mechanism wants. When the lookup is finished, call the + given callback with the result in 'result' parameter, and if the lookup was + successful the credentials in 'password' parameter. + +Plaintext authentication mechanisms typically call 'verify_plain()', which is +possible to implement with all the passdbs. Non-plaintext mechanisms typically +call 'lookup_credentials()', which isn't possible to implement always (eg. +PAM). If it's not possible to implement 'lookup_credentials()', you can leave +the pointer to it NULL. + +If the passdb uses connections to external services, it's preferred that they +use non-blocking connections. Dovecot does this whenever possible (PostgreSQL +and LDAP for example). If it's not possible, set 'blocking = TRUE'. + +With both functions 'auth_request->passdb->passdb' contains the passdb_module +returned by your 'preinit()' function. 'auth_request->user' contains the +username whose password we're verifying. You don't need to worry about <master +users> [MasterUsers.txt] here. It's also possible to use any other fields in +'auth_request' to do the lookup, such as 'service', 'local_ip' or 'remote_ip' +if they exist. Often you want to let user to configure the lookup with +<variables> [Variables.txt] (eg. SQL query). In that case you can use +'auth_request_get_var_expand_table()' to retrieve the variable table for +'var_expand()'. + +The passdb lookup can return one of the following results: + +PASSDB_RESULT_INTERNAL_FAILURE: + The lookup failed. For example SQL server is down. + +PASSDB_RESULT_SCHEME_NOT_AVAILABLE: + 'lookup_credentials()' requested a scheme which isn't in the passdb + +PASSDB_RESULT_USER_UNKNOWN: + The user doesn't exist in the database. + +PASSDB_RESULT_USER_DISABLED: + The user is disabled either entirely, or for this specific login (eg. only + POP3 logins allowed). This isn't commonly implemented in passdbs. + +PASSDB_RESULT_PASS_EXPIRED: + The user's password had expired. This isn't commonly implemented in passdbs. + +PASSDB_RESULT_PASSWORD_MISMATCH: + The password given in 'verify_plain()' wasn't valid. + +PASSDB_RESULT_OK: + Success. + +User databases +-------------- + +See <UserDatabase.txt> for a description of userdbs and a list of already +implemented ones. + +'struct userdb_module' is very similar to 'struct passdb_module'. The lookup +callback is a bit different though: + +---%<------------------------------------------------------------------------- +typedef void userdb_callback_t(enum userdb_result result, + struct auth_stream_reply *reply, + struct auth_request *request); +---%<------------------------------------------------------------------------- + +'result' contains one of: + +USERDB_RESULT_INTERNAL_FAILURE: + The lookup failed. For example SQL server is down. + +USERDB_RESULT_USER_UNKNOWN: + The user doesn't exist in the database. + +USERDB_RESULT_OK: + Success. + +There is no equivalent for PASSDB_RESULT_USER_DISABLED currently. Practically +the userdb result is used only by Dovecot's <deliver> [LDA.txt] to figure out +if the user exists or not. When logging in with IMAP or POP3, the user's +existence was already checked in passdb lookup, so only in rare conditions when +a user is logging in at the same time as it's being deleted, the userdb result +is USER_UNKNOWN. + +The 'reply' parameter contains the username (it's allowed to be different from +the looked up username) and a list of key=value pairs that were found from the +userdb. The userdb should make sure that at least "uid" and "gid" keys were +returned. Here's an example code based on passwd userdb: + +---%<------------------------------------------------------------------------- +reply = auth_stream_reply_init(auth_request); +auth_stream_reply_add(reply, NULL, pw->pw_name); +auth_stream_reply_add(reply, "uid", dec2str(pw->pw_uid)); +auth_stream_reply_add(reply, "gid", dec2str(pw->pw_gid)); +auth_stream_reply_add(reply, "home", pw->pw_dir); +callback(USERDB_RESULT_OK, reply, auth_request); +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.AuthProtocol.txt b/doc/wiki/Design.AuthProtocol.txt new file mode 100644 index 0000000..14ab2e6 --- /dev/null +++ b/doc/wiki/Design.AuthProtocol.txt @@ -0,0 +1,251 @@ +Dovecot Authentication Protocol v1.1 +==================================== + +General +------- + +This is a line based protocol. Each line is a command which ends with an LF +character. The maximum line length isn't defined, but it's currently expected +to fit into 8192 bytes. Authentication mechanism specific data transfers are +the largest single parameters. + +Each command is in format: + +---%<------------------------------------------------------------------------- +<command name> TAB <parameters separated with TAB> +---%<------------------------------------------------------------------------- + +Parameters are split into required and optional parameters. Required parameters +aren't in any specific format, but optional parameters are either booleans +without a value, or a name=value pair. If optional parameter name is unknown, +the parameter should just be ignored. + +Typical command looks like (without spaces): + +---%<------------------------------------------------------------------------- +command TAB param1 TAB param2 TAB optname=value TAB optboolean +---%<------------------------------------------------------------------------- + +There is no way to have TABs or LFs in parameters. + +Client <-> Server +----------------- + +Client is an untrusted authentication client process. It can serve one or more +users, so from user's point of view it's usually eg. IMAP or SMTP server +process. + +Server is an authentication server process. + +The connection starts by both client and server sending handshakes: + +---%<------------------------------------------------------------------------- +C: "VERSION" TAB <major> TAB <minor> +C: "CPID" TAB <pid> +S: "VERSION" TAB <major> TAB <minor> +S: "SPID" TAB <pid> +S: "CUID" TAB <pid> +S: "COOKIE" TAB <cookie> +S: "MECH" TAB <name> [TAB <parameters>] (multiple times) +S: "DONE" +---%<------------------------------------------------------------------------- + +Both client and server should check that they support the same major version +number. If they don't, the other side isn't expected to be talking the same +protocol and should be disconnected. Minor version can be ignored. This +document is version number 1.1. + + * CPID and SPID specify client and server Process Identifiers (PIDs). They + should be unique identifiers for the specific process. UNIX process IDs are + good choices. + * CUID is a server process-specific unique connection identifier. It's + different each time a connection is established for the server. + * CPID is used by master's REQUEST command. + * SPID can be used by authentication client to tell master which server + process handled the authentication. + * CUID is currently useful only for APOP authentication. + * COOKIE returns connection-specific 128 bit cookie in hex. It must be given + to REQUEST command. (Protocol v1.1+ / Dovecot v2.0+) + * DONE finishes the handshake from server. CPID finishes the handshake from + client. + +Authentication Mechanisms +------------------------- + +MECH command announces an available authentication SASL mechanism. Mechanisms +may have parameters giving some details about them: + +anonymous: + Anonymous authentication + +plaintext: + Transfers plaintext passwords + +dictionary: + Subject to passive (dictionary) attack + +active: + Subject to active (non-dictionary) attack + +forward-secrecy: + Provides forward secrecy between sessions + +mutual-auth: + Provides mutual authentication + +private: + Don't advertise this as available SASL mechanism (eg. APOP) + +Authentication Request +---------------------- + +---%<------------------------------------------------------------------------- +C: "AUTH" TAB <id> TAB <mechanism> TAB service=<service> [TAB <parameters>] +S1: "FAIL" TAB <id> [TAB <parameters>] +S2: "CONT" TAB <id> TAB <base64 data> +S3: "OK" TAB <id> [TAB <parameters>] +---%<------------------------------------------------------------------------- + +ID is a connection-specific unique request identifier. It must be a 32bit +number, so typically you'd just increment it by one. + +Service is the service requesting authentication, eg. POP3, IMAP, SMTP. + +AUTH and USER (see below) common parameters are: + +lip=<ip>: + Local IP - in standard string format, + +rip=<ip>: + Remote IP - ie. for IPv4 127.0.0.1 and for IPv6 ::1 + +lport=<port>: + Local port + +rport=<port>: + Remote port + +AUTH-only parameters are: + +secured: + Remote user has secured transport to auth client] (e.g. localhost, SSL, TLS) + +valid-client-cert: + Remote user has presented a valid SSL certificate. + +no-penalty: + Ignore auth penalty tracking for this request + +cert_username: + Username taken from client's SSL certificate. + +resp=<base64>: + Initial response for authentication mechanism. NOTE: This must be the last + parameter. Everything after it is ignored. This is to avoid accidental + security holes if user-given data is directly put to base64 string without + filtering out tabs. + +FAIL parameters may contain: + +reason=<str>: + <str> should be sent to remote user instead of the standard "Authentication + failed" messages. For example "invalid base64 data". It must NOT be used to + give exact reason for authentication failure (i.e. "user not found" vs. + "password mismatch"). + +code=temp_fail (v2.3+), temp (<v2.2): + This is a temporary internal failure, e.g. connection was lost to SQL + database. + +code=authz_fail (v2.3+), authz (v1.2..v2.2): + Authentication succeeded, but authorization failed (master user's password + was ok, but destination user was not ok). + +code=user_disabled (v2.3+), user_disabled (v2.2): + User is disabled (password may or may not have been correct) + +code=pass_expired (v2.3+), pass_expired (v2.2): + User's password has expired. + +A CONT response means that the authentication continues, and more data is +expected from client to finish the authentication. Given base64 data should be +sent to client. The client may continue the process issuing + +---%<------------------------------------------------------------------------- +C: "CONT" TAB <id> TAB <base64 data> +---%<------------------------------------------------------------------------- + +The <id> must match the <id> of the AUTH command. + +FAIL and OK may contain multiple unspecified parameters which authentication +client may handle specially. The only one specified here is "user=<userid>" +parameter, which should always be sent if the userid is known. + +Server <-> Master +----------------- + +Master is a trusted process which may query results of previous client +authentication or information about a specific user. Master is optional and in +SMTP AUTH case it's not needed. + +The connection starts by both server and master sending handshakes: + +---%<------------------------------------------------------------------------- +S: "VERSION" TAB <major> TAB <minor> +S: "SPID" TAB <pid> +M: "VERSION" TAB <major> TAB <minor> +---%<------------------------------------------------------------------------- + +Auth with client <-> server, both should check that the version numbers are +valid. + +SPID can be used to let master identify the server process. + +Master Requests +--------------- + +---%<------------------------------------------------------------------------- +M: "REQUEST" TAB <id> TAB <client-pid> TAB <client-id> TAB <cookie> +M: "USER" TAB <id> TAB <userid> TAB service=<service> [TAB <parameters>] +S: "NOTFOUND" TAB <id> +S: "FAIL" TAB <id> TAB <error message> +S: "USER" TAB <id> TAB <userid> [TAB <parameters>] +---%<------------------------------------------------------------------------- + +Master commands can request information about existing authentication request, +or about a specified user. + +USER command's service and parameters are the same as with AUTH client request. + +ID is a connection-specific unique request identifier. It must be a 32bit +number, so typically you'd just increment it by one. + +NOTFOUND reply means that the user wasn't found. (v1.x also reported unknown +request IDs with NOTFOUND.) + +FAIL reply means an internal error occurred. Usually either a configuration +mistake or temporary error caused by lost resource (eg. database down). Also +unknown request IDs are reported as FAILs (since v2.0). + +USER reply is sent if request succeeded. It can return parameters: + +uid=<uid>: + System user ID. + +gid=<gid>: + System group ID. + +home=<dir>: + Home directory. + +chroot=<dir>: + Chroot directory. + +mail=<data>: + Mail location. + +system_user=<user>: + System user name which can be used to get extra groups. This will probably + be replaced later by giving just multiple gid fields. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Buffers.txt b/doc/wiki/Design.Buffers.txt new file mode 100644 index 0000000..03542dc --- /dev/null +++ b/doc/wiki/Design.Buffers.txt @@ -0,0 +1,65 @@ +Buffers +======= + +'lib/buffers.h' describes Dovecot's buffer API. Unless your code happens to be +VERY performance critical, you shouldn't handle writing to buffers/arrays +manually, but instead use the buffer API's safe functions to guarantee that +your code can't write past the buffer and cause a security hole. + +Dovecot's buffers are the basic building block for <arrays> [Design.Arrays.txt] +and <strings> [Design.Strings.txt]. Use them instead if they make more sense +than buffers. + +There are a two different ways to create buffers: statically and dynamically +allocated. + +Static buffers +-------------- + +You can create statically allocated buffers with 'buffer_create_data()'. Trying +to write past the given buffer size will panic. The code to initialize this +looks like: + +---%<------------------------------------------------------------------------- +unsigned char buf_data[1024]; +buffer_t buf; + +buffer_create_data(&buf, buf_data, sizeof(buf_data)); +---%<------------------------------------------------------------------------- + +Trying to write more than 1024 bytes to the buffer will cause an assert-crash, +so these buffers shouldn't be used unless you know exactly what the maximum +buffer size is. + +To avoid accidental buffer overflows, don't use any more complex calculations +in the size parameter of 'buffer_create_data()'. It should always be +'sizeof(data_buffer)'. + +You can also create non-writable buffers with 'buffer_create_const_data()'. +Static buffers don't need to be freed. + +Dynamic buffers +--------------- + +Dynamically growing buffers can be created with 'buffer_create_dynamic(pool, +init_size)'. Memory for buffer is allocated from the given pool. When memory +needs to be grown, it's grown exponentially (2^n), with some exceptions to +avoid growing the given memory pool unless necessary. The initial buffer size +is always a guess - try to make it large enough that buffer wouldn't be grown +most of the time, but not so large that it wastes memory. + +You should be careful with memory returned by 'buffer_get_space_unsafe()' and +'buffer_append_space_unsafe()'. This returned memory should be accessed +immediately afterwards and it must not be accessed anymore after other +'buffer_*()' calls, because they may reallocate the buffer and move it +elsewhere in memory. + +Buffers always look like they're filled with NUL bytes. If you write past the +end of buffer, all the inserted bytes are filled with NULs. If you shrink the +buffer with 'buffer_set_used_size()' and again write past the end of used size, +all the old data is again gone and filled with NULs. If you for some reason +want to just temporarily shrink the buffer size and then change it back, you +can use 'buffer_set_used_size()' to grow it back to its original size (but no +larger). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Code.txt b/doc/wiki/Design.Code.txt new file mode 100644 index 0000000..5fbddba --- /dev/null +++ b/doc/wiki/Design.Code.txt @@ -0,0 +1,203 @@ +Code Design +=========== + +Generally Dovecot follows Linux kernel coding style +[https://www.kernel.org/doc/Documentation/CodingStyle]. + +Most of the coding style design is about getting as many compiler warnings and +errors as possible. Dovecot already has some patched-Clang-specific features to +get more warnings, and will likely have more in future. Issues found by static +analyzers should also be fixed in some way, e.g. adding extra asserts. + +Runtime errors should be caught by asserts or NULL pointer dereferences, which +cleanly crash the program instead of it continuing and possibly corrupting data +or causing other bad things. Dovecot's master process restarts the crashed +processes anyway. Obviously the master process should be very careful to avoid +crashing, but even then in some OSes a crashed Dovecot master gets restarted by +the init process. + +Dovecot's bottlenecks are primarily disk I/O and secondarily memory usage, so +using extra CPU for asserts and other extra checks costs practically nothing. + +Types +----- + + * Unsigned types are used whenever the value isn't allowed to be negative. + This makes it easier to do "value too large" checks when you don't also have + to check for negative values. Also in arithmetic it's better to have the + value wrap (and hopefully checked later!) than cause undefined behavior with + a signed integer overflow. + * 'char *' always points to a NUL-terminated string, 'unsigned char *' + doesn't. + * 'size_t' should generally be used when pointing to a large memory area, + especially for 'mmap()'. Since 'size_t' can be slower to access than + 'unsigned int' (or at least use memory), it's fine to use 'unsigned int' + when it's "very unlikely" that the size ever goes beyond 4 GB + (e.g.'string_t'). + * 'uoff_t' is used for file offsets/sizes. This is usually 64bit, even with + 32bit machines. + * 'uint32_t' vs. 'unsigned int': Use 'uint32_t' when the type really should be + 32bit, but don't spend too much energy trying to avoid mixing it with + 'unsigned int', since they are going to be the same types probably for the + rest of Dovecot's life.. + * 'uint8_t' vs. 'unsigned char': I doubt Dovecot will ever be compiled + anywhere where these differ from one another, but for readability use + 'uint8_t' for binary data and 'unsigned char' for text data. + +Function parameters +------------------- + + * Try to avoid using/allowing NULL pointers. For example for a public API + instead of having 'foo(struct bar *bar)' where bar can be NULL, you could + have both 'foo(void)' and 'foo_with_bar(struct bar *bar)'. Of course don't + try too hard if it makes the API otherwise ugly. + * Dovecot v2.2+ marks all such parameters with ATTR_NULL. These can be + verified with a patched clang. Unfortunately the API isn't very nice, it + would be better to mark each parameter separately with ATTR_NULL instead + of having a numbered list. This will likely change in future. + * Also unless you know that a parameter can be NULL, don't bother wasting + code on checking if it is. Ideally those are noticed by the patched clang + check, but even if not, it's not that bad to crash on NULL pointer + dereference. + * '_r' suffix in parameter is used for values that are returned (e.g. + 'foo(const char **error_r)'). + * Use const for pointers pretty much whenever possible. + * Some day in future I'd like compiler to give warnings if function parameters + are modified by the function itself. There's probably a lot of code that + does this currently, but try avoiding it in future. + +Function return values +---------------------- + + * 'int' type is commonly used for return values. Usually this is used to mean + one of: + * -1 = error, 0 = ok + * -1 = error, 0 = unfinished (e.g. non-blocking call), 1 = finished + * unfortunately there are also other uses. I've been wondering about using + different types for these some day, such as "err" and "err3", but haven't + figured out an easy enough to use design, especially one where compiler + verifies that types aren't accidentally mixed. + * 'bool' shouldn't be used as return value for ok/error, use int 0/-1 instead. + (Old code has some of these. Sometimes it's also not quite clear if + something is an "error" or not, so this rule isn't perfect.) + * Functions returning pointers shouldn't use NULL pointer to mean an error, + only for things like "not found". For example instead of 'if ((ctx = init()) + == NULL)' use 'if (init(&ctx) < 0)' + * Usually when calling a function, either save/check the return value or + explicitly say that you don't care about it by saying '(void)func();' + * Some functions where the return value can nearly always be ignored it's + annoying to add the '(void)' prefix. You can avoid these by adding + ATTR_NOWARN_UNUSED_RESULT to such function's prototype. A patched clang + can be used to find missing return value checks. + * If a system call fails unexpectedly, always log an error about it, possibly + even kill the process if it's vital for correct functionality + (e.g.'gettimeofday()'). '%m' in Dovecot's 'printf()'-style functions expands + to 'strerror(errno)'. + +Boolean expressions +------------------- + +Try to use boolean expressions the way they work in Java. C doesn't require +this, but I think it makes the code easier to understand and reduces bugs in +some cases (e.g.'if (!foo())' when thinking foo() returns bool/FALSE, but +actually returns int/-1 on error). We've a clang patch +[http://dovecot.org/patches/clang/] to give warnings in these cases. As +expected, it found quite a lot of bugs (some real bugs and a lot of "it just +accidentally worked" +[https://github.com/dovecot/core/commit/d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995]). + + * 'bool x' and 'bool x:1' are the boolean types + * TRUE and FALSE are the only valid explicit boolean values (not 0 or 1, and + currently also not true/false although that could be changed) + * !=, ==, <, >, etc. comparisons create a boolean + * if, for, while, etc. require a boolean + +So: + + * 'if (!ptr)' -> 'if (ptr == NULL)' + * 'if (!num)' -> 'if (num == 0)' + * 'if (flags & FLAG_FOO)' -> 'if ((flags & FLAG_FOO) != 0)' + +Memory +------ + +Memory is always allocated through one of Dovecot's wrappers, e.g. 'i_malloc()' +or 'i_new()'. All of Dovecot's memory allocations always succeed or kill the +process. There's no point in writing a lot of code to check for memory +allocation failures that happen just about never. The only reason some memory +allocations fail in Dovecot currently is because a process VSZ limit is +reached, which usually indicates either a memory leak or trying to access a +mailbox that is too large. In either of these cases it's better to just +completely restart the process than try to limp along without getting anything +useful done anymore. + +Memory allocations can be assumed to be zero-initialized. All of the memory +allocation functions do it, except 't_malloc()' and 't_buffer_get()', which you +should almost never use directly anyway. The code currently also assumes that +pointers in zero-initialized memory area are NULL, which isn't guaranteed by +ANSI-C, but practically Dovecot isn't going to be run in systems where it's not +true and you're not going to remember to NULL-initialize all of your pointers +anyway without compiler/runtime failure. + +When using a struct, always zero-initialize it with 'memset()' instead of +setting each field separately to 0. It's too easy to cause bugs by adding a new +field to the struct and forgetting to initialize it. + +Double-frees in C are bad. Better to crash with NULL pointer dereference than +possibly allow an attacker to exploit heap corruption and run executable code. +Most of the pointers are set to NULL when they are freed: + + * 'i_free_and_null()' is a macro to free the memory and set the pointer to + NULL. + * 'i_free()' also currently sets the pointer to NULL, but another thought was + to set this pointing to some other invalid pointer. But arguably this should + be defined to be exactly the same as 'i_free_and_null()'. + * Most deinit() functions take a pointer-to-pointer parameter and set the + original one to NULL. There's no need to explicitly set the same pointer to + NULL afterwards. + +Buffers +------- + +Use dynamically growing strings/buffers wherever necessary instead of a static +sized buffer, where on larger input the function fails or truncates the data. +It's of course not good to allow users to infinitely grow memory usage, so +there should be some limits added, but it shouldn't fail even if the limit is +set to infinite. + +Avoid explicitly calculating memory usage for allocations. If you do, mark it +with '/* @UNSAFE */' comment unless it's the calculation is "so obvious that +you see it's correct at the first glance". If in doubt, just mark it UNSAFE. +The idea is that anyone can easily grep for these and verify their correctness. + +Type safety +----------- + + * Try to avoid using void pointers. + * Try to avoid casting types to other types, especially if the cast isn't + necessary to avoid a compiler warning. + +It's better if compiler can give a warning when something is accidentally used +wrong. + +Callback functions +------------------ + +Callback functions make the code more difficult to follow, especially when a +callback calls another callback, or when using function pointers to jump to +different callbacks depending on state. Of course with asynchronous C code it's +pretty much impossible to avoid callbacks. Still, try to avoid them where +possible to keep the code readable. lib-fs/fs-api.h is an example API which +supports async operations but with a single common "do more now" callback +rather than every single operation having its own callback parameter. This +makes it similar to async network IO with read()/write() EAGAIN handling. + +Often callback functions can be avoided by creating iterator functions instead. +For example instead of 'parse(callback, context' use 'ctx = parse_init(); while +(parse_next(ctx)) { .. } parse_deinit(&ctx);' + +Dovecot has some helper macros to make callbacks' context parameters type-safe. +In v2.2+ see 'CALLBACK_TYPECHECK()' macro and for example 'io_add()' for +example usage. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Dcrypt.txt b/doc/wiki/Design.Dcrypt.txt new file mode 100644 index 0000000..e17f017 --- /dev/null +++ b/doc/wiki/Design.Dcrypt.txt @@ -0,0 +1,113 @@ +lib-dcrypt +========== + +lib-dcrypt is component for abstracting asymmetric and symmetric cryptographic +operations. It can be used for public/private key handling too. Currently we +support OpenSSL backing, but it is possible to write alternative backends for +dcrypt. + +ECDH algorithm +-------------- + +ECDH (Elliptic curve Diffie-Hellman) is widely used in lib-dcrypt for both key +and data storage. This algorithm is also known as ECIES +[https://en.wikipedia.org/wiki/ECIES] (Elliptic curve Integrated Encryption +Scheme). + +When encrypting data, we perform following steps, this is the currently used +algorithm. There is also a legacy algorithm, but since that has not been used +publicly, we do not describe it here. You can deduce it from the code if you +want to. + +ENCRYPT(RECIPIENT-KEY, DATA): + + 1. Ensure recipient key is not point at infinity + 2. Generate new keypair from same group + 3. Choose ephemeral public key as R + 4. Calculate P = R * RECIPIENT-KEY + 5. From P = (x,y) choose x as S + 6. Generate random salt + 7. Use PBKDF2(SHA256, S, salt, 2000) to produce iv+key, and hmac seed or aad + 8. Encrypt data + 9. OUTPUT R, salt and encrypted data. + +In dcrypt-openssl.c, we use EVP_PKEY_derive_* for the actual derivations. +ephemeral public key is exported with EC_POINT_point2oct in compressed form. + +DECRYPT(PRIVATE-KEY, R, SALT, DATA): + + 1. Ensure R is not point at infinity + 2. Calculate P = R * PRIVATE-KEY + 3. From P = (x,y) choose x as S + 4. Use PBKDF2(SHA256, S, salt, 2000) to produce iv+key, and hmac seed or aad + 5. Decrypt data + 6. OUTPUT decrypted data + +Key formats +----------- + +lib-dcrypt can consume keys in PEM format [https://tools.ietf.org/html/rfc1421] +(with or without password), and in Dovecot's special format intended for dict +storage. + +Dovecot's format consists from unencrypted and encrypted keys. You can encrypt +keys using password or another key. There are also two version, version 1 +(deprecated) and version 2 (current). Both versions support either tab or : +separated fields. ECC keys are stored always in compressed form. Version 1 +format is not described as it's deprecated and should not be used. + +Version 2 format +---------------- + +---%<------------------------------------------------------------------------- +public key id: HEX(SHA256(public key in DER format)) +key data: + RSA: i2d_PrivateKey + ECC: BN_bn2mpi using compressed form + +public key: 2:HEX(public key in DER format):public key ID +private key (unencrypted) : 2:key algo oid:0:key data:public key ID +private key (encrypted, key) : 2:key algo oid:1:symmetric algo:salt:digest algo +(for pbkdf2):rounds:encrypted key data:ephemeral public key:digest of +encryption key:public key ID +private key (encrypted, pwd) : 2:key algo oid:2:symmetric algo:salt:digest algo +(for pbkd2f):rounds:encrypted key data:public key ID +---%<------------------------------------------------------------------------- + +File format +----------- + +This library can also generate encrypted files that are encrypted using +asymmetric key pair. File encryption can be done using whatever algorithm(s) +the underlying library supports. For integrity support, either HMAC based or +AEAD based system is used when requested. + +File format is described below + +---%<------------------------------------------------------------------------- +000 - 008 CRYPTED\x03\x07 (MAGIC) +009 - 009 \x02 (VERSION FIELD, 2) +010 - 013 MSB flags +014 - 017 MSB total header length (starting from 000) +018 - cod cipher oid in DER format +cod - mod MAC algorithm oid in DER format +mod - +4 MSB PBKDF2 rounds ++5 - +8 MSB length of key data ++9 - +9 number of key blocks +----- key block ----- ++10 - +10 key type (1 = RSA, 2 = ECC) ++11 - +43 public key id (SHA256 of public key in DER format, point compressed) ++44 - +48 MSB length of ephemeral key ++49 - epk ephemeral key +epk - +4 MSB length of encrypted key ++4 - ek encrypted key +----- end of key block (this can then repeat) ----- +eokb - +4 MSB length of encryption key hash ++4 - ekh encryption key hash +ekh - (eof-maclen) payload data +---%<------------------------------------------------------------------------- + +There is a small script for decrypting these files, see +[attachment:decrypt.rb]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.DoveadmProtocol.HTTP.txt b/doc/wiki/Design.DoveadmProtocol.HTTP.txt new file mode 100644 index 0000000..a9718e4 --- /dev/null +++ b/doc/wiki/Design.DoveadmProtocol.HTTP.txt @@ -0,0 +1,113 @@ +Doveadm HTTP API +================ + +Doveadm HTTP API is available since v2.2.22. It is considered *experimental* in +v2.2.22. Can be considered as stable since 2.2.23. It lets you perform doveadm +commands over HTTP transport. + +Configuration +------------- + +To enable HTTP API, add following to your config file: + +---%<------------------------------------------------------------------------- +service doveadm { + inet_listener http { + port = 8080 + #ssl = yes # uncomment to enable https + } +} +---%<------------------------------------------------------------------------- + +To enable SSL make sure 'ssl=yes' or 'ssl=required' in global settings, and set +'ssl=yes' in the listener. + +You can use unix listener too, and define host to listen on. You also need to +either define 'doveadm_password', or 'doveadm_api_key'. With +'doveadm_password', the username is doveadm. This is going to change in future +release. With API Key you are expected to send + +---%<------------------------------------------------------------------------- +Authorization: X-Dovecot-API Base64(apikey) +---%<------------------------------------------------------------------------- + +header to access the API. (In v2.2.22-2.2.23, this key was incorrectly +"X-Doveadm-API".) + +Usage +----- + +You can see valid commands and their parameters by accessing +'http://host:port/doveadm/v1'. + +To send command(s), you can send following with 'Content-Type: +application/json' + +---%<------------------------------------------------------------------------- +[ + ["command", {"parameter":"value"}, "optional identifer"] +] +---%<------------------------------------------------------------------------- + +In following examples, you can either use Basic or X-Dovecot-API authorization. +X-Dovecot-API usage: + +---%<------------------------------------------------------------------------- +curl -H "Authorization: X-Dovecot-API <base64 dovecot_api_key>" +---%<------------------------------------------------------------------------- + +Basic authorization uses "doveadm" as the username, and doveadm_password +setting as the password: + +---%<------------------------------------------------------------------------- +curl -H "Authorization: Basic <base64 doveadm:doveadm_password>" +---%<------------------------------------------------------------------------- + +To get acceptable routes + +---%<------------------------------------------------------------------------- +curl -H "Authorization: Basic <base64 doveadm:doveadm_password>" +http://server:8080/ +---%<------------------------------------------------------------------------- + +To get acceptable commands and their parameters + +---%<------------------------------------------------------------------------- +curl -H "Authorization: Basic <base64 doveadm:doveadm_password>" +http://server:8080/doveadm/v1 +---%<------------------------------------------------------------------------- + +an example command would be + +---%<------------------------------------------------------------------------- +curl -H "Content-Type: application/json" -H "Authorization: Basic <base64 +doveadm:doveadm_password>" -d +'[["fetch",{"user":"username","field":["uid"],"query":["mailbox","INBOX"]},"c01"]]' +http://server:8080/doveadm/v1 +---%<------------------------------------------------------------------------- + +You can have multiple commands in the array, but for now it is safest *not* to +do so, as some commands may kill the server in certain error conditions and +leaving you without any response. + +Responses are in same format, command is replaced with either "error" or +"doveadmResponse" and parameters with array of response variables. In case of +*successful* command which has *no* output, response is going to be []. + +Errors are indicated with "error" and type, exit-code in response part. + +Logging +------- + +The logs will indicated execute command(s) and also Apache access.log format +strings on requests. In case of fatal errors, the access.log string might be +missing. + +Example clients +--------------- + + * A PoC API client/library written in Python is available at + https://github.com/hnsk/doveadm-http-cli + * See also internal doveadm protocol clients in <Design.DoveadmProtocol.txt> + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.DoveadmProtocol.txt b/doc/wiki/Design.DoveadmProtocol.txt new file mode 100644 index 0000000..10d8bd5 --- /dev/null +++ b/doc/wiki/Design.DoveadmProtocol.txt @@ -0,0 +1,95 @@ +Doveadm protocol +================ + +See also <doveadm HTTP protocol> [Design.DoveadmProtocol.HTTP.txt]. + +doveadm-server can be accessed via UNIX sockets or TCP protocol (by adding +inet_listener to doveadm service). The protocol looks like: + +Initial handshake from client to server: + +---%<------------------------------------------------------------------------- +C: VERSION doveadm-server 1 0 +---%<------------------------------------------------------------------------- + +Note that the spaces you see are TABs. All the fields are TAB-separated. The +server will send you back either: + + * "+" means you are preauthenticated and can start sending commands. This + happens when connecting to the UNIX socket. + * "-" means you need to authenticate first. + +Authentication +-------------- + +The authentication is done with a regular SASL PLAIN authentication, i.e. +"PLAIN<tab>base64(\0username\0password)". Currently the username must be +"doveadm". For example for user=doveadm, password=secret use: + +---%<------------------------------------------------------------------------- +C: PLAIN AGRvdmVhZG0Ac2VjcmV0 +S: + +---%<------------------------------------------------------------------------- + +Running commands +---------------- + +The actual commands are in format: flags<tab>username<tab>command +name[<tab>parameter[<tab>parameter2...]], where the flags can be either empty, +"v" (verbose) or "D" (debug). Note that if the command name has spaces, they +are sent as spaces instead of as tabs (e.g. "quota get", not "quota<tab>get"). +So for example to get a quota for user tss: + +---%<------------------------------------------------------------------------- +C: tss quota get +S: user STORAGE 1814 - 0 user MESSAGE 6 - 0 + +S: + +---%<------------------------------------------------------------------------- + +The storage values are all given in kilobytes. + +The server replies using the same fields TAB-separated as what a regular +doveadm command sends. The reply itself ends with LF. So if the reply is large, +it may return a very long line as a reply. After the reply follows a status +line: + + * "+" = success. + * In future the "+" may be followed by more text, for now you should just + ignore those. + * "-" = failed (the error was probably logged to Dovecot's error log) + * "-NOUSER" = the user doesn't exist + * Other "-SOMETHING" errors may be added in future. + +Available commands +------------------ + +The command names and output are exactly the same as what regular doveadm +commands on command line do. Currently only "mail commands" are available via +doveadm protocol, but this will change in future. + +You can use the doveadm itself to find out what the output format will look +like. For example: + +---%<------------------------------------------------------------------------- +doveadm -f tab search mailbox inbox 1:2 +mailbox-guid uid +fa8cb722dfad9c52b62600007049b30b 125159 +fa8cb722dfad9c52b62600007049b30b 125160 +---%<------------------------------------------------------------------------- + +There are two fields, "mailbox-guid" and "uid" in the output. The title names +won't be sent via doveadm protocol, but everything else will be sent in one +line. So in the above case the protocol output will be: + +---%<------------------------------------------------------------------------- +fa8cb722dfad9c52b62600007049b30b<tab>125159<tab>fa8cb722dfad9c52b62600007049b30b<tab>125160 +---%<------------------------------------------------------------------------- + +Example Clients +--------------- + + * Perl: Net::Doveadm [https://metacpan.org/pod/Net::Doveadm] + * See also HTTP protocol-based clients in <Design.DoveadmProtocol.HTTP.txt> + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Dsync.txt b/doc/wiki/Design.Dsync.txt new file mode 100644 index 0000000..7b51c93 --- /dev/null +++ b/doc/wiki/Design.Dsync.txt @@ -0,0 +1,114 @@ +Dsync Design +============ + +FIXME: This describes the design for v2.0/v2.1. The v2.2 design is somewhat +different. + +Two-way synchronization +----------------------- + +dsync attempts to preserve all changes done by both sides of the synced +mailboxes. + +Mailbox list +------------ + +Mailboxes have 128 bit globally unique IDs, which are used for figuring out +when two mailboxes should actually be synchronized. This solves two major +problems: + + * If mailbox has been renamed in one side, dsync finds it because its GUID + hasn't changed. + * If mailbox has been deleted and recreated, dsync doesn't attempt to sync it + because it's a different mailbox. + +Then there's the problem of how to correctly sync mailbox renames and +deletions. How do you know which side of the sync has the most recent name for +the mailbox? How do you know if one side had deleted mailbox, or if the other +side had created it? To solve these problems, Dovecot v2.0 created a "mailbox +log", which adds a record with mailbox GUID and timestamp whenever mailbox is +renamed or deleted. So: + + * If mailbox has different names on two sides, its "last renamed" timestamp is + looked up from the mailbox list index. The side with the most recent + timestamp is assumed to contain the newer name and the other side's mailbox + is renamed to it. + * If neither side has a "last renamed" timestamp, one side is picked. This + shouldn't happen, except when mailbox log is deleted for some reason or + if the renaming is done outside Dovecot. + * If mailbox exists only on one side, the other side checks if mailbox log + contains a delete record for its GUID. If there is one, the mailbox is + deleted from the other side. If there's not, the mailbox is created and + synced. + * Subscriptions and unsubscriptions are synced in a similar way. But because + it's possible to be subscribed to nonexistent mailboxes, mailbox log can't + contain mailbox GUIDs for them. Instead the first 128 bits of SHA1 of + mailbox name are used. Collisions for mailbox names are highly unlikely, but + even if one happens, the worst that can happen is that user gets + unsubscribed from wrong mailbox. + +dsync writes timestamps to changelog using the original timestamps, so that +dsync's changes won't override changes done by user during sync. + +Mailbox +------- + +When saving new mails, dsync preserves all of their immutable state: + + * GUID + * Received date + * Save date + * Message contents + +It also attempts preserve IMAP UID. This works as long as the other side hasn't +already used the UID for another mail. If it has, dsync doesn't attempt to +preserve the UID, because an IMAP client might have already seen the UID and +cached another mail's contents for it. IMAP requires that message's contents +must never change, so UIDs can't be reused. So whenever an UID conflict +happens, dsync gives messages in both sides a new UID, because it can't know +which message the client had seen, or perhaps user used two clients and both +saw a different message. (This assumes a master/slave replication use case for +dsync.) + +The mutable metadata that dsync preserves is: + + * Message flags and keywords + * Modification sequences (modseqs) + +Flags and keywords are synced based on modseqs. Whichever side has a higher +modseq for the message, its flags and keywords are synced to the other side. +Currently there's no per-flag or per-keyword synchronization, so that if one +side had added \Seen flag and other side had added \Answered flag, one of them +would be dropped. + +Finding what to sync +-------------------- + +dsync can run in full mode or fast mode. Full mode means it goes through all +messages in all mailboxes, making sure everything is fully synchronized. In +fast mode it relies on uidvalidity, uid-next and highest-modseq values to find +out changes. If any of the values changed, the mailbox is included in sync. + +FIXME: A superfast mode should still be implemented, where once a mailbox is +selected for syncing, it should sync only mails whose modseq is higher than a +given one. This would improve performance and network traffic with large +mailboxes. + +Copy optimizations +------------------ + +Before dsync actually starts syncing anything, it first fetched a list of all +to-be-synced messages and adds them to a GUID -> message hash table. Whenever +dsync needs to sync a new message to the other side, it first checks if the +message's GUID already exists on the other side. If it does, it starts a +message copy operation instead of a full save. It's possible that this copy +operation fails if the message just gets expunged from the other side, so there +needs to be fallback handling for this. If the message exists in multiple +mailboxes, a copy from the next mailbox is attempted. If all of them fail, +dsync fallbacks to saving the message. + +FIXME: This optimization currently works only in full sync mode. If this were +to work in fast sync mode, the full mailbox list would have to be looked up +from local side. And this would slow it down.. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Events.txt b/doc/wiki/Design.Events.txt new file mode 100644 index 0000000..c6df740 --- /dev/null +++ b/doc/wiki/Design.Events.txt @@ -0,0 +1,264 @@ +Events (v2.3+) +============== + +Dovecot v2.3 introduces "events", which improves both logging and statistics. +See <Events.txt> for list of all events. + +Each logging call can be attached to a specific event, which can provide more +metadata and context than just the log message string. This will eventually +allow implementing things like machine-parseable (e.g. JSON) log lines +containing key=value pairs, while still keeping the human readable text +available. Each logging event can also be captured and sent to stats, even if +it's not actually logged. Commonly statistics-related events are logged with +debug level. + +Events have: + + * Categories, such as "storage", "mailbox" or "auth". + * Fields, such as 'user=foo@example.com' or 'service=imap'. + * Creation timestamp with microsecond precision. + * Source code file and line number location when sending the event. + * It may have an easy human-readable name. This is important for events that + are expected to be used for statistics, so they can be easily referred to. + * "Forced debug"-flag. Debug logging is enabled for this event regardless of + the global debug log filters. A child event will inherit this flag. + +Events are hierarchical, so they can have parent events. The events always +inherit all of their parents' categories and fields. A child event can replace +a parent's field, and it can also remove a parent's field with +'event_field_clear()'. Ideally most events would have a parent hierarchy that +reaches the top event that was created for the current user/session. This +allows statistics to track which events happened due to which users. In some +cases this may not really be possible, such as an HTTP connection that is +shared across multiple users in the same process. Generic libraries should take +the parent event in function parameters or in a settings struct or similar. + +An event's lifetime is usually the same as the "object" it attaches to. For +example an IMAP client connection should have a single event created at the +beginning of the connection and destroyed at disconnection. The IMAP client +connection event could be used for logging things like "Client connected" and +"Client disconnected" and perhaps some other connection-specific events. +However, most of the logging should be done by new events that have the IMAP +client connection event as their parent. For example IMAP command event should +exist during the execution of the IMAP command, and its parent should be the +IMAP client connection event. Note that there's an automatic "duration" +statistics field that is calculated from the creation of the event to the +(last) sending of the event, so for it to make sense the event lifetime and its +logging also needs to make sense. So for example if the IMAP client connection +event was used for logging many things throughout the session, the "duration" +field would make little sense for most of those events. + +Events are "sent" by logging it. Any e_debug(), e_info(), e_warning() or +e_error() call will also send the event, which may be redirected to the stats +process. Often events that are intended for statistics are sent using the +e_debug() call. The event can be sent to statistics even if it's not actually +logged. Avoid sending events excessively. For example an e_debug() call every +time connection reads or writes something will likely result in a huge amount +of unnecessary debug logging. + +Event names +----------- + +Events that are expected to be used in statistics should have a name. Be +consistent when naming the events. The name's prefix should be the subsystem +that is logging the event. Usually this would be the primary category of the +event. For example imap related events should begin with "imap_" and mailbox +related events begin with "mailbox_". + +The name should consist of only [a-z], [0-9] and '_' characters. + +Current naming conventions for name suffixes: + + * _connected (for connections) + * _disconnected (for connections) + * _finished (when some operation finishes, e.g. IMAP command or HTTP request) + * e.g. http_request_finished, dns_request_finished, imap_command_finished + * This should be used regardless of whether the operation succeeded or + failed. The details would be in fields. + * _retried (if an operation is internally retried one or more times before + it's finished) + +Categories +---------- + +The event categories are hierarchical. For example "mail" category has parent +"mailbox", which has parent "storage". If an event filter contains +"category:storage", it will match the "mail" and "mailbox" child categories as +well. + +Note that a category isn't the same as a service/process name. So for example +imap process has an "imap" category for its IMAP-related events, such as IMAP +client connection and IMAP command related events. Because most events would be +child events under these IMAP events, they would all inherit the "imap" +category. So it would appear that using "category:imap" filter would match most +of the logging from imap process. However, there would likely be some events +that wouldn't have the IMAP client as their parent event, so these wouldn't +match the imap category. + +The same category name must not be duplicated within the process. This is +because event handling is optimized and performs category checking by comparing +the categories' pointers, not names' strings. (Then again, if the struct +event_category variable names were consistent, you'd get duplicate symbol +errors from linker as well.) + +Be careful naming events that go through client and server boundaries. For +example if both lib-dns and dns service use "dns" as their category and also +have identically named "dns_lookup" event, there's no easy way to differentiate +in event filters between these two. So a statistics filter could end up +counting each DNS lookup twice. Since it's more difficult to remember to check +for event naming conflicts, it would be safer to use different category names +entirely. + +The category name should consist of only [a-z], [0-9] and '_' characters. + +Fields +------ + +Each event can have any number of key=value fields. Parent event's fields are +inherited by the child event. + +There are 3 types of fields: + + * strings + * numbers (intmax_t = signed 64bit usually) + * timestamp (struct timeval) + +The fields can be used for various purposes: + + * Filtering events with field_name=value matching + * Counting fields in statistics (most commonly number fields) + * They can include metadata that are internally used by the code. For example + passing data from one plugin to others. + * Later on these fields can be used by the logging system. + +Field names should be consistent across the code. Besides making it easier for +admins to configure the events, this allows statistics code to sum up fields +from different unrelated events. For example if all the networking events +include "ip", "bytes_in" and "bytes_out" fields, statistics can globally track +how much network traffic Dovecot is doing from its own point of view, +regardless of whether it's HTTP traffic or IMAP traffic or something else. + +Current naming conventions: + + * The name should consist of only [a-z], [0-9] and '_' characters. + * Timestamps should have "_time" suffix + * Durations should have "_usecs" suffix and be in microseconds. + * Try to avoid adding extra duration fields for most events. There's the + automatic "duration" field already that contains how long the event has + existed. So usually the event lifetime should be the same as the wanted + duration field. + * Incoming TCP/IP connections should have "remote_ip", "remote_port", + "local_ip" and "local_port" fields + * Outgoing TCP/IP connections should have "ip" and "port" for the remote side. + + * For local side "client_ip" and "client_port" may optionally be used + * NOTE: These are all different from incoming connection's IP/port fields. + This is because often everything starts from an incoming connection, + which will be used as the root event. So we may want to filter e.g. + outgoing HTTP events going to port 80 which were initiated from IMAP + clients that connected to port 993 (port=80 local_port=993) + * Connection reads/writes should be counted in "bytes_in" and "bytes_out" + fields + * These fields were chosen over e.g. network_in/out because a lot of code + is rather generic and can work over TCP/IP or UNIX sockets, or maybe even + any other kind of iostreams. Using a generic bytes_in/out makes it + simpler to count these. If further differentiation is wanted on + statistics side, networking events can be filtered out with "ip". + * These fields are usually easiest updated with 'event_add_int(event, + "bytes_in", istream->v_offset)' and 'event_add_int(event, "bytes_out", + ostream->offset)'. If iostreams aren't used, 'event_inc_int()' maybe be + easier. + * (Local) disk reads should have "disk_read" and "disk_write" fields + * With remote filesystems like NFS it may be difficult to differentiate + between disk IO and network IO. Generally the disk_read/write should be + used for POSIX read() and write() calls from filesystem. + * Counting only read()s and write()s doesn't necessarily translate to + actual disk IO since it may only be accessing the kernel page cache. + Still, this may be useful. + * There is a lot of disk IO performed all over the code, so Dovecot will + likely never include events for all disk reads/writes. + * error=<value> : The operation failed. The <value> may be simply "y" or + contain more details. This field shouldn't exist at all for successful + operations. + * error_code=<value> : Machine-readable error code for a failed operation. If + set, the "error" field must also be set. + +Note that events shouldn't be sent every time when receiving/sending network +traffic. Instead, the bytes_in/out fields should be updated internally so that +whenever the next event is sent it will have an updated traffic number. + +Generally it's not useful for events to be counting operations. Rather each +operation should be a separate event, and the statistics code should be the one +counting them. This way statistics can only be counting e.g. operations with +duration> 1 sec. If the statistics code was seeing only bulk operation counts +this wouldn't be possible. The bytes_in/out and such fields are more of an +exception, because it would be too inefficient to send individual events each +time those were updated. + +Note that even though internally updating a field for an event's parent will be +immediately visible to its children, the update won't be automatically sent to +the stats process. We may need to fix this if it becomes a problem. + +Field inheritance may become problematic also when multiple nested ioloops are +used. For example an outgoing imapc connection could receive a reply, which +synchronously triggers an outgoing quota SQL connection. The quota SQL +connection's parent event likely shouldn't be the imapc connection's event, +because otherwise they could be mixing the IP/port fields and perhaps others. +This isn't necessarily a problem though, but this is why when connection.c +performs outgoing UNIX socket connection it clears the IP/port fields to make +sure they don't exist for the connection event due to inheritance from a parent +event. + +Passthrough events +------------------ + +Passthrough events' main purpose is to make it easier to create temporary +events as part of the event parameter in e_error(), e_warning(), e_info() or +e_debug(). These passthrough events are automatically freed when the e_*() call +is finished. Because this makes the freeing less obvious, it should be avoided +outside e_*()'s event parameter. + +A passthrough event's creation timestamp is the same as the parent event's +timestamp, because its intention is to only complement it with additional +fields. This way the generated event "duration" field is preserved properly. + +The passthrough events also change the API to be more convenient towards being +used in a parameter. Instead of having to use e.g. + +---%<------------------------------------------------------------------------- +event_add_str(event_set_name(event_create(parent), "name"), "key", "value") +---%<------------------------------------------------------------------------- + +The event_passthrough API can be a bit more readable as: + +---%<------------------------------------------------------------------------- +event_create_passthrough(parent)->set_name("name")->add_str("key", +"value")->event(). +---%<------------------------------------------------------------------------- + +The passthrough event is converted to a normal event at the end with the +event() call. Note that this API works by modifying the last created +passthrough event, so it's not possible to have multiple passthrough events +created in parallel. + +Log prefixes +------------ + +Events allow replacing the current log prefix or appending to it. This way for +example opening a mailbox can add a "Mailbox<name>: " prefix and then use +'e_debug(box->event, ...)' without having to specify the mailbox name in every +log message. + +Global events +------------- + +Sometimes there's not really any specific event that a log message would belong +to, or it would be difficult to transfer the event there. In these cases the +old i_debug(), i_info(), i_error(), etc. logging calls can still be used. These +will be using the global event and its logging prefix. + +The global events are pushed/popped in a stack. For example with IMAP the +initial global event is the user's event. During IMAP command execution the +global event is the IMAP command event. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Indexes.Cache.txt b/doc/wiki/Design.Indexes.Cache.txt new file mode 100644 index 0000000..45e75a7 --- /dev/null +++ b/doc/wiki/Design.Indexes.Cache.txt @@ -0,0 +1,137 @@ +Cache file +========== + +Cache file is used for storing immutable data. It supports several different +kinds of fields: + +MAIL_CACHE_FIELD_FIXED_SIZE: + The field size doesn't need to be stored in the cache file. It's always the + same. + +MAIL_CACHE_FIELD_BITMASK: + A fixed size bitmask field. It's possible to add new bits by updating this + field. All the added fields are ORed together. + +MAIL_CACHE_FIELD_VARIABLE_SIZE: + Variable sized binary data. + +MAIL_CACHE_FIELD_STRING: + Variable sized string. + +MAIL_CACHE_FIELD_HEADER: + Variable sized message header. The data begins with a 0-terminated 'uint32_t + line_numbers[]'. The line number exists only for each header, header + continuation lines in multiline headers don't get listed. After the line + numbers comes the list of headers, including the "header-name: " prefix for + each line, LFs and the TABs or spaces for continued lines. + +The last 3 variable sized fields are treated identically by the cache file +code. Their main purpose is to make it easier for "dump cache file's contents" +programs ('src/util/idxview') to do their job. + +Locking +------- + +Because cache file is typically used in potentially long-running operations, +such as with IMAP command 'FETCH 1:* (BODY.PEEK[] ENVELOPE BODYSTRUCTURE)' it's +important that updating the cache file doesn't block out any other readers. +Also because the readers are often also writers (if something isn't cached, +it's added there), it's important that they don't block writers either. + +Reading cache files requires no locking. Writing is done by first locking the +file, reserving some space to write to, and immediately after that unlocking +the file. This way the transaction can keep writing to the cache file as long +as it wants to without blocking other writers. When the transaction is +committed, the updated cache offsets are written to the transaction log which +makes them visible to other processes. + +This also means that it's possible for two processes to write the same cached +fields twice to the cache file. Because the data written to the cache file are +really just cached data, the fields' contents are identical. Having the data +exist twice (or even more times) means wasting some disk space, but otherwise +it isn't a problem. The duplicates are dropped the next time the file is +compressed. + +Cache decisions +--------------- + +Dovecot tries to be smart about what it keeps in the cache file. If the client +never fetches the cached data, it's just waste of disk space and disk I/O. + +The caching decisions are: + +MAIL_CACHE_DECISION_NO: + This field isn't cached currently. + +MAIL_CACHE_DECISION_TEMP: + This field is cached for new mails. + +MAIL_CACHE_DECISION_YES: + This field is cached for all mails. + +Normally Dovecot changes the decisions based on what fields are fetched and for +what messages. A specific decision can be forced by ORing it with +'MAIL_CACHE_DECISION_FORCED'. + +'mail-cache-decisions.c' file contains the rules how Dovecot changes the +decisions. The following is copied from the file: + +Users can be divided to three groups: + + 1. Most users will use only a single IMAP client which caches everything + locally. For these users it's quite pointless to do any kind of caching as + it only wastes disk space. That might also mean more disk I/O. + 2. Some users use multiple IMAP clients which cache everything locally. These + could benefit from caching until all clients have fetched the data. After + that it's useless. + 3. Some clients don't do permanent local caching at all. For example Pine and + webmails. These clients would benefit from caching everything. Some locally + caching clients might also access some data from server again, such as when + searching messages. They could benefit from caching only these fields. + +After thinking about these a while, I figured out that people who care about +performance most will be using Dovecot optimized LDA anyway which updates the +indexes/cache immediately. In that case even the first user group would benefit +from caching the same way as second group. LDA reads the mail anyway, so it +might as well extract some information about it and store them into cache. + +So, group 1. and 2. could be optimally implemented by keeping things cached +only for a while. I thought a week would be good. When cache file is +compressed, everything older than week will be dropped. + +But how to figure out if user is in group 3? One quite easy rule would be to +see if client is accessing messages older than a week. But with only that rule +we might have already dropped useful cached data. It's not very nice if we have +to read and cache it twice. + +Most locally caching clients always fetch new messages (all but body) when they +see them. They fetch them in ascending order. Noncaching clients might fetch +messages in pretty much any order, as they usually don't fetch everything they +can, only what's visible in screen. Some will use server side sorting/threading +which also makes messages to be fetched in random order. Second rule would then +be that if a session doesn't fetch messages in ascending order, the fetched +field type will be permanently cached. + +So, we have three caching decisions: + + 1. Don't cache: Clients have never wanted the field + 2. Cache temporarily: Clients want this only once + 3. Cache permanently: Clients want this more than once + +Different mailboxes have different decisions. Different fields have different +decisions. + +There are some problems, such as if a client accesses message older than a +week, we can't know if user just started using a new client which is just +filling its local cache for the first time. Or it might be a client user hasn't +just used for over a week. In these cases we shouldn't have marked the field to +be permanently cached. User might also switch clients from non-caching to +caching. + +So we should re-evaluate our caching decisions from time to time. This is done +by checking the above rules constantly and marking when was the last time the +decision was right. If decision hasn't matched for two months, it's changed. I +picked two months because people go to at least one month vacations where they +might still be reading mails, but with different clients. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Indexes.MailIndexApi.txt b/doc/wiki/Design.Indexes.MailIndexApi.txt new file mode 100644 index 0000000..e7f597b --- /dev/null +++ b/doc/wiki/Design.Indexes.MailIndexApi.txt @@ -0,0 +1,47 @@ +Mail Index API +============== + +'lib-index/mail-index.h' contains the functions to access the index files. +'mail-cache.h' contains the functions to access the cache file. + +The purpose of the main structures are: + + * 'struct mail_index': Global state of the index. + * 'struct mail_index_view': You can have multiple views to the index. The + views see new messages come and expunged messages go only when it's being + explicitly synchronized. With mmaped indexes you can't really trust the + record data (flags, keywords, extensions) not to change. This doesn't matter + with IMAP. + * 'struct mail_index_map': Index file is accessed via maps. Views can point to + one or more maps. Maps can be shared by different views. Maps can contain + either mmap()ed memory areas pointing to the index file, or a in-memory copy + of it. + * 'struct mail_index_transaction': In-memory list of changes to be written to + the transaction log. The writing is done only when the transaction is + committed. + +Views and maps +-------------- + +In general you access all the data in the index files via views. The mails are +accessed using sequence numbers, which change only when the view is +synchronized. + +For accessing messages with their UIDs, you'll first need to convert them to +sequences with either 'mail_index_lookup_uid()' or +'mail_index_lookup_uid_range()'. + +'mail_index_lookup()' can be used to look up a single record's UID and flags. +The returned record points to the latest map, so that it contains the latest +flag changes. If the message was already expunged from the latest map, it +returns 0. + +'mail_index_lookup_full()' can be used to get also the map where the message +was found. This can be important with extensions. If extension record's state +depends on the extension header, they must be looked up from the same map. For +this reason there exists 'mail_index_map_get_header_ext()' and +'mail_index_lookup_ext_full()' functions which take the map as parameter. The +non-map versions return the data from the latest map if the message hasn't been +expunged. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Indexes.MainIndex.txt b/doc/wiki/Design.Indexes.MainIndex.txt new file mode 100644 index 0000000..db0fb0f --- /dev/null +++ b/doc/wiki/Design.Indexes.MainIndex.txt @@ -0,0 +1,284 @@ +Main index +========== + +The main index can be used to quickly look up messages' UIDs, flags, keywords +and extension-specific data, such as cache file or mbox file offsets. + +Reading, writing and locking +---------------------------- + +Reading 'dovecot.index' file requires locking, unfortunately. Shared read +locking is done using the standard index locking method specified in +'lock_method' setting ('lock_method' parameter for 'mail_index_open()'). + +Writing to index files requires transaction log to be exclusively locked first. +This way the index locking only has to worry about existing read locks. The +locking works by first trying to lock the index with the standard locking +method, but if it couldn't acquire the lock in two seconds, it'll fallback to +copying the index file to a temporary file, and when unlocking it'll 'rename()' +the temporary file over the 'dovecot.index' file. Note that this is safe only +because of the exclusive transaction log lock. This way the writers are never +blocked by readers who are allowed to keep the shared lock as long as they +want. + +The copy-locking is used always when doing anything that could corrupt the +index file if it crashed in the middle of an operation. For example if the +header or record size changes, or if messages are expunged. New messages can be +appended however, because the message count in the header is updated last. +Expunging the last messages would probably be safe also (because only the +header needs updating), but it's not done currently. + +The index file should never be directly modified. Everything should go through +the transaction log, and the only time the index needs to be write-locked is +when transactions are written to it. + +Currently the index file is updated whenever the backend mailbox is +synchronized. This isn't necessary, because an old index file can be updated +using the transaction log. In future there could be some smarter decisions +about when writing to the index isn't worth the extra disk writes. + +Header +------ + +---%<------------------------------------------------------------------------- +struct mail_index_header { + uint8_t major_version; + uint8_t minor_version; + + uint16_t base_header_size; + uint32_t header_size; + uint32_t record_size; + + uint8_t compat_flags; + uint8_t unused[3]; + + uint32_t indexid; + uint32_t flags; + + uint32_t uid_validity; + uint32_t next_uid; + + uint32_t messages_count; + uint32_t unused_old_recent_messages_count; + uint32_t seen_messages_count; + uint32_t deleted_messages_count; + + uint32_t first_recent_uid; + uint32_t first_unseen_uid_lowwater; + uint32_t first_deleted_uid_lowwater; + + uint32_t log_file_seq; + uint32_t log_file_tail_offset; + uint32_t log_file_head_offset; + + uint64_t unused_old_sync_size; + uint32_t unused_old_sync_stamp; + + uint32_t day_stamp; + uint32_t day_first_uid[8]; +} +---%<------------------------------------------------------------------------- + +Fields that won't change without recreating the index: + +major_version: + If this doesn't match 'MAIL_INDEX_MAJOR_VERSION', don't try to read the + index. Dovecot recreates the index file then. + +minor_version: + If this doesn't match 'MAIL_INDEX_MINOR_VERSION' there are some backwards + compatible changes in the index file (typically header fields). Try to + preserve the headers and the minor version when updating the index file. + +base_header_size: + Extension headers begin after the base headers. This is normally the same as + 'sizeof(struct mail_index_header)'. + +header_size: + Records begin after base and extension headers. + +record_size: + Size of each record and its extensions. Initially the same as 'sizeof(struct + mail_index_record)'. + +compat_flags: + Currently there is just one compatibility flag: + 'MAIL_INDEX_COMPAT_LITTLE_ENDIAN'. Dovecot doesn't try to bother to read + different endianess files, they're simply recreated. + +indexid: + Unique index file ID. This is used to make sure that the main index, + transaction log and cache file are all part of the same index. + +Header flags: + +MAIL_INDEX_HDR_FLAG_CORRUPTED: + Set whenever the index file is found to be corrupted. If the reader notices + this flag, it shouldn't try to continue using the index. + +MAIL_INDEX_HDR_FLAG_HAVE_DIRTY: + This index has records with 'MAIL_INDEX_MAIL_FLAG_DIRTY' flag set. + +MAIL_INDEX_HDR_FLAG_FSCK: + Call 'mail_index_fsck()' as soon as possible. This flag isn't actually set + anywhere currently. + +Message UIDs and counters: + +uid_validity: + IMAP UIDVALIDITY field. Initially can be 0, but after it's set we don't + currently try to even handle the case of UIDVALIDITY changing. It's done by + marking the index file corrupted and recreating it. That's a bit ugly, but + typically the UIDVALIDITY never changes. + +next_uid: + UID given to the next appended message. Only increases. + +messages_count: + Number of records in the index file. + +recent_messages_count: + Number of records with 'MAIL_RECENT' flag set. + +seen_messages_count: + Number of records with 'MAIL_SEEN' flag set. + +deleted_messages_count: + Number of records with 'MAIL_DELETED' flag set. + +first_recent_uid_lowwater: + There are no UIDs lower than this with 'MAIL_RECENT' flag set. + +first_unseen_uid_lowwater: + There are no UIDs lower than this *without* 'MAIL_SEEN' flag set. + +first_deleted_uid_lowwater: + There are no UIDs lower than this with 'MAIL_DELETE' flag set. + +The lowwater fields are used to optimize searching messages with/without a +specific flag. + +Fields related to syncing: + +log_file_seq: + Log file the log_*_offset fields point to. + +log_file_int_offset, log_file_ext_offset: + All the internal/external transactions before this offset in the log file are + synced to the index. External transactions are synced more often than + internal, so 'log_file_int_offset' <= 'log_file_ext_offset'. + +sync_size, sync_stamp: + Used by the mailbox backends to store their synchronization information. Some + day these should be removed and replaced with extension headers. + +Then there are day fields: + +day_stamp: + UNIX timestamp to the beginning of the day when new records were last added + to the index file. + +day_first_uid[8]: + These fields are updated when 'day_stamp' < today. The [0..6] are first moved + to [1..7], then [0] is set to the first appended UID. So they contain the + first UID of the day for last 8 days when messages were appended. + +The 'day_first_uid[]' fields are used by cache file compression to decide when +to drop 'MAIL_CACHE_DECISION_TEMP' data. + +Extension headers +----------------- + +After the base header comes a list of extensions and their headers. The first +extension begins from 'mail_index_header.base_header_size' offset. The second +begins after the first one's 'data[]' and so on. The extensions always begin +64bit aligned however, so you may need to skip a few bytes always. Read the +extensions as long as the offset is smaller than +'mail_index_header.header_size'. + +---%<------------------------------------------------------------------------- +struct mail_index_ext_header { + uint32_t hdr_size; /* size of data[] */ + uint32_t reset_id; + uint16_t record_offset; + uint16_t record_size; + uint16_t record_align; + uint16_t name_size; + /* unsigned char name[name_size] */ + /* unsigned char data[hdr_size] (starting 64bit aligned) */ +}; +---%<------------------------------------------------------------------------- + +'reset_id', record offset, size and alignment is explained in +<Design.Indexes.TransactionLog.txt>'s 'struct mail_transaction_ext_intro'. + +Records +------- + +There are 'hdr.messages_count' records in the file. Each record contains at +least two fields: Record UID and flags. The UID is always increasing for the +records, so it's possible to find a record by its UID with binary search. The +record size is specified by 'mail_index_header.record_size'. + +The flags are a combination of 'enum mail_flags' and 'enum +mail_index_mail_flags'. There exists only one index flag currently: +'MAIL_INDEX_MAIL_FLAG_DIRTY'. If a record has this flag set, it means that the +mailbox syncing code should ignore the flag in the mailbox and use the flag in +the index file instead. This is used for example with mbox and +'mbox_lazy_writes=yes'. It also allows having modifiable flags for read-only +mailboxes. + +The rest data is stored in record extensions. + +Keywords +-------- + +The keywords are stored in record extensions, but for better performance and +lower disk space usage in transaction logs, they are quite tightly integrated +to the index file code. + +The list of keywords is stored in "keywords" extension header: + +---%<------------------------------------------------------------------------- +struct mail_index_keyword_header { + uint32_t keywords_count; + /* struct mail_index_keyword_header_rec[] */ + /* char name[][] */ +}; +struct mail_index_keyword_header_rec { + uint32_t unused; /* for backwards compatibility */ + uint32_t name_offset; /* relative to beginning of name[] */ +}; +---%<------------------------------------------------------------------------- + +The unused field originally contained 'count' field, but while writing this +documentation I noticed it's not actually used anywhere. Apparently it was +added there accidentally. It'll be removed in later versions. + +So there exists 'keywords_count' keywords, each listed in a NUL-terminated +string beginning from 'name_offset'. + +Since crashing in the middle of updating the keywords list pretty much breaks +the keywords, adding new keywords causes the index file to be always copied to +a temporary file and be replaced. + +The keywords in the records are stored in a "keywords" extension bitfield. So +the nth bit in the bitfield points to the nth keyword listed in the header. + +It's not currently possible to safely remove existing keywords. + +Extensions +---------- + +The extensions only specify their wanted size and alignment, the index file +syncing code is free to assign any offset inside the record to them. The +extensions may be reordered at any time. + +Dovecot's current extension ordering code works pretty well, but it's not +perfect. If the extension size isn't the same as its alignment, it may create +larger records than necessary. This will be fixed later. + +The records size is always divisible by the maximum alignment requirement. This +isn't strictly necessary either, so it could be fixed later as well. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Indexes.TransactionLog.txt b/doc/wiki/Design.Indexes.TransactionLog.txt new file mode 100644 index 0000000..e86751b --- /dev/null +++ b/doc/wiki/Design.Indexes.TransactionLog.txt @@ -0,0 +1,265 @@ +Transaction log +=============== + +The transaction log is a bit similar to transaction logs in databases. All the +updates to the main index files are first written to the transaction log, and +only after that the main index file is updated. There are several advantages to +this: + + * It provides atomic transactions: The transaction either succeeds, or it + doesn't. For example if a transaction sets a flag to one message and removes + it from another, it's guaranteed that both changes happen. + * When updating the changes to the main index file, the last thing that's + done is to update the "transaction log position" in the header. So if + Dovecot crashes after having updated only the first flag, the next time + the mailbox is opened both of the changes are done all over again. + * It allows another process to quickly see what changes have been made. For + example IMAP needs to get a list of external changes after each command. + * This is also important when storing the index files in NFS or in a + clustered filesystem. Instead of re-reading the whole index file after + each external change, Dovecot can simply read the new changes from the + transaction log and apply them to the in-memory copy of the main index. + In-memory caching of 'dovecot.index.cache' file also relies on the + transaction log telling what parts of the file has changed. + * In future the transaction logs can be somewhat easily used to implement + replication. + +Internal vs. external +--------------------- + +Transactions are either internal or external. The difference is that external +transactions describe changes that were already made to the mailbox, while +internal transactions are commands to do something to the mailbox. When +beginning to synchronize a mailbox with index files, the index file is first +updated with all the external changes, and the uncommitted internal +transactions are applied on top of them. + +When synchronizing the mailbox, using the synchronization transaction writes +only external transactions. Also if the index file is updated when saving new +mails to the mailbox, the append transactions must be external. This is because +the changes are already in the mailbox at the time the transaction is read. + +Reading and writing +------------------- + +Reading transaction logs doesn't require any locking at all. Writing is +exclusively locked using the index files' default lock method (as specified by +the 'lock_method' setting). + +A new log is created by first creating a 'dovecot.index.log.newlock' dotlock +file. Once you have the dotlock, check again that the 'dovecot.index.log' +wasn't created (or recreated) by another process. If not, go ahead and write +the log header to the dotlock file and finally 'rename()' it to +'dovecot.index.log'. + +Currently there doesn't exist actual transaction boundaries in the log file. +All the changes in a transaction are simply written as separate records to the +file. Each record begins with a 'struct mail_transaction_header', which +contains the record's size and type. The size is in <lockless integer format> +[Design.Indexes.txt]. + +The first transaction record is written with the size field being 0. Once the +whole transaction has been written, the 0 is updated with the actual size. This +way the transaction log readers won't see partial transactions because they +stop at the size=0 if the transaction isn't fully written yet. + +Note that because there are no transaction boundaries, there's a small race +condition here with mmap()ed log files: + + 1. Process A: write() half of the transaction + 2. Process B: mmap() the file. + 3. Process A: write() the rest of the transaction, updating the size=0 also + 4. Process B: parse the log file. it'll go past the original size=0 because + the size had changed in the mmap, but it stops in the middle of the + transaction because the mmap size doesn't contain the whole transaction + +This probably isn't a big problem, because I've never seen this happen even +with stress tests. Should be fixed at some point anyway. + +Header +------ + +The transaction log's header never changes, except the indexid field may be +overwritten with 0 if the log is found to be corrupted. The fields are: + +major_version: + If this doesn't match 'MAIL_TRANSACTION_LOG_MAJOR_VERSION', don't try to + parse it. If Dovecot sees this, it'll recreate the log file. + +minor_version: + If this doesn't match 'MAIL_TRANSACTION_LOG_MINOR_VERSION', the log file + contains some backwards compatible changes. Currently you can just ignore + this field. + +hdr_size: + Size of the log file's header. Use this instead of 'sizeof(struct + mail_transaction_log_header)', so that it's possible to add new fields and + still be backwards compatible. + +indexid: + This field must match to main index file's indexid field. + +file_seq: + The file's creation sequence. Must be increasing. + +prev_file_seq, prev_file_offset: + Contains the sequence and offset of where the last transaction log ended. + When transaction log is rotated and the reader's "sync position" still points + to the previous log file, these fields allow it to easily check if there had + been any more changes in the previous file. + +create_stamp: + UNIX timestamp when the file was created. Used in determining when to rotate + the log file. + +Record header +------------- + +The transaction record header ('struct mail_transaction_header') contains +'size' and 'type' fields. The 'size' field is in <lockless integer format> +[Design.Indexes.txt]. A single transaction record may contain multiple changes +of the same type, although some types don't allow this. Because the size of the +transaction record for each type is known (or can be determined from the +type-specific record contents), the 'size' field can be used to figure out how +many changes need to be done. So for example a record can contain: + + * 'struct mail_transaction_header { type = MAIL_TRANSACTION_APPEND, size = + sizeof(struct mail_index_record) * 2 }' + * 'struct mail_index_record { uid = 1, flags = 0 } ' + * 'struct mail_index_record { uid = 2, flags = 0 } ' + +UIDs +---- + +Many record types contain 'uint32_t uid1, uid2' fields. This means that the +changes apply to all the messages in uid1..uid2 range. The messages don't +really have to exist in the range, so for example if the first messages in the +mailbox had UIDs 1, 100 and 1000, it would be possible to use uid1=1, uid2=1000 +to describe changes made to these 3 messages. This also means that it's safe to +write transactions describing changes to messages that were just expunged by +another process (and already written to the log file before our changes). + +Appends +------- + +As described above, the appends must be in external transactions. The append +transaction's contents is simply the 'struct mail_index_record', so it contains +only the message's UID and flags. The message contents aren't written to +transaction log. Also if the message had any keywords when it was appended, +they're in a separate transaction record. + +Expunges +-------- + +Because expunges actually destroy messages, they deserve some extra protection +to make it less likely to accidentally expunge wrong messages in case of for +example file corruption. The expunge transactions must have +'MAIL_TRANSACTION_EXPUNGE_PROT' ORed to the transaction type field. If an +expunge type is found without it, assume a corrupted transaction log. + +Flag changes +------------ + +The flag changes are described in: + +---%<------------------------------------------------------------------------- +struct mail_transaction_flag_update { + uint32_t uid1, uid2; + uint8_t add_flags; + uint8_t remove_flags; + uint16_t padding; +}; +---%<------------------------------------------------------------------------- + +The 'padding' is ignored completely. A single flag update structure can add new +flags or remove existing flags. Replacing all the files works by setting +'remove_flags = 0xFF' and the 'add_flags' containing the new flags. + +Keyword changes +--------------- + +Specific keywords can be added or removed one keyword at a time: + +---%<------------------------------------------------------------------------- +struct mail_transaction_keyword_update { + uint8_t modify_type; /* enum modify_type : MODIFY_ADD / MODIFY_REMOVE +*/ + uint8_t padding; + uint16_t name_size; + /* unsigned char name[]; + array of { uint32_t uid1, uid2; } + */ +}; +---%<------------------------------------------------------------------------- + +There is padding after 'name[]' so that uid1 begins from a 32bit aligned +offset. + +If you want to replace all the keywords (eg. IMAP's 'STORE 1:* FLAGS (keyword)' +command), you'll first have to remove all of them with +'MAIL_TRANSACTION_KEYWORD_RESET' and then add the new keywords. + +Extensions +---------- + +Extension records allow creating and updating extension-specific header and +message record data. For example messages' offsets to cache file or mbox file +are stored in extensions. + +Whenever using an extension, you'll need to first write +'MAIL_TRANSACTION_EXT_INTRO' record. This is a bit kludgy and hopefully will be +replaced by something better in future. The intro contains: + +---%<------------------------------------------------------------------------- +struct mail_transaction_ext_intro { + /* old extension: set ext_id. don't set name. + new extension: ext_id = (uint32_t)-1. give name. */ + uint32_t ext_id; + uint32_t reset_id; + uint32_t hdr_size; + uint16_t record_size; + uint16_t record_align; + uint16_t unused_padding; + uint16_t name_size; + /* unsigned char name[]; */ +}; +---%<------------------------------------------------------------------------- + +If the extension already exists in the index file (it can't be removed), you +can use the 'ext_id' field directly. Otherwise you'll need to give a name to +the extension. It's always possible to just give the name if you don't know the +existing extension ID, but this uses more space of course. + +'reset_id' contains kind of a "transaction validity" field. It's updated with +'MAIL_TRANSACTION_EXT_RESET' record, which also causes the extension records' +contents to be zeroed. If an introduction's 'reset_id' doesn't match the last +EXT_RESET, it means that the extension changes are stale and they must be +ignored. For example: + + * 'dovecot.index.cache' file's 'file_seq' header is used as a 'reset_id'. + Initially it's 1. + * Process A: Begins a cache transaction, updating some fields in it. + * Process B: Decides to compress the cache file, and issues a 'reset_id = 2' + change. + * Process A: Commits the transaction with 'reset_id = 1', but the cache file + offsets point to the old file, so the changes must be ignored. + +'hdr_size' specifies the number of bytes the extension wants to have in the +index file's header.'record_size' specifies the number of bytes it wants to use +for each record. The sizes may grow or shrink any time.'record_align' contains +the required alignmentation for the field. For example if the extension +contains a 32bit integer, you want it to be 32bit aligned so that the process +won't crash in CPUs which require proper alignmentation. Then again if you want +to access the field as 4 bytes, the alignmentation can be 1. + +Extension record updates typically are message-specific, so the changes must be +done for each message separately: + +---%<------------------------------------------------------------------------- +struct mail_transaction_ext_rec_update { + uint32_t uid; + /* unsigned char data[]; */ +}; +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Indexes.txt b/doc/wiki/Design.Indexes.txt new file mode 100644 index 0000000..00b55a2 --- /dev/null +++ b/doc/wiki/Design.Indexes.txt @@ -0,0 +1,70 @@ +Dovecot's index files +===================== + +Dovecot's index files consist of three different files: + + * <Main index file> [Design.Indexes.MainIndex.txt] ('dovecot.index') + * <Transaction log> [Design.Indexes.TransactionLog.txt] ('dovecot.index.log' + and 'dovecot.index.log.2') + * <Cache file> [Design.Indexes.Cache.txt] ('dovecot.index.cache') + +See <IndexFiles.txt> for more generic information about what they contain and +why. + +The index files can be accessed using <mail-index.h API> +[Design.Indexes.MailIndexApi.txt]. + +Locking +------- + +The index files are designed so that readers cannot block a writer, and write +locks are always short enough not to cause other processes to wait too long. +Dovecot v0.99's index files didn't do this, and it was common to get lock +timeouts when using multiple connections to the same large mailbox. + +The main index file is the only file which has read locks. They can however +block the writer only for two seconds (and even this could be changed to not +block at all). The writes are locked only for the duration of the mailbox +synchronization. + +Transaction logs don't require read locks. The writing is locked for the +duration of the mailbox synchronization, and also for single transaction +appends. + +Cache files doesn't require read locks. They're locked for writing only for the +duration of allocating space inside the file. The actual writing inside the +allocated space is done without any locks being held. + +In future these could be improved even further. For example there's no need to +keep any index files locked while synchronizing, as long the mailbox backend +takes care of the locking issues. Also writing to transaction log could work in +a similar way to cache files: Lock, allocate space, unlock, write. + +Lockless integers +----------------- + +Dovecot uses several different techniques to allow reading files without +locking them. One of them uses fields in a "lockless integer" format. Initially +these fields have "unset" value. They can be set to a wanted value in range +0..2^28 (with 32bit fields) once, but they cannot be changed. It would be +possible to set them back to "unset", but setting them the second time isn't +safe anymore, so Dovecot never does this. + +The lockless integers work by allocating one bit from each byte of the value to +"this value is set" flag. The reader then verifies that the flag is set for the +value's all bytes. If all of them aren't set, the value is still "unset". +Dovecot uses the highest bit for this flag. So for example: + + * 0x00000000: The value is unset + * 0xFFFF7FFF: The value is unset, because one of the bytes didn't have the + highest bit set + * 0xFFFFFFFF: The value is 2^28-1 + * 0x80808080: The value is 0 + * 0x80808180: The value is 0x80 + +Dovecot contains 'mail_index_uint32_to_offset()' and +'mail_index_offset_to_uint32()' functions to translate values between integers +and lockless integers. The "unset" value is returned as 0, so it's not possible +to differentiate between "unset" and "set" 0 values. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.InputStreams.txt b/doc/wiki/Design.InputStreams.txt new file mode 100644 index 0000000..c64d4cb --- /dev/null +++ b/doc/wiki/Design.InputStreams.txt @@ -0,0 +1,207 @@ +Input Streams +============= + +'lib/istream.h' describes Dovecot's input streams. Input streams can be stacked +on top of each others as many times as wanted. + +Input streams actually reading data: + + * file: Read data from fd using 'pread()' for files and 'read()' for + non-files. + * unix: Read data from UNIX socket. Similar to file, but supports receiving + file descriptors. + * mmap: Read data from file using 'mmap()'. This usually seems to be slower + than just using it with 'read()', so this input stream is probably quite + unnecessary. + * data: Read data from memory. + +Input stream filters: + + * concat: Concatenate multiple input streams together + * chain: Chain multiple input streams together. Similar to istream-concat, but + more istreams can be added after initialization and EOF needs to be + explicitly added. + * seekable: Make a number of (possibly non-seekable) input streams into a + single seekable input stream. If all of the input streams are already + seekable, a concat stream is created instead. + * Usually the only non-seekable input streams are non-file fds, such as + pipes or sockets. + * crlf: Change all newlines to either LFs or CRLFs, by adding or removing CRs + as necessary. + * limit: Limit input stream's length, so after reading a given number of bytes + it returns EOF. + * sized: Require istream's length to be exactly the given size, or the last + read returns error. + * timeout: Fail the read when given timeout is reached. + * try: Read from the first input stream that doesn't fail with EINVAL. + * tee: Fork an input stream to multiple streams that can be read + independently. + * multiplex: Multiplex-iostreams support multiple iostream channels inside a + single parent istream. + * callback: Build an input stream by calling callback functions that return + the data. + * base64-encoder, base64-decoder: Encode/decode base64. + * failure-at: Insert a failure at the specified offset. This can be useful for + testing. + * hash: Calculate hash of the istream while it's being read. + * lib-mail/dot: Read SMTP-style DATA input where the input ends with an empty + "." line. + * lib-mail/header-filter: Add/remove/modify email headers. + * lib-compression/*: Read zlib/bzlib/lz4/lzma compressed data. + +Reading +------- + +'i_stream_read()' tries to read more data into the stream's buffer. It returns: + + * -2: Nothing was read, because buffer is full. + * -1: Either input reached EOF, or read failed and stream_errno was set. + * 0: Input stream is non-blocking, and no more input is available now. + * >0: Number of bytes read. + +Reading from a stream doesn't actually go forward in the stream, that needs to +be done manually with 'i_stream_skip()'. This makes it easy to read full data +records into the stream directly instead of creating separate buffers. For +example when reading line-based input you can keep reading input into the +stream until you find LF and then just access the string directly from the +input buffer. There are actually helper functions for +this:'i_stream_next_line()' attempts to return the next line if available, +'i_stream_read_next_line()' does the same but does a read to try to get the +data. + +Because more and more data can be read into the buffer, the buffer size is +typically limited, and once this limit is reached read returns -2. The buffer +size is usually given as parameter to the 'i_stream_create_*()', filters use +their parent stream's buffer size. The buffer size can be also changed with +'i_stream_set_max_buffer_size()'. Figuring out what the buffer size should be +depends on the situation. It should be large enough to contain all valid input, +but small enough that users can't cause a DoS by sending a too large record and +having Dovecot eat up all the memory. + +Once read returns -1, the stream has reached EOF. 'stream->eof=TRUE' is also +set. In this situation it's important to remember that there may still be data +available in the buffer. If 'i_stream_have_bytes_left()' returns FALSE, there +really isn't anything left to read. + +Whenever i_stream_read() returns >0, all the existing pointers are potentially +invalidated. v2.3+: When i_stream_read() returns<= 0, the data previously +returned by i_stream_get_data() are still valid, preserved in "snapshots". +(<v2.3 may or may not have invalidated them.) + +Example: + +---%<------------------------------------------------------------------------- +/* read line-based data from file_fd, buffer size has no limits */ +struct istream *input = i_stream_create_fd(file_fd, (size_t)-1, FALSE); +const char *line; + +/* return the last line also even if it doesn't end with LF. + this is generally a good idea when reading files (but not a good idea + when reading commands from e.g. socket). */ +i_stream_set_return_partial_line(input, TRUE); +while ((line = i_stream_read_next_line(input)) != NULL) { + /* handle line */ +} +i_stream_destroy(&input); +---%<------------------------------------------------------------------------- + +Internals +--------- + +'lib/istream-internal.h' describes the internal API that input streams need to +implement. The methods that need to be implemented are: + + * 'read()' is the most important function. It can also be tricky to get it + completely bug-free. See the existing unit tests for other istreams and try + to test the edge cases as well (such as ability to read one byte at a time + and also with max buffer size of 1). When it needs to read from parent + streams, try to use 'i_stream_read_memarea(parent)' if possible so a new + snapshot isn't unnecessarily created (see the snapshot discussion below). + * 'seek(v_offset, mark)' seeks to given offset. The 'mark' parameter is + necessary only when it's difficult to seek backwards in the stream, such as + when reading compressed input. + * 'sync()' removes everything from internal buffers, so that if the underlying + file has changed the changes get noticed immediately after sync. + * 'get_size(exact)' returns the size of the input stream, if it's known. If + 'exact=TRUE', the returned size must be the same how many bytes can be read + from the input. If 'exact=FALSE', the size is mainly used to compare against + another stat to see if the underlying input had changed. For example with + compressed input the size could be the compressed size. + * 'stat(exact)' stats the file, filling as much of the fields as makes sense. + 'st_size' field is filled the same way as with 'get_size()', or set to -1 if + it's unknown. + * 'snapshot(prev_snapshot)' creates a snapshot of the data that is currently + available via i_stream_get_data(), merges it with prev_snapshot (if any) and + returns the merged snapshot (see below more more details). + +There are some variables available: + + * 'buffer' contains pointer to the data. + * First 'skip' bytes of the buffer are already skipped over (with + 'i_stream_skip()' or seeking). + * Data up to 'pos' bytes (beginning after 'skip') in the buffer are available + with 'i_stream_get_data()'. If pos=skip, it means there is no available data + in the buffer. + +If your input stream needs a write buffer, you can use some of the common +helper functions and variables: + + * 'w_buffer' contain the pointer where you can write data. It should be kept + in sync with 'buffer'. + * 'buffer_size' specifies the buffer's size, and 'max_buffer_size' the max. + size the buffer can be grown to. + * 'i_stream_try_alloc(wanted_size, size_r)' can be used when you want to store + 'wanted_bytes' into 'w_buffer'. If the buffer isn't large enough for it, + it's grown if possible. The buffer isn't grown above the stream's max buffer + size. The returned 'size_r' specifies how many bytes are actually available + for writing at 'stream->w_buffer + stream->pos'. + * 'i_stream_alloc(size) is like 'i_stream_try_alloc()', except it always + succeeds allocating'size` bytes, even if it has to grow the buffer larger + then the stream's max buffer size. + * Lower-level memory allocation functions: + * 'i_stream_w_buffer_realloc(old_size)' reallocates 'w_buffer' to the + current 'buffer_size'. If memarea's refcount is 1, this can be done with + 'i_realloc()', otherwise new memory is allocated. + * 'i_stream_grow_buffer(bytes)' grows the 'w_buffer' by the given number of + bytes, if possible. It won't reach the stream's current max buffer size. + The caller must verify from 'buffer_size' how large the buffer became as + a result of this call. + * 'i_stream_compress()' attempts to compress the current 'w_buffer' by + removing already-skipped data with 'memmove()'. If 'skip' is 0, it does + nothing. Note that this function must not be called if 'memarea' has + refcount>1. Otherwise that could be modifying a snapshotted memarea. + +The snapshots have made implementing slightly more complicated than earlier. +There are a few different ways to implement istreams: + + * Always point 'buffer=w_buffer' and use 'i_stream_try_alloc()' and/or + 'i_stream_alloc()' to allocate the 'w_buffer'. The generic code will handle + all the snapshotting. Use 'i_stream_read_memarea()' to read data from parent + stream so multiple snapshots aren't unnecessarily created. + * Guarantee that if 'read()' returns <=0, the existing 'buffer' will stay + valid. Use 'ISTREAM_CREATE_FLAG_NOOP_SNAPSHOT' flag in 'i_stream_create()' + so your filter stream isn't unnecessarily snapshotted (or causing a panic + due to missing 'snapshot()' implementation). + * One way of doing this with filter streams is to read from the parent + stream via 'i_stream_read(parent)' and always use + 'buffer=i_stream_get_data(parent)'. The parent's snapshotting guarantees + that the buffer will stay valid. + * Implement the 'snapshot()' yourself in the stream. You'll need to create a + new memarea of the current data available via 'i_stream_get_data()' and it + must not change, i.e. most likely you'll need to duplicate the allocated + memory. Create a new 'struct istream_snapshot' and assign the allocated + memarea to its 'old_memarea'. Fill 'prev_snapshot' field and return your new + snapshot. The snapshot will be freed by the generic istream code either when + the next 'read()' returns >0 or when the istream is destroyed. + * Filter streams that only pass through parent stream's contents without + changes can just point to the parent stream. The default snapshotting causes + the parent to be snapshotted, so the filter stream can simply use + 'i_stream_read_memarea()' and point to the parent's buffer. + +When Dovecot is configured with '--enable-devel-checks', 'i_stream_read()' will +verify that the first and the last two bytes of the buffer didn't unexpectedly +change due to a 'read()'. While developing istream changes you should use this +to make sure the istream is working properly. Running the istream unit test +also via valgrind can also be used to verify that the buffer wasn't freed. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Lua.txt b/doc/wiki/Design.Lua.txt new file mode 100644 index 0000000..805e00b --- /dev/null +++ b/doc/wiki/Design.Lua.txt @@ -0,0 +1,249 @@ +Dovecot Lua support +=================== + +Since v2.3.0 dovecot supports Lua scripting. Dovecot supports lua 5.0 or newer. +See also: + + * <Lua based authentication> [AuthDatabase.Lua.txt]. Since v2.3.0 + * <Lua push notifications> [Plugins.PushNotification.txt]. Since v2.3.4 + +lib-lua +------- + +Dovecot provides a lib-lua internal helper as part of libdovecot.so. It has +facilities for loading scripts from various sources, and also helps with +reusing scripts by keeping track of which scripts are loaded. Each script has +it's own memory pool, which is guaranteed to be released when script is +unloaded. + +When script is loaded, *script_load* function is called if found. This can +return non-zero to indicate that the script has a problem. + +C API +----- + + * 'dlua_register_dovecot(script)' + +Register dovecot variable. This item can also be extended by context specific +tables, like authentication database adds *dovecot.auth*. + + * 'dlua_push_event(event)' + +Pushes an Dovecot Event to stack. + +Lua API +------- + + * 'i_debug(text)' + * 'i_error(text)' + * 'i_info(text)' + * 'i_warning(text)' + +Functions within dovecot variable that do generic logging + +Event functions are available from v2.3.4 on + + * 'dovecot.event()' + * 'dovecot.event(parent)' + +Creates a new event for dovecot + +object event +------------ + +Note: + + * object event_passthrough has same API, except the 'passthrough_event' method + is not present. + +Functions: + + * 'append_log_prefix("prefix")' - set prefix to append + * 'replace_log_prefix("prefix")' - replace append prefix + * 'set_name("name")' - set name for event + * 'add_str("key","value")' - add a key-value pair to event + * 'add_int("key",1)' - add a key-value pair to event + * 'add_timeval("key",seconds)' - add a key-value pair to event + * 'inc_int("key",1)' - increment key-value pair + * 'log_debug("message")' - emit debug message + * 'log_info("message")' - emit info message + * 'log_warning("message")' - emit warning message + * 'log_error("message")' - emit error message + * 'passthrough_event()' - returns an passthrough event. A log message *must + be* logged or else a panic will occur. + +mail-lua +-------- + +Available from v2.3.4 on + +mail-lua is a plugin that can be loaded to provide API for mail storage Lua +plugins. Mail-lua provides a common script to be used in mail storage instead +of per-plugin scripts. + +C API +----- + + * 'dlua_register_mail_storage(script)' + +Register storage Lua interface to script context + + * 'bool mail_lua_plugin_get_script(user, script_r)' + +Returns script context if available. If FALSE is returned, no Lua script has +been loaded, and you should optionally deal this yourself. + + * 'dlua_push_mail_user(script, user)' + +Pushes a mail user on top of stack. + + * 'dlua_push_mailbox(script, box)' + +Pushes a mailbox on top of stack. + + * 'dlua_push_mail(script, mail)' + +Pushes a mail on top of stack. + +Lua API +------- + +When mail user is created, a script is loaded if present as *mail_lua_script* +and *mail_user_created* is called if present in script. + +On deinitialization, *mail_user_deinit_pre* is called first, if present, +followed by *mail_user_deinit*. + +dovecot.storage +--------------- + +Following constants are specified + + * 'STATUS_MESSAGES' + * 'STATUS_RECENT' + * 'STATUS_UIDNEXT' + * 'STATUS_UIDVALIDITY' + * 'STATUS_UNSEEN' + * 'STATUS_FIRST_UNSEEN_SEQ' + * 'STATUS_KEYWORDS' + * 'STATUS_HIGHESTMODSEQ' + * 'STATUS_PERMANENT_FLAGS' + * 'STATUS_FIRST_RECENT_UID' + * 'STATUS_HIGHESTPVTMODSEQ' + * 'MAILBOX_FLAG_READONLY' + * 'MAILBOX_FLAG_SAVEONLY' + * 'MAILBOX_FLAG_DROP_RECENT' + * 'MAILBOX_FLAG_NO_INDEX_FILES' + * 'MAILBOX_FLAG_KEEP_LOCKED' + * 'MAILBOX_FLAG_IGNORE_ACLS' + * 'MAILBOX_FLAG_AUTO_CREATE' + * 'MAILBOX_FLAG_AUTO_SUBSCRIBE' + * 'MAILBOX_SYNC_FLAG_FULL_READ' + * 'MAILBOX_SYNC_FLAG_FULL_WRITE' + * 'MAILBOX_SYNC_FLAG_FAST' + * 'MAILBOX_SYNC_FLAG_NO_EXPUNGES' + * 'MAILBOX_SYNC_FLAG_FIX_INCONSISTENT' + * 'MAILBOX_SYNC_FLAG_EXPUNGE' + * 'MAILBOX_SYNC_FLAG_FORCE_RESYNC' + +object mail_user +---------------- + +Meta: + + * has tostring + * is comparable (by username) + +Functions: + + * 'plugin_getenv(key)' - returns key from user plugin settings or userdb + environment + * 'var_expand(template)' - expands mail user variables (see <Variables.txt>) + * 'mailbox(name, flags)' - allocates a mailbox, flags optional + +Variables: + + * 'home' - home directory (if available) + * 'username' - user's name + * 'uid' - system uid + * 'gid' - system gid + * 'service' - IMAP/POP3/LMTP/LDA/... + * 'session_id' - Current session ID + * 'session_create_time' - When session was created + * 'nonexistent' - If user does not really exist + * 'anonymous' - If user is anonymous + * 'autocreated' - If user was automatically created internally for some + operation + * 'mail_debug' - If debugging is turned on + * 'fuzzy_search' - FIXME: Undocumented + * 'dsyncing' - If user is being dsync'd + * 'session_restored' - If this is a restored session + +object mailbox +-------------- + +Meta: + + * has tostring + * is comparable (by full mailbox name) + +Functions: + + * 'open()' - opens the mailbox + * 'close()' - closes the mailbox + * 'free()' - releases mailbox (must be done) + * 'sync(flags)' - synchronizes the mailbox (should usually be done, flags + optional) + * 'status(item,item,item...)' - returns requested mailbox status items as + table + +Variables: + + * 'vname' - Full mailbox name + * 'name' - Mailbox name + +table mailbox status +-------------------- + +Variables: + + * 'mailbox' - full name of mailbox + * 'messages' - number of messages + * 'recent' - number of \Recent messages + * 'unseen' - number of \Unseen messages + * 'uidvalidity' - current UID validity + * 'uidnext' - next UID + * 'first_unseen_seq' - first seqno of unseen mail + * 'first_recent_uid' - first UID of unseen mail + * 'highest_modseq' - highest modification sequence + * 'highest_pvt_modseq' - highest private modification sequence + * 'permanent_flags' - supported permanent flags as a bitmask + * 'flags' - supported flags as a bitmask + * 'permanent_keywords' - if permanent keywords are supported + * 'allow_new_keywords' - if new keywords can be added + * 'nonpermanent_modseqs' - whether non-permanent keywords are allowed + * 'no_modseq_tracking' - no modification sequence tracking + * 'have_guids' - whether GUIDs exist + * 'have_save_guids' - whether GUIDs can be saved + * 'have_only_guid128' - whether GUIDs are 128 bit always + * 'keywords' - table of current keywords + +object mail +----------- + +Meta: + + * has tostring + * is comparable (within same mailbox, by UID) + +Functions: + + * None yet + +Variables: + + * 'mailbox' - mailbox object + * 'seq' - Sequence number (can change) + * 'uid' - UID number (immutable) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.MailProcess.txt b/doc/wiki/Design.MailProcess.txt new file mode 100644 index 0000000..b583d46 --- /dev/null +++ b/doc/wiki/Design.MailProcess.txt @@ -0,0 +1,12 @@ +Mail Process Design +=================== + +FIXME: + + * IMAP/POP3 protocol specific code + * Mail storage API + * Index files under everything + * Plugins + * etc. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Memory.txt b/doc/wiki/Design.Memory.txt new file mode 100644 index 0000000..64ad013 --- /dev/null +++ b/doc/wiki/Design.Memory.txt @@ -0,0 +1,193 @@ +Memory Allocations +================== + +C language requires explicitly allocating and freeing memory. The main two +problems with this are: + + 1. A lot of allocations and frees cause memory fragmentation. The longer a + process runs, the more it could have leaked memory because there are tiny + unused free spots all around in heap. + 2. Freeing memory is easy to forget, causing memory leaks. Sometimes it can be + accidentally done multiple times, causing a potential security hole. A lot + of free() calls all around in the code also makes the code more difficult + to read and write. + +The second problem could be solved with Boehm garbage collector, which Dovecot +can use optionally (prior to 2.3), but it's not very efficient. It also doesn't +help with the first problem. + +To reduce the problems caused by these issues, Dovecot has several ways to do +memory management. + +Common Design Decisions +----------------------- + +All memory allocations (with some exceptions in data stack) return memory +filled with NULs. This is also true for new memory when growing an allocated +memory with realloc. The zeroing reduces accidental use of uninitialized memory +and makes the code simpler since there is no need to explicitly set all fields +in allocated structs to zero/NULL. (I guess assuming that this works correctly +for NULLs isn't strictly ANSI-C compliant, but I don't see this assumption +breaking in any system anyone would really use Dovecot.) The zeroing is cheap +anyway. + +In out-of-memory situations memory allocation functions die internally by +calling 'i_fatal_status(FATAL_OUTOFMEM, ..)'. There are several reasons for +this: + + * Trying to handle malloc() failures explicitly would add a lot of error + handling code paths and make the code much more complex than necessary. + * In most systems malloc() rarely actually fails because the system has run + out of memory. Instead the kernel will just start killing processes. + * Typically when malloc() does fail, it's because the process's address space + limit is reached. Dovecot enforces these limits by default. Reaching it + could mean that the process was leaking memory and it should be killed. It + could also mean that the process is doing more work than anticipated and + that the limit should probably be increased. + * Even with perfect out-of-memory handling, the result isn't much better + anyway than the process dying. User isn't any happier by seeing "out of + memory" error than "server disconnected". + +When freeing memory, most functions usually also change the pointer to NULL. +This is also the reason why most APIs' deinit functions take pointer-to-pointer +parameter, so that when they're done they can change the original pointer to +NULL. + +malloc() Replacements +--------------------- + +'lib/imem.h' has replacements for all the common memory allocation functions: + + * 'malloc', 'calloc' -> 'i_malloc()' + * 'realloc()' -> 'i_realloc()' + * 'strdup()' -> 'i_strdup()' + * 'free()' -> 'i_free' + * etc. + +All memory allocation functions that begin with 'i_' prefix require that the +memory is later freed with 'i_free()'. If you actually want the freed pointer +to be set to NULL, use 'i_free_and_null()'. Currently 'i_free()' also changes +the pointer to NULL, but in future it might change to something else. + +Memory Pools +------------ + +'lib/mempool.h' defines API for allocating memory through memory pools. All +memory allocations actually go through memory pools. Even the 'i_*()' functions +get called through 'default_pool', which by default is 'system_pool' but can be +changed to another pool if wanted. All memory allocation functions that begin +with 'p_' prefix have a memory pool parameter, which it uses to allocate the +memory. + +Dovecot has many APIs that require you to specify a memory pool. Usually (but +not always) they don't bother freeing any memory from the pool, instead they +assume that more memory can be just allocated from the pool and the whole pool +is freed later. These pools are usually alloconly-pools, but can also be data +stack pools. See below. + +Alloc-only Pools +---------------- + +'pool_alloconly_create()' creates an allocate-only memory pool with a given +initial size. + +As the name says, alloconly-pools only support allocating more memory. As a +special case its last allocation can be freed.'p_realloc()' also tries to grow +the existing allocation only if it's the last allocation, otherwise it'll just +allocates new memory area and copies the data there. + +Initial memory pool sizes are often optimized in Dovecot to be set large enough +that in most situations the pool doesn't need to be grown. To make this easier, +when Dovecot is configured with --enable-devel-checks, it logs a warning each +time a memory pool is grown. The initial pool size shouldn't of course be made +too large, so usually I just pick some small initial guessed value and later if +I get too many "growing memory pool" warnings I start growing the pool sizes. +Sometimes there's just no good way to set the initial pool size and avoid the +warnings, in that situation you can prefix the pool's name with MEMPOOL_GROWING +and it doesn't log warnings. + +Alloconly-pools are commonly used for an object that builds its state from many +memory allocations, but doesn't change (much of) its state. It's a lot easier +when you can do a lot of small memory allocations and when destroying the +object you'll just free the memory pool. + +Data Stack +---------- + +'lib/data-stack.h' describes the low-level data stack functions. Data stack +works a bit like C's control stack.'alloca()' is quite near to what it does, +but there's one major difference: In data stack the stack frames are explicitly +defined, so functions can return values allocated from data +stack.'t_strdup_printf()' call is an excellent example of why this is useful. +Rather than creating some arbitrary sized buffer and using snprintf(), which +might truncate the value, you can just use t_strdup_printf() without worrying +about buffer sizes being large enough. + +Try to keep the allocations from data stack small, since the data stack's +highest memory usage size is kept for the rest of the process's lifetime. The +initial data stack size is 32kB, which should be enough in normal use. If +Dovecot is configured with --enable-devel-checks, it logs a warning each time +the data stack needs to be grown. + +Stack frames are preferably created using T_BEGIN/T_END block, for example: + +---%<------------------------------------------------------------------------- +T_BEGIN { + string_t *str1 = t_str_new(256); + string_t *str2 = t_str_new(256); + /* .. */ +} T_END; +---%<------------------------------------------------------------------------- + +In the above example two strings are allocated from data stack. They get freed +once the code goes past T_END, that's why the variables are preferably declared +inside the T_BEGIN/T_END block so they won't accidentally be used after they're +freed. + +T_BEGIN and T_END expand to 't_push()' and 't_pop()' calls and they must be +synchronized. Returning from the block without going past T_END is going to +cause Dovecot to panic in next T_END call with "Leaked t_pop() call" error. + +Memory allocations have similar disadvantages to alloc-only memory pools. +Allocations can't be grown, so with the above example if str1 grows past 256 +characters, it needs to be reallocated, which will cause it to forget about the +original 256 bytes and allocate 512 bytes more. + +Memory allocations from data stack often begin with 't_' prefix, meaning +"temporary". There are however many other functions that allocate memory from +data stack without mentioning it. Memory allocated from data stack is usually +returned as a const pointer, so that the caller doesn't try to free it (which +would cause a compiler warning). + +When should T_BEGIN/T_END used and when not? This is kind of black magic. In +general they shouldn't be used unless it's really necessary, because they make +the code more complex. But if the code is going through loops with many +iterations, where each iteration is allocating memory from data stack, running +each iteration inside its own stack frame would be a good idea to avoid +excessive memory usage. It's also difficult to guess how public APIs are being +used, so I've tried to make such API functions use their own private stack +frames. Dovecot's ioloop code also wraps all I/O callbacks and timeout +callbacks into their own stack frames, so you don't need to worry about them. + +You can create temporary memory pools from data stack too. Usually you should +be calling 'pool_datastack_create()' to generate a new pool, which also tries +to track that it's not being used unsafely across different stack frames. Some +low-level functions can also use 'unsafe_data_stack_pool' as the pool, which +doesn't do such tracking. + +Data stack's advantages over malloc(): + + * FAST, most of the time allocating memory means only updating a couple of + pointers and integers. Freeing memory all at once also is a fast operation. + * No need to 'free()' each allocation resulting in prettier code + * No memory leaks + * No memory fragmentation + +It also has some disadvantages: + + * Allocating memory inside loops can accidentally allocate a lot of memory + * Memory allocated from data stack can be accidentally stored into a permanent + location and accessed after it's already been freed. + * Debugging invalid memory usage may be difficult using existing tools + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.OutputStreams.txt b/doc/wiki/Design.OutputStreams.txt new file mode 100644 index 0000000..97bc741 --- /dev/null +++ b/doc/wiki/Design.OutputStreams.txt @@ -0,0 +1,96 @@ +Output Streams +============== + +'lib/ostream.h' describes Dovecot's output streams. Output streams can be +stacked on top of each others as many times as wanted. + +Output streams actually writing data: + + * file: Write to given fd using 'pwrite()' for files and 'write()' for + non-files. + * unix: Write to given UNIX socket. Similar to file, but supports sending file + descriptors. + * buffer: Write to <buffer> [Design.Buffers.txt]. + +Output stream filters: + + * hash: Calculate hash of the ostream while it's being written. + * escaped: Write output escaped via callback. Built-in support for HEX and + JSON escaping. + * multiplex: Multiplex-iostreams support multiple iostream channels inside a + single parent istream. + * null: All the output is discarded. + * failure-at: Insert a failure at the specified offset. This can be useful for + testing. + * lib-mail/ostream-dot: Write SMTP-style DATA input where the output ends with + an empty "." line. + * lib-dcrypt/encrypt: Write encrypted data. + * lib-compression/*: Write zlib/bzlib/lz4/lzma compressed data. + +A typical life cycle for an ostream can look like: + + * create + * 'o_stream_cork()' + * 'o_stream_nsend*()' one or more times + * 'o_stream_uncork()' + * If necessary, check errors with 'o_stream_flush()' + * 'o_stream_cork()' + * 'o_stream_nsend*()' one or more times + * 'o_stream_uncork()' + * finalize the ostream with 'o_stream_finish()' + * optionally close the ostream with 'o_stream_close()' + * unref or destroy + +Once the ostream is finished, it can't be written to anymore. The +'o_stream_finish()' call writes any potential trailer that the ostream may have +(e.g. ostream-gz, ostream-encrypt, ostream-dot) while still allowing the caller +to check if the trailer write failed. After 'o_stream_finish()' is called, any +further write will panic. The ostreams that require a trailer will panic if +'o_stream_finish()' hasn't been called before the stream is destroyed, but +other ostreams don't currently require this. Still, it's not always easy to +know whether there might be ostreams that require the trailer, so if there's +any doubt, it's preferred to call 'o_stream_finish()' just before destroying +the ostream. + +Usually calling 'o_stream_finish()' will also finish its parent ostream. This +may or may not be wanted depending on the situation. For example ostream-dot +must be finished to write the last "." line, but ostream-dot is always a +sub-stream of something else that must not be finished yet. This is why +ostream-dot by default has called 'o_stream_set_finish_also_parent(FALSE)', so +finishing the ostream-dot won't finish the parent stream. Similarly +'connection.c' API sets 'o_stream_set_finish_via_child(FALSE)' so none of the +socket connections created via it will be finished even though one of their +sub-streams is finished. These functions may need to be called explicitly in +other situations. + +When doing a lot of writes, you can simplify the error handling by delaying the +error checking. Use the 'o_stream_nsend*()' functions and afterwards check the +error with 'o_stream_flush()' or 'o_stream_finish()'. If you forgot to do this +check before the ostream is destroyed, it will panic with:'output stream %s is +missing error handling' regardless of whether there is an error or not. If you +don't care about errors for the ostream (e.g. because it's a client socket and +there's nothing you can do about the write errors), you can use +'o_stream_set_no_error_handling()' to fully disable error checks. You can also +use 'o_stream_ignore_last_errors()' to ignore the errors so far, but not for +future writes. + +Writes are non-buffered by default. To add buffering, use 'o_stream_cork()' to +start buffering and 'o_stream_uncork()' to stop/flush. When output buffer gets +full, it's automatically flushed even while the stream is corked. The term +"cork" is used because with TCP connections the call actually sets/removes TCP +cork option. It's quite easy to forget to enable the corking with files, making +the performance worse. The corking/uncorking is done automatically when flush +callbacks are called. Using 'o_stream_uncork()' will trigger an automatic +'o_stream_flush()' but the error is ignored. This is why it acts similarly to +'o_stream_nsend*()', i.e. it requires another explicit 'o_stream_flush()', +'o_stream_finish()' or error ignoring before the ostream is destroyed. + +If output buffer's size isn't unlimited, the writes can also fail or be partial +because there's no more space in the buffer and 'write()' syscall is returning +'EAGAIN'. This of course doesn't happen with blocking fds (e.g. files), but you +need to handle this in some way with non-blocking network sockets. A common way +in Dovecot to handle this is to just use unlimited buffer sizes and after each +write check if the buffer size becomes too large, and when it does it stops +writing until more space is available. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.ParameterForwarding.txt b/doc/wiki/Design.ParameterForwarding.txt new file mode 100644 index 0000000..4413b58 --- /dev/null +++ b/doc/wiki/Design.ParameterForwarding.txt @@ -0,0 +1,65 @@ +Forwarding parameters in IMAP/POP3/LMTP/SMTP proxying +===================================================== + +Dovecot supports proxying various pieces of information and even variables for +various protocols when forwarding connection.It requires that the sender is +listed under 'trusted_networks'. For IMAP, it uses the 'ID' command, for other +protocols,'XCLIENT' is used. + +This feature is supported since v1.2, except for x-forward which was added in +v2.2.29. + +IMAP protocol +------------- + +For IMAP protocol, this is done by extending the ID command. The maximum length +of parameters to parse is 255 bytes.The parameters are forwarded as part of the +ID command key-value list. + +'5 ID (x-originating-ip "127.0.0.1" x-originating-port "143"... )' + +Supported parameters +-------------------- + + * 'x-originating-ip' - Client IP + * 'x-originating-port' - Client port + * 'x-connected-ip' - Server IP + * 'x-connected-port' - Server port + * 'x-proxy-ttl' - TTL which is reduced by each hop, loop prevention. When TTL + drops to 0, the connection is dropped. + * 'x-session-id' / 'x-session-ext-id' - Session ID to be used. + * 'x-forward-<variable_name>' - Forwarded variable, see <Variables.txt> + +POP3 protocol +------------- + +For POP3 protocol, this is done with custom 'XCLIENT' command which accepts a +space separated list of key=value parameters. + +Supported parameters +-------------------- + + * 'ADDR' - Client IP + * 'PORT' - Client port + * 'SESSION' - Session ID + * 'TTL' - TTL which is reduced by each hop, loop prevention. When TTL drops to + 0, the connection is dropped. + * 'FORWARD' - Base64 encoded key=value parameter to be stored. + +SMTP/LMTP protocol +------------------ + +See http://www.postfix.org/XCLIENT_README.html + + * 'ADDR' - Client IP, IPV6: prefix is needed for IPv6. + * 'PORT' - Client port + * 'SESSION' - Session ID + * 'HELO' - Original HELO/EHLO + * 'LOGIN' - Original LOGIN value + * 'TIMEOUT' - Original TIMEOUT + * 'TTL' - TTL which is reduced by each hop, loop prevention. When TTL drops to + 0, the connection is dropped. + * 'PROTO' - Forwarded protocol, can be one of SMTP, ESTMP, LMTP. + * 'FORWARD' - Base64 encoded key=value parameter to be stored. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Plugins.txt b/doc/wiki/Design.Plugins.txt new file mode 100644 index 0000000..7d28af4 --- /dev/null +++ b/doc/wiki/Design.Plugins.txt @@ -0,0 +1,62 @@ +Plugins +======= + +Plugins in Dovecot are really simple. They basically have two functions: + + * <plugin_name>_init(module) is called when 'module_dir_init()' is called. + * <plugin_name>_deinit() is called when 'module_dir_deinit()' or + 'module_dir_unload()' is called. + +The <plugin_name> is the short version of the plugin name, based on the +filename. For example if the filename is 'lib11_imap_quota_plugin.so', the +<plugin_name> is "imap_quota" and the init function to be called is +imap_quota_plugin_init(). + +Versioning +---------- + +Since different Dovecot versions can have different APIs, your plugin should +usually also define<plugin_name>_version, like: + +---%<------------------------------------------------------------------------- +const char *imap_quota_plugin_version = DOVECOT_ABI_VERSION; +---%<------------------------------------------------------------------------- + +If the version string in plugin doesn't match the version of the running +binary, the plugin loading fails. The DOVECOT_ABI_VERSION is defined in +Dovecot's 'config.h', which you're typically including. + +Dependencies +------------ + +Some plugins depend on another one. In some systems (but not all) it's possible +to handle this by giving a nicer error message than "symbol xyz not found". +There are two steps for this: + +First create <plugin_name>_dependencies array listing plugin names that the +plugin depends on, like: + +---%<------------------------------------------------------------------------- +const char *imap_quota_plugin_dependencies[] = { "quota", NULL }; +---%<------------------------------------------------------------------------- + +Then you'll also have to make the plugin .so binary link to the other plugins: + +---%<------------------------------------------------------------------------- +if PLUGIN_DEPS +lib11_imap_quota_plugin_la_LIBADD = \ + ../quota/lib10_quota_plugin.la +endif +---%<------------------------------------------------------------------------- + +PLUGIN_DEPS is set only if plugin dependencies are actually supported. +Otherwise the build might fail or plugin loading might fail. + +Once all this is done, trying to load imap_quota plugin without quota plugin +gives a nice error message: + +---%<------------------------------------------------------------------------- +Error: Can't load plugin imap_quota_plugin: Plugin quota must be loaded also +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Processes.txt b/doc/wiki/Design.Processes.txt new file mode 100644 index 0000000..189960c --- /dev/null +++ b/doc/wiki/Design.Processes.txt @@ -0,0 +1,137 @@ +Dovecot processes +================= + +Dovecot is split into multiple processes where each process does only one +thing. This is partially because it makes the code cleaner, but alsobecause it +allows setting up different privileges for each process. Themost important +processes are: + + * Master process (dovecot) + * Login processes (imap-login, pop3-login) + * Authentication process (dovecot-auth) + * Mail processes (imap, pop3) + +Master process +-------------- + +This process keeps all the other processes running. If a child process dies, +another one is restarted automatically. It always runs as root,unless you're +specifically running everything under a single normal UID. + +The master process reads the configuration file and exports the settings to +other processes via environment variables. + +All logging also goes through master process. This avoids problems with +rotating log files, as there's only a single process to send a signal toreopen +the log file. Also writing to the same log file (if not using syslog)isn't +necessarily safe to do in multiple processes concurrently. + +Making the logging go through master process also gives a couple of advantages +from security and reliability point of view: All log lines canbe prefixed with +the process's name and the username of the user who was logged in, withoutthe +possibility for the process itself to forge them. Flooding logs canalso be +prevented. By default Dovecot allows non-privileged processes towrite 10 lines +per second before it begins to delay reading their input,which finally causes +the badly behaving process to start blocking onwriting to stderr instead of +eating all the CPU and disk space. + +In the Dovecot 2.0 design, the master process is split to three parts: the +Masterprocess which does nothing more than keep the processes running, the +configprocess which handles reading the configuration file (supporting also eg. +SQL storages!) and the log process which handles the logging. + +Login processes +--------------- + +The login processes implement the required minimum of the IMAP and POP3 +protocolsbefore a user logs in successfully. There are separate processes (and +binaries) to handle IMAP and POP3 protocols. + +These processes are run with least possible privileges. Unfortunately the +default UNIX security model still allows them to do much more than theywould +have to: Accept new connections on a socket, connect to new UNIXsockets and +read and write to existing file descriptors. Still, the loginprocess is by +default run under a user account that has no special accessto anything, and +inside a non-writable chroot where only a couple of filesexist. Doing any +damage inside there should be difficult. + +When a new connection comes, one of the login processes accept()s it. After +that the client typically does nothing more than ask the server'scapability +list and then log in. The client may also start TLS sessionbefore logging in. + +Authentication is done by talking to the authentication process. The login +process is completely untrusted by the authentication process, so even if +anattacker is able to execute arbitrary code inside a login process, they won't +be able tolog in without a valid username and password. + +After receiving a successful authentication reply from the authentication +process, the login process sends the file descriptor to the master processwhich +creates a new mail process and transfers the fd into it. Before doingthat, the +master process verifies from the authentication process that theauthentication +really was successful. + +By default each login process will handle only a single connection and +afterwards kill itself (but see SSL proxying below). This way attacker can't +see other people'sconnections. This can however be disabled +('login_process_per_connection=no'), in which case the security of the design +suffers greatly. + +The login processes handle SSL/TLS connections themselves completely. They keep +proxying the connection to mail processes for the entire lifetime ofthe +connection. This way if a security hole is found from the SSL library,an +authenticated user still can't execute code outside the login process. + +See <LoginProcess.txt> for more information about different settings related to +login processes. + +Authentication process +---------------------- + +The authentication process handles everything related to the actual +authentication: SASL authentication mechanisms, looking up and verifyingthe +passwords and looking up user information. + +It listens for two different kinds of connections: untrusted authentication +client connections (from login processes) and master connections (frommaster +process, but also from Dovecot LDA). The client connections are onlyallowed to +try to authenticate. The master connections are allowed to askif an +authentication request with a given ID was successful, and also to lookup user +information based on a username. This user lookup feature is usedby Dovecot +LDA. + +Each client connection tells their process ID to the authentication process in +a handshake. If a connection with the same PID already exists, an erroris +logged and the new connection is refused. Although this makes DoSattacks +possible, it won't go unnoticed for long and I don't see this as areal issue +for now. + +Having the authentication process know the PID of the client connection allows +all authentication requests to be mapped to one specific client +connection.Since the master process knows the login process's real PID, it's +used whenasking from authentication process if the request was successful. This +makes it impossible for a login process to try to fake another login +process'slogin requests. Faking PIDs will also be quite pointless. + +Once the master process has done the verification request for a successful +authentication request, the request is freed from memory. The requests arealso +freed about 2 minutes after their creation, regardless of the statethey +currently are in. + +For blocking password and user database backends (eg. MySQL) separate "worker +processes" are used. Initially only one of them exists, butmore are created as +needed. <PAM> [PasswordDatabase.PAM.txt] can be configured to use worker +processes instead of doing the forking itself, but this isn'tcurrently done by +default and there may be problems related to it. Also <checkpassword> +[PasswordDatabase.CheckPassword.txt] currently does the forking itself. + +Mail processes +-------------- + +These processes handle the actual post-login mail handling using the privileges +of the logged in user. It's possible to chroot these processes,but practically +it's usually more trouble than worth. + +See <mail process design> [Design.MailProcess.txt] for their internal design +documentation. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.ErrorHandling.txt b/doc/wiki/Design.Storage.ErrorHandling.txt new file mode 100644 index 0000000..7497598 --- /dev/null +++ b/doc/wiki/Design.Storage.ErrorHandling.txt @@ -0,0 +1,63 @@ +Lib-storage Error Handling +========================== + +'src/lib-storage/mail-error.h' describes different types of errors and has some +other error-related functions and macros. + +Only errors returning "int" can actually return a failure. + + * Functions that return a pointer will never return failure with NULL. Only + "find" type of functions can return NULL, which means "not found". + * Iterators usually work by the init() returning iterator pointer and next() + returning a boolean. If there were any errors in either init() or next(), + deinit() finally returns a failure. + +Getting lib-storage errors +-------------------------- + + * 'mailbox_list_*()' functions set their errors to the given mailbox_list + structure. You can get these errors with 'mailbox_list_get_last_error()'. + * All other functions that have some way of accessing mail_storage (mailbox, + mail, transactions, etc.) set their errors to the storage. You can get these + errors with 'mail_storage_get_last_error()'. + * Mail user and namespace functions have their own error handling, + typically by returning error strings as parameters. + * Both '*_get_last_error()' functions should be called soon after the error is + noticed, before other failing lib-storage calls overwrite the error. + * In deinit failures it usually doesn't matter if you get the first or the + last error, so it's easier to just call all the different deinit + functions and finally look up what the last failure was. + +Setting lib-storage errors +-------------------------- + +Errors can be set with two calls: + + * 'mail_storage_set_error()' and 'mailbox_list_set_error()' should be used + when the error is user's fault in some way. For example invalid mailbox + name, out of quota, etc. The error string will be shown to user. It won't be + written to a log file. + * 'mail_storage_set_critical()' and 'mailbox_list_set_critical()' should be + used when the error is a problem in the system and sysadmin should be + notified. For example out of disk space or just in general an unexpected + syscall failure. The error string that will be shown to user is the + "Internal error occurred", but it will be logged as an error. + * The reason for the separation of these two is: + 1. Only log errors that sysadmin can do something about. + 2. Never show user anything even potentially sensitive about the system, + such as path names. + +There are also a few other calls that aren't used as often, but can be helpful: + + * 'mail_storage_set_internal_error()' and 'mailbox_list_set_internal_error()' + simply set the user-visible error message to "Internal error occurred". + These can be used if the actual error was already logged. + * 'mail_storage_set_error_from_errno()' and + 'mailbox_list_set_error_from_errno()' set the user-visible error message + based on some common 'errno' values. Currently: + * EACCESS, EPERM, EROFS: Permission denied + * ENOSPC, EDQUOT: Not enough disk space + * ENOENT, ENOTDIR: Not found + * ELOOP: Directory structure is broken + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mail.txt b/doc/wiki/Design.Storage.Mail.txt new file mode 100644 index 0000000..a86d722 --- /dev/null +++ b/doc/wiki/Design.Storage.Mail.txt @@ -0,0 +1,100 @@ +Mail +==== + +Mail is first allocated with 'mail_alloc()'. Mails always belong to a +<transaction> [Design.Storage.Mailbox.Transaction.txt]. Even if mail is treated +read-only, Dovecot might write data to cache file, so whenever possible, mail +transactions should be committed. When mail is allocated, you can specify a +list of fields and headers that you're (most likely) going to need. This allows +Dovecot to optimize the later 'mail_get_*()' lookups so that it doesn't need to +parse the message multiple times. These fields are also added to cache file, so +you shouldn't list fields unless you're fairly certain you need them. + +If you need to jump around in the mailbox based on already known sequences or +UIDs, you can do this with 'mail_set_seq()' and 'mail_set_uid()'. This way you +don't have to go through all the trouble of setting up a mailbox search. + +Getting data +------------ + +Some of the mail fields can be accessed directly: + + * 'box': Mail's mailbox, same as the transaction's. + * 'transaction': Mail's transaction, the same that was given to + 'mail_alloc()'. + * 'seq': Currently selected message's sequence number. + * 'uid': Currently selected message's UID. + * 'expunged': We already detected that the message is expunged and can't be + accessed. This may also be set (and looked up) later when some + 'mail_get_*()' function fails. + * 'has_nuls' and 'has_no_nuls': Message body is known to (not) have NUL + characters. + +The final field is 'lookup_abort', which is write-only. Normally when doing a +'mail_get_*()' operation for a field that isn't in a cache, the field is +generated and added to cache. If you don't want this, but instead have figured +out some better optimized way to do non-cached lookups, you can change this +field so that 'mail_get_*()' lookups fail instead. This is primarily used by +searching code internally. + + * 'MAIL_LOOKUP_ABORT_NEVER': The default - do whatever it takes to return the + value. + * 'MAIL_LOOKUP_ABORT_READ_MAIL': If returning the value would require reading + message headers/body, abort. + * 'MAIL_LOOKUP_ABORT_NOT_IN_CACHE': If the value isn't already in cache, + abort. For example if looking up message's physical size would require + 'stat()'ing the file this wouldn't be done. + +Most of the 'mail_get_*()' should be fairly obvious in how they work. Only +functions returning int can fail, others don't. + + * Keywords can be looked up either by getting an array of keyword strings or + keyword indexes. The index lookups are slightly faster. Keyword indexes can + be converted to strings by using the 'status.keywords' array returned by + 'mailbox_get_status()'. + * 'mail_get_first_header()' return 0 if header wasn't found, 1 if it was. + * 'mail_get_special()' can return various special fields. If a special isn't + implemented by some backend, the call returns success and sets the value to + "". + * 'mail_get_stream()' returns an input stream that can be used to access the + mail. If this function is called multiple times, each call seeks the stream + to beginning. Don't unreference the stream, it's destroyed automatically. + * Typically the input contains the raw data in disk, lines may end with LF + or CRLF depending on how they're on disk. + * mbox drops Dovecot's internal headers from the stream (X-UID:, Status:, + etc.). + * Plugins (e.g. zlib) can also hook into this call and modify the input + stream. + +Sometimes you might notice that some looked up field is actually corrupted. For +example you might notice that input stream returns EOF earlier than previous +'mail_get_physical_size()' said. This might have been caused by various +different things, but in any case all you can really do then is to just call +'mail_set_cache_corrupted()' and try again. + +Setting data +------------ + +Some of the messages' metadata can be updated: + + * 'mail_update_flags()' and 'mail_update_keywords()' changes flags/keywords. + * Usually you should set 'modify_type' parameter to 'MODIFY_ADD' or + 'MODIFY_REMOVE', instead of replacing all the flags. That allows + concurrent flag updates not to overwrite each others changes. + * 'mail_expunge()' expunges a message. + +Other functions are mainly intended for mailbox replication or restoring an +existing mailbox (e.g. dsync): + + * 'mail_update_modseq()' can be used to increase message's modseq + * 'mail_update_uid()' can be used to give a new (higher) UID for the message. + If such UID can't be given, this call is just ignored. + * 'mail_update_pop3_uidl()' can be used to give a specific POP3 UIDL for the + message. This is used internally when 'pop3_save_uidl=yes'. + +Other metadata can't be changed. IMAP protocol requires that messages are +immutable, so it's not possible to change message's received date, headers or +body. If you wish to modify any of them, you need to create a new message and +expunge the old one. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.MailNamespace.txt b/doc/wiki/Design.Storage.MailNamespace.txt new file mode 100644 index 0000000..1613a87 --- /dev/null +++ b/doc/wiki/Design.Storage.MailNamespace.txt @@ -0,0 +1,91 @@ +Mail Namespace +============== + +'src/lib-storage/mail-namespace.h' describes mail namespaces. See +<Namespaces.txt> for more information about what they are actually about. + +Hierarchy separators and namespace prefixes +------------------------------------------- + +A namespace and <mailbox list> [Design.Storage.MailboxList.txt] has 1:1 +relationship. A namespace is mainly about dealing with hierarchy separators and +namespace prefixes, which mailbox list doesn't know or care much about. + +Mailbox lists have their native hierarchy separators. For example with FS +layout the separator is '/', because child mailboxes are physically in +subdirectories and '/' is the separator for directories. With Maildir++ layout +the separator is (currently) hardcoded to '.' in the maildir directory name, so +that's its native hierarchy separator. + +Dovecot allows separators to be configurable, so namespaces have two +separators: + + * 'ns->sep' is the configured virtual separator, which defaults to same as + native separator. + * 'ns->real_sep' is the native separator. + +Namespaces also have prefixes. The prefixes are visible for users/clients and +they appear to be part of the actual mailbox name. One commonly used namespace +prefix is "INBOX.", so all mailboxes (other than INBOX itself) appear to be +children of the INBOX. + +So the same mailbox can be visible in three different forms: + + * Virtual name uses the virtual separator and namespace prefix. For example + "INBOX/foo/bar". + * Storage name uses the native separator and doesn't have a namespace prefix. + For example "foo.bar". + * Physical directory name on disk can be different again. For example with + Maildir++ it could be ".../Maildir/.foo.bar" (not the leading dot before + "foo"). + +Users and owners +---------------- + +When accessing other users' shared mailboxes, there's a difference between a +namespace's user and owner: + + * 'ns->user' points to the mail user actually accessing the mailbox (e.g. the + IMAP connection's mail user). + * 'ns->owner' points to the mail user who shared the mailbox. + +The distinction can be important sometimes. For example if user adds or removes +messages from the shared mailbox, the owner's quota must be updated instead of +the user's. + +Functions +--------- + +Functions about finding namespaces: + + * 'mail_namespace_find()' returns namespace for given virtual name and changes + the virtual name -> storage name. It also has a few variations: + * 'mail_namespace_find_visible()' skips hidden=yes namespaces. + * 'mail_namespace_find_subscribable()' skips subscriptions=no namespaces. + * 'mail_namespace_find_unsubscribable()' skips subscriptions=yes + namespaces. + * 'mail_namespace_find_inbox()' returns the namespace with inbox=yes. (There + can be only one.) + * 'mail_namespace_find_prefix()' returns namespace that has the given prefix. + * 'mail_namespace_find_prefix_nosep()' does the same, but ignores the + trailing separator in prefix (e.g. "foo" would find namespace with + prefix=foo/). + +Functions about translating between virtual and storage names when the +namespace is known: + + * 'mail_namespace_fix_sep()' changes virtual separators -> native separators. + * 'mail_namespace_get_storage_name()' changes virtual name -> storage name. + * 'mail_namespace_get_vname()' changes storage name -> virtual name. + * 'mail_namespace_update_name()' returns FALSE if virtual name doesn't + actually match the given namespace. Otherwise returns TRUE and changes + virtual name -> storage name. + +A single namespace can currently point to only a single storage, but there is +already some code that attempts to make the transition to multiple storages per +namespace easier. In general you shouldn't try to access 'ns->storage' +directly. When creating new mailboxes,'mail_namespace_get_default_storage()' +returns the storage that should be used. For other purposes you should find the +storage via <mailbox list> [Design.Storage.MailboxList.txt] functions. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.MailStorage.txt b/doc/wiki/Design.Storage.MailStorage.txt new file mode 100644 index 0000000..3052d8f --- /dev/null +++ b/doc/wiki/Design.Storage.MailStorage.txt @@ -0,0 +1,41 @@ +Mail Storage +============ + +'src/lib-storage/mail-storage.h' and 'mail-storage-private.h' describes mail +storage. Mail storage is mainly about being a common container for its +mailboxes. For example with <multi-dbox> [MailboxFormat.dbox.txt] each storage +has one directory where all the message bodies are written to, while the +per-mailbox directories only contain index files. With other mailbox formats +mail storage doesn't do much else than allow allocating <mailboxes> +[Design.Storage.Mailbox.txt]. + +The only public functions for mail storage are: + + * 'mail_storage_purge()' frees disk space used by expunged messages. Currently + the only mailbox format that uses this is multi-dbox. + * 'mail_storage_get_settings()' returns mail storage settings. + * 'mail_storage_set_callbacks()' can be used to specify "OK" and "NO" + callbacks, which are called when a long running operation wants to send a + status update. For example "OK Stale mailbox lock file detected, will + override in n seconds" or "NO Mailbox is locked, will abort in n seconds". + +Methods that mail storage backends need to implement are: + + * 'get_setting_parser_info()': Returns storage-specific settings parser + information. + * 'alloc()': Allocate memory for a storage and set its virtual functions. + * 'create(ns)': Initialize the storage based on given namespace settings. The + same storage can be used by other namespaces, but they don't call 'create()' + again. This function typically shouldn't fail, except when storage can't + handle the wanted namespace settings. + * 'destroy()': Destroys the storage. + * 'add_list(list)': Called every time the storage is attached to a new + namespace / mailbox list. + * 'get_list_settings(ns, set)': Used to get storage's default settings. + * 'autodetect(ns, set)': Returns TRUE if based on the given settings it looks + like this storage should be handling the namespace. This is done when + mail_location doesn't explicitly specify the mailbox format. + * 'mailbox_alloc()': Allocate memory for <mailbox> + [Design.Storage.Mailbox.txt]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.MailUser.txt b/doc/wiki/Design.Storage.MailUser.txt new file mode 100644 index 0000000..1656aef --- /dev/null +++ b/doc/wiki/Design.Storage.MailUser.txt @@ -0,0 +1,25 @@ +Mail User +========= + +'src/lib-storage/mail-user.h' describes mail user. The struct contains all +kinds of useful information about the user that can be accessed directly. Some +of the most useful things you can do with a user are: + + * 'user->username' gives you the actual username string (e.g. + 'user@domain.org'). + * 'user->set' gives you access to user's settings. + * 'user->namespaces' points to a linked list of user's namespaces. + * 'mail_user_get_home()' returns user's home directory, if there's one. + * 'mail_user_home_expand()' expands '~/' at the beginning of given path to + user's actual home directory. + * 'mail_user_plugin_getenv()' returns value for a setting defined in 'plugin + {}' section. + +Typically each new IMAP/POP3/etc. connection creates a single mail user. +Currently multiple connections for same user don't even try to share the mail +user, but this may change in future. If a user has shared mailboxes from other +users (not public namespaces), a mail user is also created whenever necessary +to list/access the user's mailboxes. Again there is no attempt to share the +created mail user with other connections. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mailbox.Save.txt b/doc/wiki/Design.Storage.Mailbox.Save.txt new file mode 100644 index 0000000..69ee754 --- /dev/null +++ b/doc/wiki/Design.Storage.Mailbox.Save.txt @@ -0,0 +1,51 @@ +Mailbox Saving +============== + +Both saving and copying messages begins by calling 'mailbox_save_alloc()'. +After that you can set message's metadata fields: + + * 'mailbox_save_set_flags()' sets flags and keywords. + * 'mailbox_save_set_received_date()' sets message's received date (IMAP + INTERNALDATE). It also supports specifying timezone, but most backends don't + support saving it. + * 'mailbox_save_set_dest_mail()' specifies a mail that can be used to access + the partially saved mail after save/copy is finished (but not committed). + You should be able to do pretty much anything with the mail, but its UID is + usually 0 at this point. + * 'mailbox_save_set_from_envelope()' sets the envelope sender. Currently this + is only used by mbox format to specify the address in From_-line. + +When copying, most of the metadata fields are automatically copied from the +source message. The only exception is message's flags and keywords. If you want +to preserve them, the easiest way is to call 'mailbox_save_copy_flags()'. + +Some metadata fields are mainly useful when you're replicating or restoring an +existing mailbox and want to preserve metadata: + + * 'mailbox_save_set_min_modseq()' sets message's modseq to at least the + specified modseq. If the modseqs are already higher in the mailbox, the + resulting modseq is what it would have been without this call. + * 'mailbox_save_set_uid()' sets message's UID. If mailbox's next_uid is + already higher than the specified UID, the UID request is ignored. + * 'mailbox_save_set_guid()' sets message's globally unique ID. A new GUID is + generated by default, and if there already exists a message with the same + GUID a different one may or may not be given. For example with maildir the + GUID is same as the base filename, while dbox has an explicit GUID metadata + field. + * 'mailbox_save_set_pop3_uidl()' sets POP3 UIDL value. Not all backends + support this. + * 'mailbox_save_set_save_date()' sets "message saved" date, i.e. the date/time + when the message was saved to this mailbox. The default is the current time. + +Once you're done with setting the metadata fields, you can either copy an +existing mail with 'mailbox_copy()' or provide message body with: + + * 'mailbox_save_begin()' starts saving from given input stream. + * 'mailbox_save_continue()' saves all data from input stream. If input stream + is blocking, typically a single call to this function should be enough. If + input stream is non-blocking, you need to call this function until you're + done. In any case call this until 'i_stream_is_eof()' returns TRUE. + * 'mailbox_save_finish()' finishes saving the mail, or 'mailbox_save_cancel()' + aborts it. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mailbox.Search.txt b/doc/wiki/Design.Storage.Mailbox.Search.txt new file mode 100644 index 0000000..d1438ba --- /dev/null +++ b/doc/wiki/Design.Storage.Mailbox.Search.txt @@ -0,0 +1,101 @@ +Mailbox Searching +================= + +'mailbox_search_*()' functions should be used always when you're iterating +through multiple messages. The search queries can be complex or as simple as +"all messages". Without searching there's also a way to directly switch to a +specific message by its sequence number or UID, but this should be avoided +usually. + +Initializing +------------ + +Search is initialized with 'mailbox_search_init()' on top of a <transaction> +[Design.Storage.Mailbox.Transaction.txt]. Although it would appear that a +search is a read-only operation, it can actually write data to Dovecot's cache +file. For example if you search for a specific header not yet in cache file, +the results are saved to cache file so the next search will be fast. This is +why you should always commit search transactions, even if the rest of your +operation fails (you should use separate transactions for search and for +updates if necessary). + +You'll need a search query. 'src/lib-storage/mail-search.h' and +'mail-search-build.h' contain all the functions and structures related to it. +Usually you should start with 'mail_search_build_init()' and then start adding +the search parameters, either manually or with one of the existing +'mail_search_build_add_*()' helper functions. The same search query structures +can be saved and used for other searches later, but because search state is +stored inside the structs you need to be careful that multiple searches aren't +using them at the same time. This is usually more trouble than worth, so avoid +doing it. + +Search results can be sorted by giving a sort program. Dovecot optimizes this +by keeping sort indexes in the index files. + +Reading search results +---------------------- + +While 'mailbox_search_next()' returns TRUE, a new search result is found and it +changes the given <mail> [Design.Storage.Mail.txt] to point to the search +result. The mail's "wanted fields/headers" parameters don't need to include +anything needed by the search query, Dovecot optimizes them internally. + +If the search needs to parse message bodies and the mailbox is large, this call +can take a long time. If you want to do other things while searching, you can +use 'mailbox_search_next_nonblock()' that does only a bit of work and then +returns either with a result or "try again later" status. Dovecot attempts to +keep each non-matching call to this function between 200 and 250 milliseconds, +although the upper bound can't be guaranteed. + +It's possible that messages are being expunged while Dovecot is searching them, +so it can't determine if they would have matched the search rule or not. In +this case it skips over them, but if you want to know if this has happened, you +can see if 'mailbox_search_seen_lost_data()' returns TRUE. + +Deinitializing +-------------- + +'mailbox_search_deinit()' finishes the search. If it returns -1, some error +occurred and some search results might not have been returned. + +Example +------- + +Iterating through all messages in a mailbox goes like: + +---%<------------------------------------------------------------------------- +/* build search query */ +search_args = mail_search_build_init(); +mail_search_build_add_all(search_args); + +search_ctx = mailbox_search_init(trans, search_args, NULL); +/* search context keeps args referenced */ +mail_search_args_unref(&search_args); + +mail = mail_alloc(trans, 0, NULL); +while (mailbox_search_next(ctx, mail)) { + printf("matched uid %u\n", mail->uid); +} +mail_free(&mail); +if (mailbox_search_deinit(&search_ctx) < 0) + i_error("search failed"); +---%<------------------------------------------------------------------------- + +Saving search results +--------------------- + +Search results can be saved for future use by calling +'mailbox_search_result_save()' just after initializing the search. The results +as returned as UIDs with 'mailbox_search_result_get()' and may contain UIDs +that are already expunged. Once you're done with the saved result, free it with +'mailbox_search_result_free()'. + +The search result can also be automatically updated whenever mailbox is synced +if 'MAILBOX_SEARCH_RESULT_FLAG_UPDATE' is set. The update is optimized, so +Dovecot doesn't do a full re-search, but matches only new and changed messages. +If 'MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC' is also set, search result additions +and removals are also tracked and can be retrieved with +'mailbox_search_result_sync()', i.e. with this you can implement "what changed +in search results since last time I checked". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mailbox.Sync.txt b/doc/wiki/Design.Storage.Mailbox.Sync.txt new file mode 100644 index 0000000..a7d295a --- /dev/null +++ b/doc/wiki/Design.Storage.Mailbox.Sync.txt @@ -0,0 +1,128 @@ +Mailbox Synchronization +======================= + +The idea behind synchronization is to find out what changes other sessions have +done to the mailbox and to finalize our own changes to the mailbox. + +For example if you expunge a message in a transaction and commit it, the commit +will only write a "please expunge UID n" record to Dovecot's transaction log +file. The message still exists on the disk. The next time Dovecot syncs the +mailbox (either the session that wrote the record or another one), it goes +through all the non-synchronized records in transaction log and applies the +requested changes to the backend mailbox. Syncing can be a bit heavyweight +operation, so it's possible to commit multiple transactions and perform a +single sync for all of them. Dovecot attempts to do this with IMAP protocol +when pipelining commands. + +The other important job of syncing is to refresh mailbox's state: + + * Finding out about external modifications to mailbox (e.g. a new mail + delivered to Maildir/new/). + * Updating in-memory view of what messages exist, what their flags are, etc. + +When a mailbox is opened, its state starts with what index files contain at the +time. Since the backend mailbox may have already changed, and syncing an +up-to-date mailbox is usually really cheap, there isn't much point in not +syncing mailbox immediately after opening. The mailbox state stays the same +until you synchronize the mailbox again, before that no new messages show up +and no messages get expunged. + +Typically you would sync the mailbox + + * after committing a transaction that modifies backend mailbox in any way + (instead of just internal index data), such as after changing message flags + or expunging a message. + * whenever you want to find out if there are any changes. With IMAP protocol + this is done every time after running a command. + +Initializing +------------ + +'mailbox_sync_init()' initializes syncing. + +There are some flags that control how much effort is spent on syncing: + + * 'MAILBOX_SYNC_FLAG_FAST' can be given when you're ready for mailbox to be + refreshed, but don't care much if it actually is or not. When this flag is + set, Dovecot still notices all internal changes, but external changes are + checked only once every few seconds or so. + * 'MAILBOX_SYNC_FLAG_FULL_READ' is mainly useful with mboxes. If + 'mbox_dirty_syncs=yes' and a new mail gets appended to mbox by an external + program, Dovecot assumes that the only change was the added mail, even + though the program may have also modified existing messages' flags by + rewriting Status: headers. If 'mbox_very_dirty_syncs=no', these changes are + noticed after the next time mailbox is opened. So when this flag is enabled, + it means Dovecot should try harder to find out if there were any external + unexpected changes. It's currently used only with IMAP SELECT and CHECK + commands and POP3 startup. Probably unnecessary elsewhere. + * 'MAILBOX_SYNC_FLAG_FULL_WRITE' is again mainly useful with mboxes. If + 'mbox_lazy_writes=no', Dovecot delays writing flag changes to mbox file + until mailbox is closed or IMAP CHECK command is issued. Using this + elsewhere is probably unnecessary, except as an optimization if mailbox is + in any case synced just before closing it, you might as well give this flag + to it to avoid double-syncing with mbox. + * 'MAILBOX_SYNC_FLAG_FORCE_RESYNC' is used to force resyncing indexes. The + only time this should be done is when manually triggered by administrator. + +Then there are also other syncing flags: + + * 'MAILBOX_SYNC_FLAG_NO_EXPUNGES': No expunged messages are removed from the + in-memory mailbox view. Their removal is delayed until syncing is done + without this flag. Attempting to access the expunged messages may or may not + work, depending on what information is accessed and what storage backend is + used. + * 'MAILBOX_SYNC_FLAG_FIX_INCONSISTENT': Normally when the internal mailbox + state can't be consistently updated (typically due to index file + corruption), the syncing fails. When this flag is set, it means that the + caller doesn't care about mailbox's previous state and just wants to get it + accessible again. Typically this is used when the mailbox is being opened, + but not afterwards. + * 'MAILBOX_SYNC_FLAG_EXPUNGE' is mainly intended for virtual plugin with IMAP + protocol. You probably shouldn't use it. + +Reading changes +--------------- + +While 'mailbox_sync_next()' returns TRUE, it fills out sync record: + + * seq1, seq2: Message sequence numbers that were affected + * type: expunge, flag change or modseq change. + +Expunge records don't immediately change the view's sequence numbers. After +seeing an expunge record you can still fetch the expunged messages' flags and +possibly other information. Only after syncing is deinitialized, the sequences +change. + +Message flag change records don't actually show what the changes were. You can +find the new flags just by fetching them ('mail_get_flags()', etc.), they're +available immediately. You'll need to create a <transaction> +[Design.Storage.Mailbox.Transaction.txt] and a <mail> [Design.Storage.Mail.txt] +for that. For example: + +---%<------------------------------------------------------------------------- +sync_ctx = mailbox_sync_init(box, flags); +trans = mailbox_transaction_begin(box, 0); +mail = mail_alloc(trans, MAIL_FETCH_FLAGS, 0); +---%<------------------------------------------------------------------------- + +If you don't actually care about sync records, you don't necessarily have to +even call 'mailbox_sync_next()'. In that case it's actually easiest to perform +the whole sync using a one-step 'mailbox_sync()' function. This function also +sets 'MAILBOX_SYNC_FLAG_FIX_INCONSISTENT' flag automatically. + +Deinitializing +-------------- + +'mailbox_sync_deinit()' finalizes the syncing. If any errors occurred during +sync, it'll return -1. + +If 'MAILBOX_SYNC_FLAG_NO_EXPUNGES' was used and some expunges were actually +delayed,'status_r->sync_delayed_expunges' is set to TRUE. + +Implementing sync for a storage backend +--------------------------------------- + +FIXME: talk about mail_index_sync_*() and how to change stuff and how to update +internal state. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mailbox.Transaction.txt b/doc/wiki/Design.Storage.Mailbox.Transaction.txt new file mode 100644 index 0000000..63a37e1 --- /dev/null +++ b/doc/wiki/Design.Storage.Mailbox.Transaction.txt @@ -0,0 +1,52 @@ +Mailbox Transactions +==================== + +Before you can read any mails or do any changes to mails, you need to create a +transaction with 'mailbox_transaction_begin()'. It has a few flags: + + * 'MAILBOX_TRANSACTION_FLAG_HIDE': Mark the changes in a way that when later + <syncing> [Design.Storage.Mailbox.Sync.txt] the mailbox in this session, + 'mailbox_sync_next()' won't return sync records for the changes done by this + transaction. This is primarily meant for flag and keyword changes, you can't + hide expunges. For example IMAP's 'STORE FLAGS.SILENT' command is + implemented by setting this flag for the transaction. + * 'MAILBOX_TRANSACTION_FLAG_EXTERNAL': Changes done by this transaction should + be marked as external changes. Internal changes can be thought of as "change + requests" that syncing later finishes, while external changes are done + immediately and syncing ignores them. Normally you would use this flag when + you want to save or copy messages, nothing else. + * 'MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS': Require assigning UIDs to + saved/copied messages immediately. Normally this is done only when it's easy + (maildir: if dovecot-uidlist can be locked without waiting, mbox: if mbox is + already fully synced). + * 'MAILBOX_TRANSACTION_FLAG_REFRESH': Do a quick index refresh, so any recent + flag/modseq changes done by other Dovecot sessions will be visible. You + shouldn't usually need this, because usually you should have recently done a + mailbox sync. + +Changes for a transaction are kept in memory until the transaction is +committed. If you want to cancel the changes, you can call +'mailbox_transaction_rollback()'. Transaction can be commited with +'mailbox_transaction_commit()'. If you want to know a bit more about the +results of the transaction, use 'mailbox_transaction_commit_get_changes()' +instead. It returns a change structure: + + * uid_validity: UIDVALIDITY used by returned UIDs + * saved_uids: UIDs assigned to saved/copied mails. Typically they're in an + ascending order, unless you explicitly requested some specific UIDs for + mails while saving them (e.g. dsync does this). + * ignored_uid_changes: Number of UIDs that couldn't be changed by + 'mail_update_uid()' calls, because the UIDs were less than next_uid's value. + + * ignored_modseq_changes: Number of modseqs that couldn't be changed by + 'mail_update_modseq()' calls, because they would have lowered the modseq. + +Once you're done with reading the change structure, be sure to free the memory +used by it with 'pool_unref(&changes->pool)'. + +'mailbox_transaction_set_max_modseq()' can be used to implement atomic +conditional flag changes. If message's modseq is higher than the given +max_modseq while transaction is being committed, the change isn't done and the +message's sequence number is added to the given array. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Mailbox.txt b/doc/wiki/Design.Storage.Mailbox.txt new file mode 100644 index 0000000..5af8263 --- /dev/null +++ b/doc/wiki/Design.Storage.Mailbox.txt @@ -0,0 +1,34 @@ +Mailbox +======= + +'src/lib-storage/mail-storage.h' and 'mail-storage-private.h' describes mailbox +API, among others. Mailbox life cycle often goes like: + + * 'mailbox_alloc()' allocates memory for the mailbox and initializes some + internal settings, but doesn't actually try to open it. + * 'mailbox_open()' opens the mailbox. Instead of opening a mailbox, you can + also create it with 'mailbox_create()'. + * If you're immediately syncing the mailbox, you don't need to open it, + because it's done implicitly. This reduces your code and error handling a + bit. + * 'mailbox_close()' closes the mailbox, so that it needs to be opened again if + it's wanted to be accessed. This is rarely needed. + * 'mailbox_free()' closes and frees the mailbox. + +There are a lot of functions to deal with mailboxes. The most important ones +are: + + * 'mailbox_get_status()' to get a summary of mailbox, such as number of + messages in it. + * <Syncing> [Design.Storage.Mailbox.Sync.txt]: 'mailbox_sync_*()' to + synchronize changes from the backend to memory. + * <Transactions> [Design.Storage.Mailbox.Transaction.txt]: + 'mailbox_transaction_*()' for transaction handling. All message reads and + writes are done in a transaction. + * <Searching> [Design.Storage.Mailbox.Search.txt]: 'mailbox_search_*()' is + used for searching messages. Even simple operations like "get all messages" + go through this API, it'll then simply do "search all". + * <Saving> [Design.Storage.Mailbox.Save.txt]: 'mailbox_save_*()' and + 'mailbox_copy()' is used for saving/copying new messages to mailbox. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.MailboxList.txt b/doc/wiki/Design.Storage.MailboxList.txt new file mode 100644 index 0000000..6c27883 --- /dev/null +++ b/doc/wiki/Design.Storage.MailboxList.txt @@ -0,0 +1,159 @@ +Mailbox List +============ + +'src/lib-storage/mailbox-list.h' and 'mailbox-list-private.h' describes mailbox +list. The purpose of mailbox list is to manage mailbox storage name<-> physical +directory path mapping. Its most important functions are: + + * listing existing mailboxes, + * creating directories for new mailboxes (but not the mailboxes themselves, + that's storage's job), + * deleting mailboxes, + * renaming mailboxes and + * managing mailbox subscriptions. + +Mailbox list code also internally creates and updates mailbox changelog (in +'dovecot.mailbox.log' file), which keeps track of mailbox deletions, renames +and subscription changes. This is primarily useful for dsync utility. + +Mailbox list is configured by <mail_location> [MailLocation.txt] setting, which +fills 'struct mailbox_list_settings': + + * root_dir: The root mail directory (e.g. with + 'mail_location=maildir:~/Maildir' it would be the '~/Maildir'). + * index_dir: Directory under which index files are written to. Empty string + means in-memory indexes. Defaults to root_dir. + * control_dir: Directory under which control files are written to. Control + files are files that contain some important metadata information about + mailbox so (unlike index files) they should never be deleted. For example + subscriptions file is a control file. Defaults to root_dir. + * alt_dir: This is currently <dbox> [MailboxFormat.dbox.txt]-specific setting. + + * inbox_path: Path to INBOX mailbox. This exists mainly because with mbox + format INBOX is often in a different location than other mailboxes. + * subscription_fname: Filename used by subscriptions file. + * dir_guid_fname: Filename used to store directories' (not mailboxes') global + UIDs. Directory GUIDs are mainly useful for dsync. + * maildir_name: Directory name under which the actual mailboxes are stored in, + such as dbox-Mails/ with dbox. See the .h file for more detailed + description. + * mailbox_dir_name: If non-empty, store all mailboxes under + root_dir/mailbox_dir_name/. + +Listing mailboxes +----------------- + +First the list operation is initialized with one of the init functions: + + * 'mailbox_list_iter_init()' lists mailboxes that match the given pattern. + * 'mailbox_list_iter_init_multiple()' lists mailboxes that match any of the + given patterns list. + * 'mailbox_list_iter_init_namespaces()' lists matching mailboxes from all + namespaces. + * 'MAILBOX_LIST_ITER_SKIP_ALIASES' flag skips namespaces that have + 'alias_for' set. You usually want to set this flag to avoid processing + the same mailbox multiple times. + +The patterns are IMAP-style patterns with '%' and '*' wildcards as described by +RFC 3501: '%' matches only up to next hierarchy separator, while '*' matches +the rest of the string. + +These flags control what mailboxes are returned: + + * 'MAILBOX_LIST_ITER_NO_AUTO_INBOX' doesn't list INBOX unless it physically + exists. Normally INBOX is listed, because INBOX doesn't need to be (and + cannot be) explicitly created. It can always be opened and messages can be + saved to it, it's just automatically created when it doesn't exist. + * 'MAILBOX_LIST_ITER_SELECT_SUBSCRIBED' lists only subscribed mailboxes. + * 'MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH' is currently only useful when + combined with '_SELECT_SUBSCRIBED' flag. Then it adds + 'MAILBOX_CHILD_SUBSCRIBED' flags for mailboxes whose children are + subscribed. It also lists mailboxes that aren't themselves subscribed, but + have children that do. + +These flags control what is returned for matching mailboxes: + + * 'MAILBOX_LIST_ITER_RETURN_NO_FLAGS' can be set when you don't care about + mailbox flags. They're then set only if it can be done without any + additional disk I/O. + * 'MAILBOX_LIST_ITER_RETURN_SUBSCRIBED' returns mailbox's subscription state. + * 'MAILBOX_LIST_ITER_RETURN_CHILDREN' sets "has child mailboxes" or "doesn't + have child mailboxes" flag. + +Other flags: + + * 'MAILBOX_LIST_ITER_RAW_LIST' should usually be avoided. It ignores ACLs and + just returns everything. + * 'MAILBOX_LIST_ITER_VIRTUAL_NAMES' enables listing to use virtual names + instead of storage names in patterns and returned mailbox names. + +Once listing is initialized, 'mailbox_list_iter_next()' can be called until it +returns NULL. The returned mailbox_info struct contains: + + * 'name': Mailbox's name, either virtual or storage name depending on + '_VIRTUAL_NAMES' flag. + * 'ns': Mailbox's namespace. This is useful only when mailboxes are listed + using 'mailbox_list_iter_init_namespaces()'. + * 'flags': Mailbox flags: + * 'MAILBOX_NOSELECT': Mailbox exists, but can't be selected. It's possible + that it can be created and then it becomes selectable. For example with + mbox and FS layout the directories aren't selectable mailboxes. + * 'MAILBOX_NONEXISTENT': Mailbox doesn't exist. It's listed only because it + has child mailboxes that do exist but don't match the pattern. + * Example: "foo/bar" exists, but "foo" doesn't. "%", "foo" or "*o" + pattern would list "foo", because it matches the pattern but its child + doesn't. Then again "*", "*bar" or "%/%" wouldn't list "foo", because + "foo/bar" matches the pattern (and is also listed). Something like + "*asd*" wouldn't match either "foo" or "foo/bar" so neither is + returned. + * 'MAILBOX_CHILDREN' and 'MAILBOX_NOCHILDREN': Mailbox has or doesn't have + children. If neither of these flags are set, it's not known if mailbox + has children. + * 'MAILBOX_NOINFERIORS': Mailbox doesn't have children and none can ever be + created. For example with mbox and FS layout the mailboxes have this flag + set, because files can't be created under files. + * 'MAILBOX_MARKED' and 'MAILBOX_UNMARKED': Mailbox has or doesn't have + messages with \Recent flags. If neither is set, the state is unknown. + Because this check is done in a very cheap way, having 'MAILBOX_MARKED' + doesn't always mean that there are \Recent flags. However, if + 'MAILBOX_UNMARKED' is returned it is guaranteed to be correct. (False + positives are ok, false negatives are not ok.) + * 'MAILBOX_SUBSCRIBED': Mailbox is subscribed. + * 'MAILBOX_CHILD_SUBSCRIBED': Mailbox has a child that is subscribed (and + '_SELECT_RECURSIVEMATCH' flag was set). + +Finally the listing is deinitalized with 'mailbox_list_iter_deinit()'. If it +returns -1, it means that some mailboxes perhaps weren't listed due to some +internal error. + +If you wish to get mailbox_info flags only for a single mailbox, you can use +'mailbox_list_mailbox()'. + +Directory permissions +--------------------- + +'mailbox_list_get_permissions()' and 'mailbox_list_get_dir_permissions()' can +be used to get wanted permissions for newly created files and directories. + + * For global files, give NULL as the mailbox name. The permissions are then + based on the root_dir. If root_dir doesn't exist, it returns 0700/0600 mode. + * For per-mailbox files, give the mailbox name. The permissions are then based + on the mailbox's directory. + +The returned permissions are: + + * mode: Creation mode, like 0600. + * gid: Group that should be set, unless it's '(gid_t)-1'. There are 3 reasons + why it could be that: + * directory has g+s bit set, so the wanted group is set automatically + * group is the same as process's effective GID, so it gets set + automatically + * mode's group permissions are the same as world permissions, so group + doesn't matter. + * gid_origin: This string points to the directory where the group (and + permissions in general) was based on, or "defaults" for internal defaults. + +If changing the group fails with EPERM, 'eperm_error_get_chgrp()' can be used +to log a nice and understandable error message. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Storage.Plugins.txt b/doc/wiki/Design.Storage.Plugins.txt new file mode 100644 index 0000000..349ab2e --- /dev/null +++ b/doc/wiki/Design.Storage.Plugins.txt @@ -0,0 +1,124 @@ +Mail Plugins +============ + +Typically plugins add hooks in their init() function by calling +'mail_storage_hooks_add()', and remove the hooks at deinit() with +'mail_storage_hooks_remove()'. Hooks that are currently supported: + + * mail_user_created: A new mail user was created. It doesn't yet have any + namespaces. + * mail_storage_created: A new mail storage was created. It's not connected to + any namespaces/mailbox lists yet. + * mailbox_list_created: A new mailbox list was created. It's not connected to + any storages yet. Because of this, some internal virtual methods haven't + been overridden by the storage yet, so plugins rarely want to use this hook. + Instead they should use: + * mail_namespace_storage_added: Storage was connected to its first + namespace/mailbox list. This hook should usually be used if plugin wants to + override mailbox_list's methods. + * mail_namespaces_created: User's all namespaces have been created. This hook + is called only per user at startup. More internal namespaces may be created + later when using shared mailboxes. + * mailbox_allocated: 'mailbox_alloc()' was called. + * mailbox_opened: Mailbox (and its index) was actually opened, either + explicitly with 'mailbox_open()' or implicitly by some other function. + +Overriding methods +------------------ + +When the hook gets called, you usually want to override some method of the +created object. This is the easy part, for example: + +---%<------------------------------------------------------------------------- +static void plugin_mailbox_allocated(struct mailbox *box) +.. + box->v.transaction_begin = plugin_transaction_begin; +---%<------------------------------------------------------------------------- + +The problem is that once 'plugin_transaction_begin()' is called, it should call +the original 'transaction_begin()'. There may also be multiple plugins that +want to override the same method, so the idea is to just have each plugin call +the previous 'transaction_begin()'. The next problem is where do you save the +previous value? Most objects have a 'module_contexts' array for storing +per-plugin pointers for this purpose. There are several helper functions to +make setting and accessing them in a quite safe way. + +Easiest way to set up the module context is to just copy&paste code from an +existing plugin that sets the same context. Here's some documentation about it +anyway: + +First you start by creating register for the plugin. There are different +registers for different types of objects: + + * mail_user_module_register: For mail_user. + * mailbox_list_module_register: For mailbox_list. + * mail_storage_module_register: For mail_storage, mailbox, mailbox_transaction + and mail_search. + * mail_module_register: For mail. + +We'll assume you want to use mail_storage_module_register: + +---%<------------------------------------------------------------------------- +static MODULE_CONTEXT_DEFINE_INIT(plugin_storage_module, +&mail_storage_module_register); +---%<------------------------------------------------------------------------- + +If you need to make it external, use: + +---%<------------------------------------------------------------------------- +extern MODULE_CONTEXT_DEFINE(plugin_storage_module, +&mail_storage_module_register); +struct plugin_storage_module plugin_storage_module = + MODULE_CONTEXT_INIT(&mail_storage_module_register); +---%<------------------------------------------------------------------------- + +Next you'll need to allocate memory for the structure you want to place in the +context. If you only want to override some methods, you can use: + +---%<------------------------------------------------------------------------- +union mailbox_module_context *mbox; +struct mailbox_vfuncs *v = box->vlast; + +mbox = p_new(box->pool, union mailbox_module_context, 1); +mbox->super = *v; +box->vlast = &mbox->super; + +v->transaction_begin = plugin_transaction_begin; +MODULE_CONTEXT_SET_SELF(box, plugin_storage_module, mbox); +---%<------------------------------------------------------------------------- + +If you want to store some more plugin-specific data to the object instead of +just the super methods, you can do: + +---%<------------------------------------------------------------------------- +struct plugin_mailbox { + /* must be called module_ctx */ + union mailbox_module_context module_ctx; +}; +/* .. */ + +struct plugin_mailbox *mbox; +struct mailbox_vfuncs *v = box->vlast; + +mbox = p_new(box->pool, struct plugin_mailbox, 1); +mbox->module_ctx.super = *v; +box->vlast = &mbox->super; + +v->transaction_begin = plugin_transaction_begin; +MODULE_CONTEXT_SET(box, plugin_storage_module, mbox); +---%<------------------------------------------------------------------------- + +Note that when using union directly you use 'MODULE_CONTEXT_SET_SELF()', while +when it's inside a struct you use 'MODULE_CONTEXT_SET()'. + +Once all this initialization is done, you can look up the module context with: + +---%<------------------------------------------------------------------------- +#define PLUGIN_CONTEXT(obj) MODULE_CONTEXT(obj, plugin_storage_module) +/* .. */ +struct plugin_mailbox *mbox = PLUGIN_CONTEXT(box); +---%<------------------------------------------------------------------------- + +(Yes, this API seems a bit too difficult to use and could use a redesign.) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.Strings.txt b/doc/wiki/Design.Strings.txt new file mode 100644 index 0000000..72ca055 --- /dev/null +++ b/doc/wiki/Design.Strings.txt @@ -0,0 +1,70 @@ +Dynamic Strings +=============== + +'lib/str.h' describes Dovecot's dynamically growing strings. Strings are +actually only a simple wrapper on top of <buffers> [Design.Buffers.txt]. Even +the 'string_t' type is only a typedef of 'buffer_t', so it's possible to use +'buffer_*()' functions with strings (although it's ugly so it should be +avoided). The decision of whether to use a string_t or a buffer_t is mainly for +human readability: if the buffer's contents are (ASCII/UTF8) text use string_t, +otherwise for binary data use buffer_t. + +Once you're done modifying a string with 'str_*()' functions, you can get it +out as a NUL-terminated string with 'str_c()' or 'str_c_modifiable()'. These +pointers shouldn't be accessed after modifying the string again, they could +have moved elsewhere in memory and they're no longer guaranteed to be +NUL-terminated. + +Example: + +---%<------------------------------------------------------------------------- +T_BEGIN { + string_t *str = t_str_new(64); + + str_append(str, "hello world"); + str_printfa(str, "\nand %u", str_len(str)); + + printf("%s\n", str_c(str)); +} T_END; +---%<------------------------------------------------------------------------- + +String Handling Functions +========================= + +'lib/strfuncs.h' contains a lot of functions intended to make string handling +easier. They use C's NUL-terminated strings instead of Dovecot's dynamic +strings. + + * '[pt]_strdup_printf()' and '[pt]_strconcat()' are the most commonly used + functions.'*_strconcat' is slightly faster than '*_strdup_printf()', so use + it if you simply need to concatenate strings. + * Various functions for doing a 'strdup()' from wanted input. + * 'i_snprintf()' is a wrapper to 'snprintf()' that makes it easier to check if + result was truncated. It also adds few other safety checks. This should be + avoided in general, except in situations where you just don't want to use + data stack and there's no way for the result to get truncated. + * 'i_strocpy()' is similar to 'strlcpy()', but makes it easier to check if + result was truncated. This has the same problems as 'i_snprintf()'. + * Functions for uppercasing and lowercasing strings. + * Functions you can pass to 'bsearch()' and 'qsort()' for handling string + arrays. + * '[pt]_strsplit()' is an easy way to split a string into an array of strings + from given separator. + * 't_strarray_join()' reverses this. + * There are also some other functions to handle array of strings, like + getting its length or finding a given string. + * 'dec2str()' can be used to convert a number to a string. This can be useful + if you don't know the correct type and don't want to add casting (that could + potentially truncate the string). For example:'print("pid = %s\n", + dec2str(getpid()));' + +String Escaping +=============== + +'lib/strescape.h' contains functions to escape and unescape <">. <'> and <\> +characters in strings using<\> character.\ + +Dovecot's internal protocols are often line-based with TAB as the field +separator. This file also contains functions to escape and unescape such data. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Design.txt b/doc/wiki/Design.txt new file mode 100644 index 0000000..c27f4ec --- /dev/null +++ b/doc/wiki/Design.txt @@ -0,0 +1,66 @@ +Dovecot Design +============== + + * <Overview of Dovecot processes> [Design.Processes.txt] + * <Design of index files> [Design.Indexes.txt] + * <API for accessing the index files> [Design.Indexes.MailIndexApi.txt] + * <Design of authentication process> [Design.AuthProcess.txt] + * <Authentication protocol> [Design.AuthProtocol.txt] + * <Design of IMAP/POP3 processes> [Design.MailProcess.txt] + * <Doveadm server protocol> [Design.DoveadmProtocol.txt] and <Doveadm HTTP + server protocol> [Design.DoveadmProtocol.HTTP.txt] + * <Doveadm synchronization> [Design.Dsync.txt] + * <Dovecot Lua support> [Design.Lua.txt] + +Protocol extensions +------------------- + + * <Forwarding parameters in IMAP/POP3/LMTP/SMTP proxying> + [Design.ParameterForwarding.txt] + +Code APIs +--------- + + * <Code design> [Design.Code.txt] - explanations how and why the coding style + is the way it is + +Look at the *.h files for the actual API documentation. The documentation below +doesn't attempt to list full API documentation. + +liblib: + + * <Memory allocations> [Design.Memory.txt] + * <Static/dynamic buffers> [Design.Buffers.txt] + * <Dynamic arrays> [Design.Arrays.txt] + * <String handling> [Design.Strings.txt] + * <Input streams> [Design.InputStreams.txt] + * <Output streams> [Design.OutputStreams.txt] + * <Events> [Design.Events.txt] + * <Plugins> [Design.Plugins.txt] + +lib-dcrypt: + + * <lib-dcrypt data formats> [Design.Dcrypt.txt] + +lib-storage: + + * <Mail user> [Design.Storage.MailUser.txt] contains everything related to a + single user. + * <Mail namespace> [Design.Storage.MailNamespace.txt]: A single user can + contain multiple <namespaces> [Namespaces.txt]. + * <Mailbox list> [Design.Storage.MailboxList.txt] is used to list/manage a + list of mailboxes for a single namespace (1:1 relationship). + * <Mail storage> [Design.Storage.MailStorage.txt] is used to access mails in a + specific location with a specific mailbox format. Multiple namespaces can + point to the same storage. A single namespace may in future (but not + currently) point to multiple storages (e.g. a mixed mbox and Maildir + directory). + * <Mailbox> [Design.Storage.Mailbox.txt] is used to access a specific mailbox + in a storage. + * <Mail> [Design.Storage.Mail.txt] is used to access a specific mail in a + mailbox. + * <Error handling> [Design.Storage.ErrorHandling.txt]. + * <Plugins> [Design.Storage.Plugins.txt] - how to hook into lib-storage + functions. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Dict.txt b/doc/wiki/Dict.txt new file mode 100644 index 0000000..082fb4a --- /dev/null +++ b/doc/wiki/Dict.txt @@ -0,0 +1,45 @@ +Dict Proxy Process +================== + +Dict server is used for providing <dictionary> [Dictionary.txt] access via +server processes instead of doing it directly from whichever process wants to +access the dictionary. This is useful for some backends with relatively high +connection cost (e.g. SQL), but not necessarily for others (e.g. Redis). + +When a mail process uses the dict proxy, it needs to have access the dict UNIX +socket. By default only the "dovecot" user has access to the dict socket, which +doesn't typically work in any installation. However, giving too wide +permissions by default might allow untrusted users to access the dict and cause +problems. + +If all users share a single UNIX UID (e.g. "vmail"), you could make the dict +socket accessible only to it: + +---%<------------------------------------------------------------------------- +service dict { + unix_listener dict { + mode = 0600 + user = vmail + } +} +---%<------------------------------------------------------------------------- + +If you use multiple UNIX UIDs, you can add an extra group for all Dovecot mail +processes. This works even if you have untrusted system users who have shell +access to the server: + +---%<------------------------------------------------------------------------- +mail_access_groups = dovecot + +service dict { + unix_listener dict { + mode = 0660 + group = dovecot + } +} +---%<------------------------------------------------------------------------- + +However, it works with <LDA.txt> only if it's started as root. If this isn't +possible, look into using <LMTP.txt> instead. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Dictionary.txt b/doc/wiki/Dictionary.txt new file mode 100644 index 0000000..1eb078b --- /dev/null +++ b/doc/wiki/Dictionary.txt @@ -0,0 +1,268 @@ +Dovecot Dictionaries +==================== + +Dovecot's lib-dict can be used to access simple key-value databases. This is +used by for example <quota-dict> [Quota.Dict.txt], <passdb&userdb> +[AuthDatabase.Dict.txt], <last-login plugin> [Plugins.LastLogin.txt], +<METADATA> [ImapMetadata.txt], etc. The dictionaries can be accessed either +directly by the mail processes or they can be accessed via <dict proxy> +[Dict.txt] processes. + +Currently supported dict backends are: + + * Flat files + * FS (lib-fs wrapper) + * Memcached (ASCII protocol) + * Memcached (Binary protocol) + * Redis + * Proxy + * SQL + * LDAP (read only) + +Flat Files +---------- + +---%<------------------------------------------------------------------------- +file:<path> +---%<------------------------------------------------------------------------- + +The file will simply contain all the keys that are used. Not very efficient for +large databases, but good for small ones such as a single user's quota. + +FS (v2.2.11+) +------------- + +---%<------------------------------------------------------------------------- +fs:<driver>:<driver args> +---%<------------------------------------------------------------------------- + +This is a wrapper for lib-fs, which most importantly has the "posix" backend. +So using: + +---%<------------------------------------------------------------------------- +fs:posix:prefix=/var/lib/dovecot/dict +---%<------------------------------------------------------------------------- + +Would create a separate file under /var/lib/dovecot/dict for each key. + +Memcached (Binary Protocol) (v2.2.9+) +------------------------------------- + +This driver uses the "new" Memcache binary protocol. + +https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol + +---%<------------------------------------------------------------------------- +memcached:param=value:param2=value2:... +---%<------------------------------------------------------------------------- + +Supported parameters are: + + * host: Memcached server host (default: 127.0.0.1) + * port: Memcached server port (default: 11211) + * prefix: Prefix to add to all keys (default: empty) + * timeout_msecs: Abort lookups after specified number of milliseconds + (default: 30000) + +Memcached (ASCII Protocol) (v2.2.9+) +------------------------------------ + +This driver uses the "legacy" Memcache ASCII protocol. + +https://github.com/memcached/memcached/blob/master/doc/protocol.txt + +---%<------------------------------------------------------------------------- +memcached_ascii:param=value:param2=value2:... +---%<------------------------------------------------------------------------- + +Supported parameters are: + + * host: Memcached server host (default: 127.0.0.1) + * port: Memcached server port (default: 11211) + * prefix: Prefix to add to all keys (default: empty) + * timeout_msecs: Abort lookups after specified number of milliseconds + (default: 30000) + +Redis (v2.2.9+) +--------------- + +---%<------------------------------------------------------------------------- +redis:param=value:param2=value2:... +---%<------------------------------------------------------------------------- + +Supported parameters are: + + * host: Redis server host (default: 127.0.0.1) + * port: Redis server port (default: 6379) + * prefix: Prefix to add to all keys (default: empty) + * db: Database number (default: 0) + * expire_secs=<n>: Set expiration value to all the keys + * timeout_msecs: Abort lookups after specified number of milliseconds + (default: 30000) + +Proxy +----- + +---%<------------------------------------------------------------------------- +proxy:[<dict path>]:<destination dict> +---%<------------------------------------------------------------------------- + +Proxying is used to perform all dictionary accessing via the dict processes. +(The dict processes exist only if dict proxying is used.) This is especially +useful with backends where their initialization is relatively expensive, such +as SQL. The dict processes will then perform also connection pooling. + +If <dict path> is specified, it points to the socket where the dict server is +answering. The default is to use $base_dir/dict. Usually this is changed to +"dict-async" if the dict backend support asynchronous lookups (e.g. ldap, +pgsql, cassandra). The dict-async service allows more than one client, so this +configuration prevents creating unnecessarily many dict processes. + +The <destination dict> contains the dict name in the dict { .. } settings. For +example:'proxy:dict-async:quota' + +See <Dict.txt> for more information about the dict server. + +SQL +--- + +---%<------------------------------------------------------------------------- +<sql driver>:<path to dict-sql config> +---%<------------------------------------------------------------------------- + +The <sql driver> contains the SQL driver name, such as "mysql", "pgsql", +"sqlite" or "cassandra". + +The dict-sql config file consists of SQL server configuration and mapping of +keys to SQL tables/fields. + +SQL Connect String +------------------ + +---%<------------------------------------------------------------------------- +connect = host=localhost dbname=mails user=sqluser password=sqlpass +---%<------------------------------------------------------------------------- + +The connect setting is exactly the same as used for <SQL passdb/userdb> +[AuthDatabase.SQL.txt]. See 'example-config/dovecot-sql.conf.ext' for detailed +information. + +SQL Mapping +----------- + +SQL mapping is done with a dict key pattern and fields. When a dict lookup or +update is done, Dovecot goes through all the maps and uses the first one whose +pattern matches the dict key. + +For example when using dict for a per-user quota value the map looks like: + +---%<------------------------------------------------------------------------- +map { + pattern = priv/quota/storage + table = quota + username_field = username + value_field = quota_bytes +} +---%<------------------------------------------------------------------------- + +This means that: + + * The dict key must match exactly "priv/quota/storage". The dict keys are + hardcoded in the Dovecot code, so depending on what functionality you're + configuring you need to know the available dict keys used it. + * This is a private dict key ("priv/" prefix), which means that there must be + a username_field. The username_field is assumed to be (at least part of) the + primary key. In this example we don't have any other primary keys. + * With MySQL the above map translates to SQL queries: + * 'SELECT quota_bytes FROM quota WHERE username = '$username_field'' + * 'INSERT INTO quota (username, quota_bytes) VALUES ('$username_field', + '$value') ON DUPLICATE KEY UPDATE quota_bytes='$value'' + +You can also access multiple SQL fields. For example acl_shared_dict can +contain: + +---%<------------------------------------------------------------------------- +map { + pattern = shared/shared-boxes/user/$to/$from + table = user_shares + value_field = dummy + + fields { + from_user = $from + to_user = $to + } +} +---%<------------------------------------------------------------------------- + + * The acl_shared_dict always uses "1" as the value, so here the value_field is + called "dummy". + * The SQL from_user and to_user fields are the interesting ones. Typically the + extra fields would be part of the primary key. + * With MySQL the above map translates to SQL queries: + * 'SELECT dummy FROM user_shares WHERE from_user = '$from' AND to_user = + '$to'' + * 'INSERT INTO user_shares (from_user, to_user, dummy) VALUES ('$from', + '$to', '$value') ON DUPLICATE KEY UPDATE dummy='$value'' + +LDAP (v2.2.24+) +--------------- + +LDAP support is very similar to SQL support, but there is no write support. + +Configuration +------------- + +---%<------------------------------------------------------------------------- +dict { + somedict = ldap:/path/to/dovecot-ldap-dict.conf.ext +} +---%<------------------------------------------------------------------------- + +Then in ext file put + +---%<------------------------------------------------------------------------- +uri = ldap://hostname +bind_dn = optional bind dn +password = optional password +timeout = optional timeout +debug = 0 or 1 (optional, as well) +tls = yes|try|no (default is try) +---%<------------------------------------------------------------------------- + + * uri - LDAP connection URI as expected by OpenLDAP. + * bind_dn - DN or upn to use for binding + * password - password to use, only SIMPLE auth is supported at the moment + * timeout - How long to wait for reply, default is 30 seconds + * debug - 0 off, 1 on, will produce metric ton of output + * tls - yes = require either ldaps or successful start TLS, try = send start + TLS if necessary, no = do not send start TLS + +To map some key to a search do + +---%<------------------------------------------------------------------------- +map { + pattern = priv/test/mail + filter = (mail=*) # the () is required + base_dn = ou=container,dc=domain + username_attribute = uid # default is cn + value_attribute = mail +} +---%<------------------------------------------------------------------------- + +To do some more complex search + +---%<------------------------------------------------------------------------- +map { + pattern = priv/test/mail/$location + filter = (&(mail=*)(location=%{location}) # the () is required + base_dn = ou=container,dc=domain + username_attribute = uid # default is cn + value_attribute = mail + + fields { + location=$location + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Director.txt b/doc/wiki/Director.txt new file mode 100644 index 0000000..1ffa364 --- /dev/null +++ b/doc/wiki/Director.txt @@ -0,0 +1,366 @@ +Director +======== + +Director can be used by <Dovecot's IMAP/POP3/LMTP proxy> +[PasswordDatabase.ExtraFields.Proxy.txt] to keep a temporary user -> mail +server mapping. As long as user has simultaneous connections, the user is +always redirected to the same server. Each proxy server is running its own +director process, and the directors are communicating the state to each others. +Directors are mainly useful for setups where all of the mail storage is seen by +all servers, such as with NFS or a cluster filesystem. + +First test non-director proxying +-------------------------------- + +The director is simply a small add-on for Dovecot proxy. Before configuring +director, you should test that a simple proxying setup with static destination +server works. See the <Proxy> [PasswordDatabase.ExtraFields.Proxy.txt] page for +more information about how to configure it. If you have a simple setup, you can +test this easily using a static passdb: + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = proxy=y host=10.2.0.20 nopassword=y +} +---%<------------------------------------------------------------------------- + +Once finished testing, remember to remove the "host" field. + +Servers +------- + +You need one or more servers assigned for Dovecot proxies. The same servers +could also act as backends handling the mails, but you need to run <two +separate Dovecot configurations> [RunningDovecot.txt] in different ports. This +may get a bit confusing, so it's not recommended (although v2.1 makes it easier +with 'instance_name' setting). + +The directors are going to connect to each others in a ring. For example if you +have servers called A, B and C, director will create connections A->B, B->C and +C->A. + +Director configuration +---------------------- + +In example configuration you can configure director from +'conf.d/10-director.conf'. + +Listeners +--------- + +Configure the listeners that director requires: + +---%<------------------------------------------------------------------------- +service director { + unix_listener login/director { + mode = 0666 + } + fifo_listener login/proxy-notify { + mode = 0600 + user = $default_login_user + } + # NOTE: director-userdb socket is actually used only for passdb lookups, not +userdb lookups + unix_listener director-userdb { + mode = 0600 + } + inet_listener { + port = 9090 + } + ## uncomment this if you want to use + ## doveadm director status -a ip:9091 + #inet_listener director-doveadm { + # port = 9091 + #} +} +---%<------------------------------------------------------------------------- + +The port 9090 will be used for listening and connecting to other directors. +You're free to use any port number you want. + +Configuring list of director servers +------------------------------------ + +List all of your directors in 'director_servers' setting separated by spaces. +You can use: + + * IP addresses + * hostnames + * hostnames that expand to multiple IPs (e.g. you could have a "directors-all" + DNS entry that expands to all directors' IPs) + +You can also add :port after the IP/host. The default port is the same as what +director service's inet_listener is using (the port 9090 above). + +Note that the same director must not be listed multiple times with different +IPs. This especially means that a hostname can't expand to both IPv4 and IPv6 +address. Otherwise Dovecot becomes confused about what directors actually +exist. This also means that a single director ring must use either IPv4 or IPv6 +addresses, but not both at the same time. + +For example if you have 3 directors, you could set: + +---%<------------------------------------------------------------------------- +director_servers = 10.1.0.2 10.1.0.3 10.1.0.4 +---%<------------------------------------------------------------------------- + +Configuring list of mail servers +-------------------------------- + +List all of your backend mail servers in 'director_mail_servers' setting +separated by spaces. You can use: + + * IP addresses + * IP ranges (e.g. 10.2.0.10-10.2.0.30) + * hostnames + * hostnames that expand to multiple IPs + +For example if you had 20 mail servers with consecutive IPs: + +---%<------------------------------------------------------------------------- +director_mail_servers = 10.2.0.11-10.2.0.30 +---%<------------------------------------------------------------------------- + +Enabling director +----------------- + +Enable director for the wanted login services by telling them to connect to +director socket instead of the default login socket: + +---%<------------------------------------------------------------------------- +service imap-login { + executable = imap-login director +} +service pop3-login { + executable = pop3-login director +} +---%<------------------------------------------------------------------------- + +Consistent hashing should be enabled for new director clusters. It's not +possible to change this setting without a complete director cluster shutdown. +Using it reduces users being moved around when doing backend changes. + +---%<------------------------------------------------------------------------- +director_consistent_hashing = yes # Supported by v2.2.16+ +---%<------------------------------------------------------------------------- + +If you want to enable director for LMTP, also set: + +---%<------------------------------------------------------------------------- +# LMTP first does a passdb lookup to to see if there's a proxy field returned. +# If not, it fallbacks to doing userdb lookup. +lmtp_proxy = yes + +protocol lmtp { + # NOTE: director-userdb socket is actually used only for passdb lookups, not +userdb lookups + auth_socket_path = director-userdb +} + +# If you want lmtp-proxy listening on the network, uncomment the following: +#service lmtp { +# inet_listener lmtp { +# port = 24 +# } +#} +---%<------------------------------------------------------------------------- + +By default LMTP proxy connects to the same port in backend as what was used for +the incoming connection. + +Other settings +-------------- + +Directors redirect a user to the same server always the user has active +connections. The redirection is also done for a while after the last connection +already disconnected. This is mainly to avoid trouble with NFS caches that +haven't yet expired. You can configure this setting from: + +---%<------------------------------------------------------------------------- +director_user_expire = 15 min +---%<------------------------------------------------------------------------- + +'doveadm director kick' and 'doveadm director move' need to be able to connect +to the 'ipc' socket. Make sure the director process can do it: + +---%<------------------------------------------------------------------------- +service ipc { + unix_listener ipc { + user = dovecot # This is already the default in v2.3.1+ + } +} +---%<------------------------------------------------------------------------- + +Passdb configuration +-------------------- + +Your passdb must return "proxy" <extra field> +[PasswordDatabase.ExtraFields.txt], otherwise director doesn't do anything. + +Director works by adding a "host" extra field to the auth reply, which contains +the temporary destination mail server. This "host" field isn't added if the +passdb lookup already returns "host". This allows configuring some users to be +always proxied to a specific server. + +If the backend servers verify password, you can use static passdb for director: + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = proxy=y nopassword=y +} +---%<------------------------------------------------------------------------- + +Note that while this is the simplest director configuration, users will be +assigned to a backend before they have been authenticated. A director +configured this way can be attacked by sending it a large number of unknown +users. To prevent this, the director should be configured to authenticate the +user and might make use of a master password to log into the backend servers. + +Doveadm server +-------------- + +Use these settings for both director and backends: + +---%<------------------------------------------------------------------------- +service doveadm { + inet_listener { + # any port you want to use for this: + port = 24245 + } +} + +local 10.10.10.0/24 { + # password to use for client authentication + doveadm_password = secret + # allow client to only use specified list of commands (default is all): + #doveadm_allowed_commands = +} +---%<------------------------------------------------------------------------- + +The director also needs the following configuration: + +---%<------------------------------------------------------------------------- +# same port as doveadm's inet_listener +doveadm_proxy_port = 24245 + +protocol doveadm { + # NOTE: director-userdb socket is actually used only for passdb lookups, not +userdb lookups + auth_socket_path = director-userdb +} +---%<------------------------------------------------------------------------- + +Now you can run doveadm commands on the director, and it'll run them +automatically on the correct backend server. + +Health monitoring of backend servers +------------------------------------ + +Brad Davidson has written a small daemon for monitoring backend servers, and +disable/enable them on demand. +Ref:https://dovecot.org/list/dovecot/2010-August/051946.html + +Forcefully moving users to a different backend +---------------------------------------------- + +This is useful if you need to do maintenance on one of the backend servers and +want (active) clients to move to a different backend: + + 1. Disable any watchdog system that will undo changes you make to backend + server weights, such as poolmon. + * Not needed if the watchdog is new enough to use HOST-UP/HOST-DOWN + commands rather than change weights. + 2. Set the weight of the backend server to be worked on to 0: 'doveadm + director add <backend server ip> 0' + 3. Flush current assignments to disable new connections to this backend: + 'doveadm director flush <backend server ip>' + * This will also kick the existing connections to the backend in v2.2.19+. + +Most IMAP clients will silently just reconnect to the (new backend) server +after being kicked (at least Apple Mail 6.0 and Thunderbird 14.0). + +For moving specific users to other servers (e.g. because there are too many +"heavy users" assigned to the same backend), you can use 'doveadm director +move' command in v2.0.14+. This requires the ipc permissions to be configured +correctly (see above). + +Tags +---- + +(Requires v2.2.16+) + +*WARNING*: This feature isn't working perfectly in v2.2.26.1 and older. If two +users with different tags have the same 32bit hash, they may end up going to +the wrong tag's backend. + +With tags you can use a single director ring to serve multiple backend +clusters. Each backend cluster is assigned a tag name, which can be anything +you want. By default everything has an empty tag. A passdb lookup can return +"director_tag" field containing the wanted tag name. If there aren't any +backend servers with the wanted tag, it's treated the same as if there aren't +any backend servers available (= wait for 30 secs for a backend and then return +temporary failure). + +Tags can be added to configuration by adding @tag suffix to IPs/hosts. For +example: + +---%<------------------------------------------------------------------------- +director_mail_servers = 10.0.0.100-10.0.0.110@name1 10.0.0.120@name2 +---%<------------------------------------------------------------------------- + +"doveadm director add" can also add tags either with @tag suffix or with -t +parameter. "doveadm director status user@domain" requires giving the user's +correct tag with -t parameter or the results won't be correct (empty tag's +results are shown). Tags can't currently be changed for an existing host +without removing it first. + +Director and Backend in same server (broken) +-------------------------------------------- + +NOTE: This feature never actually worked. It would require further development +to fix (director would need to add "proxy" field to extra fields and notify +auth that the auth_request can be freed). + +Have the passdb lookup return 'director_proxy_maybe=y'. LMTP however doesn't +currently support mixing recipients to both being proxied and store locally. + +Flush socket +------------ + +(Requires v2.2.26+) + +This allows calling a script for each user (hash) that is moved between +backends. This is triggered by "doveadm director move" and "doveadm director +flush" commands. What happens is: + + * User's connections are kicked from the director cluster + * Flush socket is called and waited on. + * User logins are delayed until the flush socket is finished, or the user move + times out after 30 seconds (hardcoded). + * Only the director that initiated the doveadm command will call the flush + socket. + * director_user_kick_delay is ignored by the initiating director, but used + by the other directors. + +Configuration: + +---%<------------------------------------------------------------------------- +director_flush_script = user-flush +service user-flush { + executable = script /usr/local/bin/user-flush.sh + unix_listener user-flush { + user = dovecot + } +} +---%<------------------------------------------------------------------------- + +The user-flush.sh will receive as parameters: + + * "FLUSH" + * username hash + * old host's IP + * new host's IP + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/DomainLost.txt b/doc/wiki/DomainLost.txt new file mode 100644 index 0000000..d7d24a5 --- /dev/null +++ b/doc/wiki/DomainLost.txt @@ -0,0 +1,60 @@ +Domain (%d) is empty +==================== + +IMAP or POP3 protocol doesn't have explicit support for domains. The usernames +are commonly in user@domain format, and that is also where Dovecot gets the +domain from. If the username doesn't have @domain, then the domain is also +usually empty (unless 'auth_default_realm' setting is used). + +If you login as user@domain, but the %d is still empty, the problem is that +your configuration lost the domain part by changing the username. Dovecot +doesn't keep track of the domain separately from username, so if something +changes username from "user@domain" to just plain "user", the domain is lost +and %d returns nothing. If you have 'auth_debug=yes', this shows up in logs +like: + +---%<------------------------------------------------------------------------- +Info: auth(user@domain.org): username changed user@domain.org -> user +---%<------------------------------------------------------------------------- + +Below are some of the most common reasons for this. + +Settings +-------- + +'auth_username_format = %Ln' lowercases the username but also drops the domain. +Use 'auth_username_format = %Lu' instead. + +'auth_username_format' changes the username permanently, currently it's not +possible to make it affect only the authentication part. + +SQL +--- + +'password_query' gets often misconfigured to drop the domain if username and +domain are stored separately. For example: + +---%<------------------------------------------------------------------------- +# BROKEN: +password_query = SELECT username AS user, password FROM users WHERE username = +'%n' AND domain = '%d' +---%<------------------------------------------------------------------------- + +The "username AS user" changes the username permanently and the domain is +dropped. You can instead use: + +---%<------------------------------------------------------------------------- +# MySQL: +password_query = SELECT concat(username, '@', domain) AS user, password FROM +users WHERE username = '%n' AND domain = '%d' +---%<------------------------------------------------------------------------- + +Or you can return username and domain fields separately and Dovecot will merge +them into a single user field: + +---%<------------------------------------------------------------------------- +password_query = SELECT username, domain, password FROM users WHERE username = +'%n' AND domain = '%d' +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Errors.ChgrpNoPerm.txt b/doc/wiki/Errors.ChgrpNoPerm.txt new file mode 100644 index 0000000..721c672 --- /dev/null +++ b/doc/wiki/Errors.ChgrpNoPerm.txt @@ -0,0 +1,28 @@ +Operation Not Permitted +======================= + +---%<------------------------------------------------------------------------- +imap(user): Error: chown(/home/user/mail/.imap/INBOX, group=12(mail)) failed: +Operation not permitted (egid=1000(user), group based on /var/mail/user - see +http://wiki2.dovecot.org/Errors/ChgrpNoPerm) +---%<------------------------------------------------------------------------- + +This means that Dovecot tried to copy '/var/mail/user' file's group (mail) to +the index file directory it was creating ('/home/user/mail/.imap/INBOX'), but +the process didn't belong to the mail group, so it failed. This is important +for preserving access permissions with <shared mailboxes> +[SharedMailboxes.txt]. Group copying is done only when it actually changes the +access permissions; for example with 0600 or 0666 mode the group doesn't matter +at all, but with 0660 or 0640 it does. + +To solve this problem you can do only one of two things: + + 1. If the group doesn't actually matter, change the permissions so that the + group isn't copied (e.g.'chmod 0600 /var/mail/*', see + <MailLocation.mbox.txt>) + 2. Give the mail process access to the group (e.g. 'mail_access_groups=mail' + setting). However, this is dangerous.It allows users with shell access to + read other users' INBOXes + [http://dovecot.org/list/dovecot-news/2008-March/000060.html]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Events.txt b/doc/wiki/Events.txt new file mode 100644 index 0000000..39e0a5a --- /dev/null +++ b/doc/wiki/Events.txt @@ -0,0 +1,288 @@ +Events +====== + +List of all events that can be used in <Statistics.txt> and elsewhere. Note +that in v2.3 these are added on version basis, so not all events are available +in all v2.3 releases. + +Contents + + + 1. Events + + 1. Authentication Server (v2.3.6) + + 2. Authentication Client (v2.3.6) + + 3. Connection + + 4. HTTP + + 5. IMAP + + 6. DNS + + 7. SQL + +Authentication Server (v2.3.6) +------------------------------ + +These events are generated by authentication in auth process(es). + +*auth_request_finished* + + * user: full username + * original_username: original username used + * translated_username: username after translations + * login_user: when doing login using master_user, this is the user we are + logging in as + * master_user: master username + * error: set when error happens + * successful: yes, when succeeded + * transport: insecure, trusted, TLS + * mechanism: name of used mechanism + * credentials_scheme: type of credential (SHA256-CRYPT, PLAIN, ...) + * policy_penalty: time of penalty added by policy server + * policy_result: ok, delayed, refused + +*auth_passdb_request_started* + + * passdb_name: name of passdb + * passdb: driver + +*auth_passdb_request_finished* + + * passdb_name: name of passdb + * passdb: driver + * user: full username + * master_user: master user name + * username: username without domain + * domain: domain if present + * result: authentication result + +*auth_userdb_request_started* + + * userdb_name: name of passdb + * userdb: driver + +*auth_userdb_request_finished* + + * userdb_name: name of passdb + * userdb: driver + * user: full username + * master_user: master user name + * username: username without domain + * domain: domain if present + * result: authentication result + +*auth_policy_request_finished* + + * mode: allow, report + * policy_response: number + +Authentication Client (v2.3.6) +------------------------------ + +These events are generated by authentication clients (lib-auth). + +*auth_client_request_started* + + * id: event id + +*auth_client_request_continue* + + * id: event id + +*auth_client_request_finished* + + * id: event id + * error: reason + +*auth_client_request_challenged* + + * id: event id + +*auth_client_userdb_lookup_started* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + +*auth_client_userdb_lookup_finished* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + * error: error if occured + +*auth_client_passdb_lookup_started* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + +*auth_client_passdb_lookup_finished* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + * error: error if occured + +*auth_client_userdb_list_started* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + +*auth_client_userdb_list_finished* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + * error: error if occured + +*auth_client_cache_flush_started* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + +*auth_client_cache_flush_finished* + + * service: name of service (smtp, imap, lmtp...) + * local_ip: local ip + * local_port: local port + * remote_ip: remote ip + * remote_port: remote port + * user: full username + * error: error if occured + +Connection +---------- + +These events apply only for connections using the "connection API". +Unfortunately not all connections currently use this, so these events work for +some types of connections, but not for others. + +*client_connection_connected* + + * client_ip: source IP + * client_port: source port + * ip: target IP + * port: target port + +*client_connection_disconnected* + + * fields from *client_connection_connected* + * bytes_in: amount of data read + * bytes_out: amount of data written + * reason: disconnection reason + +*server_connection_connected* + + * client_ip: source IP + * client_port: source port + * ip: target IP + * port: target port + * bytes_in: amount of data read + * bytes_out: amount of data written + +*server_connection_disconnected* + + * fields from *server_connection_connected* + * bytes_in: amount of data read + * bytes_out: amount of data written + * reason: disconnection reason + +HTTP +---- + +*http_request_finished* + + * status_code: HTTP result status code + * attempts: Number of individual HTTP request attempts that were done (i.e. + number of retries after failures + 1) + * redirects: Number of redirects that were done while processing this request. + + * bytes_in, bytes_out: Number of bytes received/sent for this request. + +*http_request_redirected* + + * Intermediate event sent while HTTP request is being redirected. The + *http_request_finished* is still being sent as well. + * Same fields as *http_request_finished* + +*http_request_retried* + + * Intermediate event sent while HTTP request is being retried. The + *http_request_finished* is still being sent as well. + * Same fields as *http_request_finished* + +IMAP +---- + +*imap_command_finished* + +NOTE: These are currently not sent for pre-login IMAP commands. + + * tag: Command tag + * name: Command name + * args: Command's full parameters + * human_args: Command's parameters as more human-readable output + * tagged_reply_state: OK, NO, BAD + * tagged_reply: Full tagged reply, e.g. "OK SELECT finished." + * last_run_time: Timestamp when the command was running last time (it's + followed by "mailbox sync" that can take some time) + * running_usecs: How many usecs this command itself has spent running + * lock_wait_usecs: How many usecs this command itself has spent waiting for + locks. + * bytes_in, bytes_out: How many bytes of client input/output command has used. + +DNS +--- + +*dns_worker_request_finished* and *dns_request_finished* + + * error: Human readable error + * error_code: Error code usable with net_gethosterror() + +*dns_worker_request_started* and *dns_request_started* + +SQL +--- + +*sql_query_finished* + + * error: Human readable error + * error_code: Error code (if available) + * query_first_word: First word of the query, such as SELECT + +*sql_transaction_finished* + + * error: Human readable error + * error_code: Error code (if available) + +*sql_connection_finished* + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/FindMailLocation.txt b/doc/wiki/FindMailLocation.txt new file mode 100644 index 0000000..ed8d62c --- /dev/null +++ b/doc/wiki/FindMailLocation.txt @@ -0,0 +1,65 @@ +Finding Your Mail +================= + +Before configuring Dovecot, you'll need to know where your mails are located. +You should already have an SMTP server installed and configured to deliver +mails somewhere, so the easiest way to make Dovecot work is to just use the +same location. Otherwise you could create '~/Maildir' directory and configure +your SMTP server to use the Maildir format. + +First send a test mail to yourself (as your own non-root user): + +---%<------------------------------------------------------------------------- +echo "Hello me" | mail -s "Dovecot test" $USER +---%<------------------------------------------------------------------------- + +Now, find where the mail went. Here's a simple script which checks the most +common locations: + +---%<------------------------------------------------------------------------- +for mbox in /var/mail/$USER /var/spool/mail/$USER ~/mbox ~/mail/* ~/*; do + grep -q "Dovecot test" "$mbox" && echo "mbox: $mbox" +done +grep -q "Dovecot test" ~/Maildir/new/* 2>/dev/null && echo "Maildir: ~/Maildir" +---%<------------------------------------------------------------------------- + +mbox +---- + +In most installations your mail went to '/var/mail/username' file. This file is +called *INBOX* in IMAP world. Since IMAP supports multiple mailboxes, you'll +also have to have a directory for them as well. Usually '~/mail' is a good +choice for this. For installation such as this, the mail location is specified +with (typically in 'conf.d/10-mail.conf'): + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +Where '%u' is replaced with the username that logs in. Similarly if your INBOX +is in '~/mbox', use: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=~/mbox +---%<------------------------------------------------------------------------- + +Maildir +------- + +Maildir exists almost always in '~/Maildir' directory. The mail location is +specified with (typically in 'conf.d/10-mail.conf'): + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +---%<------------------------------------------------------------------------- + +Problems? +--------- + +If you can't find the mail, you should check your SMTP server logs and +configuration to see where it went or what went wrong. + +If you can find the mail, but it's in more exotic location, see if +<MailLocation.txt> can help you to configure it. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/FinishBasicConfiguration.txt b/doc/wiki/FinishBasicConfiguration.txt new file mode 100644 index 0000000..42a63ad --- /dev/null +++ b/doc/wiki/FinishBasicConfiguration.txt @@ -0,0 +1,12 @@ +Finishing Basic Configuration +============================= + +Unless you're going to have only virtual users and you don't care about their +passwords,*switch back to disable_plaintext_only = yes* and <set up SSL> +[SSL.txt]. + +Plaintext authentication is still allowed from localhost, so you can have your +webmail application to connect to Dovecot without using SSL or even having to +configure it. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HAProxy.txt b/doc/wiki/HAProxy.txt new file mode 100644 index 0000000..e7194c7 --- /dev/null +++ b/doc/wiki/HAProxy.txt @@ -0,0 +1,90 @@ +HAProxy Support +=============== + +For high availability, client connections can be spread across multiple backend +servers using HAProxy [http://www.haproxy.org/]. This solution is often +employed for large Dovecot installations as a replacement for a hardware load +balancer. A common problem with such a reverse proxy +[http://en.wikipedia.org/wiki/Reverse_proxy] is that Dovecot does not talk to +the client directly. This means that the connection information (IP:port) that +Dovecot uses for logging and authentication purposes points to the proxy, +rather than the real client. To solve this, the proxy needs to convey the +connection information to the backend somehow, so that that information is +available there. The developers of HAProxy defined a custom Proxy Protocol +[http://blog.haproxy.com/haproxy/proxy-protocol/] for this purpose. By this +protocol, the proxy sends the connection information immediately after +connection setup in a special initial header. Note that this isn't normally +needed after the initial Dovecot proxies, because Dovecot internally uses +IMAP/POP3/LMTP extensions to forward the original IP address. Dovecot supports +both versions of the Proxy Protocol since Dovecot version 2.2.19. + +Dovecot Configuration +--------------------- + +The following global settings relate to HAProxy: + +haproxy_trusted_networks = : + A space-separated list of trusted network ranges for HAProxy connections. + Connections from networks outside these ranges to ports that are configured + for HAProxy are aborted immediately. + +haproxy_timeout = 3 : + The time in seconds after which a HAPRoxy connection is aborted when no + complete header is received. + +The HAPRoxy protocol can be enabled for specific <TCP listeners> +[Services.txt]. This way, a service such as IMAP or POP3 can accept both normal +and HAProxy connections. A TCP listener is configured for HAProxy by setting +'haproxy=yes' for that listener. If 'haproxy=yes' is set for a listener, its +use is mandatory on that port; i.e., if the client is not a proper proxy (its +omits the PROXY header), the connection will be aborted. + +For example, to enable normal IMAP connections on port 143, SSL connections on +port 993 and HAProxy connections on port 10143, the 'imap-login' service is +configured as follows: + +---%<------------------------------------------------------------------------- +service imap-login { + inet_listener imap { + port = 143 + } + inet_listener imaps { + port = 993 + ssl = yes + } + inet_listener imap_haproxy { + port = 10143 + haproxy = yes + } +} +---%<------------------------------------------------------------------------- + +HAProxy Configuration +--------------------- + +The documentation of this feature on the HAProxy side is a bit fragmented +between the HAProxy Configuration Manual +[http://www.haproxy.org/download/1.6/doc/configuration.txt] and the Proxy +Protocol documentation +[http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt]. In summary, it is +enabled by including the 'send-proxy' setting in the 'server' lines. It is +therefore only enabled on a per-server basis. + +For example, the 'frontend' and 'backend' configuration of HAProxy could look +as follows: + +---%<------------------------------------------------------------------------- +frontend ft_imap + bind :143 + mode tcp + default_backend bk_imap + +backend bk_imap + mode tcp + balance leastconn + stick store-request src + stick-table type ip size 200k expire 30m + server s1 backend.example.com:10143 send-proxy-v2 +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.AntispamWithSieve.txt b/doc/wiki/HowTo.AntispamWithSieve.txt new file mode 100644 index 0000000..e8aea06 --- /dev/null +++ b/doc/wiki/HowTo.AntispamWithSieve.txt @@ -0,0 +1,270 @@ +Replacing antispam plugin with IMAPSieve +======================================== + +Contents + + + 1. Replacing antispam plugin with IMAPSieve + + 1. Caveats and possible pitfalls + + 2. Dovecot configuration + + 3. Sieve scripts + + 4. Shell scripts + + 1. For spamassassin + + 2. For dspam + + 3. For rspamd + + 5. Debugging + + 6. RoundCube + +You will need at least pigeonhole v0.4.14 for this. If you have already +configured sieve, please adjust the following to match your setup. + +Caveats and possible pitfalls +----------------------------- + + * INBOX name is case-sensitive + * <IMAP Sieve> [Pigeonhole.Sieve.Plugins.IMAPSieve.txt] will *only* apply to + IMAP. It *will not* apply to LDA or LMTP. Use <Sieve> [Pigeonhole.Sieve.txt] + normally for LDA/LMTP. + * With this configuration, moving mails will slow down due to learn being done + per email. If you want to avoid this, you need to think of something else. + Probably piping things into a FIFO or perhaps using a socket based worker + might work better. + * Please read <Pigeonhole.Sieve.txt> and <Pigeonhole.Sieve.Configuration.txt> + to understand sieve configuration better. + * Please read <Pigeonhole.Sieve.Plugins.txt> for more information about sieve + extensions. + * If you run Spamassassin trough Amavis and you use a virtual users setup, you + should instead configure Spamassassin to use MySQL/PostgreSQL as a backend, + unless you want a headache with file permissions and lock files. You can + find instructions here + [http://www.iredmail.org/docs/store.spamassassin.bayes.in.sql.html]. In this + case, the '-u' parameter passed to 'sa-learn' (and the relevant sieve + variables) is obsolete and can be safely removed. + * Reloading dovecot doesn't activate changes in this configuration, you'll + need to perform a full restart. + +Changes: + + * 2017/11/20 - Possibility of using spamc with <SpamAssassin.txt> to mitigate + multi-message delays + * 2017/05/05 - Recommendation about Virtual Users and using an SQL Backend. + Added brief info about <RoundCube.txt>. + * 2017/04/01 - Pass imap user to scripts. + * 2017/03/19 - Added rspamd scripts and mention about sieve plugins. + * 2017/02/13 - Improved documentation and added instructions for Spam->Trash. + (Thanks for everyone who commented on mailing list) + * 2017/02/10 - Removed imap_stats (it's not needed). + * 2018/04/11 - Added notes about sa-learn/spamc and warning about sieve script + location. + +Dovecot configuration +--------------------- + +---%<------------------------------------------------------------------------- +protocol imap { + mail_plugins = $mail_plugins imap_sieve +} + +plugin { + sieve_plugins = sieve_imapsieve sieve_extprograms + + # From elsewhere to Spam folder + imapsieve_mailbox1_name = Spam + imapsieve_mailbox1_causes = COPY + imapsieve_mailbox1_before = file:/usr/lib/dovecot/sieve/report-spam.sieve + + # From Spam folder to elsewhere + imapsieve_mailbox2_name = * + imapsieve_mailbox2_from = Spam + imapsieve_mailbox2_causes = COPY + imapsieve_mailbox2_before = file:/usr/lib/dovecot/sieve/report-ham.sieve + + sieve_pipe_bin_dir = /usr/lib/dovecot/sieve + + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment +} +---%<------------------------------------------------------------------------- + +Sieve scripts +------------- + +*You cannot run scripts anywhere you want* + +Sieve allows you to only run scripts under sieve_pipe_bin_dir. You can't use +/usr/local/bin/my-sieve-filter.sh, you have to put the script under +sieve_pipe_bin_dir and use my-sieve-filter.sh instead. + +Create directory /usr/lib/dovecot/sieve and put following files to that: + +report-spam.sieve + +---%<------------------------------------------------------------------------- +require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; + +if environment :matches "imap.user" "*" { + set "username" "${1}"; +} + +pipe :copy "sa-learn-spam.sh" [ "${username}" ]; +---%<------------------------------------------------------------------------- + +report-ham.sieve + +---%<------------------------------------------------------------------------- +require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; + +if environment :matches "imap.mailbox" "*" { + set "mailbox" "${1}"; +} + +if string "${mailbox}" "Trash" { + stop; +} + +if environment :matches "imap.user" "*" { + set "username" "${1}"; +} + +pipe :copy "sa-learn-ham.sh" [ "${username}" ]; +---%<------------------------------------------------------------------------- + +Shell scripts +------------- + +For spamassassin +---------------- + +*Untested* + +spamc interaction scripts are not tested yet. + +sa-learn-spam.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +# you can also use tcp/ip here, consult spamc(1) 2 +exec /usr/bin/spamc -u ${1} -L spam -C report 3 +---CodeArea------------------------------------------------------------------- + +sa-learn-ham.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +# you can also use tcp/ip here, consult spamc(1) 2 +exec /usr/bin/spamc -u ${1} -L ham -C report 3 +---CodeArea------------------------------------------------------------------- + +You can also use sa-learn. + +Note that using sa-learn often incurs significant start-up time for every +message. This can cause "lockout" of the user until all the processes +sequentially complete, potentially tens of seconds or minutes. If spamd is +being used and the administrator is willing to accept the potential security +issues of allowing unauthenticated learning of spam/ham, spamd can be envoked +with the --allow-tell option and spamc with the --learntype= option. Please +consult the man pages of spamd and spamc for further details. + +sa-learn-spam.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/sa-learn -u ${1} --spam 2 +---CodeArea------------------------------------------------------------------- + +sa-learn-ham.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/sa-learn -u ${1} --ham 2 +---CodeArea------------------------------------------------------------------- + +For dspam +--------- + +sa-learn-spam.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/dspam --client --user ${1} --class=spam --source=error 2 +---CodeArea------------------------------------------------------------------- + +sa-learn-ham.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/dspam --client --user ${1} --class=innocent --source=error 2 +---CodeArea------------------------------------------------------------------- + +*CRLF handling* + +dspam may fail to read the mail if it contains CRLF line endings, add the +*Broken lineStripping* option in dspam.conf if needed. + +For rspamd +---------- + +By default, rspamd does global learning. If you want per-user classification, +or something more complex, see +https://rspamd.com/doc/configuration/statistic.html + +Alternative scripts can be found from +https://github.com/darix/dovecot-sieve-antispam-rspamd/ + +sa-learn-spam.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/rspamc -h /run/rspamd/worker-controller.socket -P <secret> +learn_spam 2 +---CodeArea------------------------------------------------------------------- + +sa-learn-ham.sh + +---CodeArea------------------------------------------------------------------- +#!/bin/sh 1 +exec /usr/bin/rspamc -h /run/rspamd/worker-controller.socket -P <secret> +learn_ham 2 +---CodeArea------------------------------------------------------------------- + +Before running following commands, make sure dovecot.conf has all the sieve +configuration you want. Then run following commands: + +---%<------------------------------------------------------------------------- +sievec /usr/lib/dovecot/sieve/report-spam.sieve +sievec /usr/lib/dovecot/sieve/report-ham.sieve +chmod +x /usr/lib/dovecot/sieve/sa-learn-ham.sh +/usr/lib/dovecot/sieve/sa-learn-spam.sh +---%<------------------------------------------------------------------------- + +Now your learn scripts should be invoked when you move mails between folders. + +Debugging +--------- + +To debug, you need to import "vnd.dovecot.debug" extension. Then you can put, +when required + +---%<------------------------------------------------------------------------- +debug_log "something" +---%<------------------------------------------------------------------------- + +variables are supported in this. + +RoundCube +--------- + +Recent versions of RoundCube [https://roundcube.net/] include a markasjunk2 +plugin [https://plugins.roundcube.net/packages/johndoh/markasjunk2] for +allowing users to mark Spam/Ham in a convenient way. Please make sure the +Junk/Spam folder matches your configuration. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.EximAndDovecotSASL.txt b/doc/wiki/HowTo.EximAndDovecotSASL.txt new file mode 100644 index 0000000..99d178c --- /dev/null +++ b/doc/wiki/HowTo.EximAndDovecotSASL.txt @@ -0,0 +1,54 @@ +Exim and Dovecot SASL +===================== + +Exim v4.64+ users can use Dovecot SASL instead of Cyrus SASL for authenticating +SMTP clients. + +conf.d/10-master.conf +--------------------- + +---%<------------------------------------------------------------------------- +service auth { +... +#SASL + unix_listener auth-client { + mode = 0660 + user = mail + } +... +} +---%<------------------------------------------------------------------------- + +conf.d/10-auth.conf +------------------- + +---%<------------------------------------------------------------------------- +auth_mechanisms = plain login +---%<------------------------------------------------------------------------- + +exim.conf +--------- + +Create authenticators for Dovecot: + +---%<------------------------------------------------------------------------- +dovecot_login: + driver = dovecot + public_name = LOGIN + server_socket = /var/run/dovecot/auth-client +# setting server_set_id might break several headers in mails sent by +authenticated smtp. So be careful. + server_set_id = $auth1 + +dovecot_plain: + driver = dovecot + public_name = PLAIN + server_socket = /var/run/dovecot/auth-client + server_set_id = $auth1 +---%<------------------------------------------------------------------------- + +If you are having problems with this not working ensure that you are using +version 4.72 or greater of exim. Previous versions of exim have trouble with +the version of the protocol used in Dovecot 2 + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.ImapcProxy.txt b/doc/wiki/HowTo.ImapcProxy.txt new file mode 100644 index 0000000..805c989 --- /dev/null +++ b/doc/wiki/HowTo.ImapcProxy.txt @@ -0,0 +1,174 @@ +Dovecot imapc proxy +=================== + +Using Dovecot as a secure IMAP Proxy in front of Exchange, using Exchange +Authentication and IMAPC. This requires Dovecot 2.1.rc1 or newer. + +Many thanks to Timo on the Dovecot mailing list for all his help! + +This " <HowTo.txt>" is based on already having Dovecot already compiled and +installed. + + 1. Create an unprivileged, non-system account user and group for the proxy, + with a home directory. This needs to have a writable home directory, but no + other privileges. + + ---%<--------------------------------------------------------------------- + [root@localhost]# useradd imapproxy + ---%<--------------------------------------------------------------------- + + 2. Verify that the user can not login: + + ---%<--------------------------------------------------------------------- + [root@localhost]# grep imapproxy /etc/shadow + ---%<--------------------------------------------------------------------- + + You should see something like: + + ---%<--------------------------------------------------------------------- + imapproxy:!!:nnnn:0:nn:n::: + ---%<--------------------------------------------------------------------- + + The important part is the "!!". This indicates that the account is locked. + If you don't see this, lockout the account (check man passwd) + 3. Create '/etc/dovecot/dovecot.conf' or + ('/usr/local/etc/dovecot/dovecot.conf') as appropriate: + + ---%<--------------------------------------------------------------------- + ## Dovecot configuration file + + mail_uid = imapproxy + mail_gid = imapproxy + + protocols = imap + + listen = *, :: + + mail_location = imapc:~/imapc + # Change the line below to reflect the IP address of your Exchange Server. + imapc_host = 10.1.2.3 + imapc_port = 143 + + passdb { + driver = imap + # Change the line below to reflect the IP address of your Exchange + Server. + args = host=10.1.2.3 + default_fields = userdb_imapc_user=%u userdb_imapc_password=%w + } + userdb { + driver = prefetch + } + + # /home/imapproxy is the home directory for the imapproxy user, and + # %u is a subdir that will be automatically created for each IMAP user when + they connect + + mail_home = /home/imapproxy/%u + + auth_mechanisms = plain login + + # This is the auth service used by Postfix to do dovecot auth. + service auth { + unix_listener auth-userdb { + } + inet_listener { + port = 12345 + } + } + + ## + ## SSL settings + ## + + # These will need to ba adjusted to point to *your* certificates, not mine + 8-) + # The ssl_ca line refers to the intermediate certificate bundle which may + or may not be required by your SSL provider + + ssl_cert = </etc/pki/tls/certs/machine.example.org.crt + ssl_key = </etc/pki/tls/private/machine.example.org.key + ssl_ca = </etc/pki/tls/certs/gd_bundle.crt + ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL + ---%<--------------------------------------------------------------------- + +Start dovecot and test it with openssl as: + +---%<------------------------------------------------------------------------- +openssl s_client -connect machine.example.org:143 -starttls imap +---%<------------------------------------------------------------------------- + +You should see a whole bunch of SSL information, and the last line should say: + +---%<------------------------------------------------------------------------- +. OK Pre-login capabilities listed, post-login capabilities have more. +---%<------------------------------------------------------------------------- + +Next, type: + +---%<------------------------------------------------------------------------- +01 LOGIN username badpassword +---%<------------------------------------------------------------------------- + +You should then see: + +---%<------------------------------------------------------------------------- +01 NO [AUTHENTICATIONFAILED] Authentication failed +---%<------------------------------------------------------------------------- + +And should see a list similar to this: + +---%<------------------------------------------------------------------------- +* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT +SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN +NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT +SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS FUZZY +02 OK Logged in +---%<------------------------------------------------------------------------- + +If you get this far, the proxy is working and is authenticating against your +exchange server. + +Postfix Configuration +--------------------- + +My configuration is for a closed server that will never allow inbound SMTP from +unauthenticated clients, and authenticates inbound SMTP TLS connections against +the above Dovecot auth service, which in turn authenticates against Exchange, +which authenticates against Active Directory. + +This means that disabling an account in Active Directory, also disables inbound +and outbound mail access. + +If this is what you want, add the following to you /etc/postfix/main.cf file.: + +---%<------------------------------------------------------------------------- +smtpd_sasl_type = dovecot +smtpd_sasl_path = inet:127.0.0.1:12345 +smtpd_sasl_auth_enable = yes + +smtpd_client_restrictions = permit_sasl_authenticated, reject +## Don't relay for anybody from or to anywhere, unless they authenticated + +smtpd_recipient_restrictions = permit_sasl_authenticated reject + +broken_sasl_auth_clients = yes +# Talk to outlook <= 2003 and O Express <=6 + +smtpd_tls_security_level = encrypt +smtpd_tls_received_header = yes + +smtpd_tls_cert_file = /etc/pki/tls/certs/machine.example.org.crt +smtpd_tls_key_file = /etc/pki/tls/private/machine.example.org.key + +smtpd_tls_CAfile = /etc/pki/tls/certs/gd_bundle.crt +# If your Certification Authority requires intermediate certificates, the +bundle goes here. + +tls_random_source = dev:/dev/urandom + +smtpd_tls_auth_only = yes +# only allow auth if it's encrypted +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.PopBSMTPAndDovecot.txt b/doc/wiki/HowTo.PopBSMTPAndDovecot.txt new file mode 100644 index 0000000..edacc19 --- /dev/null +++ b/doc/wiki/HowTo.PopBSMTPAndDovecot.txt @@ -0,0 +1,363 @@ +Contents + + + 1. POP3 (IMAP) before SMTP + + 1. Are you sure you want this? + + 1. Problems with POP-before-SMTP + + 2. Advantages of POP-before-SMTP over SMTP AUTH + + 2. Pop-before-smtp.pl + + 3. DRAC + + 4. SQL + + 1. Example for postgresql, postfix + + 2. Example for MySQL, postfix + + 5. relay-ctrl + +POP3 (IMAP) before SMTP +======================= + +/sometimes also called SMTP-after-POP3 or SMTP-after-IMAP/ + +Are you sure you want this? +--------------------------- + +POP-before-SMTP is generally considered a kludge, originally invented to make +up for the lack of authentication in the original SMTP +[http://en.wikipedia.org/wiki/Smtp] specification for clients on dynamic IP +addresses.ESMTP [http://en.wikipedia.org/wiki/Extended_SMTP] resolved that +shortcoming long ago, and all modern mail clients and servers support it by +now. You should consider implementing ESMTP AUTH +[http://en.wikipedia.org/wiki/SMTP-AUTH] in your mail transport/submission +agent, and using it in your clients, rather than using POP-before-SMTP. See +also <HowTo.PostfixAndDovecotSASL.txt> or <HowTo.EximAndDovecotSASL.txt>. + +Problems with POP-before-SMTP +----------------------------- + + * *Shared IP addresses* are in widespread use. You are opening your server not + only to your user, but to anyone else who might be sharing the same IP + address, other users, other computers in the same NAT. If you lose the + connection, the next one who is assigned your IP also inherits your relay + permit. This might include virus-infected spambot machines. Or consider a + public wireless hotspot or an Internet cafe: both types of establishments + are known to be frequented by spammers. + * *Not properly implemented* in all mail clients: it only works right if the + client checks for new mail immediately before attempting to send. And it can + be very unsafe if longer timeouts are used, such that the user has time to + write an email. + * Probably others. <I> [RobMcGee.txt] ( <Rob McGee> [RobMcGee.txt]) just + thought it was wrong to have a HOWTO page here without a warning about why + /not/ to. Know what you are doing. If you are setting up a new mail service + from scratch, by all means, do it right! + +Advantages of POP-before-SMTP over SMTP AUTH +-------------------------------------------- + + * Likely to be relatively easier to implement in your mail submission agent. + What's easier is a matter of opinion, and it varies, of course, but probably + all MTA/MSA servers support some form of access lists without patching or + recompiling. + * Simple non-technical instructions for users: /"Remember to check for new + mail before you try to send mail."/ + +Pop-before-smtp.pl +================== + +If you want to use pop-before-smtp.pl (from http://popbsmtp.sourceforge.net/) +together with Dovecot, you can use this regular expression to match successful +POP3 and IMAP logins: + +---%<------------------------------------------------------------------------- +$pat = '^(... .. ..:..:..) \S+ (?:pop3|imap)-login: Login: .+ +\[(\d+\.\d+\.\d+\.\d+)\]'; +---%<------------------------------------------------------------------------- + +v1.0RC2 seems to need this format to work properly: + +---%<------------------------------------------------------------------------- +$pat = '^dovecot: (... .. ..:..:..) \S+ (?:pop3|imap)-login: Login: \S+ \S+ \S+ +lip=(\d+\.\d+\.\d+\.\d+)'; +---%<------------------------------------------------------------------------- + +Note: This only works with IPv4, anyone who wants to fix it for IPv6, please do +so:) + +worked for me on Fedora: <drak at navel.gr> + +---%<------------------------------------------------------------------------- +$pat = '(?:pop3|imap)-login: (... .. ..:..:..) Info: Login: \S+ +\[(\d+\.\d+\.\d+\.\d+)\]'; +---%<------------------------------------------------------------------------- + +With v1.0 Alpha 4, the following pattern works: + +---%<------------------------------------------------------------------------- +$pat = '^(... .. ..:..:..) \S+ (?:dovecot: )?(?:imap|pop3)-login: Login: \S+ +\S+ rip=(\d+\.\d+\.\d+\.\d+)' +---%<------------------------------------------------------------------------- + +This works with RHEL 4.3 (at least until IPv6 really catches): + +---%<------------------------------------------------------------------------- +$pat = '(?:pop3|imap)-login: (... .. ..:..:..) Info: Login: \S+ +\[::ffff:(\d+\.\d+\.\d+\.\d+)\]'; +---%<------------------------------------------------------------------------- + +DRAC +==== + +The DRAC historical plugin for Dovecot 1.x, located here +[http://mail.cc.umanitoba.ca/drac/], doesn't work with Dovecot 2.x, since it +relies on the "IP" environment variable, not set anymore by Dovecot 2.x + +a more recent version of this plugin is available here: DRAC Plugin for Dovecot +2.x [http://sourceforge.jp/projects/dovecot2-drac/]. The README file explains +how to compile it. Change the path to your Dovecot 2.x source code into the +Makefile to compile it. + +DRAC runs as a separate daemon, maintaining a BerkeleyDB database of IPs that +have successfully authenticated via POP3 or IMAP, expiring them after 30 +minutes. Installing it therefore requires that both your POP3/IMAP server and +your SMTP daemon (Postfix/Sendmail/qmail) be set up to support it. +DRAC-PLUGIN.c is a small C program, and accessing BerkeleyDB databases is +efficient so it works pretty well. + +By following the instructions you will install a file drac_plugin.so in your +dovecot 'lib/' directories for IMAP and/or POP3 loadable modules. + +To turn on the new DRAC plugin in dovecot, you must set up these lines in your +dovecot.conf. There is a separate section for ''protocol imap'' and another +under ''protocol pop3''; make sure you enable both. + +---%<------------------------------------------------------------------------- + # Support for dynamically loadable modules + mail_plugin_dir = /usr/lib/dovecot/imap # not mandatory + mail_plugins = drac # provide a list of all +plugins you want to load here +---%<------------------------------------------------------------------------- + +Permissions note: the directory containing the drac_plugin.so file has to be +readable by ordinary users. Check your Dovecot error log for help. + +To get DRAC working on your machine, download the main DRAC +[http://mail.cc.umanitoba.ca/drac/] daemon, edit the makefile as directed in +the instructions, and make and install it. You will also want to ensure that +you register the rpcs by executing rpcgen. See the Makefile for more details. + +SQL +=== + +Advantage: you do not have a multi-megabyte Perl daemon reading your logs + +Disadvantage: for each login you need the time and space to execute this script + + 1. tell your MTA to look up IPs authorized to relay in an SQL table + 2. delete old IPs from the table regularly (cron job for example, or a + modification to the script below) + 3. tell dovecot to update the SQL table upon successful login + +Dovecot 1.0 (and probably 0.99) can update a SQL table with the script below. + +/!\ *Note* that *you* must set up a script that deletes old IPs separately, and +*you* also must configure your MTA properly. The script *only* performs the +'update on successful login' step, which alone is insecure without expiring +older IPs!/Add your working examples to this section. This Wiki depends on your +help!/ + +---%<------------------------------------------------------------------------- +#!/bin/sh +# This script created 2005-08-21 by Lorens Kockum +# Released into the Public Domain +# Changes: +# 2006-06-06 Matthias Andree +# - changed $* to "$@" for more robust argument quoting +# Action: when called by dovecot 1.0 as described below, updates an SQL table +# with logged-in IP and current time, and then executes the relevant process. +# Output: normally nothing +# dovecot.conf should be modified with these lines (where +# /usr/lib/dovecot/popbsmtp.sh represents this script): +# protocol pop3 { +# mail_executable = /usr/lib/dovecot/popbsmtp.sh /usr/lib/dovecot/pop3 +# } +# protocol imap { +# mail_executable = /usr/lib/dovecot/popbsmtp.sh /usr/lib/dovecot/imap +# } +# The HOME= lines are necessary to find $HOME/.my.cnf containing login info, +# because mail_executable is executed as root, but without a home directory. +# Of course this script must not be writable by anyone else than root. +( + # drop out IPs from local networks that can relay anyway + IP=`echo $IP | grep -v '^192\.168\.'` + if [ -n "$IP" ] + then + export HOME=/root/ + echo "replace into popbsmtp VALUES('$IP',now());" | mysql mail + export HOME=/ + fi +) >> /var/log/dovecot3 2>&1 +exec "$@" +---%<------------------------------------------------------------------------- + +Example for postgresql, postfix +------------------------------- + +/usr/lib/dovecot/popbsmtp.sh + +---%<------------------------------------------------------------------------- +#!/bin/sh +( + if [ -n "$IP" ] + then + /usr/bin/psql -U popbsmtp -d popbsmtp -c "begin;update auth set +accessed=now() where host=substring('$IP' from 8);commit;insert into auth(host, +accessed) values(substring('$IP' from 8),now());" + fi + +) >> /var/log/dovecot3 2>&1 +exec "$@" +---%<------------------------------------------------------------------------- + +The substring call was necessary because $IP has '::ffff:' or something like +that in front of the IP address on my system. The update followed by an insert, +with the update in a transaction is necessary to replicate mysql's REPLACE INTO +functionality. The INSERT will produce an error if the IP already exists but it +doesn't matter as the UPDATE will have committed by then. + +/etc/postfix/main.cf + +---%<------------------------------------------------------------------------- +smtpd_recipient_restrictions = + permit_mynetworks + permit_sasl_authenticated + permit_tls_clientcerts + check_client_access pgsql:/etc/postfix/popbsmtp.cf + reject_unauth_destination + check_policy_service unix:private/policy +---%<------------------------------------------------------------------------- + +/etc/postfix/popbsmtp.cf + +---%<------------------------------------------------------------------------- +hosts = localhost +user = username +password = secret +dbname = popbsmtp +query = SELECT 'OK' as result FROM auth WHERE host = '%s' +---%<------------------------------------------------------------------------- + +/etc/cron.hourly/popbsmtp_purge + +---%<------------------------------------------------------------------------- +#!/bin/bash +/usr/bin/psql -U popbsmtp -d popbsmtp -c "DELETE FROM auth WHERE (now() - +accessed) > '30 minutes'::interval" +---%<------------------------------------------------------------------------- + +Example for MySQL, postfix +-------------------------- + +Note that you can use this even if pop/imap and smtp are not on the same host +as it is the case in my setup. + +First you have to create a table (in this example named "popbsmtp") with 2 +fields: + + * address (varchar 39, primary) + * last_seen (datetime) + +varchar size 39 is for IPv6 addresses.You should definitely consider adding +IPv6 support to your popbsmtp solution because postfix and dovecot do well with +IPv6. + +/!\ *address field* must be *primary* for "REPLACE into" to work. + +/opt/dovecot-popbsmtp.sh + +---%<------------------------------------------------------------------------- +#!/bin/sh +( + if [ -n "$IP" ] + then + echo "REPLACE INTO virtual_mail.popbsmtp (address,last_seen) +VALUES ('$IP', NOW( ))" \ + | mysql -u user -p secret -h host > /dev/null 2>&1 + fi +) +exec "$@" +---%<------------------------------------------------------------------------- + +mail_executable in dovecot.conf looks something like this: + +---%<------------------------------------------------------------------------- +mail_executable = /opt/dovecot-popbsmtp.sh /usr/libexec/dovecot/imap +---%<------------------------------------------------------------------------- + +postfix map (/etc/postfix/mysql_popbsmtp_access_maps.cf): + +---%<------------------------------------------------------------------------- +hosts = mysqlhost +user = user +password = secret +dbname = virtual_mail +query = SELECT 'OK' FROM popbsmtp WHERE last_seen >= DATE_SUB(NOW(),INTERVAL 30 +MINUTE) AND address = '%s' +---%<------------------------------------------------------------------------- + +In postfix main.cf add the following access map to your recipient restrictions +(/!\ *before* "reject_unauth_destination"): + +---%<------------------------------------------------------------------------- +check_client_access mysql:$config_directory/mysql_popbsmtp_access_maps.cf +---%<------------------------------------------------------------------------- + +The 30 minute relay access period is handled by the INTERVAL in DATE_SUB. So +it's safe anyway, but you should definitely run a cron job daily that deletes +older records. That's to keep the table clean and speed up lookups. You might +also need to run "OPTIMIZE TABLE" via the cron job to free up allocated space. + +relay-ctrl +========== + +relay-ctrl [http://untroubled.org/relay-ctrl/] consists of a few small programs +designed to fit in qmail-like command chains. The most important: + + * 'relay-ctrl-allow' runs after a successful POP/IMAP login, recording the + client IP and timestamp + * 'relay-ctrl-check' runs before the SMTP server, enabling relaying if the + client IP has authenticated recently + +'relay-ctrl-allow' expects to find the client IP in the environment as +'$TCPREMOTEIP'. Dovecot provides it as '$IP', so you'll need this tiny +'dovecot-settcpremoteip' wrapper script: + +---%<------------------------------------------------------------------------- +#!/bin/sh +# +# Wrapper for relay-ctrl-allow that sets TCPREMOTEIP. +TCPREMOTEIP="${IP}"; export TCPREMOTEIP +exec "$@" +---%<------------------------------------------------------------------------- + +Edit 'dovecot.conf' and set 'mail_executable' appropriately, e.g., for IMAP +(this is one long line): + +---%<------------------------------------------------------------------------- +mail_executable = /usr/local/bin/envdir /etc/relay-ctrl +/usr/local/bin/relay-ctrl-chdir /usr/local/bin/dovecot-settcpremoteip +/usr/local/bin/relay-ctrl-allow /usr/local/libexec/dovecot/imap +Dove +---%<------------------------------------------------------------------------- + +Restart Dovecot. Verify that your IMAP client still works. Verify that +relay-ctrl has recorded your client IP. Hook 'relay-ctrl-check' into your SMTP +service, as documented in the relay-ctrl README, and you're done. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.PopRelay.txt b/doc/wiki/HowTo.PopRelay.txt new file mode 100644 index 0000000..e8e9532 --- /dev/null +++ b/doc/wiki/HowTo.PopRelay.txt @@ -0,0 +1,139 @@ +Poprelay is a service that allows your Dovecot pop users to also send e-mails +through your sendmail SMTP server on the same machine.When they check their +e-mails, their IP address is logged in a database. Once the same user wants to +send an e-mail using your SMTP port, then sendmail checks this database and if +the IP is present, then the relay is allowed. This makes it completely +transparent to the user and the server will still be very secure and blocking +all other IP addresses for relaying.The IP address is kept in the database for +about 15 minutes only, so there is no chance for anyone else to use the same IP +address and server. + +Dated 2005-08-19 you can now use this poprelay service with Dovecot. + +The main page of poprelayd is the following: +http://sourceforge.net/projects/poprelay + +Download the latest source there. You have an install script that does almost +everything for you. You still need some manual intervention to add some +required lines in your sendmail.mc file. This is described in the install +documentation.Once this is done, you will have to replace your +/etc/mail/poprelay.conf file by the lines below.Once this is done restart the +poprelay service and it should be working. + +Please report any problem on the poprelay forum. You will need to leave the +v6-mapped ip4 address in the /etc/mail/maillog for the moment (e.g. you should +see '[::ffff:IP_ADDRESS]' in the pop user's login logs). + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +You might have to adapt the first configuration lines if you are using +something else than CentOS 4. + +OpenBSD (using ip4 addresses) produces syslog lines such as: + +Jun 7 09:54:53 mail dovecot: pop3-login: Login: user=<user>, method=PLAIN, +rip=[IP Address], lip=[IP Address] + +To fix the extra word in the split use this line: + +($crap, $info, $string)=split(/\: /,$line); + +To accommodate ip4 address in the form rip=w.x.y.z, use this line: + +($ip) = $line=~/\, rip\=(\d+\.\d+\.\d+\.\d+)/; + +---%<------------------------------------------------------------------------- +#This file is interpreted by perl +#you can do a quick syntax check by doing "perl poprelay.conf" + +#=======================Standard configuration options===================== + +# where POP3/IMAP daemon connections get logged +$logfile = "/var/log/maillog"; + +# Where we put our PID. (dieing output +# will be dumped here too) +$pidfile = "/var/run/poprelayd.pid"; + +# Sendmail map to update. +$dbfile = "/etc/mail/popip.db"; + +#Change this to match the type of db file sendmail needs +#Your perl must support that type of file as well +$dbtype = "DB_HASH"; + +# Minutes an entry lasts. (3000 = ~ 2 days) +# IMAP connections can last a very long time so I like to keep this long. +# The odds that someone will hop onto one of your valid user's old IP's and +# spam from it are so small I wouldn't worry about it. I recommend making +# this long to avoid complications. +$timeout_minutes = 15; + +# Number of seconds to sleep between checks +$log_wait_interval = 5; + +#=======================Advanced configuration options===================== + +#Alternate log line parsers: + +#There can be only one log parser. +#the standard one should work for most systems. The other +#ones may be slightly out of date. I don't have any systems +#that run these servers so I can't update or test the routines. +#If you fix anything with them please let me know and I will +#roll the changes into the main version. +# +#$log_parser = \&log_parse_standard; +#$log_parser = \&log_parse_berkeley; +#$log_parser = \&log_parse_qpopper; +#$log_parser = \&log_parse_qpopper_old; +#$log_parser = \&log_parse_cucipop; +$log_parser = \&log_parse_custom; + +#Custom log line parsing scripts: + +#If you want to create your own log parsing routine, do it here in +#the config file so you can update the poprelayd without losing your +#custom parsing routine. The routine below does the same thing as +#log_parse_standard. It should be a good starting point for any +#customization. It parses lines in many stages so it can be easily +#customized. It will even do dns lookups of hostnames using +#gethostbyname if the program logs the hostname instead of the ip. +# +#If you get something working post it to the forums at +#http://sourceforge.net/projects/poprelay so the next guy doesn't have +#to go through the same headache. I'll try and roll new routines into +#the main program so that poprelayd can work out of the box for all +#the log formats. + +# Dovecot maillog parser: +sub log_parse_custom ($) { + my $s = $_[0]; + my @paddrs; # Packed IP addresses. + my @addrs; # ASCII addresses. + my ($junk,$info,$string,$service,$ip,$host); + ($info, $string)=split(/\: /,$line); + ($service) = $info=~/(\S+)$/; + $service=~s/\[\d+\]//; + return () unless $service=~/^(pop2|pop3|imap)-login$/; + return () unless $string=~/^(Login|Authenticated)/; + ($ip) = $line=~/.*\:\:ffff\:(\d+\.\d+\.\d+\.\d+)\]/; + if ($ip) { + print "$service: $ip\n"; + return ($ip); + } else { + ($host) = $string=~/^(\S+)/; + print "$service: $host\n"; + ($junk, $junk, $junk, $junk, @paddrs) = gethostbyname($host); + while (@paddrs) { + push(@addrs, join('.', unpack('C4', shift(@paddrs)))); + } + return (@addrs); + } +} + +#leave this alone: +1; +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.PostfixAndDovecotSASL.txt b/doc/wiki/HowTo.PostfixAndDovecotSASL.txt new file mode 100644 index 0000000..48aaf15 --- /dev/null +++ b/doc/wiki/HowTo.PostfixAndDovecotSASL.txt @@ -0,0 +1,113 @@ +Postfix and Dovecot SASL +------------------------ + +Since version 2.3, Postfix supports SMTP AUTH through <Dovecot SASL> [Sasl.txt] +as introduced in the Dovecot 1.0 series. If using Postfix obtained from a +binary (such as a .rpm or .deb file), you can check if Postfix was compiled +with support for Dovecot SASL by running the command: + +---%<------------------------------------------------------------------------- +postconf -a +---%<------------------------------------------------------------------------- + +Once you have verified that your installation of Postfix supports Dovecot SASL, +it's very simple to configure: + +Example conf.d/10-master.conf excerpt +------------------------------------- + +---%<------------------------------------------------------------------------- +service auth { +... + unix_listener /var/spool/postfix/private/auth { + mode = 0660 + # Assuming the default Postfix user and group + user = postfix + group = postfix + } + ... +} + +# Outlook Express and Windows Mail works only with LOGIN mechanism, not the +standard PLAIN: +auth_mechanisms = plain login +---%<------------------------------------------------------------------------- + +Example Postfix main.cf excerpt +------------------------------- + +---%<------------------------------------------------------------------------- +smtpd_sasl_type = dovecot + +# Can be an absolute path, or relative to $queue_directory +# Debian/Ubuntu users: Postfix is setup by default to run chrooted, so it is +best to leave it as-is below +smtpd_sasl_path = private/auth + +# On Debian Wheezy path must be relative and queue_directory defined +#queue_directory = /var/spool/postfix + +# and the common settings to enable SASL: +smtpd_sasl_auth_enable = yes +# With Postfix version before 2.10, use smtpd_recipient_restrictions +smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, +reject_unauth_destination +---%<------------------------------------------------------------------------- + +Using SASL with Postfix submission port +--------------------------------------- + +When Dovecot is used as the authentication backend for Postfix it is good +practice to use a dedicated submission port for the MUAs (TCP 587). Not only +can you specify individual parameters in *master.cf* overriding the global ones +but you will not run into internet mail rejection while the Dovecot Auth +Mechanism is unavailable. In this example Postfix is configured to accept TLS +encrypted sessions only, along with several other sanity checks: + + * Verification of alias ownership via Login Maps + * Domainname and recipient plausibility + +'master.cf' + +---%<------------------------------------------------------------------------- +submission inet n - n - - smtpd + -o smtpd_tls_security_level=encrypt + -o smtpd_sasl_auth_enable=yes + -o smtpd_sasl_type=dovecot + -o smtpd_sasl_path=private/auth + -o smtpd_sasl_security_options=noanonymous + -o smtpd_sasl_local_domain=$myhostname + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o smtpd_sender_login_maps=hash:/etc/postfix/virtual + -o smtpd_sender_restrictions=reject_sender_login_mismatch + -o +smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject +---%<------------------------------------------------------------------------- + +Dovecot authentication via TCP +------------------------------ + +If Postfix and Dovecot are running on separate servers, you can also +authenticate via TCP. For Dovecot set up an inet_listener: + +---%<------------------------------------------------------------------------- +service auth { + inet_listener { + port = 12345 + } +} +---%<------------------------------------------------------------------------- + +And configure Postfix to use it: + +---%<------------------------------------------------------------------------- +smtpd_sasl_path = inet:dovecot.example.com:12345 +smtpd_sasl_type = dovecot +---%<------------------------------------------------------------------------- + +See also: +--------- + + * http://www.postfix.org/SASL_README.html#server_dovecot + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.Rootless.txt b/doc/wiki/HowTo.Rootless.txt new file mode 100644 index 0000000..b9f23f7 --- /dev/null +++ b/doc/wiki/HowTo.Rootless.txt @@ -0,0 +1,119 @@ +Rootless Installation +===================== + +It's possible to make Dovecot run under a single system user without requiring +root privileges at any point. This shouldn't be thought of as a security +feature, but instead simply as a way for non-admins to run Dovecot in their +favorite mail server. It's also useful if you just wish to test Dovecot without +messing up your system. + +If you think of this as a good way to achieve security, ask yourself which is +worse: + +a) + + * A very small possibility to get root privileges through Dovecot. + * A small possibility without logging in to get into system as a + non-privileged *dovecot* user, chrooted into an empty directory. + * A small possibility to get user's privileges after logging in, but no + possibility to read others' mails since they're saved with different UIDs + (plus you might also be chrooted to your own mailbox). + +b) + + * Absolutely zero possibility to get root privileges through Dovecot. + * A small possibility to get into system as a mail user, possibly even without + logging in, and being able to read everyone's mail (and finally gaining + roots by exploiting some just discovered local vulnerability, unless you + bothered to set up a special chrooted environment). + +Installation +------------ + +Install somewhere under home directory: + +---%<------------------------------------------------------------------------- +./configure --prefix=$HOME/dovecot +make +make install +---%<------------------------------------------------------------------------- + +Dovecot is then started by running '~/dovecot/sbin/dovecot'. The example +configuration file exists in '~/dovecot/share/doc/dovecot/example-config/' and +needs to be copied to '~/dovecot/etc/dovecot/'. + +Configuration +------------- + +The important settings to change for rootless installation are: + + * Set usernames and group to the user which dovecot will be run under: + + ---%<---------------------------------------------------------------------- + default_internal_user = user + default_login_user = user + default_internal_group = group + ---%<---------------------------------------------------------------------- + + * Remove default chrooting from all services: + + ---%<---------------------------------------------------------------------- + service anvil { + chroot = + } + service imap-login { + chroot = + } + service pop3-login { + chroot = + } + ---%<---------------------------------------------------------------------- + + * Change listener ports: + + ---%<---------------------------------------------------------------------- + service imap-login { + inet_listener imap { + port = 10143 + } + inet_listener imaps { + port = 10993 + } + } + service pop3-login { + inet_listener pop3 { + port = 10110 + } + inet_listener pop3s { + port = 10995 + } + } + ---%<---------------------------------------------------------------------- + + * Change logging destination: + + ---%<---------------------------------------------------------------------- + log_path = /home/user/dovecot.log + ---%<---------------------------------------------------------------------- + + * Instead of <passdb PAM> [PasswordDatabase.PAM.txt] use for example + <passwd-file> [AuthDatabase.PasswdFile.txt]: + + ---%<---------------------------------------------------------------------- + passdb { + driver = passwd-file + args = /home/user/dovecot/etc/passwd + } + userdb { + driver = passwd + } + ---%<---------------------------------------------------------------------- + + Where the 'passwd' file contains the username and password for your login + user: + + ---%<---------------------------------------------------------------------- + user:{PLAIN}pass + ---%<---------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.SimpleVirtualInstall.txt b/doc/wiki/HowTo.SimpleVirtualInstall.txt new file mode 100644 index 0000000..cdc21fe --- /dev/null +++ b/doc/wiki/HowTo.SimpleVirtualInstall.txt @@ -0,0 +1,188 @@ +Simple Virtual User Installation +================================ + + * Virtual users configured in '/etc/dovecot/passwd' file + * Assuming an unmodified Dovecot v2.x installation + * Assuming you're not using NFS. See <NFS.txt> for problems related to it. + +Contents + + + 1. Simple Virtual User Installation + + 2. System configuration + + 3. dovecot.conf + + 4. /etc/dovecot/passwd + + 1. Passwords + + 5. SMTP server configuration + + 1. Delivering mails + + 2. SMTP AUTH + + 6. Quota + +System configuration +==================== + + * Create *dovecot* and *dovenull* users and groups if they don't exist yet. + These are unprivileged users for Dovecot's internal use. They doen't need a + home directory or a shell. + * Create *vmail* user and *vmail* group. This is the user/group that's used to + access the mails. + * Create '/home/vmail' directory owned by vmail:vmail. The mails for all users + are stored under this directory. + * Create '/var/log/dovecot.log' and '/var/log/dovecot-info.log' files owned by + vmail:vmail, so that <dovecot-lda> [LDA.txt] can write to them. + +dovecot.conf +============ + +Below is a fully working 'dovecot.conf' file. You can use it directly, but it +might be better to instead use the included example-config as the base and make +the same modifications to it. + +If you want to configure SSL, see <SSL.txt>. + +---%<------------------------------------------------------------------------- +protocols = imap pop3 + +# It's nice to have separate log files for Dovecot. You could do this +# by changing syslog configuration also, but this is easier. +log_path = /var/log/dovecot.log +info_log_path = /var/log/dovecot-info.log + +# Disable SSL for now. +ssl = no +disable_plaintext_auth = no + +# We're using Maildir format +mail_location = maildir:~/Maildir + +# If you're using POP3, you'll need this: +pop3_uidl_format = %g + +# Authentication configuration: +auth_verbose = yes +auth_mechanisms = plain +passdb { + driver = passwd-file + args = /etc/dovecot/passwd +} +userdb { + driver = static + args = uid=vmail gid=vmail home=/home/vmail/%u +} +---%<------------------------------------------------------------------------- + +/etc/dovecot/passwd +=================== + +See <AuthDatabase.PasswdFile.txt> for the full file format. Here we're +interested only having usernames and passwords in it. Below's an example file: + +---%<------------------------------------------------------------------------- +test:{PLAIN}pass:::::: +bill:{PLAIN}secret:::::: +timo@example.com:{PLAIN}hello123:::::: +dave@example.com:{PLAIN}world234:::::: +joe@elsewhere.org:{PLAIN}whee:::::: +jane@elsewhere.org:{PLAIN}mypass:::::: +---%<------------------------------------------------------------------------- + +As you can see, you can use multiple domains in the file, or no domains at all. +Dovecot doesn't care about domains. The extra colons are needed for <userdb> +[UserDatabase.txt] passwd-file format, and can be omitted if you are using the +static user database in the example above. + +Users can be added by editing this file. Dovecot automatically notices the new +users immediately after they're added. It also creates their home directories +when the user logs in. + +Passwords +--------- + +The passwords in the example passwd file are listed using plaintext scheme. +It's possible to use other <password schemes> +[Authentication.PasswordSchemes.txt] as well. For example SSHA256 would be a +pretty strong scheme. You can create them using 'doveadm pw' utility, for +example: + +---%<------------------------------------------------------------------------- +doveadm pw -s ssha256 +Enter new password: foo +Retype new password: foo +{SSHA256}ZpgszeowIcHdoxe3BNqvUTtPxFd6fMsyQxEWyY0Qlobaacjk +---%<------------------------------------------------------------------------- + +Note that you won't get the same output after {SSHA256} as above, because +Dovecot uses random salts when creating the SSHA256 hash. This means that even +if multiple users have the same password, you won't know that because their +hashes are different. + +The passwd file entry would be: + +---%<------------------------------------------------------------------------- +{SSHA256}ZpgszeowIcHdoxe3BNqvUTtPxFd6fMsyQxEWyY0Qlobaacjk +---%<------------------------------------------------------------------------- + +Joe would now have "foo" as his password. + +SMTP server configuration +========================= + +Delivering mails +---------------- + +You can configure the SMTP server to deliver mails internally, or you can use +<dovecot-lda> [LDA.txt]. Using dovecot-lda gives you better performance because +it updates Dovecot's index files while saving the mails. See <LDA.txt> for how +to configure this. Alternatively you can also use <LMTP.txt>. In config you +should have: + +---%<------------------------------------------------------------------------- +protocol lda { + postmaster_address = postmaster@example.com +} +---%<------------------------------------------------------------------------- + +SMTP AUTH +--------- + +If you're using Postfix v2.3+ or Exim v4.64+ you can use Dovecot SASL instead +of Cyrus SASL. + + * <Postfix configuration> [HowTo.PostfixAndDovecotSASL.txt] + * <Exim configuration> [HowTo.EximAndDovecotSASL.txt] + +Quota +===== + +If you need to have quota, add this to 'dovecot.conf': + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins quota +protocol imap { + mail_plugins = $mail_plugins imap_quota +} +plugin { + quota = maildir +} +---%<------------------------------------------------------------------------- + +Then configure quota by adding 'userdb_quota_rule' <extra field> +[UserDatabase.ExtraFields.txt] to '/etc/dovecot/passwd', for example: + +---%<------------------------------------------------------------------------- +joe:{PLAIN}pass::::::userdb_quota_rule=*:storage=100M +jane:{PLAIN}pass::::::userdb_quota_rule=*:storage=200M +---%<------------------------------------------------------------------------- + +Joe has now 100MB quota and Jane has 200MB quota. See <Quota.txt> for more +information about quota settings. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.WriteConfiguration.txt b/doc/wiki/HowTo.WriteConfiguration.txt new file mode 100644 index 0000000..72960b8 --- /dev/null +++ b/doc/wiki/HowTo.WriteConfiguration.txt @@ -0,0 +1,56 @@ +local / remote blocks +===================== + +Use 'local' and 'remote' blocks in this order: + +---%<------------------------------------------------------------------------- +local 127.0.0.1 { +# next block is used only, if TLS SNI extension is used. It expands to the TLS +SNI hostname. +# Typically this is only used to configure per-host TLS certificates. + local_name foo { + remote 127.0.0.1 { + protocol imap { + } + } + } +} +---%<------------------------------------------------------------------------- + +The protocol block is the innermost block always, you can leave some blocks +out. + +Change a Setting +================ + +Typically you can change each setting in another block, like so: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +mail_plugins = quota +protocol imap { + # overwrites a setting + mail_location = mbox:~/mbox + # adds other values to the setting + mail_plugins = $mail_plugins imap_quota +} +---%<------------------------------------------------------------------------- + +This way, you can keep all settings for a feature, e.g. ACL in one .conf file. + +Unfortunately, you cannot access variables from the plugin section, e.g.: + +---%<------------------------------------------------------------------------- +plugin { + sieve_plugins = extdata +} + +# other file or later + +plugin { + # this won't work !!! + sieve_plugins = $sieve_plugins extdata +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/HowTo.txt b/doc/wiki/HowTo.txt new file mode 100644 index 0000000..d2be24c --- /dev/null +++ b/doc/wiki/HowTo.txt @@ -0,0 +1,93 @@ +HOWTOs / Examples / Tutorials +============================= + +<Virtual users> [VirtualUsers.txt] with <passwd-files> +[AuthDatabase.PasswdFile.txt]: + + * <A simple virtual passwd file installation> [HowTo.SimpleVirtualInstall.txt] + + * <Virtual passwd file and Exim> [HowTo.VirtualhostingWithExim.txt] + * <Virtual passwd file and Postfix> [HowTo.VirtualUserFlatFilesPostfix.txt] + +<Virtual users> [VirtualUsers.txt] with <LDAP> [AuthDatabase.LDAP.txt]: + + * <OpenLDAP> [HowTo.DovecotOpenLdap.txt] ( <Cheat sheet> + [HowTo.DoveLdapCheatSheet.txt]) + * Postfix and Active Directory or OpenLDAP [http://www.linuxmail.info] + +<System users> [SystemUsers.txt] and/or <Virtual users> [VirtualUsers.txt] with +<LDAP> [AuthDatabase.LDAP.txt]: + + * Dovecot, ManageSieve, Exim, OpenLDAP and getmail + [http://www.effinger.org/blog/2009/03/22/dovecot-exim-openldap-und-getmail-unter-ubuntu-1-openldap/] + (Instructions in German) - LDAP users (can be both <System users> + [SystemUsers.txt] and <Virtual users> [VirtualUsers.txt] depending on how + you use <LDAP> [AuthDatabase.LDAP.txt]) with the possibility to add + subaccounts for each user. For example if you have a LDAP user named peter, + you can add a separate subordinate mailbox to retrieve mail from an external + mail account like peter[at]gmail.com + +<Virtual users> [VirtualUsers.txt] with <SQL> [AuthDatabase.SQL.txt]: + + * MySQL + * <Using Dovecot with XAMS> [HowTo.DovecotXAMS.txt] + * <Dovecot, Postfix with Dovecot LDA transport and Dovecot SASL Auth, + Postfix Admin, MySQL and SquirrelMail> + [HowTo.DovecotLDAPostfixAdminMySQL.txt] + * MySQL, Exim, SpamAssassin and ClamAV + [http://struction.de/projects/HOWTO_VirtualMail_Exim-MySQL-Spamassassin-ClamAV-Dovecot/] + * Postfix and Dovecot with MySQL and TLS/SSL, Postgrey and DSPAM + [http://johnny.chadda.se/2007/04/15/mail-server-howto-postfix-and-dovecot-with-mysql-and-tlsssl-postgrey-and-dspam/] + * ISP-style Email Server with Debian-Etch and Postfix (MySQL, Dovecot, + Postfix etc.) [http://workaround.org/ispmail] + * PostgreSQL + * <PostgreSQL and Postfix> [HowTo.DovecotPostgresql.txt] + * PostgreSQL, Postfix (Dovecot LMTP and Dovecot SASL), Dovecot and vmm + (command line tool) [http://vmm.localdomain.org/] + * Installing a fully fledged, ready to use mailserver on Centos 6 with + Postfix, PostgreSQL, Amavis, ClamAV, Spamassassin and Dovecot + [http://shisaa.jp/postset/mailserver-1.html] + * SQLite + * Postfix+Dovecot with SQLite3 backend [http://rob0.nodns4.us/howto/] (also + implements system users) + +Others: + + * SMTP AUTH + * <With Postfix> [HowTo.PostfixAndDovecotSASL.txt] + * <With Exim> [HowTo.EximAndDovecotSASL.txt] + * With HALON [http://wiki.halon.se/SASL] + * <With chasquid> [HowTo.ChasquidAndDovecotSASL.txt] + * <Default Debian stable setup with Exim, modified to use Maildir> + [HowTo.DebianStable.txt] + * <IMAPC: Configuring Dovecot as an IMAP Proxy in front of Exchange (Dovecot + >= 2.1)> [HowTo.ImapcProxy.txt] + * <CRAM-MD5 authentication HOWTO> [HowTo.CRAM-MD5.txt] + * <Rootless installation> [HowTo.Rootless.txt] + * <POP-before-SMTP> [HowTo.PopBSMTPAndDovecot.txt] + * <Pop Relay Compatibility> [HowTo.PopRelay.txt] + * <Refiltering mail> [HowTo.RefilterMail.txt] + * <Triggering getmail on IMAP access> [HowTo.TriggerGetmailOnIMAPAccess.txt] + * <Outlook calendar sharing using Bynari Connector (commercial software) with + dovecot> [HowTo.BynariConnector.txt] + * <Using fail2ban with Dovecot> [HowTo.Fail2Ban.txt] + * <VMailMgr with Dovecot> [HowTo.VMailMgr.txt] + * <NTLM authentication against Active Directory> + [HowTo.ActiveDirectoryNtlm.txt] + * <Postfix and Dovecot LMTP> [HowTo.PostfixDovecotLMTP.txt] + * Apple Discussion Forum: Mail Services in Mac OS X Server v10.6 Snow Leopard + [http://discussions.apple.com/forum.jspa?forumID=1350] + * <Postfix + Dspam + Dovecot via LTMP> + [HowTo.Virtual+Postfix+Dspam+Dovecot.txt] + * Postfix + Dovecot2.0.13 + MySQL virtual_users as proxy to DBMail + [http://content.fens.org/index.php?q=admin-howto/mail/dovecot2dbmail-proxy] + * <Configuration files> [HowTo.WriteConfiguration.txt] + * <Replacing antispam plugin with sieve> [HowTo.AntispamWithSieve.txt] + * Debian + Dovecot + chasquid how-to + [https://blitiri.com.ar/git/r/chasquid/b/master/t/docs/f=howto.md.html] + * The ultimate mail server setup + [https://www.ohreally.nl/2018/11/19/mail-server/]: Dovecot (IMAP + SASL + + LDA + Pigeonhole) + Postfix + Let's Encrypt + Greylisting + SPF + DKIM + + Bogofilter + Clamav + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/IMAPServer.Hibernation.txt b/doc/wiki/IMAPServer.Hibernation.txt new file mode 100644 index 0000000..21d4a3f --- /dev/null +++ b/doc/wiki/IMAPServer.Hibernation.txt @@ -0,0 +1,51 @@ +Hibernation +=========== + +This is not supported on kqueue based systems currently, such as FreeBSD. + +Dovecot supports moving connections that have issued IDLE to a special holding +process, called imap-hibernate. This process is responsible for holding the +idle processes until they need to be thawed. + +Configuration +------------- + +'imap_hibernate_timeout' specifies the delay before moving users to +'imap-hibernate' process. This requires inter-process communication between +'imap' and 'imap-hibernate' process. + +---%<------------------------------------------------------------------------- +imap_hibernate_timeout = 5s + +service imap { + # Note that this change will allow any process running as + # $default_internal_user (dovecot) to access mails as any other user. + # This may be insecure in some installations, which is why this isn't + # done by default. + unix_listener imap-master { + user = $default_internal_user + } +} + +# The following is the default already in v2.3.1+: +service imap { + extra_groups = $default_internal_group +} +service imap-hibernate { + unix_listener imap-hibernate { + mode = 0660 + group = $default_internal_group + } +} +---%<------------------------------------------------------------------------- + +How it works +------------ + +When client issues IDLE, the connection socket is moved to the hibernation +process. This process is responsible for keeping all connections that are +idling, until they issue some command that requires them to be thawed into a +imap process. This way, memory and CPU resources are saved, since there is only +one hibernation process. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/IMAPServer.txt b/doc/wiki/IMAPServer.txt new file mode 100644 index 0000000..8681cfe --- /dev/null +++ b/doc/wiki/IMAPServer.txt @@ -0,0 +1,20 @@ +Dovecot as an IMAP server +========================= + +Dovecot was optimized since the beginning to work as an efficient IMAP server. +Dovecot supports a lot of IMAP extensions [http://imapwiki.org/Specs]. + +Some of the extensions need to be explicitly enabled: + + * <METADATA> [ImapMetadata.txt] + * <COMPRESS> [Plugins.Compress.txt] + * <SEARCH=FUZZY> [Plugins.FTS.txt] + * <SPECIAL-USE> [MailboxSettings.txt] + * NOTIFY: Set mailbox_list_index=yes + * URLAUTH: Set imap_urlauth_host and mail_attribute_dict + +Other features: + + * <Hibernation> [IMAPServer.Hibernation.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/ImapMetadata.txt b/doc/wiki/ImapMetadata.txt new file mode 100644 index 0000000..8583415 --- /dev/null +++ b/doc/wiki/ImapMetadata.txt @@ -0,0 +1,25 @@ +IMAP METADATA +============= + +Dovecot supports the IMAP METADATA extension (RFC 5464) +[https://tools.ietf.org/html/rfc5464], which allows per-mailbox, per-user data +to be stored and accessed via IMAP commands. + +To activate metadata storage, a <dictionary> [Dictionary.txt] needs to be +configured in the Dovecot configuration using the 'mail_attribute_dict' option. + +To activate the IMAP METADATA commands, the 'imap_metadata' option needs to be +activated. + +Example: + +---%<------------------------------------------------------------------------- +# Store METADATA information within user's Maildir directory +mail_attribute_dict = file:%h/Maildir/dovecot-attributes + +protocol imap { + imap_metadata = yes +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/IndexFiles.txt b/doc/wiki/IndexFiles.txt new file mode 100644 index 0000000..88ff012 --- /dev/null +++ b/doc/wiki/IndexFiles.txt @@ -0,0 +1,192 @@ +Dovecot's index files +===================== + +The basic idea behind Dovecot's index files is that it makes reading the +mailboxes a lot faster. The index files consist of the following files: + + * dovecot.index: Main index file + * dovecot.index.cache: Cached mailbox data + * dovecot.index.log: Transaction log file + * dovecot.index.log.2: .log file is rotated to .log.2 file when it grows too + large. + * dovecot.list.index*: Mailbox list index files + +Each mailbox has its own separate index files. If the index files are disabled, +the same structures are still kept in the memory, except cache file is disabled +completely (because the client probably won't fetch the same data twice within +a connection). + +If index files are missing, Dovecot creates them automatically when the mailbox +is opened. If at any point creating a file or growing a file gives "not enough +disk space" error, the indexes are transparently moved to memory for the rest +of the session. This isn't done with mailbox formats that rely on index files +(e.g. dbox). + +See <Design.Indexes.txt> for more technical information how the index files are +handled. + +Main index +---------- + +The main index contains the following information for each message: + + * IMAP UID + * Current flags and keywords + * Pointer to cache file + * mbox-only: mbox file offset + * mbox-only: MD5 sum of some of the message headers, intended to help find the + message when its X-UID: header hasn't yet been written + * Other extensions in Dovecot v1.1+, such as mailbox sorting data + +This is the same information that most other IMAP servers keep in memory while +the mailbox is open, but Dovecot has the advantage of keeping the information +permanently stored so it's easy to get it when opening the mailbox. + +The index file's header also contains some summary information, such as how +many messages exist, how many of them are unseen and how many are marked with +\Deleted flag. Opening mailboxes and answering to STATUS IMAP commands can be +usually done simply by getting the required information from the index file's +header. This is why these operations are extremely fast with Dovecot compared +to other servers that don't use an equivalent index file. + +Mailbox synchronization +----------------------- + +The main index's header also contains mailbox syncing state: + + * Maildir: cur/ and new/ directories' timestamps + * mbox: mbox file's mtime and size + +The index file is synchronized against mailbox only if the syncing information +changes. + +Cache file +---------- + +Cache file may contain the following information for messages: + + * Message headers (some, not all) + * Sent date (parsed Date: header) + * Received date (IMAP's INTERNALDATE field) + * Physical and virtual message sizes + * Message's parsed MIME structure, allowing to quickly read only a specific + MIME part (IMAP's FETCH BODY[1.2.3] command) + * IMAP's BODY and BODYSTRUCTURE fields + * If both are used, only BODYSTRUCTURE is saved, since BODY can be + generated from it + * IMAP's ENVELOPE isn't cached currently. Instead the headers used to build it + are cached directly. + +IMAP clients can work in many different ways. There are basically 2 types: + + 1. Online clients that ask for the same information multiple times (eg. + webmails, Pine) + 2. Offline clients that usually download first some of the interesting message + headers and only after that the message bodies (possibly automatically, or + possibly only when the user opens the mail). Most IMAP clients behave like + this. + +Cache file is extremely helpful with the type 1 clients. The first time that +client requests message headers or some other metadata they're stored into the +cache file. The second time they ask for the same information Dovecot can now +get it quickly from the cache file instead of opening the message and parsing +the headers. + +For type 2 clients the cache file is helpful if they use multiple clients or if +the data was cached while the message was being saved (Dovecot v1.1+ can do +this). Some of the information is helpful in any case, for example it's +required to know the message's virtual size when downloading the message. +Without the virtual size being in cache Dovecot first has to read the whole +message to calculate it. + +Only the mailbox metadata that client(s) have asked for earlier are stored into +cache file. This allows Dovecot to be adaptive to different clients' needs and +still not waste disk space (and cause extra disk I/O!) for fields that client +never needs. + +Dovecot can cache fields either permanently or temporarily. Temporarily cached +fields are dropped from the cache file after about a week. Dovecot uses two +rules to determine when data should be cached permanently instead of +temporarily: + + 1. Client accessed messages in non-sequential order within this session. This + most likely means it doesn't have a local cache. + 2. Client accessed a message older than one week. + +<Design.Indexes.Cache.txt> explains the reasons for these rules. + +Transaction log +--------------- + +All changes to the main index go through transaction log first. This has two +advantages when the mailbox is accessed using multiple simultaneous +connections: + + 1. It allows getting a list of changes quickly so that IMAP clients can be + notified of the changes. An alternative would be to do a comparison of two + index mappings, which is what most other IMAP servers do. + 2. 'mmap_disable=yes' implementation relies on the transaction log. Instead of + re-reading the whole main index file after each change it's necessary to + only read a few bytes from the transaction log. + +In Dovecot v1.1+ the transaction log plays an even more important role. The +main index file is updated only "once in a while" to reduce disk writes, so it +is common to first read the main index and then apply new changes from the +transaction log on top of that. With empty mailboxes (eg. download+delete POP3 +users) it would even be possible to delete the whole main index and keep only +the transaction log (although this isn't done currently). + +List index +---------- + +Mailbox list index file is called dovecot.list.index[.log] and it basically +contains: + + * Header contains ID => name mapping. The name isn't the full mailbox name, + but rather each hierarchy level has its own ID and name. For example a + mailbox name "foo/bar" (with '/' as separator) would have separate IDs for + "foo" and "bar" names. + * The records contain { parent_uid, uid, name_id } field that can be used to + build the whole mailbox tree. parent_uid=0 means root, otherwise it's the + parent node's uid. + * Each record also contains GUID for each selectable mailbox. If a mailbox is + recreated using the same name, its GUID also changes. Note however that the + UID doesn't change, because the UID refers to the mailbox name, not to the + mailbox itself. + * The records may contain also extensions for allowing mailbox_get_status() to + return values directly from the mailbox list index. + * Storage backends may also add their own extensions to figure out if a record + is up to date. + +Settings +-------- + +Since v2.2.34+ you can configure some of the hardcoded optimization-related +settings. It's not recommended to change these settings without fully +understanding the consequences. + + * 'mail_cache_unaccessed_field_drop': Drop fields that haven't been accessed + for n seconds. + * 'mail_cache_record_max_size': If cache record becomes larger than this, + don't add it. + * 'mail_cache_compress_min_size': Never compress the file if it's smaller than + this. + * 'mail_cache_compress_delete_percentage': Compress the file when n% of + records are deleted (by count, not by size). + * 'mail_cache_compress_continued_percentage': Compress the file when n% of + rows contain continued rows. For example 200% means that the record has 2 + continued rows, i.e. it exists in 3 separate segments in the cache file. + * 'mail_cache_compress_header_continue_count': Compress the file when we need + to follow more than n next_offsets to find the latest cache header. + * 'mail_index_rewrite_min_log_bytes', 'mail_index_rewrite_max_log_bytes': + Rewrite the index when the number of bytes that needs to be read from the + .log on refresh is between these min/max values. + * 'mail_index_log_rotate_min_size', 'mail_index_log_rotate_max_size', + 'mail_index_log_rotate_min_age': Rotate transaction log after it's a) + min_size or larger and it was created at least min_age_secs or b) larger + than max_size. + * 'mail_index_log2_max_age': Delete .log.2 when it's older than + log2_stale_secs. Don't be too eager, because older files are useful for + QRESYNC and dsync. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.Exim.txt b/doc/wiki/LDA.Exim.txt new file mode 100644 index 0000000..1b2ab21 --- /dev/null +++ b/doc/wiki/LDA.Exim.txt @@ -0,0 +1,163 @@ +Dovecot LDA with Exim +===================== + +System users +------------ + +Change the localuser router to use dovecot_delivery transport: + +---%<------------------------------------------------------------------------- +localuser: + driver = accept + check_local_user +# local_part_suffix = +* : -* +# local_part_suffix_optional + transport = dovecot_delivery +---%<------------------------------------------------------------------------- + +'check_local_user' is required. It makes Exim execute the transport with the +user's UID and GID and it also sets HOME environment. + +Next create a new transport for dovecot-lda: + +---%<------------------------------------------------------------------------- +dovecot_delivery: + driver = pipe + + # Use /usr/lib/dovecot/dovecot-lda if using Debian's package. + # You may or may not want to add -d $local_part@$domain depending on if you +need a userdb lookup done. + command = /usr/local/libexec/dovecot/dovecot-lda -f $sender_address + + message_prefix = + message_suffix = + log_output + delivery_date_add + envelope_to_add + return_path_add + #group = mail + #mode = 0660 + temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78 +---%<------------------------------------------------------------------------- + +LDA is now running using the local user's UID and GID. The mail is delivered to +the location specified by <mail_location> [MailLocation.txt] setting. Note that +the above configuration doesn't do any <userdb> [UserDatabase.txt] lookups, so +you can't have any per-user configuration. If you want that, see the virtual +user setup below. + +Virtual users +------------- + +Make sure that 'check_local_user' isn't set in the router. + +Single UID +---------- + +Configure the transport to run as the user you want, for example vmail: + +---%<------------------------------------------------------------------------- +dovecot_virtual_delivery: + driver = pipe + command = /usr/local/libexec/dovecot/dovecot-lda -d $local_part@$domain -f +$sender_address + # v1.1+: command = /usr/local/libexec/dovecot/dovecot-lda -d +$local_part@$domain -f $sender_address -a +$original_local_part@$original_domain + message_prefix = + message_suffix = + delivery_date_add + envelope_to_add + return_path_add + log_output + user = vmail + temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78 +---%<------------------------------------------------------------------------- + +You'll also need to have a master authentication socket and give vmail user +access to it. See <LDA.txt> for more information. + +List of temp_errors can be found in '/usr/include/sysexits.h'. + +Multiple UIDs +------------- + +If you need multiple uids/gids you'll need to set dovecot-lda setuid root. See +<LDA#multipleuids> [LDA.txt] for how to do this securely. + +You could alternatively set 'user = root', but this requires that you built +Exim without root being in FIXED_NEVER_USERS list. + +Multiple UIDs, without running dovecot-lda as root +-------------------------------------------------- + +In this mode, dovecot-lda won't be querying Dovecot's master socket, instead +trusting Exim to setup its execution environment. This means you must set up +Exim to get the UID, GID, Home directory from LDAP/SQL/whatever. Here, we're +setting them in the router and the transport automatically inherits them. + +Router configuration +-------------------- + +Insert the following router after your external delivery routers and before +your local system delivery routers. + +This assumes you're using macros set elsewhere to handle your external queries, +as they can quickly become unwieldy to manage. Make sure you adjust it to suit +your installation first! + +---%<------------------------------------------------------------------------- +ldap_local_user: + debug_print = "R: ldap_local_user for $local_part@$domain" + driver = accept + domains = +ldap_local_domains + condition = LDAP_VIRT_COND + router_home_directory = LDAP_VIRT_HOME + user = LDAP_VIRT_UID + group = LDAP_VIRT_GID + #local_part_suffix = +* : -* + #local_part_suffix_optional + transport = dovecot_lda +---%<------------------------------------------------------------------------- + +Transport configuration +----------------------- + +This transport has been tested with Exim 4.69-9 and Dovecot 1:1.2.5-2 +(backported) on Debian Lenny. You also have to set + +---%<------------------------------------------------------------------------- +dovecot_lda: + debug_print = "T: dovecot_lda for $local_part@$domain" + driver = pipe + # Uncomment the following line and comment the one after it if you want +dovecot-lda to try + # to deliver subaddresses into INBOX.{subaddress}. If you do this, uncomment +the + # local_part_suffix* lines in the router as well. Make sure you also change +the separator + # to suit your local setup. + #command = /usr/lib/dovecot/dovecot-lda -e -k -m +"INBOX|${substr_1:$local_part_suffix}" \ + command = /usr/lib/dovecot/dovecot-lda -e -k \ + -f "$sender_address" -a "$original_local_part@$original_domain" + environment = USER=$local_part@$domain + home_directory = /var/mail/home/$domain/$local_part + umask = 002 + message_prefix = + message_suffix = + delivery_date_add + envelope_to_add + return_path_add + log_output + log_defer_output + return_fail_output + freeze_exec_fail + #temp_errors = * + temp_errors = 64 : 69 : 70 : 71 : 72 : 73 : 74 : 75 : 78 +---%<------------------------------------------------------------------------- + +You need to have <home directory> [VirtualUsers.Home.txt] set to have duplicate +database enabled, among other reasons. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.Indexing.txt b/doc/wiki/LDA.Indexing.txt new file mode 100644 index 0000000..abde8f8 --- /dev/null +++ b/doc/wiki/LDA.Indexing.txt @@ -0,0 +1,47 @@ +LDA Indexing +============ + +LDA's indexing basically does two things while message is being saved: + + 1. It updates the main index file. + * This improves performance with <mbox> [MailboxFormat.mbox.txt] format, + especially if 'mbox_very_dirty_syncs=no'. + * With <Maildir> [MailboxFormat.Maildir.txt] the benefits of this are + almost irrelevant. + 2. It updates the 'dovecot.index.cache' file. + +Cache file +---------- + +The LDA also updates the cache file, which can be very useful with all mailbox +formats. It means that when an IMAP client wants to fetch the message's +metadata (e.g. some header fields), they're can be retrieved from the cache +file and Dovecot doesn't have to open and parse the message file. There are +some tradeoffs though: + + * LDA indexing wastes disk I/O because it has to open and update index files + * LDA indexing saves disk I/O because it already has the message body in + memory, so it doesn't need to read it from disk. + * IMAP indexing wastes disk I/O because it has to open and read message files + * IMAP indexing may save disk I/O because IMAP process always has index files + opened, and many IMAP clients are configured to download all new message + bodies anyway, so the second time message bodies are read they're already in + memory + +So it depends on IMAP client if it's faster to use LDA or IMAP time indexing. +In any case the user experience is typically faster with LDA indexing, because +the message list metadata can be returned faster when it's pre-indexed. + +See <IndexFiles.txt> for more information about what the index files contain. + +Non-indexed mail delivery +------------------------- + +Ignoring the benefits of cache file updates, the only thing left is the main +index updates. As mentioned above, with Maildir format these benefits are very +small. This also means that it's perfectly fine to use a non-Dovecot MDA to +deliver mails that doesn't update indexes. Dovecot can efficiently see and +index such new mails without doing anything expensive like "rebuilding +indexes". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.Postfix.txt b/doc/wiki/LDA.Postfix.txt new file mode 100644 index 0000000..bf519af --- /dev/null +++ b/doc/wiki/LDA.Postfix.txt @@ -0,0 +1,255 @@ +Dovecot LDA with Postfix +======================== + +This page contains only information specific to using LDA with Postfix, see +<LDA.txt> for more information about using the LDA itself. + +System users +------------ + +If you wish you use 'dovecot-lda' for all system users on a single domain mail +host you can do it by editing 'mailbox_command' parameter in + +'/etc/postfix/main.cf' (postconf(5) [http://www.postfix.org/postconf.5.html]): + +---%<------------------------------------------------------------------------- +mailbox_command = /usr/local/libexec/dovecot/dovecot-lda -f "$SENDER" -a +"$RECIPIENT" +# or +mailbox_command = /usr/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT" +# or +mailbox_command = /usr/lib/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT" +# or wherever it was installed in your system. +---%<------------------------------------------------------------------------- + +Then run 'postfix reload'. + + * This command doesn't do a <userdb> [UserDatabase.txt] lookup. If you want + that (e.g. for per-user quota lookups) you need to add '-d "$USER"' + parameter. + * Postfix runs 'mailbox_command' with both the uid and gid of the destination + user. This may not allow 'dovecot-lda' to write a lock file in '/var/mail'. + When this directory is writable by a privileged group (say 'main', see the + option 'mail_privileged_group'), we can use the setgid permission bit on the + 'dovecot-lda' executable: + + ---%<---------------------------------------------------------------------- + # chgrp mail /usr/lib/dovecot/dovecot-lda + # chmod 2755 /usr/lib/dovecot/dovecot-lda + ---%<---------------------------------------------------------------------- + + Alas these permission will disappear if you update dovecot. A more robust + way to do so is to compile a relay program '/etc/postfix/dovecot-lda-relay' + that has the setgid permission and execs the real 'dovecot-lda'. + + ---%<---------------------------------------------------------------------- + # cd /etc/postfix + # cat >dovecot-lda-relay.c <<EOF + #include <unistd.h> + char *pgm = "/usr/lib/dovecot/dovecot-lda"; /* wherever dovecot-lda is + located */ + int main{int argc, char**argv) { argv[0]=pgm; execv(pgm,argv); return + 10; } + EOF + # gcc -o dovecot-lda-relay dovecot-lda-relay.c + # chown root:mail dovecot-lda-relay + # chmod 2755 dovecot-lda-relay + ---%<---------------------------------------------------------------------- + + Then, simply invoke '/etc/postfix/dovecot-lda-relay' instead of + 'dovecot-lda' in 'mailbox_command'. + * Postfix's 'mailbox_size_limit' setting applies to all files that are written + via dovecot-lda. The default is 50 MB, so dovecot-lda can't write *any* + files larger than that, including mbox files or log files. This shows up + only in Dovecot's logs: + + ---%<---------------------------------------------------------------------- + dovecot-lda(user): write() failed with mbox file /home/user/mail/foo: File + too large (process was started with ulimit -f limit) + ---%<---------------------------------------------------------------------- + + * If you have trouble seeing anything in Dovecot's logs, see <LDA#Logging> + [LDA.txt]. + +Virtual users +------------- + +Dovecot LDA is very easy to use on large scale installations with Postfix +virtual domains support, just add a 'dovecot' service in +'/etc/postfix/master.cf' (master(5) [http://www.postfix.org/master.5.html]): + +---%<------------------------------------------------------------------------- +dovecot unix - n n - - pipe + flags=DRhu user=vmail:vmail argv=/usr/local/libexec/dovecot/dovecot-lda -f +${sender} -d ${recipient} +---%<------------------------------------------------------------------------- + +An example using address extensions (ie user+extension@domain.com (don't forget +to define the proper recipient_delimiter in Postfix's main.cf)) to deliver to +the folder 'extension' in your maildir (If you wish to preserve the case of +${extension}, remove the 'hu'flags [http://www.postfix.org/pipe.8.html], and be +sure to utilize <Modifiers> [Variables.txt] in your dovecot.conf for mail +locations and other configuration parameters that are expecting lower case): + +---%<------------------------------------------------------------------------- +dovecot unix - n n - - pipe + flags=DRhu user=vmail:vmail argv=/usr/local/libexec/dovecot/dovecot-lda -f +${sender} -d ${user}@${nexthop} -m ${extension} + +# or if you have a INBOX/ namespace prefix: +dovecot unix - n n - - pipe + flags=DRhu user=vmail:vmail argv=/usr/local/libexec/dovecot/dovecot-lda -f +${sender} -d ${user}@${nexthop} -m INBOX/${extension} +---%<------------------------------------------------------------------------- + +This example ignores address extensions (ie user+extension@domain.com delivers +just like user@domain.com ), but still shows the original address for Sieve: + +---%<------------------------------------------------------------------------- +dovecot unix - n n - - pipe + flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -f ${sender} -a +${original_recipient} -d ${user}@${nexthop} +---%<------------------------------------------------------------------------- + +Replace 'vmail' above with your virtual mail user account. + +Then set 'virtual_transport' to 'dovecot' in '/etc/postfix/main.cf': + +---%<------------------------------------------------------------------------- +dovecot_destination_recipient_limit = 1 +virtual_mailbox_domains = your.domain.here +virtual_transport = dovecot +---%<------------------------------------------------------------------------- + +And remember to run + +---%<------------------------------------------------------------------------- +postfix reload +---%<------------------------------------------------------------------------- + +Virtual users with multiple uids/gids +------------------------------------- + +If you need multiple uids/gids you'll need to set dovecot-lda setuid root or +invoke it through sudo. See <LDA#multipleuids> [LDA.txt] for how to do this +securely. + +Postfix with a NFS mail store +----------------------------- + +If you are experiencing problems with dovecot-lda processes hanging when +delivering to an NFS mail store, it's likely that the dovecot-lda process is +hanging while waiting for free locks. The occurrence of this can be greatly +reduced, if not eradicated, by forcing Postfix to only deliver to the same +recipient one at a time. + +---%<------------------------------------------------------------------------- +dovecot_destination_concurrency_limit = 1 +---%<------------------------------------------------------------------------- + +Prevent backscatter +------------------- + +To prevent backscatter you should configure Postfix to reject mail for non +existent recipients. + +This is the default behaviour (smtpd_reject_unlisted_recipient = yes) so +there's no need to set "reject_unlisted_recipient" in any of your restriction. +But: Postfix must know if a recipient exists. Depending on how you've +configured Dovecot and Postfix this can be done several ways. + +System users +------------ + +If you only use local system users this is no problem - all valid recipients +can be found in the local password or alias database. + +Virtual users (static) +---------------------- + +When you use virtual users and domains you should maintain a list of valid +recipients. The relevant settings settings are: + +*virtual_alias_maps, virtual_mailbox_maps* + +For static verification you can maintain the content of the files yourself. For +every recipient or alias you need one entry. Example: + +*virtual_alias_maps* + +---%<------------------------------------------------------------------------- +name_recipient@example.com external@example.net +---%<------------------------------------------------------------------------- + +*virtual_mailbox_maps* + +---%<------------------------------------------------------------------------- +name@example.com OK +recipient@example.com available +---%<------------------------------------------------------------------------- + +Don't forget to run "postmap" afterwards. + +*Info:* if you use the Dovecot LDA or LMTP it doesn't matter what you use +behind the recipient address. Use "OK", the full name of the user or else. + +Virtual users (dynamic) +----------------------- + +Do you already use a database (MySQL, PostgreSQL) for Dovecot? Use the same +source for Postfix. You only have to to define a valid sql query for Postfix. +Example: + +---%<------------------------------------------------------------------------- +virtual_mailbox_maps = proxy:mysql:/etc/postfix/virtual_mailbox_maps.cf +---%<------------------------------------------------------------------------- + +*virtual_mailbox_maps.cf* + +---%<------------------------------------------------------------------------- +user = mysql-user +password = mysql-password +hosts = unix:/var/run/mysql/mysqld.sock +dbname = mailserver +query = SELECT name FROM mailbox WHERE email='%s' +---%<------------------------------------------------------------------------- + +This query will return the value of the filed "name" from table "mailbox" if +the email address of the recipient matches the email from the field "email". +This is enough for Postfix because Postfix must only know if the recipient +exists. The value doesn't matter. When you use a database (or LDAP) there's no +need to manually maintain a file with valid recipients. + +*Info:* If you use "relay_domains" instead of "virtual_mailbox_domains" you +have to use "relay_recipient_maps" instead of "virtual_mailbox_maps". + +Dynamic address verification with LMTP +-------------------------------------- + +With Dovecot 2.0 you can also use LMTP and the Postfix setting +"reject_unverified_recipient" for dynamic address verification. It's really +nice because Postfix doesn't need to query an external datasource (MySQL, +LDAP...). Postfix maintain a local database with existing/non existing +addresses (you can configure how long positive/negative results should be +cached). + +To use LMTP and dynamic address verification you must first get Dovecot +working. Then you can configure Postfix to use LMTP and set +"reject_unverified_recipient" in the smtpd_recipient_restrictions. + +On every incoming email Postfix will probe if the recipient address exists. You +will see similar entries in your logfile: + +---%<------------------------------------------------------------------------- +Recipient address rejected: undeliverable address: host +tux.example.com[private/dovecot-lmtp] said: 550 5.1.1 < tzknvtr@example.com > +User doesn't exist: tzknvtr@example.com (in reply to RCPT TO command); from=< +cnrilrgfclra@spammer.org > to=< tzknvtr@example.com > +---%<------------------------------------------------------------------------- + +If the recipient address exists (status=deliverable) Postfix accepts the mail. + +*Info:* you can not use "reject_unverified_recipient" with "pipe" so this +doesn't work with the Dovecot LDA "deliver". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.Qmail.txt b/doc/wiki/LDA.Qmail.txt new file mode 100644 index 0000000..d13756d --- /dev/null +++ b/doc/wiki/LDA.Qmail.txt @@ -0,0 +1,31 @@ +Dovecot LDA with Qmail +====================== + +System users +------------ + +The delivery command you need is + +---%<------------------------------------------------------------------------- +|/var/qmail/bin/preline -f /usr/local/libexec/dovecot/dovecot-lda +---%<------------------------------------------------------------------------- + +(You may need to adjust the paths to match your qmail and dovecot +installations.) The 'preline' command will add the 'Return-Path:' and +'Delivered-To:' lines, because 'dovecot-lda' doesn't recognize qmail's +environment variables. + +For site-wide usage, put that in '/var/qmail/control/defaultdelivery' (assuming +you installed qmail according to LWQ [http://www.lifewithqmail.org/lwq.html]). +Or, save it as '.qmail' in selected users' home directories. + +Virtual users +------------- + +Add the '-d' parameter to specify the destination username: + +---%<------------------------------------------------------------------------- +|/var/qmail/bin/preline -f /usr/local/libexec/dovecot/dovecot-lda -d $EXT@$USER +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.Sendmail.txt b/doc/wiki/LDA.Sendmail.txt new file mode 100644 index 0000000..b14e4f0 --- /dev/null +++ b/doc/wiki/LDA.Sendmail.txt @@ -0,0 +1,105 @@ +Dovecot LDA with Sendmail +========================= + +The following describes how to configure Sendmail to use 'dovecot-lda' where +'root' permission is not granted and Dovecot runs under a single user ID. It +may need some adjustment for more typical setups. Other assumptions are that +Sendmail is configured for virtual hosting and that local-system mail delivery +is not handled by 'dovecot-lda'. + +Allowing that 'sendmail.mc' has 'MAILER(procmail)dnl' included, edit +'sendmail.cf' adding these lines after the 'Mprocmail' definition: + +---%<------------------------------------------------------------------------- +######################*****############## +### DOVECOT Mailer specification ### +##################*****################## +Mdovecot, P=/usr/local/libexec/dovecot/dovecot-lda, F=DFMPhnu9, + S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP/HdrFromSMTP, + T=DNS/RFC822/X-Unix, + A=/usr/local/libexec/dovecot/dovecot-lda -d $u +---%<------------------------------------------------------------------------- + +If you're using 'sendmail.mc' then put the lines above into a new file +'/usr/share/sendmail-cf/mailer/dovecot.m4' and put 'MAILER(dovecot)' into your +'sendmail.mc' + +=================================== + +Another method of doing the above is by editing your 'hostname.mc' with the +following three lines: + +---%<------------------------------------------------------------------------- +FEATURE(`local_procmail', +`/usr/local/libexec/dovecot/dovecot-lda',`/usr/local/libexec/dovecot/dovecot-lda +-d $u') +MODIFY_MAILER_FLAGS(`LOCAL', `-f') +MAILER(procmail) +---%<------------------------------------------------------------------------- + +After editing 'hostname.mc' with the above, be sure to remake your +'hostname.cf' file. This is confirmed to work with: + + * dovecot-1.0.7 + * FreeBSD 6.3-RELEASE-p3 i386 + * sendmail Version 8.14.2 + * Compiled with: DNSMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8 MIME8TO7 + NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS PIPELINING SASLv2 SCANF + STARTTLS TCPWRAPPERS USERDB XDEBUG + +=================================== + +If 'sendmail' runs under a different non-'root' UID via + + * 'define(`confRUN_AS_USER', `sendmail')dnl' + +in 'sendmail.mc', then the /env_put(t_strconcat("RESTRICT_/ lines in +'deliver.c' must be commented-out. + +Now add a + +---%<------------------------------------------------------------------------- +virtualdomain.example.com vmail:vmail +---%<------------------------------------------------------------------------- + +line for each virtual domain to 'mailertable.cf' and run 'makemap hash +mailertable.db < mailertable.cf'. The 'dovecot' (or some other random text) +after the colon character is required, else 'sendmail' will fail to pass +command arguments to 'dovecot-lda' correctly. Make sure all the virtual +domains are in the 'virtuserdomains' file. + +=========================================== + +(Fedora 14: dovecot 2.0.8 & sendmail 8.14.4) + +Summing up all previous experience, one may keep all virtual user accounts +under one system account. + +The sendmail's "U=" mailer option with changing the owner of lda (to "keeper" +here for instance): + +---%<------------------------------------------------------------------------- +-rwxr-xr-x. 1 keeper mail 14536 Dec 7 16:43 /usr/libexec/dovecot/dovecot-lda +---%<------------------------------------------------------------------------- + +allows to run virtual users under one system account without applying SUID. + +Sendmail can pass a user account to LDA with or without the domain. Passing a +user name without the domain can be achievedwith S=/R= rewriting rules of the +local mailer. Finally, into '/usr/share/sendmail-cf/mailer/dovecot.m4' goes the +block of lines: + +---%<------------------------------------------------------------------------- +Mdovecot, P=/usr/libexec/dovecot/dovecot-lda, + F=l59DFMPhnu, + S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + M=51200000, + U=keeper:mail, + T=DNS/RFC822/X-Unix, + A=/usr/libexec/dovecot/dovecot-lda -d $u +---%<------------------------------------------------------------------------- + +dovecot.m4 [http://sites.google.com/site/mclroy/dovecot/dovecot-m4] can be a +bit more complex. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LDA.txt b/doc/wiki/LDA.txt new file mode 100644 index 0000000..80e2ee6 --- /dev/null +++ b/doc/wiki/LDA.txt @@ -0,0 +1,298 @@ +Dovecot LDA +=========== + +The Dovecot LDA is a <local delivery agent> [MDA.txt], which takes mail from an +<MTA.txt> and delivers it to a user's mailbox, while keeping Dovecot index +files up to date. Nowadays you should probably use the <LMTP server> [LMTP.txt] +instead, because it's somewhat easier to configure (especially related to +permissions) and gives better performance. + +This page describes the common settings required to make LDA work. You should +read it first, and then the MTA specific pages: + + * <LDA.Postfix.txt> + * <LDA.Exim.txt> + * <LDA.Sendmail.txt> + * <LDA.Qmail.txt> + * <LDA.ZMailer.txt> + +Main features of Dovecot LDA +---------------------------- + + * <Mailbox indexing during mail delivery> [LDA.Indexing.txt], providing faster + mailbox access later + * <Quota enforcing by a plugin> [Quota.txt] + * <Sieve language support by a plugin> [Pigeonhole.Sieve.txt] + * Mail filtering + * Mail forwarding + * Vacation auto-reply + +Common configuration +-------------------- + +The settings are listed in the example 'conf.d/15-lda.conf' file. The important +settings are: + + * 'postmaster_address' is used as the From: header address in bounce mails + * 'hostname' is used in generated Message-IDs and in Reporting-UA: header in + bounce mails + * 'sendmail_path' is used to send mails. Note that the default is + '/usr/sbin/sendmail', which doesn't necessarily work the same as + '/usr/lib/sendmail'. + * Alternatively you can use 'submission_host' to send mails via the + specified SMTP server. + * 'auth_socket_path' specifies the UNIX socket to auth-userdb where LDA can + lookup userdb information when '-d' parameter is used. See below how to + configure Dovecot to configure the socket. + +Note that the config files must be world readable to enable dovecot-lda process +read them, while running with user privileges. You can put password related +settings to a separate file, which you include with '!include_try' and +dovecot-lda skips them. + +Parameters +---------- + +Parameters accepted by dovecot-lda: + + * '-d <username>': Destination username. If given, the user information is + looked up from dovecot-auth. Typically used with virtual users, but not + necessarily with system users. + * '-a <address>': Original envelope recipient address (e.g. user+ext@domain), + typically same as SMTP's RCPT TO: value. If not specified, it's taken from + header specified by 'lda_original_recipient_header' setting (v2.0.3+). If + the header doesn't exist either, defaults to same as username. + * '-r <address>': Final envelope recipient address. Defaults to -a address, + but may differ if e.g. aliases are used or when dropping the +ext part. + (v2.0.3+) + * '-f <address>': Envelope sender address. If not specified and message data + begins with a valid mbox-style "From " line, the address is taken from it. + * '-c <path>': Alternative configuration file path. + * '-m <mailbox>': Destination mailbox (default is INBOX). If the mailbox + doesn't exist, it will not be created (unless the lda_mailbox_autocreate + setting is set to yes). If message couldn't be saved to the mailbox for any + reason, it's delivered to INBOX instead. + * If Sieve plugin is used, this mailbox is used as the "keep" action's + mailbox. It's also used if there is no Sieve script or if the script + fails for some reason. + * Deliveries to namespace prefix will result in saving the mail to INBOX + instead. For example if you have "Mail/" namespace, this allows you to + specify 'dovecot-lda -m Mail/$mailbox' where mail is stored to + Mail/$mailbox or to INBOX if $mailbox is empty. + * The mailbox name is specified the same as it's visible in IMAP client. + For example if you've a Maildir with '.box.sub/' directory and your + namespace configuration is 'prefix=INBOX/', 'separator=/', the correct + way to deliver mail there is to use '-m INBOX/box/sub' + * '-e': If mail gets rejected, write the rejection reason to stderr and exit + with EX_NOPERM. The default is to send a rejection mail ourself. + * '-k': Don't clear all environment at startup. + * '-p <path>': Path to the mail to be delivered instead of reading from stdin. + If using maildir the file is hard linked to the destination if possible. + This allows a single mail to be delivered to multiple users using hard + links, but currently it also prevents dovecot-lda from updating cache file + so it shouldn't be used unless really necessary. + * '-o name=value': Override a setting from dovecot.conf. You can give this + parameter multiple times. + +Return values +------------- + +dovecot-lda will exit with one of the following values: + + * 0 (EX_OK): Delivery was successful. + * 64 (EX_USAGE): Invalid parameter given. + * 67 (EX_NOUSER): The destination username was not found. + * 77 (EX_NOPERM): -e parameter was used and mail was rejected. Typically this + happens when user is over quota and 'quota_full_tempfail=no'. + * 75 (EX_TEMPFAIL): A temporary failure. This is returned for almost all + failures. See the log file for details. + +System users +------------ + +You can use LDA with a few selected system users (ie. user is found from +'/etc/passwd' / NSS) by calling dovecot-lda in the user's '~/.forward' file: + +---%<------------------------------------------------------------------------- +| "/usr/local/libexec/dovecot/dovecot-lda" +---%<------------------------------------------------------------------------- + +This should work with any MTA which supports per-user '.forward' files. For +qmail's per-user setup, see <LDA.Qmail.txt>. + +This method doesn't require the authentication socket explained below since +it's executed as the user itself. + +Virtual users +------------- + +With a lookup +------------- + +Give the destination username to dovecot-lda with '-d' parameter, for example: + +---%<------------------------------------------------------------------------- +dovecot-lda -f $FROM_ENVELOPE -d $DEST_USERNAME +---%<------------------------------------------------------------------------- + +You'll need to set up a auth-userdb socket for dovecot-lda so it knows where to +find mailboxes for the users: + +---%<------------------------------------------------------------------------- +service auth { + unix_listener auth-userdb { + mode = 0600 + user = vmail # User running dovecot-lda + #group = vmail # Or alternatively mode 0660 + dovecot-lda user in this +group + } +} +---%<------------------------------------------------------------------------- + +The auth-userdb socket can be used to do <userdb> [UserDatabase.txt] lookups +for given usernames or get a list of all users. Typically the result will +contain the user's UID, GID and home directory, but depending on your +configuration it may return other information as well. So the information is +similar to what can be found from eg.'/etc/passwd' for system users. This means +that it's probably not a problem to use mode=0666 for the socket, but you +should try to restrict it more just to be safe. + +Without a lookup +---------------- + +If you have already looked up the user's home directory and you don't need a +userdb lookup for any other reason either (such as overriding settings for +specific users), you can run dovecot-lda similar to how it's run for system +users: + +---%<------------------------------------------------------------------------- +HOME=/path/to/user/homedir dovecot-lda -f $FROM_ENVELOPE +---%<------------------------------------------------------------------------- + +This way you don't need to have a master listener socket. Note that you should +verify the user's existence prior to running dovecot-lda, otherwise you'll end +up having mail delivered to nonexistent users as well. + +You must have set the proper UID (and GID) before running dovecot-lda. It's not +possible to run dovecot-lda as root without '-d' parameter. + +Multiple UIDs +------------- + +If you're using more than one UID for users, you're going to have problems +running dovecot-lda, as most MTAs won't let you run dovecot-lda as root. Best +solution is to use <LMTP.txt> instead, but if you can't do that, there are two +ways to work around this problem: + + 1. Make dovecot-lda setuid-root. + 2. Use sudo to wrap the invocation of dovecot-lda. + +Making dovecot-lda setuid-root: +------------------------------- + +Beware: *it's insecure to make dovecot-lda setuid-root*, especially if you have +untrusted users in your system.*Setuid-root dovecot-lda can be used to gain +root privileges*. You should take extra steps to make sure that untrusted users +can't run it and potentially gain root privileges. You can do this by making +sure only your MTA has execution access to it. For example: + +---%<------------------------------------------------------------------------- +# chgrp secmail /usr/local/libexec/dovecot/dovecot-lda +# chmod 04750 /usr/local/libexec/dovecot/dovecot-lda +# ls -l /usr/local/libexec/dovecot/dovecot-lda +-rwsr-x--- 1 root secmail 4023932 2010-06-15 16:23 dovecot-lda +---%<------------------------------------------------------------------------- + +Then start dovecot-lda as a user that belongs to secmail group. Note that you +have to recreate these rights after each update of dovecot. + +Using sudo: +----------- + +Alternatively, you can use sudo to wrap the invocation of dovecot-lda. This has +the advantage that updates will not clobber the setuid bit, but note that *it +is just as insecure being able to run dovecot-lda via sudo as setuid-root*. +Make sure you only give your MTA the ability to invoke dovecot-lda via sudo. + +First configure sudo to allow 'dovelda' user to invoke dovecot-lda by adding +the following to your '/etc/sudoers': + +---%<------------------------------------------------------------------------- +Defaults:dovelda !syslog +dovelda ALL=NOPASSWD:/usr/local/libexec/dovecot/dovecot-lda +---%<------------------------------------------------------------------------- + +Then configure your MTA to invoke dovecot-lda as user 'dovelda' and via sudo: + +---%<------------------------------------------------------------------------- +/usr/bin/sudo /usr/local/libexec/dovecot/dovecot-lda +---%<------------------------------------------------------------------------- + +instead of just plain '/usr/local/libexec/dovecot/dovecot-lda'. + +Problems with dovecot-lda +------------------------- + + * If you are using <prefetch userdb> [UserDatabase.Prefetch.txt], keep in mind + that 'dovecot-lda' does not make a password query and thus will not work if + '-d' parameter is used. The <UserDatabase.Prefetch.txt> page explains how to + fix this. + * See <Checkpassword> [PasswordDatabase.CheckPassword.txt] for how to make + dovecot-lda work with checkpassword. + +Logging +------- + + * Normally Dovecot logs everything through its log process, which is running + as root. dovecot-lda doesn't, which means that you might need some special + configuration for it to log anything at all. + * If dovecot-lda fails to write to log files it exits with temporary failure. + * If you have trouble finding where Dovecot logs by default, see + <Logging.txt>. + * Note that Postfix's 'mailbox_size_limit' setting applies to all files that + are written to. So if you have a limit of 50 MB, dovecot-lda can't write to + log files larger than 50 MB and you'll start getting temporary failures. + +If you want dovecot-lda to keep using Dovecot's the default log files: + + * If you're logging to syslog, make sure the syslog socket (usually + '/dev/log') has enough write permissions for dovecot-lda. For example set it + world-read/writable:'chmod a+rw /dev/log'. + * If you're logging to Dovecot's default log files again you'll need to give + enough write permissions to the log files for dovecot-lda. + +You can also specify different log files for dovecot-lda. This way you don't +have to give any extra write permissions to other log files or the syslog +socket. You can do this by overriding the 'log_path' and 'info_log_path' +settings: + +---%<------------------------------------------------------------------------- +protocol lda { + .. + # remember to give proper permissions for these files as well + log_path = /var/log/dovecot-lda-errors.log + info_log_path = /var/log/dovecot-lda.log +} +---%<------------------------------------------------------------------------- + +For using syslog with dovecot-lda, set the paths empty: + +---%<------------------------------------------------------------------------- +protocol lda { + .. + log_path = + info_log_path = + # You can also override the default syslog_facility: + #syslog_facility = mail +} +---%<------------------------------------------------------------------------- + +Plugins +------- + + * Most of the <Dovecot plugins> [Plugins.txt] work with dovecot-lda. + * Virtual quota can be enforced using <Quota plugin> [Quota.txt]. + * Sieve language support can be added with the <Pigeonhole Sieve plugin> + [Pigeonhole.Sieve.txt]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LMTP.Exim.txt b/doc/wiki/LMTP.Exim.txt new file mode 100644 index 0000000..d1150b2 --- /dev/null +++ b/doc/wiki/LMTP.Exim.txt @@ -0,0 +1,153 @@ +Contents + + + 1. Using LMTP over UNIX Socket + + 2. Using LMTP over TCP Socket + + 3. Striping domain to avoid user unknown / doesn't exist error + + 4. Verifying recipients using LMTP + + 5. Delivering mails case insensitively + +Exim provides support for LMTP over UNIX sockets using the LMTP transport +[http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_lmtp_transport.html], +your distribution may/not provide this, run exim -bV and check for 'lmtp' in +'Transports:'. Support for LMTP over TCP sockets is provided by the SMTP +transport +[http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_smtp_transport.html]. + +Using LMTP over UNIX Socket +--------------------------- + +Use this configuration if dovecot runs on the same host as exim. + +Example router: + +---%<------------------------------------------------------------------------- +local_user: + debug_print = "R: local_user for $local_part@$domain" + driver = accept + domains = +local_domains + check_local_user + transport = dovecot_lmtp + cannot_route_message = Unknown user +---%<------------------------------------------------------------------------- + +Example transport: + +---%<------------------------------------------------------------------------- +dovecot_lmtp: + driver = lmtp + socket = /var/run/dovecot/lmtp + #maximum number of deliveries per batch, default 1 + batch_max = 200 + #allow suffixes/prefixes (default unset) + rcpt_include_affixes +---%<------------------------------------------------------------------------- + +Using LMTP over TCP Socket +-------------------------- + +Example router: + +---%<------------------------------------------------------------------------- +local_user: + transport = dovecot_lmtp + domains = +local_domains + driver = manualroute + route_list = "* 192.168.1.0 byname" + #if destination server is the local host enable this + #self = send +---%<------------------------------------------------------------------------- + +Set IP and port as appropriate to your setup. + +Example transport: + +---%<------------------------------------------------------------------------- +dovecot_lmtp: + driver = smtp + #allow suffixes/prefixes (default unset) + rcpt_include_affixes + protocol = lmtp + port = 2525 +---%<------------------------------------------------------------------------- + +Striping domain to avoid user unknown / doesn't exist error +----------------------------------------------------------- + +If you are using a userdb which does not have domain names, you may need to add +a setting to 20-lmtp.conf + +---%<------------------------------------------------------------------------- +protocol lmtp { + ... + # use %n to strip away the domain part + auth_username_format = %n +} +---%<------------------------------------------------------------------------- + +Symptoms: + + * Exim says something like "LMTP error after RCPT ... 550 ... User doesn't + exist someuser@somedomain" + * Dovecot verbose log says something like "auth-worker(9048): + passwd(someuser@somedomain): unknown user" + +Verifying recipients using LMTP +------------------------------- + +You can use callout verification to avoid accepting mail for addresses which do +not exist in Dovecot. Below is a config snippet which could be used in +acl_smtp_rcpt to achieve this: + +---%<------------------------------------------------------------------------- +deny + message = invalid recipient + domains = +local_domains + !verify = recipient/callout=no_cache +---%<------------------------------------------------------------------------- + +For more information on address verification see the related section of the +Exim specification +[http://www.exim.org/exim-html-current/doc/html/spec_html/ch-access_control_lists.html#SECTaddressverification]. + +Delivering mails case insensitively +----------------------------------- + +*Warning: *Just use this setup if all your login names contain only lower case +characters! (On Linux see /etc/adduser.conf under NAME_REGEX variable). + +Exim retains the case of the local part. Dovecot's LMTP /may/ fail looking up +an incorrect cased local part in your userdb. You can solve this problem by +extending the /protocol lmtp/ section: + +---%<------------------------------------------------------------------------- +protocol lmtp { + ... + # use %Ln to strip away the domain part + auth_username_format = %Lu +} +---%<------------------------------------------------------------------------- + +(If you don't mind allowing case insensitive logins for dovecoth +authentication, you may set /auth_username_format/ in the global configuration +accordingly and renounce the above change). + +In case you prefer to configure exim to lower case the local part instead, add +a router just before your local delivery router: + +---%<------------------------------------------------------------------------- +lowercase_local: + debug_print = "R: lower case local_part for local delivery" + driver = redirect + redirect_router = local_user + data = ${lc:${local_part}} +---%<------------------------------------------------------------------------- + +Make sure to reference the name you have chosen for your local delivery router +within /redirect_router/. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LMTP.txt b/doc/wiki/LMTP.txt new file mode 100644 index 0000000..ead650a --- /dev/null +++ b/doc/wiki/LMTP.txt @@ -0,0 +1,131 @@ +LMTP Server +=========== + +LMTP uses the same settings as <LDA.txt>, as specified in 'conf.d/15-lda.conf' +in example configuration. There is also a bit of extra configuration in +'conf.d/20-lmtp.conf'. The main difference is that the LDA is a short-running +process, started as a binary from command line, while LMTP is a long-running +process started by Dovecot's master process. + +Envelope Addresses +------------------ + +Compared to dovecot-lda parameters, the addresses are taken from: + + * -f / Envelope sender address: This is the MAIL FROM: value from LMTP + session. + * -r / Final envelope recipient address: This is the RCPT TO: value from LMTP + session. + * -a / Original envelope recipient address: This defaults to same as RCPT TO: + value, but may be overridden by reading it from a header specified by + 'lda_original_recipient_header' setting. + * -d / Destination username: This is the same as RCPT TO: value, but with the + "+extension" part removed when 'recipient_delimiter' setting is set. If + usernames differ from recipient email addresses, the userdb must handle the + translation. + +Listeners +--------- + +You can configure LMTP to be listening on TCP or UNIX sockets: + +---%<------------------------------------------------------------------------- +# add lmtp to protocols, otherwise its listeners are ignored +protocols = imap pop3 lmtp + +service lmtp { + inet_listener lmtp { + address = 192.168.0.24 127.0.0.1 ::1 + port = 24 + } + + unix_listener lmtp { + #mode = 0666 + } +} +---%<------------------------------------------------------------------------- + +The UNIX listener on $base_dir/lmtp is enabled by default when protocols +setting contains lmtp. + +Security +-------- + +Unfortunately LMTP process currently needs to run as root, and only temporarily +drop privileges to users. Otherwise it couldn't handle mail deliveries to more +than a single user with different UID. If you're using only a single global +UID/GID, you can improve security by running lmtp processes as that user: + +---%<------------------------------------------------------------------------- +service lmtp { + user = vmail +} +---%<------------------------------------------------------------------------- + +LMTP Proxying +------------- + +It's possible to use Dovecot LMTP server as a proxy to remote LMTP or SMTP +servers. The configuration is similar to <IMAP/POP3 proxying> +[PasswordDatabase.ExtraFields.Proxy.txt], but you'll need to tell Dovecot LMTP +to issue passdb lookups: + +---%<------------------------------------------------------------------------- +lmtp_proxy = yes +---%<------------------------------------------------------------------------- + +Performance +----------- + +For higher volume sites, it may be desirable to increase the number of active +listener processes. A range of 5 to 20 is probably good for most sites: + +---%<------------------------------------------------------------------------- +service lmtp { + process_min_avail = 5 +} +---%<------------------------------------------------------------------------- + +Logging +------- + +If you want to store LMTP delivery logs to a different file, you can do it +with: + +---%<------------------------------------------------------------------------- +service lmtp { + executable = lmtp -L +} +protocol lmtp { + info_log_path = /var/log/dovecot-lmtp.log +} +---%<------------------------------------------------------------------------- + +For rawlogs, please see <Debugging.Rawlog.txt> + +Plugins +------- + + * Most of the <Dovecot plugins> [Plugins.txt] work with LMTP. + * Virtual quota can be enforced using <Quota plugin> [Quota.txt]. + * 'lmtp_rcpt_check_quota = yes' enables quota checking already at RCPT TO + stage. This check isn't done for proxied connections. + * Sieve language support can be added with the <Pigeonhole Sieve plugin> + [Pigeonhole.Sieve.txt]. + +Address extension delivery +-------------------------- + +To make address extension work with LMTP you must check these variables are set + + * lmtp_save_to_detail_mailbox = yes + * recipient_delimiter = + + +Using LMTP with different MTAs +------------------------------ + + * <Postfix> [HowTo.PostfixDovecotLMTP.txt] + * <Exim> [LMTP.Exim.txt] + * HALON [http://wiki.halon.se/LMTP] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Logging.txt b/doc/wiki/Logging.txt new file mode 100644 index 0000000..ef5dc04 --- /dev/null +++ b/doc/wiki/Logging.txt @@ -0,0 +1,181 @@ +Contents + + + 1. Dovecot Logging + + 1. Internal Errors + + 2. Changing Log File Paths + + 3. Syslog Example + + 4. Rotating Logs + + 5. Logging verbosity + +Dovecot Logging +=============== + +*Dovecot always logs a detailed error message* if something goes wrong. If it +doesn't, it's considered a bug and will be fixed. However, almost always the +problem is that *you're looking at the wrong log file*; error messages may be +logged to a different file than informational messages. + +You can find the log file locations by running: + +---%<------------------------------------------------------------------------- +doveadm log find +---%<------------------------------------------------------------------------- + +Dovecot log configuration is found in the conf.d/10-logging.conf file in the +dovecot configuration folder (usually */etc/dovecot* but may also be +*/usr/local/etc/dovecot*). + +By default Dovecot logs to syslog using *mail* facility. You can change the +facility from 'syslog_facility' setting. The syslog configuration is often in +'/etc/syslog.conf' or '/etc/rsyslog*' files. You can also configure Dovecot to +write to log files directly, see below. + +When using syslog, Dovecot uses 5 different logging levels: + + * *debug*: Debug-level message. + * *info*: Informational messages. + * *warning*: Warnings that don't cause an actual error, but are useful to know + about. + * *err*: Non-fatal errors. + * *crit*: Fatal errors that cause the process to die. + +Where exactly these messages are logged depends entirely on your syslog +configuration. Often everything is logged to '/var/log/mail.log' or +'/var/log/maillog', and *err* and *crit* are logged to '/var/log/mail.err'. +This is not necessarily true for your configuration though. + +In an ideal configuration the errors would be logged to a separate file than +non-errors. For example you could set 'syslog_facility = local5' and set: + +---%<------------------------------------------------------------------------- +local5.* -/var/log/dovecot.log +local5.warning;local5.error;local5.crit -/var/log/dovecot-errors.log +---%<------------------------------------------------------------------------- + +Here all the Dovecot messages get logged into 'dovecot.log', while all the +important error/warning messages get logged into 'dovecot-errors.log'. + +Internal Errors +--------------- + +If IMAP or POP3 processes encounter some error, they don't show the exact +reason for clients. Instead they show: + +---%<------------------------------------------------------------------------- +Internal error occurred. Refer to server log for more information. [2006-01-07 +22:35:11] +---%<------------------------------------------------------------------------- + +The point is that whenever anything unexpected happens, Dovecot doesn't leak +any extra information about it to clients. They don't need it and they might +try to exploit it in some ways, so the less they know the better. + +The real error message is written to the error log file. The timestamp is meant +for you to help you find it. + +Changing Log File Paths +----------------------- + +If you don't want to use syslog, or if you just can't find the Dovecot's error +logs, you can make Dovecot log elsewhere as well: + +---%<------------------------------------------------------------------------- +log_path = /var/log/dovecot.log +# If you want everything in one file, just don't specify info_log_path and +debug_log_path +info_log_path = /var/log/dovecot-info.log +# Leave empty in order to send debug-level messages to info_log_path +debug_log_path = /var/log/dovecot-debug.log +---%<------------------------------------------------------------------------- + +The warning and error messages will go to file specified by 'log_path', while +informative messages goes to 'info_log_path' and debug messages goes to +'debug_log_path'. If you do this, make sure you're really looking at the +'log_path' file for error messages, since the "Starting up" message is written +to 'info_log_path' file. + +Syslog Example +-------------- + +Dovecot logging asynchronously via 'syslog_facility = local5' with basic rules: + +---%<------------------------------------------------------------------------- +local5.* -/var/log/dovecot.log +local5.info -/var/log/dovecot.info +local5.warn -/var/log/dovecot.warn +local5.err -/var/log/dovecot.err +:msg,contains,"stored mail into mailbox"\ + -/var/log/dovecot.lmtp +---%<------------------------------------------------------------------------- + +Rotating Logs +------------- + +If you change from syslog to an external log file, you can use logrotate +(available on most recent linux distros) to maintain the Dovecot logfile so it +doesn't grow beyond a manageable size. Save the below scriptlet as +'/etc/logrotate.d/dovecot': + +---%<------------------------------------------------------------------------- +/var/log/dovecot*.log { + weekly + rotate 4 + missingok + notifempty + compress + delaycompress + sharedscripts + postrotate + doveadm log reopen + endscript +} +---%<------------------------------------------------------------------------- + +*Note:* doveadm is not working properly with SELinux (e.g. doveadm cannot read +config file when called from logrotate context). SELinux safe postrotate +alternative scriplet: + +---%<------------------------------------------------------------------------- +postrotate + kill -s 0 `cat /var/run/dovecot/master.pid` || kill -s USR1 `cat +/var/run/dovecot/master.pid` +endscript +---%<------------------------------------------------------------------------- + +*Note 2:* When 'syslog_facility = local5' is used for logging (example above), +the line "/var/log/dovecot.log" should be added to the +'/etc/logrotate.d/syslog' file to enable rotation (no +'/etc/logrotate.d/dovecot' in this case!). + +Logging verbosity +----------------- + +There are several settings that control logging verbosity. By default they're +all disabled, but they may be useful for debugging. + + * 'auth_verbose=yes' enables logging all failed authentication attempts. + * 'auth_debug=yes' enables all authentication debug logging (also enables + 'auth_verbose'). Passwords are logged as '<hidden>'. + * 'auth_debug_passwords=yes' does everything that 'auth_debug=yes' does, but + it also removes password hiding (but only if you are not using PAM, since + PAM errors aren't written to Dovecot's own logs). + * 'mail_debug=yes' enables all kinds of mail related debug logging, such as + showing where Dovecot is looking for mails. + * 'verbose_ssl=yes' enables logging SSL errors and warnings. Even without this + setting if connection is closed because of an SSL error, the error is logged + as the disconnection reason. + * 'auth_verbose_passwords=no|plain|sha1' If authentication fails, this setting + logs the used password. If you don't really need to know what the password + itself was, but are more interested in knowing if the user is simply trying + to use the wrong password every single time or if it's a brute force attack, + you can set this to "sha1" and only the SHA1 of the password is logged. + That's enough to know if the password is same or different between login + attempts. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/LoginProcess.txt b/doc/wiki/LoginProcess.txt new file mode 100644 index 0000000..0918e1b --- /dev/null +++ b/doc/wiki/LoginProcess.txt @@ -0,0 +1,126 @@ +Login processes +=============== + +The main purpose of login processes is to handle the IMAP, POP3, +<Submission.txt> (v2.3), and <ManageSieve> [Pigeonhole.ManageSieve.txt] +connections before the user has logged in. The login processes don't need to be +able to do anything else than let the user log in, so they can run in highly +restricted environment. By default they are run as a non-privileged "dovenull" +user chrooted into a non-writable directory containing only authentication UNIX +sockets. + +Login processes also handle proxying the SSL and TLS connections even after the +user has logged in. This way all the SSL code runs in the same restricted +environment, which means that a security hole in the SSL library gives the +attacker access only to the restricted chroot, rather than possibly all the +users' mails. + +The default login settings should be good enough for small sites. There are two +ways to run the login processes: the high-security mode and the +high-performance mode. Both are discussed separately below. + +For explanation on the various settings for services, see <Services.txt> + +High-security mode +------------------ + +You can enable high-security mode with: + +---%<------------------------------------------------------------------------- +service imap-login { + service_count = 1 + #process_min_avail = 0 + #process_limit = $default_process_limit + #vsz_limit = 64M +} +service pop3-login { + service_count = 1 +} +---%<------------------------------------------------------------------------- + +This is the default. It works by using a new imap-login or pop3-login process +for each incoming connection. Since the processes run in a highly restricted +chroot, running each connection in a separate process means that in case there +is a security hole in Dovecot's pre-authentication code or in the SSL library, +the attacker can't see other users' connections and can't really do anything +destructive. The only way out of it is to find and exploit a kernel security +hole. + +Since one login process can handle only one connection, the service's +'process_limit' setting limits the number of users that can be logging in at +the same time (defaults to 'default_process_limit=100'). SSL/TLS proxying +processes are also counted here, so if you're using SSL/TLS you'll need to make +sure this count is higher than the maximum number of users that can be logged +in simultaneously. With TLS/SSL connections, the login process will not +terminate, and remains to perform proxying between imap backend process and the +client. + + * If the maximum login process count is reached, the oldest process in + logging-in state (ie. non-proxying) is destroyed. + * To avoid startup latency for new client connections, set 'process_min_avail' + to higher than zero. That many idling processes are always kept around + waiting for new connections. + * 'vsz_limit' should be fine at its default 64MB value. + +High-performance mode +--------------------- + +You can enable high-performance mode with: + +---%<------------------------------------------------------------------------- +service imap-login { + service_count = 0 + #client_limit = $default_client_limit + process_min_avail = 4 # number of CPU cores + vsz_limit = 1G +} +service pop3-login { + service_count = 0 +} +---%<------------------------------------------------------------------------- + +It works by using a number of long running login processes, each handling a +number of connections. This loses much of the security benefits of the login +process design, because in case of a security hole (in Dovecot or SSL library) +the attacker is now able to see other users logging in and steal their +passwords, read their mails, etc. + + * 'process_min_avail' should be set to be at least the number of CPU cores in + the system, so that all of them will be used. + * Otherwise new processes are created only once an existing one's connection + count reaches client_limit + * Default client_limit * process_limit = 1000*100 = 100k connections + * vsz_limit should be increased to avoid out of memory errors, especially if + you're using SSL/TLS. + +Login access check sockets +-------------------------- + +Dovecot login processes can check via UNIX socket if the incoming connection +should be allowed to log in. This is most importantly implemented to enable TCP +wrappers support for Dovecot. + +TCP wrappers support +-------------------- + +You must have built Dovecot with support for TCP wrappers. You can do this by +giving '--with-libwrap' parameter to 'configure'. + +Add to dovecot.conf: + +---%<------------------------------------------------------------------------- +login_access_sockets = tcpwrap + +service tcpwrap { + unix_listener login/tcpwrap { + group = $default_login_user + mode = 0600 + user = $default_login_user + } +} +---%<------------------------------------------------------------------------- + +Remember to configure your rules! The format is described in hosts.allow(5) and +hosts.deny(5). Files used are usually /etc/hosts.allow and /etc/hosts.deny. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MDA.txt b/doc/wiki/MDA.txt new file mode 100644 index 0000000..a4a0af3 --- /dev/null +++ b/doc/wiki/MDA.txt @@ -0,0 +1,17 @@ +MDA (LDA) +========= + +An MDA is a _M_ail _D_elivery _A_gent. + An LDA is a _L_ocal _D_elivery _A_gent. + These two terms are synonyms. + +An MDA is being passed messages from an <MTA.txt> and delivers it to a real or +virtual mailbox. + +Common choices include: + + * <maildrop.txt> + * procmail [http://www.procmail.org/] (appears to be unmaintained) + * <Dovecot's `deliver` LDA> [LDA.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MTA.txt b/doc/wiki/MTA.txt new file mode 100644 index 0000000..74722e4 --- /dev/null +++ b/doc/wiki/MTA.txt @@ -0,0 +1,54 @@ +MTA +=== + +MTA is an acronym for _M_ail _T_ransport _A_gent. It is the software that works +behind the scenes to transport E-Mail messages from one computer to another. +MUAs (such as mutt, thunderbird, sylpheed, evolution, kmail) hand off newly +sent messages to an MTA. MTAs talk to other MTAs, and either deliver mail +locally or hand it off for delivery to an <MDA/LDA> [MTA.txt] if it was +destined to the local system. + +MTA is a generic term and usually refers to one of these popular software +packages: + + * Postfix [http://www.postfix.org/] is Wietse Venema's secure, fast and + flexible mailer. Default on SUSE Linux and NetBSD. + * Exim [http://www.exim.org/] is Philip Hazel's flexible mailer. Default on + Debian GNU/Linux. + * Sendmail [http://www.sendmail.org/] the original BSD mailer. Default on + FreeBSD; a Sun spinoff is used on Solaris. + * Courier [http://www.courier-mta.org/] was inspired by qmail, but intends to + do things right. + * qmail [http://cr.yp.to/qmail.html] is an obsolete and unmaintained server. + Its POP3 part can be taken over by Dovecot. Qmail started off boasting about + speed and security in the mid-1990s, but has lots of unfixed bugs (this + document includes patches where known), + [http://home.pages.de/~mandree/qmail-bugs.html] among them security bugs + that remain unfixed, and the security guarantee (500 USD) denied. If you + really intend to continue using it, read Dave Sill's Life with qmail + [http://www.lifewithqmail.org/] which contains instructions to work around + some of qmail's security issues. + * HALON [https://halon.io/] is a commercial MTA, which supports Dovecot Auth + and LMTP. It's based on FreeBSD with anti-spam/virus, DKIM, DMARC, DANE, + etc. + +Some people also subsume mail fetching utilities under the MTA category, among +them: + + * fetchmail [http://www.fetchmail.info/] a fast mail retriever for the POP2, + POP3/KPOP/SDPS, IMAP2/IMAP4, ODMR and ETRN protocols, SSL and Kerberos + capable. It forwards the retrieved messages to SMTP/ESMTP, LMTP servers or + into an <LDA.txt>. Developed out of Carl Harris's popclient by Eric S. + Raymond. Fetchmail is now maintained by <MatthiasAndree.txt> and Rob F. + Funk. + * getmail [http://pyropus.ca/software/getmail/] a POP3/SDPS and IMAP4 (with + SSL) enabled mail retrieval utility written in Python. Developed by Chales + Cazabon. + +These mail fetching utilities can be used to store mail for later retrieval by +dovecot. + + Contrast this to the <message delivery agent (MDA)> [MDA.txt], sometimes +called local delivery agent (LDA). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.LocalDisk.txt b/doc/wiki/MailLocation.LocalDisk.txt new file mode 100644 index 0000000..4bd99fe --- /dev/null +++ b/doc/wiki/MailLocation.LocalDisk.txt @@ -0,0 +1,50 @@ +Mail storage in local disk +========================== + +Filesystems +----------- + + * See <MailboxFormat.Maildir.txt> for Maildir-specific filesystem + optimizations + * Dovecot doesn't rely on atime updates, so you can mount the filesystem with + noatime + +Index files +----------- + +Keeping index files on a different disk than the mail spool gives you better +performance. The indexes have a lot of write activity so it is recommended to +use RAID-10 instead of RAID-5 for them. + +Fsyncing +-------- + +By default Dovecot calls fsync() and fdatasync() whenever it's useful to +prevent potential data loss. The main reason for this is so that Dovecot won't +lie that the message was saved to the disk, if in fact a power failure a second +later would lose the message. With IMAP clients this is perhaps a less serious +problem, because the lost message was most likely either a mail in Draft +mailbox or a message in "Sent Messages" mailbox. In any case a message that the +user had already seen. However if <LDA.txt> loses a message, the user never +even knew that the message existed, unless the sender decides to resend it. + +Since power failures and kernel panics are quite rare, many people are tempted +to disable fsyncing because it may increase the performance quite a lot. +Dovecot allows this by setting 'mail_fsync=never'. However you should consider +leaving it at "optimized" for LDA and LMTP. You can do this with: + +---%<------------------------------------------------------------------------- +# Default to no fsyncing +mail_fsync = never + +protocol lda { + # Enable fsyncing for LDA + mail_fsync = optimized +} +protocol lmtp { + # Enable fsyncing for LMTP + mail_fsync = optimized +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.Maildir.txt b/doc/wiki/MailLocation.Maildir.txt new file mode 100644 index 0000000..4552cf8 --- /dev/null +++ b/doc/wiki/MailLocation.Maildir.txt @@ -0,0 +1,142 @@ +Maildir configuration +===================== + +See <MailboxFormat.Maildir.txt> for a complete description of how Dovecot has +implemented Maildir support. + +Mail location +------------- + +Maildir exists almost always in '~/Maildir' directory. The mail location is +specified with: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +---%<------------------------------------------------------------------------- + +Directory layout +---------------- + +By default Dovecot uses Maildir++ directory layout. This means that all +mailboxes are stored in a single directory and prefixed with a dot. For +example: + + * Maildir/.folder/ + * Maildir/.folder.subfolder/ + +If you want maildirs to use hierarchical directories, such as: + + * Maildir/folder/ + * Maildir/folder/subfolder/ + +you'll need to enable fs layout: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir:LAYOUT=fs +---%<------------------------------------------------------------------------- + +Control files +------------- + +Dovecot stores some Maildir metadata into two control files: + + * 'dovecot-uidlist' file contains IMAP UID <-> Maildir filename mapping + * 'dovecot-keywords' file contains Maildir filename flag (a..z = 0..25) <-> + keyword name mapping + +Both of these files are described fully in <MailboxFormat.Maildir.txt>. The +important thing to remember about them however is that they shouldn't be +treated the same way as index files. Index files can be deleted and rebuilt +without any side effects, but if you delete control files you'll cause messages +to get new UIDs and possibly lose keyword names. + +If the messages get new UIDs, the IMAP clients will invalidate their local +cache and download the messages all over again. If you do this for all the +users, you could cause huge disk I/O bursts to your server. + +Dovecot can't currently handle not being able to write the control files, so it +will cause problems with <filesystem quota> [Quota.FS.txt]. To avoid problems +with this, you should place control files into a partition where quota isn't +checked. You can specify this by adding ':CONTROL=<path>' to 'mail_location', +for example: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir:CONTROL=/var/no-quota/%u +---%<------------------------------------------------------------------------- + +Index files +----------- + +See <MailLocation#indexfiles> [MailLocation.txt] for full explanation of how to +change the index path. For example: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir:INDEX=/var/indexes/%u +---%<------------------------------------------------------------------------- + +Optimizations +------------- + + * 'maildir_very_dirty_syncs=yes': Assume that only Dovecot accesses 'cur/' + directory. If another process (or even Dovecot which doesn't update index + files) does changes to 'cur/' while the mailbox is simultaneously being + modified by Dovecot, Dovecot may not notice those external changes. It's + still safe to deliver new mails to 'new/' using non-Dovecot software (except + with 'mailbox_list_index=yes' changes aren't noticed outside INBOX). + * 'maildir_copy_with_hardlinks=yes' (default): When copying a message, do it + with hard links whenever possible. This makes the performance much better, + and it's unlikely to have any side effects. Only reason to disable this is + if you're using a filesystem where hard links are slow (e.g. HFS+). + * 'maildir_stat_dirs=no' (default): Assume that all the files beginning with a + dot in the maildir are maildirs. You shouldn't have any non-directory files + beginning with a dot in the maildirs, but if you do you may need to set this + to "yes", in which case Dovecot needs to stat() each directory entry, which + degrades the performance. Some filesystems provide the + directory/non-directory status for free without having to stat(). In those + filesystems this setting is ignored. + +Filesystem optimizations +------------------------ + +See <MailboxFormat/Maildir#Maildir_and_filesystems> +[MailboxFormat.Maildir.txt]. + +Mailbox directory name +---------------------- + +When using 'LAYOUT=fs', there is a potential for naming collisions between +Maildir's 'new/', 'cur/' and 'tmp/' subdirectories, and mail folders of the +same names. For example, consider a mail folder "foo/bar". Under 'LAYOUT=fs', +data for this mail folder will be stored at under Maildir's usual three +directories '~/Maildir/foo/bar/{new,cur,tmp}/'. + +If the user then tries to create a mail folder "foo/bar/new", this would then +imply that data should be stored in Maildir's three directories +'~/Maildir/foo/bar/new/{new,cur,tmp}/'. But this would overlap Maildir's 'new/' +subdirectory of mail folder "foo/bar". + +This may not be a problem in many installations, but if a risk of collisions +with Maildir's three subdirectory names is perceived, then the 'DIRNAME' +parameter can be used. For example, if we specify mail location as: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir:LAYOUT=fs:DIRNAME=mAildir +---%<------------------------------------------------------------------------- + +then this will push Maildir's 'new/', 'cur/' and 'tmp/' subdirectories down +into a subdirectory 'mAildir/', so a mail folder "foo/bar" would be stored at +'~/Maildir/foo/bar/mAildir/{new,cur,tmp}/'. A mail folder "foo/bar/new" would +be stored at '~/Maildir/foo/bar/new/mAildir/{new,cur,tmp}/', which would then +have no overlap with the mail folder "foo/bar". + +'DIRNAME' affects INBOX slightly differently. Without 'DIRNAME', INBOX will be +stored at '~/Maildir/{new,cur,tmp}/', but when 'DIRNAME' is specified, we get +an extra path component 'INBOX/' immediately prior to the 'DIRNAME' value, so +in the example above INBOX would be stored at +'~/Maildir/INBOX/mAildir/{new,cur,tmp}/'. + +The value for 'DIRNAME' should be chosen carefully so as to minimise the +chances of clashing with mail folder names. In the example here, unusual +upper/lower casing has been used. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.SharedDisk.txt b/doc/wiki/MailLocation.SharedDisk.txt new file mode 100644 index 0000000..528a663 --- /dev/null +++ b/doc/wiki/MailLocation.SharedDisk.txt @@ -0,0 +1,75 @@ +Mail storage on shared disks +============================ + +Dovecot supports keeping mails and index files in clustered filesystems, such +as Red Hat GFS [http://www.redhat.com/gfs/], Oracle OCFS2 +[http://oss.oracle.com/projects/ocfs2/] and HP Polyserve Matrix +[http://h18006.www1.hp.com/storage/software/clusteredfs/index.html]. + +Dovecot also supports keeping mails and index files on NFS. Everything +described in this page applies to NFS as well, but see <NFS.txt> for more +NFS-specific problems and optimizations. + +Memory mapping +-------------- + +By default Dovecot mmap()s the index files. This may not work with all +clustered filesystems, and it most certainly won't work with NFS. Setting +'mmap_disable = yes' disables mmap() and Dovecot does its own internal caching. +If mmap() is supported by your filesystem, it's still not certain that it gives +better performance. Try benchmarking to make sure. + +Locking +------- + +Dovecot supports locking index files with fcntl (default), flock or dotlocks. +Some clustered filesystems may not support fcntl, so you can change it to use +flock instead. Fcntl locks may also cause problems with some NFS +configurations, in which case you can try if switching to dotlocks helps. Note +that dotlocks are the slowest locking method. You can change the locking method +from 'lock_method' setting. Regardless of the 'lock_method' setting, Dovecot +always uses dotlocks for some locks. + +Clock synchronization +--------------------- + +Run ntpd in each computer to make sure their clocks are synchronized. If the +clocks are more than one second apart from each others and multiple computers +access the same mailbox simultaneously, you may get errors. + +Caching +------- + +Your cluster will probably perform better if users are usually redirected to +the same server. This is because the mailbox may already be cached in the +memory and it may also reduce the traffic between the clusterfs nodes. You can +use <director> [Director.txt] service to do this easily automatically. Or at +the very least make sure that your load balancer redirects connections from the +same IP address to the same server. + +FUSE / GlusterFS +---------------- + +FUSE caches dentries and file attributes internally. If you're using multiple +GlusterFS clients to access the same mailboxes, you're going to have problems. +Worst of these problems can be avoided by using NFS cache flushes, which just +happen to work with FUSE as well: + +---%<------------------------------------------------------------------------- +mail_nfs_index = yes +mail_nfs_storage = yes +---%<------------------------------------------------------------------------- + +These probably don't work perfectly. + +Samba / CIFS +------------ + +Dovecot's temporary files may include a colon character ':' in their filename, +which is not a permitted character when using cifs.Dovecot also renames the +temporary files whilst holding a lock in them, which generates the error 'Text +file is busy'. + +Cifs/smbfs is unlikely to work as a remote filesystem. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.dbox.txt b/doc/wiki/MailLocation.dbox.txt new file mode 100644 index 0000000..6ced4e3 --- /dev/null +++ b/doc/wiki/MailLocation.dbox.txt @@ -0,0 +1,88 @@ +dbox configuration +================== + +See <MailboxFormat.dbox.txt> for a description of the dbox mailbox format. +NOTE:*You must not lose the dbox index files, they can't be regenerated without +data loss*. + +Mail location +------------- + +dbox can be used in two ways: + + 1. One message per file (*single-dbox*), similar to <Maildir> + [MailboxFormat.Maildir.txt]. + 2. Multiple messages per file (*multi-dbox*), but unlike <mbox> + [MailboxFormat.mbox.txt] multiple files per mailbox. + +To use *single-dbox*, use the tag 'sdbox' in the <mail location> +[MailLocation.txt], for example: + +---%<------------------------------------------------------------------------- +# single-dbox +mail_location = sdbox:~/dbox +---%<------------------------------------------------------------------------- + +For backwards compatibility, 'dbox' is an alias to 'sdbox' in the mail +location. + +To use *multi-dbox*, use the tag 'mdbox' in the <mail location> +[MailLocation.txt], for example: + +---%<------------------------------------------------------------------------- +# multi-dbox +mail_location = mdbox:~/mdbox +---%<------------------------------------------------------------------------- + +Alternate storage +----------------- + +dbox has a feature for transparently moving message data to an <Alternate +storage> [MailboxFormat.dbox.txt] area. + +To specify an alternate storage area, use the 'ALT' parameter in the mail +location. For example, specifying the mail location as: + +---%<------------------------------------------------------------------------- +mail_location = mdbox:/var/vmail/%d/%n:ALT=/altstorage/vmail/%d/%n +---%<------------------------------------------------------------------------- + +will make Dovecot look for message data first under '/var/vmail/%d/%n', and if +it is not found there it will look under '/altstorage/vmail/%d/%n' instead. + +Keep the unmounted '/altstorage' directory permissions such that Dovecot mail +processes can't create directories under it (e.g. root:root 0755). This way if +the alt storage isn't mounted for some reason, Dovecot won't think that all the +messages in alt storage were deleted and lose their flags. + +Mailbox directory name +---------------------- + +When using the default hierarchical layout, there is a potential for naming +collisions between dbox's 'dbox-Mails/' subdirectory and mail folders of the +same name. For example, consider a mail folder "foo/bar". Under the default +hierarchical layout, data about this mail folder would be stored at +'~/mdbox/mailboxes/foo/bar/dbox-Mails/'. + +If the user then tried to create a mail folder "foo/bar/dbox-Mails", this would +then imply that data would be stored at +'~/mdbox/mailboxes/foo/bar/dbox-Mails/dbox-Mails/'. But this would overlap the +'dbox-Mails/' subdirectory of mail folder "foo/bar". + +This may not be a problem in many installations, but if a risk of collisions +with the default name "dbox-Mails" is perceived, then the 'DIRNAME' parameter +can be used. For example, if we specify mail location as: + +---%<------------------------------------------------------------------------- +mail_location = mdbox:~/mdbox:DIRNAME=DbOx-mAiLs +---%<------------------------------------------------------------------------- + +then this will make data for mail folders be stored in a subdirectory +'DbOx-mAiLs/' instead of the default 'dbox-Mails/', so a mail folder "foo/bar" +would have data stored at '~/mdbox/mailboxes/foo/bar/DbOx-mAiLs/'. + +The value for 'DIRNAME' should be chosen carefully so as to minimise the +chances of clashing with mail folder names. In the example here, unusual +upper/lower casing has been used. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.mbox.txt b/doc/wiki/MailLocation.mbox.txt new file mode 100644 index 0000000..98d6f73 --- /dev/null +++ b/doc/wiki/MailLocation.mbox.txt @@ -0,0 +1,194 @@ +mbox configuration +================== + +See <MailboxFormat.mbox.txt> for a complete description of how Dovecot has +implemented mbox support. + +Mail location +------------- + +In many systems the user's mails are by default stored in '/var/mail/username' +file. This file is called INBOX in IMAP world. Since IMAP supports multiple +mailboxes, you'll need to have a directory for them as well. Usually '~/mail' +is a good choice for this. For installation such as this, the mail location is +specified with: + +---%<------------------------------------------------------------------------- +# %u is replaced with the username that logs in +mail_location = mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +It's in no way a requirement to have the INBOX in '/var/mail/' directory. In +fact this often just brings problems because Dovecot might not be able to write +dotlock files to the directory (see below). You can avoid this completely by +just keeping everything in '~/mail/': + +---%<------------------------------------------------------------------------- +# INBOX exists in ~/mail/inbox +mail_location = mbox:~/mail +---%<------------------------------------------------------------------------- + +Index files +----------- + +See <MailLocation#indexfiles> [MailLocation.txt] for full explanation of how to +change the index path. For example: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u:INDEX=/var/indexes/%u +---%<------------------------------------------------------------------------- + +Locking +------- + +Make sure that all software accessing the mboxes are using the same locking +methods in the same order. The order is important to prevent deadlocking. From +Dovecot's side you can change these from 'mbox_read_locks' and +'mbox_write_locks' settings. See <MboxLocking.txt> for more information. + +/var/mail/ dotlocks +------------------- + +Often mbox write locks include dotlock, which means that Dovecot needs to +create a new "<mbox>.lock" file to the directory where the mbox file exists. If +your INBOXes are in '/var/mail/' directory you may have to give Dovecot write +access to the directory. There are two ways the '/var/mail/' directory's +permissions have traditionally been set up: + + * World-writable with sticky bit set, allowing anyone to create new files but + not overwrite or delete existing files owned by someone else (ie. same as + /tmp). You can do this with 'chmod a+rwxt /var/mail' + * Directory owned by a mail group and the directory set to group-writable + (mode=0770, group=mail) + +You can give Dovecot access to mail group by setting: + +---%<------------------------------------------------------------------------- +mail_privileged_group = mail +---%<------------------------------------------------------------------------- + +NOTE: With <LDA.txt> the 'mail_privileged_group' setting unfortunately doesn't +work, so you'll have to use the sticky bit, disable dotlocking completely or +use LMTP server instead. + +/var/mail/* permissions +----------------------- + +In some systems the '/var/mail/$USER' files have 0660 mode permissions. This +causes Dovecot to try to preserve the file's group, and if it doesn't have +permissions to do so, it'll fail with an error: + +---%<------------------------------------------------------------------------- +imap(user): Error: chown(/home/user/mail/.imap/INBOX, -1, 12(mail)) failed: +Operation not permitted (egid=1000(user), group based on /var/mail/user) +---%<------------------------------------------------------------------------- + +There is rarely any real need for the files to have 0660 mode, so the best +solution for this problem is to just change the mode to 0600: + +---%<------------------------------------------------------------------------- +chmod 0600 /var/mail/* +---%<------------------------------------------------------------------------- + +Optimizations +------------- + +The settings below are related to mbox performance. See +<MailboxFormat.mbox.txt> for more complete description of what they do. + + * 'mbox_lazy_writes=yes' (default): Metadata updates, such as writing X-UID + headers or flag changes, aren't written to mbox file until the mailbox is + closed or CHECK or EXPUNGE IMAP commands are sent by the client. The mbox + rewrites can be costly, so this may avoid a lot of disk writes. + * 'mbox_dirty_syncs=yes' (default): Dovecot assumes that external mbox file + changes only mean that new messages were appended to it. Without this + setting Dovecot re-reads the whole mbox file whenever it changes. There are + various safeguards in place to make this setting safe even when other + changes than appends were done to the mbox. The only downside to this + setting is that external message flag modifications may not be visible + immediately. + * 'mbox_very_dirty_syncs=yes' (not default): When opening mbox file that has + been changed externally, don't re-read it. Otherwise similar to + 'mbox_dirty_syncs=yes'. + * 'mbox_min_index_size=n': If mbox file is smaller than n kilobytes, don't + update its index files. If an index file exists for it, it's still read + however. + +Only /var/mail/ mboxes +---------------------- + +With POP3 it's been traditional that users have their mails only in the +'/var/mail/' directory. IMAP however supports having multiple mailboxes, so +each user has to have a private directory where the mailboxes are stored. +Dovecot also needs a directory for its index files unless you disable them +completely. + +If you *really* want to use Dovecot as a plain POP3 server without index files, +you can work around the problem of not having the per-user directory: + + * Set users' home directory in userdb to some empty non-writable directory, + for example '/var/empty' + * Modify 'mail_location' setting so that the mail root directory is also the + empty directory and append ':INDEX=MEMORY' to it. For example: + 'mail_location = mbox:/var/empty:INBOX=/var/mail/%u:INDEX=MEMORY' + * Note that if you have IMAP users, they'll see the '/var/empty' as the + directory containing other mailboxes than INBOX. If the directory is + writable, all the users will have their mailboxes shared. + +Directory layout +---------------- + +By default Dovecot uses filesystem layout under mbox. This means that mail is +stored in mbox files under hierarchical directories, for example: + + * '~/mail/inbox' - mbox file containing mail for INBOX + * '~/mail/foo' - mbox file containing mail for mailbox "foo" + * '~/mail/bar/baz' - mbox file containing mail for mailbox "bar/baz" + +One upshot of this is that it is not normally possible to have mailboxes which +are subfolders of mailboxes containing messages. + +As an alternative, it is possible to configure Dovecot to store all mailboxes +in a single directory with hierarchical levels separated by a dot. This can be +configured by adding ':LAYOUT=maildir++' to the mail location. There are, +however, some further considerations when doing this; see +<MboxChildFolders.txt> for some examples. + +Control files +------------- + +Under mbox format, Dovecot maintains the subscribed mailboxes list in a file +'.subscriptions' which by default is stored in the mail location root. So in +the example configuration this would be at '~/mail/.subscriptions'. + +If you want to put this somewhere else, you can change the directory in which +the '.subscriptions' file is kept by using the 'CONTROL' parameter. So for +example, if we configured the mail location using: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:CONTROL=~/mail-control +---%<------------------------------------------------------------------------- + +then the subscribed mailboxes list would be maintained at +'~/mail-control/.subscriptions'. + +One practical application of the 'CONTROL' parameter is described at +<MboxChildFolders.txt>. + +Message file name +----------------- + +By default, Dovecot stores messages for INBOX in an mbox file called "inbox", +and messages for all other mailboxes in an mbox file whose relative path is +equivalent to the name of the mailbox. Under this scheme, it is not possible to +have mailboxes which contain both messages and child mailboxes. + +However, the behaviour (for mailboxes other than INBOX) can be changed using +the 'DIRNAME' parameter. If the 'DIRNAME' parameter is specified with a +particular value, then Dovecot will store messages in a file with a name of +that value, in a directory with a name equivalent to the mailbox name. + +There are, however, some further considerations when doing this; see +<MboxChildFolders.txt> for an example. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailLocation.txt b/doc/wiki/MailLocation.txt new file mode 100644 index 0000000..eb0942b --- /dev/null +++ b/doc/wiki/MailLocation.txt @@ -0,0 +1,343 @@ +Mail location +============= + + * For mbox-specific settings, see <MailLocation.mbox.txt> + * For Maildir-specific settings, see <MailLocation.Maildir.txt> + * For dbox-specific settings, see <MailLocation.dbox.txt> + +There are three different places where the mail location is looked up from: + + 1. 'mail_location' setting in 'dovecot.conf' is used if nothing else overrides + it. + 2. 'mail' <userdb field> [UserDatabase.txt] overrides 'mail_location' setting. + + 3. 'location' setting inside namespaces overrides everything. Usually this + should be used only for public and shared namespaces. + +Autodetection +------------- + +By default the 'mail_location' setting is empty, which means that Dovecot +attempts to locate automatically where your mails are. This is done by looking, +in order, at: + + * '~/mdbox/' + * '~/sdbox/' + * '~/Maildir/' + * '~/mail/.imap/' + * '~/mail/inbox' + * '~/mail/mbox' + * '~/Mail/.imap/' + * '~/Mail/inbox' + * '~/Mail/mbox' + +For autodetection to work, one of the above locations has to be populated; when +autodetection is active, Dovecot will not attempt to create a mail folder. Note +that '.imap' is a directory, and 'inbox' and 'mbox' are files. + +It's usually a good idea to explicitly specify where the mails are, even if the +autodetection happens to work, in particular to benefit from auto-creation of +the folder for new users. + +Mailbox autocreation +-------------------- + +Dovecot in the 1.x era created mailboxes automatically regardless of whether +mail_location was set. In 2.x autocreation only gets triggered if mail_location +is correctly set. You'll see something like this if you enable debug logging: + +---%<------------------------------------------------------------------------- +Debug: Namespace : /home/user/Mail doesn't exist yet, using default permissions +Debug: Namespace : Using permissions from /home/user/Mail: mode=0700 +gid=default +---%<------------------------------------------------------------------------- + +and a 'Mail/.imap' directory will be present once that process has concluded. +This is the easiest way to ensure a freshly created user is correctly set up +for access via Dovecot. + +Format +------ + +The format of the mailbox location specification is as follows: + + * / <mailbox-format> [MailboxFormat.txt]/ : /path/ [ : /key/ = /value/ … ] + +where: + + * /mailbox-format/ is a tag identifying one of the formats described at + <Mailbox Formats> [MailboxFormat.txt]. + * /path/ is the path to a directory where the mail is stored. This must be an + absolute path, not a relative path. Even if relative paths appear to work, + this usage is deprecated and will likely stop working at some point. Do not + use the home directory, for reasons see <Home vs. mail directory> + [VirtualUsers.Home.txt] + * /key/ = /value/ can appear zero or more times to set various optional + parameters. Possible values for /key/ are: + * 'INDEX' : specifies the location of <index files> [MailLocation.txt]. + * 'ITERINDEX' : Perform mailbox listing using the INDEX directories + instead of the mail root directories. Mainly useful when the INDEX + storage is on a faster storage. It takes no value. (v2.2.32+) + * 'INBOX' : specifies the location of the <INBOX> [MailLocation.txt]. + * 'LAYOUT' : specifies the directory layout to use: + * Maildir++: The default used by Maildir format + * fs: The default used by mbox and dbox formats + * index: Uses mailbox GUIDs as the directory names. The mapping between + mailbox names and GUIDs exists in dovecot.list.index* files. + * 'NO-NOSELECT' : Automatically delete any \ <NoSelect.txt> mailboxes that + have no children. These mailboxes are sometimes confusing to users. Also + if a \ <NoSelect.txt> mailbox is attempted to be created with "CREATE + box/", it's created as selectable mailbox instead. (LAYOUT=Maildir++ + always behaves this same way.) (v2.2.32+) + * 'UTF-8' : Store mailbox names on disk using UTF-8 instead of modified + UTF-7. + * 'BROKENCHAR' : Specifies an escape character that is used for broken + mailbox names. If mailbox name can't be changed reversibly to UTF-8 and + back, encode the problematic parts using<broken_char><hex> in the + user-visible UTF-8 name. The broken_char itself also has to be encoded + the same way. This can be useful with imapc to access mailbox names that + aren't valid mUTF-7 charset from remote servers. (v2.2.32+) + * 'CONTROL' : Specifies the location of control files under the <mbox> + [MailLocation.mbox.txt] or <Maildir> [MailLocation.Maildir.txt] formats. + * 'VOLATILEDIR' : Specifies the location of volatile files. This includes + lock files and potentially other files that don't need to exist + permanently. This is especially useful to avoid creating lock files to + NFS or other remote filesystems. (v2.2.32+) + * 'SUBSCRIPTIONS' : specifies the file used for storing subscriptions. The + default is "subscriptions". If you're trying to avoid name collisions + with a mailbox named "subscriptions", then also consider setting + 'MAILBOXDIR'. + * 'MAILBOXDIR' : specifies directory name under which all mailbox + directories are stored. With <dbox formats> [MailboxFormat.dbox.txt] the + default is "mailboxes/" while with other mailbox formats the default is + empty. Typically this should be changed only for <lazy_expunge namespace> + [Plugins.Lazyexpunge.txt] with mdbox. + * 'DIRNAME' : specifies the directory name used for mailbox directories, or + in the case of mbox specifies the mailbox message file name. With <dbox + formats> [MailboxFormat.dbox.txt] the default is "dbox-Mails/" while with + other mailbox formats the default is empty. Can be used under either + <mbox> [MailLocation.mbox.txt], <Maildir> [MailLocation.Maildir.txt] or + <dbox> [MailLocation.dbox.txt] formats. Note that this directory is used + only for the mail directory and the alt directory, not for index/control + directories (but see below). + * 'FULLDIRNAME' : Same as 'DIRNAME', but use the directory name also for + index and control directory paths. This should be used instead of + 'DIRNAME' for new installations. (v2.2.8+) + * 'ALT' : specifies the <Alternate storage> [MailLocation.dbox.txt] path + for dbox formats. + * The colons and equals signs are literal and there are no spaces in an actual + mailbox location specification. + +Variables +--------- + +You can use several variables in the 'mail_location' setting. See +<Variables.txt> for a full list, but the most commonly used ones are: + + * '%u': Full username. + * '%n': User part in user@domain, same as %u if there's no domain. + * '%d': Domain part in user@domain, empty if there's no domain. + +Typical settings +---------------- + +Typically with Maildir it would be set to: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +---%<------------------------------------------------------------------------- + +with mbox: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +or if you'd like to use the <dbox> [MailboxFormat.dbox.txt] format: + +---%<------------------------------------------------------------------------- +# single-dbox +mail_location = sdbox:~/dbox +---%<------------------------------------------------------------------------- + +or: + +---%<------------------------------------------------------------------------- +# multi-dbox +mail_location = mdbox:~/mdbox +---%<------------------------------------------------------------------------- + +Use only absolute paths. Even if relative paths would appear to work, they +might just as well break some day. + +Directory hashing +----------------- + +You can use two different kinds of hashes in <variables> [Variables.txt]: + + * %H modifiers returns a 32bit hash of the given string as hex. For example + '%2.256H' would return max. 256 different hashes in range 00 .. ff. + * %M returns a MD5 hash of the string as hex. This can be used for two level + hashing by getting substrings of the MD5 hash. For example '%1Mu/%2.1Mu/%u' + returns directories from '0/0/user' to 'f/f/user'. + +Index files +----------- + +Index files are by default stored under the same directory as mails. With +maildir they are stored in the actual maildirs, with mbox they are stored under +'.imap/' directory. You may want to change the index file location if you're +using <NFS.txt> or if you're setting up <shared mailboxes> +[SharedMailboxes.txt]. + +You can change the index file location by adding ':INDEX=<path>' to +mail_location. For example: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir:INDEX=/var/indexes/%u +---%<------------------------------------------------------------------------- + +The index directories are created automatically, but note that it requires that +Dovecot has actually access to create the directories. Either make sure that +the index root directory ('/var/indexes' in the above example) is writable to +the logged in user, or create the user's directory with proper permissions +before the user logs in. + +If you really want to, you can also disable the index files completely by +appending ':INDEX=MEMORY'. + +Private index files (v2.2+) +--------------------------- + +Since v2.2 the recommended way to enable private flags for shared mailboxes is +to create private indexes with :INDEXPVT=<path>. See +<SharedMailboxes.Public.txt> for more information. + +INBOX path +---------- + +INBOX path can be specified to exist elsewhere than the rest of the mailboxes, +for example: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u +mail_location = maildir:~/Maildir:INBOX=~/Maildir/.INBOX +---%<------------------------------------------------------------------------- + +Note that it's still not possible to mix maildir and mbox formats this way. You +need to use <namespaces> [Namespaces.txt] for that. + +Homeless users +-------------- + +Having a home directory for users is highly recommended. The <Pigeonhole.txt> +<Sieve plugin> [Pigeonhole.Sieve.txt] already requires a home directory to +work, and it probably won't be the last feature to require a home. See +<VirtualUsers#homedirs> [VirtualUsers.txt] for more reasons why it's a good +idea, and how to give Dovecot a home directory even if you don't have a "real +home directory". + +If you really don't want to set any home directory, you can use something like: + +---%<------------------------------------------------------------------------- +mail_location = maildir:/home/%u/Maildir +---%<------------------------------------------------------------------------- + +Per-user mail locations +----------------------- + +It's possible to override the default 'mail_location' for specific users by +making the <user database> [UserDatabase.txt] return 'mail' <extra field> +[UserDatabase.ExtraFields.txt]. See the <user database> [UserDatabase.txt] page +for the specific userdb you're using for more information how to do this. +Below are however a couple of examples. + +Note that %h doesn't work in the userdb queries or templates. ~/ gets expanded +later, so use it instead. + +Note also that since 'location' specified within a <namespace> [Namespaces.txt] +overrides mail_location setting, in case you specified that parameter, you'll +have to override in in the user database, specifying 'namespace/inbox/location' +extra field instead of 'mail'. + +SQL +--- + +---%<------------------------------------------------------------------------- +user_query = SELECT home, uid, gid, mail FROM users WHERE user = '%u' +---%<------------------------------------------------------------------------- + +LDAP +---- + +---%<------------------------------------------------------------------------- +user_attrs = homeDirectory=home, uidNumber=uid, gidNumber=gid, +mailLocation=mail +---%<------------------------------------------------------------------------- + +Passwd-file +----------- + +---%<------------------------------------------------------------------------- +user:{PLAIN}password:1000:1000::/home/user::userdb_mail=mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +Mixing mbox and maildir +----------------------- + +It's possible to use both mboxes and maildirs for the same user by configuring +multiple namespaces. See <Namespaces.txt>. + +Having both mboxes and maildirs mixed within the same namespace isn't currently +supported. + +Custom mailbox location detection +--------------------------------- + +Dovecot by default detects the mailboxes in this order: + + 1. maildir: ~/Maildir + 2. mbox: ~/mail, and /var/mail/%u if it exists + 3. mbox: ~/Mail, and /var/mail/%u if it exists + +If you need something else, you can override the 'mail_executable' setting to +run a script, which sets the MAIL environment properly. For example: + +---%<------------------------------------------------------------------------- +#!/bin/sh + +if [ -d $HOME/.maildir ]; then + export MAIL=maildir:$HOME/.maildir +else + export MAIL=mbox:$HOME/mail:INBOX=/var/mail/$USER +fi +export USERDB_KEYS="$USERDB_KEYS mail" + +exec "$@" +---%<------------------------------------------------------------------------- + +Custom namespace location +------------------------- + +If you need to override namespace's location, first give it a name ("inbox" +below): + +---%<------------------------------------------------------------------------- +namespace inbox { + .. +} +---%<------------------------------------------------------------------------- + +Then in the script use: + +---%<------------------------------------------------------------------------- +#!/bin/sh + +# do the lookup here +location=mbox:$HOME/mail + +export USERDB_KEYS="$USERDB_KEYS namespace/inbox/location" +exec env "NAMESPACE/INBOX/LOCATION=$location" "$@" +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.Cydir.txt b/doc/wiki/MailboxFormat.Cydir.txt new file mode 100644 index 0000000..9882bbf --- /dev/null +++ b/doc/wiki/MailboxFormat.Cydir.txt @@ -0,0 +1,20 @@ +Cydir +===== + +This mailbox format is very similar to Cyrus IMAP's internal mail store: + + * Messages are stored in "<uid>." named files + * Cyrus's 'cyrus.index' is equivalent to Dovecot's 'dovecot.index'. Dovecot + however also requires 'dovecot.index.log' for its indexing to work. + * Cyrus's 'cyrus.cache' is equivalent to Dovecot's 'dovecot.index.cache'. + +Cydir is a very simple format internally. It relies on Dovecot's <index files> +[IndexFiles.txt] completely for its functionality. If the index files are lost, +all the message flags are lost. Currently the code can't even rebuild index +files if they're lost. + +Cydir is mostly meant to be used for benchmarking and stress testing index +handling code. Its code is small and simple, so it can also act as an example +for writing new mail storage backends. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.MH.txt b/doc/wiki/MailboxFormat.MH.txt new file mode 100644 index 0000000..cbe7190 --- /dev/null +++ b/doc/wiki/MailboxFormat.MH.txt @@ -0,0 +1,52 @@ +MH Mailbox Format +================= + +The MH mailbox format originated with a system developed by the RAND +corporation and the University of California. Each email message is stored in +a single file, with directories indicating folders and subfolders. The index +or order of the messages in the folder determine what each message is named +(which may not correspond to the inode index). The "safe" way to guarantee a +message gets written to a mail folder is to first write the message out to a +randomly chosen temporary file name, then link the file to the number LAST+1, +where LAST is the last sequential message in the folder. If the link fails, +increment the counter and try again. + +MH folders also maintains a meta-file called '~/Mail/.mh_context' that contains +information about the most current folder and message chosen. Each sub-folder +also contains a meta-file called '.mh_sequences' or '.xmhcache', which +maintains keyword association lists for stored queries. New messages are +stored in the "unseen" sequence for a folder. Procmail itself does not bother +making changes to this file, rather simply delivers the message to the folder +and leaves determining new messages as an exercise for the MUA. For example: + +---%<------------------------------------------------------------------------- +unseen: 1-3 8 15 +projectB: 2-8 10 +---%<------------------------------------------------------------------------- + +shows two stored sequences of messages. Command-line utilities can then use +these sequences as shortcuts.'show unseen', for example, is short-hand for +'show 1-3 8 15'. + +Deleted emails are indicated by prepending a "," to the name. One of the +largest problems that IMAP servers have with MH format is the volatility of the +email message name itself. The command-line utility 'sortm' is used to sort +mail folders by date or string matching. To do this, messages are actually +renamed to reflect the new sort order. IMAP servers are required to maintain +an index of the folder contents, so when the names of the file entries cannot +be guaranteed to be stable, IMAP servers have to throw out previous index +caches and re-index. + +When operating with a shell account on a machine that also provides IMAP access +to folders, users are encouraged not to re-sort email locally while accessing +the IMAP server remotely. + +Links + + * NMH [http://www.nongnu.org/nmh/]: New MH Client + * Original RAND MH [http://rand-mh.sourceforge.net] Code + * MH-Book [http://rand-mh.sourceforge.net/book/] + * Mutt Manual [http://www.mutt.org/doc/manual/manual-4.html#ss4.6]: Describing + how it handles MH folders + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.Maildir.txt b/doc/wiki/MailboxFormat.Maildir.txt new file mode 100644 index 0000000..5629b7d --- /dev/null +++ b/doc/wiki/MailboxFormat.Maildir.txt @@ -0,0 +1,400 @@ +Maildir +======= + +This format debuted with the qmail server in the mid-1990s. Each mailbox folder +is a directory and each message a file. This improves efficiency because +individual emails can be modified, deleted and added without affecting the +mailbox or other emails, and makes it safer to use on networked file systems +such as NFS. + +Dovecot extensions +------------------ + +Since the standard maildir specification [https://cr.yp.to/proto/maildir.html] +doesn't provide everything needed to fully support the IMAP protocol, Dovecot +had to create some of its own non-standard extensions. The extensions still +keep the maildir standards compliant, so MUAs not supporting the extensions can +still safely use it as a normal maildir. + +IMAP UID mapping +---------------- + +IMAP requires each message to have a permanent unique ID number. Dovecot uses +'dovecot-uidlist' file to keep UID <-> filename mapping. The file is basically +in the same format as Courier IMAP's courierimapuiddb file, except for one +difference (see below). + +The file begins with a header: + +---%<------------------------------------------------------------------------- +3 V1275660208 N25022 G3085f01b7f11094c501100008c4a11c1 +---%<------------------------------------------------------------------------- + + * 3 is the file format version number used by Dovecot v1.1+ + * 1275660208 is the IMAP UIDVALIDITY + * 25022 is the UID that will be given to the next added message + * 3085f01b7f11094c501100008c4a11c1 is the 128 bit mailbox global UID in hex + * There may be other fields, and the order of these fields isn't important + +Version 1 file format is compatible with Courier. Version 2 was used by a few +non-release versions. + +After the header comes the list of UID <-> filename mappings: + +---%<------------------------------------------------------------------------- +25006 :1276528487.M364837P9451.kurkku,S=1355,W=1394:2, +25017 W2481 :1276533073.M242911P3632.kurkku:2,F +---%<------------------------------------------------------------------------- + + * 25006, 25017 are message UIDs + * 2481 is the second message's virtual size. First message contains it in the + filename itself, so it's not duplicated. + * There may be more fields before ':' character + * Rest of the line after ':' is the last known filename. This filename doesn't + necessarily exist currently, because filename changes every time message's + flags change. Dovecot doesn't waste disk I/O by rewriting uidlist file every + time flags change, but whenever it is rewritten the latest filenames are + used. This allows Dovecot to try to guess what the message's current + filename is and if successful, avoid having to scan the directory's + contents. + +The dovecot-uidlist file doesn't need to be locked for reading. When writing +dovecot-uidlist.lock file needs to be created. New lines can be appended to the +end of file, but existing data must never be directly modified, it can only be +replaced with rename() call. + +dovecot-uidlist is updated lazily to optimize for disk I/O. If a message is +expunged, it may not be removed from dovecot-uidlist until sometimes later. +This means that if you create a new file using the same file name as what +already exists in dovecot-uidlist, Dovecot thinks you "unexpunged" message by +restoring a message from backup. This causes a warning to be logged and the +file to be renamed. + +Note that messages must not be modified once they've been delivered. IMAP (and +Dovecot) requires that messages are immutable. If you wish to modify them in +any way, create a new message instead and expunge the old one. + +IMAP keywords +------------- + +All the non-standard message flags are called keywords in IMAP. Some clients +use these automatically for marking spam (eg. $Junk, $NonJunk, $Spam, $NonSpam +keywords). Thunderbird uses labels which map to keywords $Label1, $Label2, etc. + +Dovecot stores keywords in the maildir filename's flags field using letters +a..z. This means that only 26 keywords are possible to store in the maildir. If +more are used, they're still stored in Dovecot's index files. The mapping from +single letters to keyword names is stored in dovecot-keywords file. The file is +in format: + +---%<------------------------------------------------------------------------- +0 $Junk +1 $NonJunk +---%<------------------------------------------------------------------------- + +0 means letter 'a' in the maildir filename, 1 means 'b' and so on. The file +doesn't need to be locked for reading, but when writing dovecot-uidlist file +must be locked. The file must not be directly modified, it can only be replaced +with rename() call. + +For example, a file named + +---%<------------------------------------------------------------------------- +1234567890.M20046P2137.mailserver,S=4542,W=4642:2,Sb +---%<------------------------------------------------------------------------- + +would be flagged as '$NonJunk' with the above keywords. + +Maildir filename extensions +--------------------------- + +The standard filename definition is: "<base filename>:2,<flags>". Dovecot has +extended the<flags> field to be "<flags>[,<non-standard fields>]". This means +that if Dovecot sees a comma in the<flags> field while updating flags in the +filename, it doesn't touch anything after the comma. However other maildir MUAs +may mess them up, so it's still not such a good idea to do that. Basic<flags> +are described here [https://cr.yp.to/proto/maildir.html]. The <non-standard +fields> isn't used by Dovecot for anything currently. + +Dovecot supports reading a few fields from the <base filename>: + + * ',S=<size>': <size> contains the file size. Getting the size from the + filename avoids doing a stat(), which may improve the performance. This is + especially useful with <Maildir++ quota> [Quota.Maildir.txt]. + * ',W=<vsize>': <vsize> contains the file's RFC822.SIZE, ie. the file size + with linefeeds being CR+LF characters. If the message was stored with CR+LF + linefeeds,<size> and <vsize> are the same. Setting this may give a small + speedup because now Dovecot doesn't need to calculate the size itself. + +A maildir filename with those fields would look something like: +'1035478339.27041_118.foo.org,S=1000,W=1030:2,S' + +Usage of timestamps +------------------- + +Timestamps of message files: + + * 'mtime' is used as IMAP INTERNALDATE, RFC 3501 sec 2.3.3. + [https://www.faqs.org/rfcs/rfc3501.html], must never change, see sec. + 2.3.1.1. 4) + * 'ctime' used as Dovecot's internal "save/copy date", unless the correct + value is found from 'dovecot.index.cache'. This is used only by external + commands, e.g. "doveadm expunge savedbefore". + * 'atime' not used + +Timestamps of 'cur' and 'new' directories: + + * 'mtime' is used to detect changes of the mailbox and may force regeneration + of <index files> [IndexFiles.txt] + * 'atime' and 'ctime' not used + +Filename examples +----------------- + ++---------------------------------------------------------------------------------------------+----------------------------+ +| Filename | Explanation | ++---------------------------------------------------------------------------------------------+----------------------------+ +| *1491941793*.M41850P8566V0000000000000015I0000000004F3030E_0.mx1.example.com,S=10956:2,STln | UNIX timestamp of arrival | ++---------------------------------------------------------------------------------------------+----------------------------+ +| 1491941793.M41850P8566V0000000000000015I0000000004F3030E_0.mx1.example.com,*S=10956*:2,STln | Size of e-mail | ++---------------------------------------------------------------------------------------------+----------------------------+ +| 1491941793.M41850P8566V0000000000000015I0000000004F3030E_0.mx1.example.com,S=10956:2,*STln* | *S*=seen (marked as read) | +| | *T*=trashed | +| | *l*=IMAP tag #12 (0=a, 1=b,| +| | 2=c, etc) as defined in | +| | that folder's | +| | dovecot-keywords. | +| | *n*=IMAP tag #14 (0=a, 1=b,| +| | 2=c, etc) as defined in | +| | that folder's | +| | dovecot-keywords. | ++---------------------------------------------------------------------------------------------+----------------------------+ + +Maildir and filesystems +----------------------- + +General comparisons of Maildir on different filesystems +------------------------------------------------------- + + * https://www.thesmbexchange.com/eng/qmail_fs_benchmark.html + * https://www.htiweb.inf.br/benchmark/fsbench.htm (including some graphs) + +Linux ext2 / ext3 +----------------- + +The main disadvantage is that searching can be slightly slower, and access to +very large mailboxes (thousands of messages) can get slow with filesystems +which don't have directory indexes. + +Old versions of ext2 and ext3 on Linux don't support directory indexing (to +speed up access), but newer versions of ext3 do, although you may have to +manually enable it. You can check if the indexing is already enabled with +tune2fs: + +---%<------------------------------------------------------------------------- +tune2fs -l /dev/hda3 | grep features +---%<------------------------------------------------------------------------- + +If you see dir_index, you're all set. If dir_index is missing, add it using: + +---%<------------------------------------------------------------------------- +umount /dev/hda3 +tune2fs -O dir_index /dev/hda3 +e2fsck -fD /dev/hda3 +mount /dev/hda3 +---%<------------------------------------------------------------------------- + +ReiserFS +-------- + +ReiserFS was built to be fast with lots of small files, so it works well with +maildir. + +XFS +--- + +XFS performance seems to depend on a lot of factors, also on the system and the +file system parameters. + + * There are early reports on the dovecot mailing list which suggest that XFS + seems quite a lot slower than ext3 or + ReiserFS:https://dovecot.org/list/dovecot/2007-January/018994.html + * But then again others recommend XFS for the use with Maildir and dovecot: + https://dovecot.org/list/dovecot/2006-May/013216.html + * This 2007 Linux.conf.au talk about "Choosing and Tuning Linux File Systems" + (Slides as PDF) + [https://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/348.pdf] + also recommends XFS for Maildir (alternatively ext3 with small blocks and + high inodetofile ratio) + * Someone else wrote here in the wiki: XFS on TSL 3.0.5 works almost twice as + fast as our prior EXT3 installation of which is significant in size. + ReiserFS is also a good option. + * Comparisons which suggest XFS as being best choice: + * https://www.thesmbexchange.com/eng/qmail_fs_benchmark.html + * https://www.htiweb.inf.br/benchmark/fsbench.htm + +Various tips +------------ + + * Mounting XFS with 'logbufs=8' option might increase the speed. + * Create the XFS with options '-b size=1024 -d su=16k,sw=3 -l + logdev=<some_other_device>' (Source: + https://www.thesmbexchange.com/eng/qmail_fs_benchmark.html) + * Use 'mkfs.xfs -f -l size=32768b,version=2' and 'mount.xfs -o + noatime,logbufs=8,logbsize=131072' (Source: + https://www.htiweb.inf.br/benchmark/fsbench.htm) + +NFS +--- + +NFS v3 performance can be adversely affected by readdirplus, which causes the +NFS server to stat() every file in a directory. The solution under Linux is to +make sure the NFS filesystem is mounted with the "nordirplus" option. + + * https://dovecot.org/list/dovecot/2012-July/066939.html + +Directory Structure +------------------- + +By default Dovecot uses Maildir++ +[https://www.courier-mta.org/imap/README.maildirquota.html] directory layout +for organizing mailbox directories. This means that all the folders are +directly inside '~/Maildir' directory: + + * '~/Maildir/new', '~/Maildir/cur' and '~/Maildir/tmp' directories contain the + messages for INBOX. The 'tmp' directory is used during delivery, new + messages arrive in 'new' and read shall be moved to 'cur' by the clients. + * '~/Maildir/.folder/' is a mailbox folder + * '~/Maildir/.folder.subfolder/' is a subfolder of a folder (ie. + "folder/subfolder") + +You can also optionally use the "fs" layout by appending ':LAYOUT=fs' to +<mail_location> [MailLocation.txt]. This makes the folder structure look like: + + * '~/Maildir/new', '~/Maildir/cur' and '~/Maildir/tmp' directories contain the + messages for INBOX, just like with Maildir++. + * '~/Maildir/folder/' is a mailbox folder + * '~/Maildir/folder/subfolder/' is a subfolder of a folder + +Filesystem permissions +---------------------- + +See <SharedMailboxes.Permissions.txt> for how permissions are set for newly +created files and directories. + +Since Dovecot v2.0 "Permissions for newly created mail files are no longer +copied from dovecot-shared file", see <Upgrading.2.0.txt>. + +Issues with the specification +----------------------------- + +Locking +------- + +Although maildir was designed to be lockless, Dovecot locks the maildir while +doing modifications to it or while looking for new messages in it. This is +required because otherwise Dovecot might temporarily see mails incorrectly +deleted, which would cause trouble. Basically the problem is that if one +process modifies the maildir (eg. a rename() to change a message's flag), +another process in the middle of listing files at the same time could skip a +file. The skipping happens because readdir() system call doesn't guarantee that +all the files are returned if the directory is modified between the calls to +it. This problem exists with all the commonly used filesystems. + +Because Dovecot uses its own non-standard locking ('dovecot-uidlist.lock' +dotlock file), other MUAs accessing the maildir don't support it. This means +that if another MUA is updating messages' flags or expunging messages, Dovecot +might temporarily lose some message. After the next sync when it finds it +again, an error message may be written to log and the message will receive a +new UID. + +Delivering mails to new/ directory doesn't have any problems, so there's no +need for LDAs to support any type of locking. + +Mail delivery +------------- + +Qmail's how a message is delivered page +[https://www.qmail.org/man/man5/maildir.html] suggests to deliver the mail like +this: + + 1. Create a unique filename (only "time.pid.host" here, later Maildir spec has + been updated to allow more uniqueness identifiers) + 2. Do 'stat(tmp/<filename>)'. If the 'stat()' found a file, wait 2 seconds and + go back to step 1. + 3. Create and write the message to the 'tmp/<filename>'. + 4. link() it into new/ directory. Although not mentioned here, the link() + could again fail if the mail existed in new/ dir. In that case you should + probably go back to step 1. + +All this trouble is rather pointless. Only the first step is what really +guarantees that the mails won't get overwritten, the rest just sounds nice. +Even though they might catch a problem once in a while, they give no guaranteed +protection and will just as easily pass duplicate filenames through and +overwrite existing mails. + +Step 2 is pointless because there's a race condition between steps 2 and 3. +PID/host combination by itself should already guarantee that it never finds +such a file. If it does, something's broken and the stat() check won't help +since another process might be doing the same thing at the same time, and you +end up writing to the same file in tmp/, causing the mail to get corrupted. + +In step 4 the link() would fail if an identical file already existed in the +maildir, right? Wrong. The file may already have been moved to cur/ directory, +and since it may contain any number of flags by then you can't check with a +simple stat() anymore if it exists or not. + +Step 2 was pointed out to be useful if clock had moved backwards. However again +this doesn't give any actual safety guarantees, because an identical base +filename could already exist in cur/. Besides if the system was just rebooted, +the file in tmp/ could probably be even overwritten safely (assuming it wasn't +already link()ed to new/). + +So really, all that's important in not getting mails overwritten in your +maildir is the step 1: Always create filenames that are guaranteed to be +unique. Forget about the 2 second waits and such that the Qmail's man page +talks about. + +Maildir and mail header metadata +-------------------------------- + +Unlike when using <mbox> [MailboxFormat.mbox.txt] as <mailbox format> +[MailboxFormat.txt], where mail headers (for example 'Status', 'X-UID', etc.) +are <used to determine and store meta-data> [MailboxFormat.mbox.txt], the mail +headers within maildir files are (usually)*not* used for this purpose by +dovecot; neither when mails are created/moved/etc. via IMAP nor when maildirs +are placed (e.g. copied or moved in the filesystem) in a mail location (and +then "imported" by dovecot).Therefore, it is (usually) *not* necessary, to +strip any such mail headers at the MTA, MDA or LDA (as it is recommended with +<mbox> [MailboxFormat.mbox.txt]). + +There is one exception, though, namely when 'pop3_reuse_xuidl=yes' (which is +however rather deprecated):In this case 'X-UIDL' is used for the POP3 UIDLs. +Therefore,*in this case, is recommended to strip the 'X-UIDL' mail headers +_case-insensitively_ at the MTA, MDA or LDA*. + +Procmail Problems +----------------- + +Maildir format is somewhat compatible with MH format. This is sometimes a +problem when people configure their procmail to deliver mails to 'Maildir/new'. +This makes procmail create the messages in MH format, which basically means +that the file is called 'msg.inode_number'. While this appears to work first, +after expunging messages from the maildir the inodes are freed and will be +reused later. This means that another file with the same name may come to the +maildir, which makes Dovecot think that an expunged file reappeared into the +mailbox and an error is logged. + +The proper way to configure procmail to deliver to a Maildir is to use +'Maildir/' as the destination. + +References +---------- + + * Official Maildir format page [https://cr.yp.to/proto/maildir.html] + * Qmail's how to deliver to Maildir man page + [https://www.qmail.org/man/man5/maildir.html] + * Maildir++ [https://www.courier-mta.org/imap/README.maildirquota.html] + * Wikipedia [https://en.wikipedia.org/wiki/Maildir] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.dbox.txt b/doc/wiki/MailboxFormat.dbox.txt new file mode 100644 index 0000000..8df69bf --- /dev/null +++ b/doc/wiki/MailboxFormat.dbox.txt @@ -0,0 +1,251 @@ +dbox +==== + +dbox is Dovecot's own high-performance mailbox format. The original version was +introduced in v1.0 alpha4, but since then it has been completely redesigned in +v1.1 series and improved even further in v2.0. + +dbox can be used in two ways: + + 1. *single-dbox* ('sdbox' in <mail location> [MailLocation.txt]): One message + per file, similar to <Maildir> [MailboxFormat.Maildir.txt]. For backwards + compatibility,'dbox' is an alias to 'sdbox' in <mail_location> + [MailLocation.txt]. + 2. *multi-dbox* ('mdbox' in <mail location> [MailLocation.txt]): Multiple + messages per file, but unlike <mbox> [MailboxFormat.mbox.txt] multiple + files per mailbox. + +One of the main reasons for dbox's high performance is that it uses Dovecot's +index files as the only storage for message flags and keywords, so the indexes +don't have to be "synchronized". Dovecot trusts that they're always up-to-date +(unless it sees that something is clearly broken). This also means that *you +must not lose the dbox index files, they can't be regenerated without data +loss*. + +dbox has a feature for transparently moving message data to an alternate +storage area. See <Alternate storage> [MailboxFormat.dbox.txt] below. + +dbox storage is extensible. Single instance attachment storage was already +implemented as such extension. + +Layout +------ + +By default, the dbox filesystem layout will be as follows. Data which isn't the +actual message content is stored in a layout common to both *single-dbox* and +*multi-dbox*: + + * <mail location root>'/mailboxes/INBOX/dbox-Mails/dovecot.index*' - Index + files for INBOX + * <mail location root>'/mailboxes/foo/dbox-Mails/dovecot.index*' - Index files + for mailbox "foo" + * <mail location root>'/mailboxes/foo/bar/dbox-Mails/dovecot.index*' - Index + files for mailbox "foo/bar" + * <mail location root>'/dovecot.mailbox.log*' - Mailbox changelog + * <mail location root>'/subscriptions' - subscribed mailboxes list + * <mail location root>'/dovecot-uidvalidity*' - IMAP UID validity + +Note that with dbox the Index files actually contain significant data which is +held nowhere else. Index files for both *single-dbox* and *multi-dbox* contain +message flags and keywords. For *multi-dbox*, the index file also contains the +map_uids which link (via the "map index") to the actual message data. This data +cannot be automatically recreated, so it is important that Index files are +treated with the same care as message data files. + +Index files can be stored in a different location by using the INDEX parameter +in the mail location specification. If the INDEX parameter is specified, it +will make Dovecot look for the Index files as follows: + + * <INDEX location>'/mailboxes/INBOX/dbox-Mails/dovecot.index*' - Index files + for INBOX + * <INDEX location>'/mailboxes/foo/dbox-Mails/dovecot.index*' - Index files for + mailbox "foo" + * <INDEX location>'/mailboxes/foo/bar/dbox-Mails/dovecot.index*' - Index files + for mailbox "foo/bar" + +Actual message content is stored differently depending on whether it is +*single-dbox* or *multi-dbox*. + +Under *single-dbox* we have: + + * <mail location root>'/mailboxes/INBOX/dbox-Mails/u.*' - Numbered files + ('u.1','u.2', ...) each containing one message of INBOX + * <mail location root>'/mailboxes/foo/dbox-Mails/u.*' - Files each containing + one message for mailbox "foo" + * <mail location root>'/mailboxes/foo/bar/dbox-Mails/u.*' - Files each + containing one message for for mailbox "foo/bar" + +Under *multi-dbox* we have: + + * <mail location root>'/storage/dovecot.map.index*' - "Map index" containing a + record for each message stored + * <mail location root>'/storage/m.*' - Numbered files ('m.1', 'm.2', ...) each + containing one or multiple messages + +With Dovecot versions 2.0.4 and later, setting the INDEX parameter sets the +location of the "map index" as well as the location of the mailbox indexes. So +this would make the "map index" be stored as follows: + + * <INDEX location>'/storage/dovecot.map.index*' - "Map index" containing a + record for each message stored + +Multi-dbox +---------- + +You can enable multi-dbox with: + +---%<------------------------------------------------------------------------- +mail_location = mdbox:~/mdbox +---%<------------------------------------------------------------------------- + +The directory layout (under '~/mdbox/') is: + + * '~/mdbox/storage/' contains the actual mail data for all mailboxes + * '~/mdbox/mailboxes/' contains directories for mailboxes and their index + files + +The storage directory has files: + + * 'dovecot.map.index*' files contain the "map index" + * 'm.*' files contain the mail data + +Each m.* file contains one or more messages. 'mdbox_rotate_size' setting can be +used to configure how large the files can grow. + +The map index contains a record for each message: + + * map_uid: Unique growing 32 bit number for the message. + * refcount: 16 bit reference counter for this message. Each time the message + is copied the refcount is increased. + * file_id: File number containing the message. For example if file_id=5, the + message is in file 'm.5'. + * offset: Offset to message within the file. + * size: Space used by the message in the file, including all metadata. + +Mailbox indexes refer to messages only using map_uids. This allows messages to +be moved to different files by updating only the map index. Copying is done +simply by appending a new record to mailbox index containing the existing +map_uid and increasing its refcount. If refcount grows over 32768, currently +Dovecot gives an error message. It's unlikely anyone really wants to copy the +same message that many times. + +Expunging a message only decreases the message's refcount. The space is later +freed in "purge" step. This is typically done in a nightly cronjob when there's +less disk I/O activity. The purging first finds all files that have refcount=0 +mails. Then it goes through each file and copies the refcount>0 mails to other +mdbox files (to the same files as where newly saved messages would also go), +updates the map index and finally deletes the original file. So there is never +any overwriting or file truncation. + +The purging can be invoked explicitly running <doveadm purge> +[Tools.Doveadm.Purge.txt]. + +There are several safety features built into dbox to avoid losing messages or +their state if map index or mailbox index gets corrupted: + + * Each message has a 128 bit globally unique identifier (GUID). The GUID is + saved to message metadata in m.* files and also to mailbox indexes. This + allows Dovecot to find messages even if map index gets corrupted. + * Whenever index file is rewritten, the old index is renamed to + 'dovecot.index.backup'. If the main index becomes corrupted, this backup + index is used to restore flags and figure out what messages belong to the + mailbox. + * Initial mailbox where message was saved to is stored in the message metadata + in m.* files. So if all indexes get lost, the messages are put to their + initial mailboxes. This is better than placing everything into a single + mailbox. + +Alternate storage +----------------- + +Unlike Maildir, with dbox the message file names don't change. This makes it +possible to support storing files in multiple directories or mount points. dbox +supports looking up files from "altpath" if they're not found from the primary +path. This means that it's possible to move older mails that are rarely +accessed to cheaper (slower) storage. + +To enable this functionality, use the 'ALT' parameter in the mail location. For +example, specifying the mail location as: + +---%<------------------------------------------------------------------------- +mail_location = mdbox:/var/vmail/%d/%n:ALT=/altstorage/vmail/%d/%n +---%<------------------------------------------------------------------------- + +will make Dovecot look for message data first under '/var/vmail/%d/%n' +("primary storage"), and if it is not found there it will look under +'/altstorage/vmail/%d/%n' ("alternate storage") instead. There's no problem +having the same (identical) file in both storages. + +Keep the unmounted '/altstorage' directory permissions such that Dovecot mail +processes can't create directories under it (e.g. root:root 0755). This way if +the alt storage isn't mounted for some reason, Dovecot won't think that all the +messages in alt storage were deleted and lose their flags. + +When messages are moved from primary storage to alternate storage, only the +actual message data (stored in files 'u.*' under *single-dbox* and 'm.*' under +*multi-dbox*) is moved to alternate storage; everything else remains in the +primary storage. + +Message data can be moved from primary storage to alternate storage using +<doveadm altmove> [Tools.Doveadm.Altmove.txt]. (In theory you could also do +this with some combination of cp/mv, but better not to go there unless you +really need to. The updates must be atomic in any case, so direct cp won't +work.) + +The granularity at which data is moved to alternate storage is individual +messages. This is true even for *multi-dbox* when multiple messages are stored +in a single 'm.*' storage file. If individual messages from an 'm.*' storage +file need to be moved to alternate storage, the message data is written out to +a different 'm.*' storage file (either new or existing) in the alternate +storage area and the "map index" updated accordingly. + +Alternate storage is completely transparent at the IMAP/POP level. Users +accessing mail through IMAP or POP cannot normally tell if any given message is +stored in primary storage or alternate storage. Conceivably users might be able +to measure a performance difference; the point is that there is no IMAP/POP +command which could be used to expose this information. It is entirely possible +to have a mail folder which contains a mix of messages stored in primary +storage and alternate storage. + +dbox and mail header metadata +----------------------------- + +Unlike when using <mbox> [MailboxFormat.mbox.txt] as <mailbox format> +[MailboxFormat.txt], where mail headers (for example 'Status', 'X-UID', etc.) +are <used to determine and store meta-data> [MailboxFormat.mbox.txt], the mail +headers within dbox files are (usually)*not* used for this purpose by dovecot; +neither when mails are created/moved/etc. via IMAP nor when dboxes are placed +(e.g. copied or moved in the filesystem) in a mail location (and then +"imported" by dovecot).Therefore, it is (usually) *not* necessary, to strip any +such mail headers at the MTA, MDA or LDA (as it is recommended with <mbox> +[MailboxFormat.mbox.txt]). + +There is one exception, though, namely when 'pop3_reuse_xuidl=yes' (which is +however rather deprecated):In this case 'X-UIDL' is used for the POP3 UIDLs. +Therefore,*in this case, is recommended to strip the 'X-UIDL' mail headers +_case-insensitively_ at the MTA, MDA or LDA*. + +Accessing expunged mails with mdbox +----------------------------------- + +"mdbox_deleted" storage can be used to access mdbox's all mails that are +completely deleted (reference count=0). The mdbox_deleted parameters should +otherwise be exactly the same as mdbox's. Then you can use e.g. doveadm fetch +or doveadm import commands to access the mails. For example: + +---%<------------------------------------------------------------------------- +# If you have mail_location=mdbox:~/mdbox:INDEX=/var/index/%u +doveadm import mdbox_deleted:~/mdbox:INDEX=/var/index/%u "" subject oops +---%<------------------------------------------------------------------------- + +This finds a deleted mail with subject "oops" and imports it into INBOX. + +Mail delivery +============= + +Some MTA configurations have the MTA directly dropping mail into Maildirs or +mboxes. Since most MTAs don't understand the dbox format, this option is not +available. Instead, the MTA could be set up to use <LMTP#mta> [LMTP.txt] or +<the Dovecot Local Delivery Agent> [LDA.txt]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.imapc.txt b/doc/wiki/MailboxFormat.imapc.txt new file mode 100644 index 0000000..0fee740 --- /dev/null +++ b/doc/wiki/MailboxFormat.imapc.txt @@ -0,0 +1,178 @@ +imapc storage +============= + +The imapc storage accesses a remote IMAP server as if it were a regular Dovecot +mailbox format. Dovecot can treat it as a very dummy storage or optionally a +more capable storage. + +---%<------------------------------------------------------------------------- +# In-memory index files: +mail_location = imapc: + +# Store index files locally: +mail_location = imapc:~/imapc +---%<------------------------------------------------------------------------- + +Connection settings +------------------- + +Do a regular IMAP LOGIN to imap.example.com using 'a LOGIN user@example.com +secret': + +---%<------------------------------------------------------------------------- +imapc_host = imap.example.com +imapc_password = secret +imapc_port = 143 +imapc_user = user@example.com +---%<------------------------------------------------------------------------- + +If you want to use a master user login, set: + +---%<------------------------------------------------------------------------- +imapc_master_user = masteruser +---%<------------------------------------------------------------------------- + +For SSL, use either: + + * ---%<---------------------------------------------------------------------- + imapc_ssl = imaps + imapc_port = 993 + ---%<---------------------------------------------------------------------- + + * ---%<---------------------------------------------------------------------- + imapc_ssl = starttls + imapc_port = 143 + ---%<---------------------------------------------------------------------- + +For testing you may want to disable all SSL certificate checks: + +---%<------------------------------------------------------------------------- +imapc_ssl_verify = no +---%<------------------------------------------------------------------------- + +You can use other SASL mechanisms besides PLAIN by specifying (the first one +advertised by IMAP server is used): + +---%<------------------------------------------------------------------------- +imapc_sasl_mechanisms = external plain login +---%<------------------------------------------------------------------------- + +The SASL client mechanisms are implemented in Dovecot's lib-sasl/ code. It's +possible to add more with plugins. + +Other settings +-------------- + +imapc_cmd_timeout: + How long to wait for an IMAP command to reply before disconnecting and + retrying (default: 5 mins). + +imapc_list_prefix: + Access only mailboxes under this prefix. For example + 'imapc_list_prefix=INBOX/' + +imapc_max_idle_time: + Send something (NOOP/DONE) to server after not sending anything for this + amount of time (default: 29 mins). + +imapc_rawlog_dir: + Log all IMAP traffic input/output to this directory. + +Features and workarounds +------------------------ + +'imapc_features' setting is a space-separated list of features and workarounds +that can be enabled. + +Optimizations +------------- + +rfc822.size: + Allow passing through message sizes using 'FETCH RFC822.SIZE' + +fetch-headers: + Allow fetching specific message headers using 'FETCH BODY.PEEK[HEADER.FIELDS + (..)]' + +fetch-bodystructure: + Allow fetching BODY and BODYSTRUCTURE from remote server. (v2.2.30+) + +search: + Allow using 'SEARCH' command. + +Features +-------- + +gmail-migration: + Enable GMail-specific migration: Use IMAP X-GM-MSGID as POP3 UIDL. Add + $GMailHaveLabels keyword to mails that have X-GM-LABELS except for \Muted (to + be used for migrating only archived emails in "All Mails"). Add + pop3_deleted_flag to mails that don't exist in POP3 server. + +proxyauth: + Use Sun/Oracle IMAP-server specific PROXYAUTH command to do master user + authentication. Normally this would be done using the SASL PLAIN + authentication. + +throttle:INIT:MAX:SHRINK: + When receiving [THROTTLED] response (from GMail), throttling is applied. INIT + = initial throttling msecs (default: 50 ms), afterwards each subsequent + [THROTTLED] doubles the throttling until MAX is reached (default: 16000 ms). + When [THROTTLED] is not received for a while, it's shrank again. The initial + shrinking is done after SHRINK (default: 500 ms). If [THROTTLED] is received + again within this timeout, it's doubled, otherwise both throttling and the + next shrinking timeout is shrank to 3/4. + +modseq: + Access MODSEQ and HIGHESTMODSEQ (v2.2.24+) + +delay-login: + Don't connect to the remote server until some command requires it. By default + the server is connected to immediately on login. (v2.2.29+) + +Quota +----- + +Using the "imapc" quota backend allows asking for the quota from remote IMAP +server (v2.2.30+). By default it uses GETQUOTAROOT INBOX for getting the quota. +There are also two parameters that can be used to control how the quota is +looked up: + + * box=<mailbox>: Use GETQUOTAROOT <mailbox> + * root=<name>: Use GETQUOTA <name> + +For example: + +---%<------------------------------------------------------------------------- +plugin { + quota = imapc:root=User Quota +} +---%<------------------------------------------------------------------------- + +Workarounds +----------- + +zimbra-workarounds: + Fetch full message using 'BODY.PEEK[HEADER] BODY.PEEK[TEXT]' instead of just + 'BODY.PEEK[]' because the header differs between these two when there are + illegal control chars or 8bit chars. This mainly caused problems with dsync, + but as of v2.2.22+ this should no longer be a problem and there's probably no + need to enable this workaround. + +no-examine: + Use SELECT instead of EXAMINE even when we don't want to modify anything in + the mailbox. This is a Courier-workaround where it didn't permanently assign + UIDVALIDITY to an EXAMINEd mailbox, but assigned it for SELECTed mailbox. + +fetch-msn-workarounds: + Try to ignore wrong message sequence numbers in FETCH replies whenever + possible, preferring to use the returned UID number instead. + +fetch-fix-broken-mails: + If a FETCH returns 'NO' (but not 'NO [LIMIT]' or 'NO [SERVERBUG]'), assume + the mail is broken in server and just treat it as if it were an empty email. + NOTE: This is often a dangerous option! It's not safe to assume that NO means + a permanent error rather than a temporary error. This feature should be + enabled only for specific users who have been determined to be broken. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.mailstore.txt b/doc/wiki/MailboxFormat.mailstore.txt new file mode 100644 index 0000000..3993602 --- /dev/null +++ b/doc/wiki/MailboxFormat.mailstore.txt @@ -0,0 +1,17 @@ +Mailstore +========= + +This format originated with exim. Each message is written as two unique +filenames ending in .env and .msg. The .env contains the message envelope, and +the .msg file contains the actual message. When an email is delivered, the +email header is created with the suffix .tmp, and the message is created with +.msg. When the .msg file is completed, the .tmp file is renamed to end in .env. +Programs wishing to access an email must wait for both files to be present, or +for the absence of the .tmp file. + +References +---------- + + * http://www.exim.org/exim-html-4.60/doc/html/spec.html/ch26.html#id2639666 + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.mbox.txt b/doc/wiki/MailboxFormat.mbox.txt new file mode 100644 index 0000000..438f9d8 --- /dev/null +++ b/doc/wiki/MailboxFormat.mbox.txt @@ -0,0 +1,290 @@ +Mbox Mailbox Format +=================== + +Contents + + + 1. Mbox Mailbox Format + + 1. Locking + + 1. Dotlock + + 2. Deadlocks + + 2. Directory Structure + + 3. Dovecot's Metadata + + 4. Dovecot's Speed Optimizations + + 5. From Escaping + + 6. Mbox Variants + + 7. References + +Usually UNIX systems are configured by default to deliver mails to +'/var/mail/username' or '/var/spool/mail/username' mboxes. In IMAP world these +files are called INBOX mailboxes. IMAP protocol supports multiple mailboxes +however, so there needs to be a place for them as well. Typically they're +stored in '~/mail/' or '~/Mail/' directories. + +The mbox file contains all the messages of a single mailbox. Because of this, +the mbox format is typically thought of as a slow format. However with +Dovecot's indexing this isn't true. Only expunging messages from the beginning +of a large mbox file is slow with Dovecot, most other operations should be +fast. Also because all the mails are in a single file, searching is much faster +than with maildir. + +Modifications to mbox may require moving data around within the file, so +interruptions (eg. power failures) can cause the mbox to break more or less +badly. Although Dovecot tries to minimize the damage by moving the data in a +way that data should never get lost (only duplicated), mboxes still aren't +recommended to be used for important data. + +Locking +------- + +Locking is a mess with mboxes. There are multiple different ways to lock a +mbox, and software often uses incompatible locking. See <MboxLocking.txt> for +how to check what locking methods some commonly used programs use. + +There are at least four different ways to lock a mbox: + + * *dotlock*: 'mailboxname.lock' file created by almost all software when + writing to mboxes. This grants the writer an exclusive lock over the mbox, + so it's usually not used while reading the mbox so that other processes can + also read it at the same time. So while using a dotlock typically prevents + actual mailbox corruption, it doesn't protect against read errors if mailbox + is modified while a process is reading. + * *flock*: 'flock()' system call is quite commonly used for both read and + write locking. The read lock allows multiple processes to obtain a read lock + for the mbox, so it works well for reading as well. The one downside to it + is that it doesn't work if mailboxes are stored in NFS. + * *fcntl*: Very similar to *flock*, also commonly used by software. In some + systems this 'fcntl()' system call is compatible with 'flock()', but in + other systems it's not, so you shouldn't rely on it.*fcntl* works with NFS + if you're using lockd daemon in both NFS server and client. + * *lockf*: POSIX 'lockf()' locking. Because it allows creating only exclusive + locks, it's somewhat useless so Dovecot doesn't support it. With Linux + 'lockf()' is internally compatible with 'fcntl()' locks, but again you + shouldn't rely on this. + +Dotlock +------- + +Another problem with dotlocks is that if the mailboxes exist in '/var/mail/', +the user may not have write access to the directory, so the dotlock file can't +be created. There are a couple of ways to work around this: + + * Give a mail group write access to the directory and then make sure that all + software requiring access to the directory runs with the group's privileges. + This may mean making the binary itself setgid-mail, or using a separate + dotlock helper program which is setgid-mail. With Dovecot this can be done + by setting 'mail_privileged_group = mail'. + * Set sticky bit to the directory ('chmod +t /var/mail'). This makes it + somewhat safe to use, because users can't delete each others mailboxes, but + they can still create new files (the dotlock files). The downside to this is + that users can create whatever files they wish in there, such as a mbox for + newly created user who hadn't yet received mail. + +Deadlocks +--------- + +If multiple lock methods are used, which is usually the case since dotlocks +aren't typically used for read locking, the order in which the locking is done +is important. Consider if two programs were running at the same time, both use +dotlock and fcntl locking but in different order: + + * Program A: fcntl locks the mbox + * Program B at the same time: dotlocks the mbox + * Program A continues: tries to dotlock the mbox, but since it's already + dotlocked by B, it starts waiting + * Program B continues: tries to fcntl lock the mbox, but since it's already + fcntl locked by A, it starts waiting + +Now both of them are waiting for each others locks. Finally after a couple of +minutes they time out and fail the operation. + +Directory Structure +------------------- + +By default, when listing mailboxes, Dovecot simply assumes that all files it +sees are mboxes and all directories mean that they contain sub-mailboxes. There +are two special cases however which aren't listed: + + * '.subscriptions' file contains IMAP's mailbox subscriptions. + * '.imap/' directory contains Dovecot's index files. + +Because it's not possible to have a file which is also a directory, it's not +normally possible to create a mailbox and child mailboxes under it. + +However if you really want to be able to have mailboxes containing both +messages and child mailboxes under mbox, then Dovecot can be configured to do +this, subject to certain provisos; see <MboxChildFolders.txt>. + +Dovecot's Metadata +------------------ + +Dovecot uses C-Client (ie. UW-IMAP, Pine) compatible headers in mbox messages +to store metadata. These headers are: + + * X-IMAPbase: Contains UIDVALIDITY, last used UID and list of used keywords + * X-IMAP: Same as X-IMAPbase but also specifies that the message is a "pseudo + message" + * X-UID: Message's allocated UID + * Status: R (\Seen) and O (non-\Recent) flags + * X-Status: A (\Answered), F (\Flagged), T (\Draft) and D (\Deleted) flags + * X-Keywords: Message's keywords + * Content-Length: Length of the message body in bytes + +Whenever any of these headers exist, Dovecot treats them as its own private +metadata. It does sanity checks for them, so the headers may also be modified +or removed completely. None of these headers are sent to IMAP/POP3 clients when +they read the mail. + +*The MTA, MDA or LDA should strip all these headers _case-insensitively_ before +writing the mail to the mbox.* + +Only the first message contains the X-IMAP or X-IMAPbase header. The difference +is that when all the messages are deleted from mbox file, a "pseudo message" is +written to the mbox which contains X-IMAP header. This is the "DON'T DELETE +THIS MESSAGE -- FOLDER INTERNAL DATA" message which you hate seeing when using +non-C-client and non-Dovecot software. This is however important to prevent +abuse, otherwise the first mail which is received could contain faked +X-IMAPbase header which could cause trouble. + +If message contains X-Keywords header, it contains a space-separated list of +keywords for the mail. Since the same header can come from the mail's sender, +only the keywords are listed in X-IMAP header are used. + +The UID for a new message is calculated from "last used UID" in X-IMAP header + +1. This is done always, so fake X-UID headers don't really matter. This is also +why the pseudo message is important. Otherwise the UIDs could easily grow over +2^31 which some clients start treating as negative numbers, which then cause +all kinds of problems. Also when 2^32 is exceeded, Dovecot will also start +having some problems. + +Content-Length is used as long as another valid mail starts after that many +bytes. Because the byte count must be exact, it's quite unlikely that abusing +it can cause messages to be skipped (or rather appended to the previous +message's body). + +Status and X-Status headers are trusted completely, so it's pretty good idea to +filter them in LDA if possible. + +Dovecot's Speed Optimizations +----------------------------- + +Updating messages' flags and keywords can be a slow operation since you may +have to insert a new header (Status, X-Status, X-Keywords) or at least insert +data in the header's value. Some mbox MUAs do this simply by rewriting all of +the mbox after the inserted data. If the mbox is large, this can be very slow. +Dovecot optimizes this by always leaving some space characters after some of +its internal headers. It can use this space to move only minimal amount of data +necessary to get the necessary data inserted. Also if data is removed, it just +grows these spaces areas. + +'mbox_lazy_writes' setting works by adding and/or updating Dovecot's metadata +headers only after closing the mailbox or when messages are expunged from the +mailbox. C-Client works the same way. The upside of this is that it reduces +writes because multiple flag updates to same message can be grouped, and +sometimes the writes don't have to be done at all if the whole message is +expunged. The downside is that other processes don't notice the changes +immediately (but other Dovecot processes do notice because the changes are in +index files). + +'mbox_dirty_syncs' setting tries to avoid re-reading the mbox every time +something changes. Whenever the mbox changes (ie. timestamp or size), it first +checks if the mailbox's size changed. If it didn't, it most likely meant that +only message flags were changed so it does a full mbox read to find it. If the +mailbox shrunk, it means that mails were expunged and again Dovecot does a full +sync. Usually however the only thing besides Dovecot that modifies the mbox is +the LDA which appends new mails to the mbox. So if the mbox size was grown, +Dovecot first checks if the last known message is still where it was last time. +If it is, Dovecot reads only the newly added messages and goes into a "dirty +mode". As long as Dovecot is in dirty mode, it can't be certain that mails are +where it expects them to be, so whenever accessing some mail, it first verifies +that it really is the correct mail by finding its X-UID header. If the X-UID +header is different, it fallbacks to a full sync to find the mail's correct +position. The dirty mode goes away after a full sync. If 'mbox_lazy_writes' was +enabled and the mail didn't yet have X-UID header, Dovecot uses MD5 sum of a +couple of headers to compare the mails. + +'mbox_very_dirty_syncs' does the same as 'mbox_dirty_syncs', but the dirty +state is kept also when opening the mailbox. Normally opening the mailbox does +a full sync if it had been changed outside Dovecot. + +From Escaping +------------- + +In mboxes a new mail always begins with a "From " line, commonly referred to as +From_-line. To avoid confusion, lines beginning with "From " in message bodies +are usually prefixed with '>' character while the message is being written to +in mbox. + +Dovecot doesn't currently do this escaping however. Instead it prevents this +confusion by adding Content-Length headers so it knows later where the next +message begins. Dovecot doesn't either remove the '>' characters before sending +the data to clients. Both of these will probably be implemented later. + +Mbox Variants +------------- + +There are a few minor variants of this format: + +*mboxo* is the name of original mbox format originated with Unix System V. +Messages are stored in a single file, with each message beginning with a line +containing "From SENDER DATE". If "From " (case-sensitive, with the space) +occurs at the beginning of a line anywhere in the email, it is escaped with a +greater-than sign (to ">From "). Lines already quoted as such, for example +">From " or ">>>From " are *not* quoted again, which leads to irrecoverable +corruption of the message content. + +*mboxrd* was named for Raul Dhesi in June 1995, though several people came up +with the same idea around the same time. An issue with the mboxo format was +that if the text ">From " appeared in the body of an email (such as from a +reply quote), it was not possible to distinguish this from the mailbox format's +quoted ">From ". mboxrd fixes this by always quoting already quoted "From " +lines (e.g. ">From ", ">>From ", ">>>From ", etc.) as well, so readers can just +remove the first ">" character. This format is used by qmail and getmail +(>=4.35.0). + +*mboxcl* format was originated with Unix System V Release 4 mail tools. It adds +a Content-Length field which indicates the number of bytes in the message. This +is used to determine message boundaries. It still quotes "From " as the +original mboxo format does (and *not* as mboxrd does it). + +*mboxcl2* is like mboxcl but does away with the "From " quoting. + +*MMDF* (Multi-channel Memorandum Distribution Facility mailbox format) was +originated with the MMDF daemon. The format surrounds each message with lines +containing four control-A's. This eliminates the need to escape From: lines. + +Dovecot currently uses mboxcl2 format internally, but it's planned to move to +combination of mboxrd and mboxcl. + +*How a message is read stored in mbox extension ?* + + * An email client reader scans throughout mbox file looking for From_ lines. + * Any From_ line marks the beginning of a message. + * Once the reader finds a message, it extracts a (possibly corrupted) envelope + sender and delivery date out of the From_ line. + * It then reads until the next From_ line or scans till the end of file, + whenever From_ comes first. + * It removes the last blank line and deletes the quoting of >From_ lines and + >>From_ lines and so on. + +References +---------- + + * Wikipedia [http://en.wikipedia.org/wiki/Mbox] + * Qmail mbox [http://www.qmail.org/man/man5/mbox.html] + * Mbox family + [http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html] + * CommuniGatePro mbox + [http://www.communigate.com/CommuniGatePro/Mailboxes.html#mbox] + * MBOX File Viewer [http://www.freeviewer.org/mbox/] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.mbx.txt b/doc/wiki/MailboxFormat.mbx.txt new file mode 100644 index 0000000..c5d76a2 --- /dev/null +++ b/doc/wiki/MailboxFormat.mbx.txt @@ -0,0 +1,24 @@ +mbx +=== + +A high performance mbox-replacement created by Mark Crispin while at University +of Washington for UW-IMAP. Each message in the file is preceded by a record +carrying all the metadata that IMAP-protocol needs. This allows changing the +metadata easily by modifying the fixed-size header, rather than moving data +around in a file like with mbox. + +File locking is handled more intelligently (only appends may need to wait for +locks), making this format a good choice for shared mailboxes. + +Downsides contain: + + * Messages don't get deleted from disk until there's only one client accessing + the mailbox, so you may need to add some forced downtime to get it done. + * Works only in local filesystem. + * Expunging is still as costly and as fragile as with mbox. + * At least on 32 bit systems, mailboxes are limited to 2GB size. (A mailbox + can't be accessed anymore without manual fixing if it reached 2GB (minus 1B) + of size on disk.) This is probably UW-IMAP -specific implementation problem + rather than actual mailbox format issue. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxFormat.txt b/doc/wiki/MailboxFormat.txt new file mode 100644 index 0000000..0f70184 --- /dev/null +++ b/doc/wiki/MailboxFormat.txt @@ -0,0 +1,147 @@ +Mailbox Formats +=============== + +Mailbox formats supported by Dovecot: ++-----------------------------+---------------+-------------------+-------------+ +| *Name* | *Tag* | *Description* | ++-----------------------------+---------------+-------------------+-------------+ +| <mbox> | 'mbox' | Traditional UNIX | +| [MailboxFormat.mbox.txt] | | mailbox format. | +| | | Users' INBOX | +| | | mboxes are | +| | | commonly stored in| +| | | '/var/spool/mail' | +| | | or '/var/mail' | +| | | directory. Single | +| | | file contains | +| | | multiple messages.| ++-----------------------------+---------------+-------------------+-------------+ +| <Maildir> | 'maildir' | One file contains | +| [MailboxFormat.Maildir.txt] | | one message. A | +| | | reliable choice | +| | | since files are | +| | | never modified and| +| | | all operations are| +| | | atomic. The | +| | | top-level | +| | | 'Maildir' | +| | | directory contains| +| | | the 'Maildir/cur',| +| | | 'Maildir/new' and | +| | | 'Maildir/tmp' | +| | | subdirectories. | ++-----------------------------+---------------+-------------------+-------------+ +| <dbox> | 'sdbox' | *single-dbox*, one| Dovecot's | +| [MailboxFormat.dbox.txt] | | message per file | own high | +| | | | performance | +| | | | mailbox | +| | | | format. | +| | | | Messages are| +| | | | stored in | +| | | | one or more | +| | | | files, each | +| | | | containing | +| | | | one or more | +| | | | messages. | ++-----------------------------+---------------+-------------------+-------------+ +| 'mdbox' | *multi-dbox*, | +| | multiple | +| | messages per | +| | file | ++-----------------------------+---------------+-------------------+-------------+ +| 'dbox' | deprecated | +| | alias for | +| | 'sdbox' | ++-----------------------------+---------------+-------------------+-------------+ +| <Cydir> | 'cydir' | Dovecot's own | +| [MailboxFormat.Cydir.txt] | | simple and high | +| | | performance | +| | | Cyrus-like mailbox| +| | | format. It should | +| | | be mostly used for| +| | | testing and | +| | | benchmarking only.| ++-----------------------------+---------------+-------------------+-------------+ +| <imapc> | 'imapc' | Use remote IMAP | +| [MailboxFormat.imapc.txt] | | server as mail | +| | | storage. | ++-----------------------------+---------------+-------------------+-------------+ +| <pop3c> | 'pop3c' | Use remote POP3 | +| [MailboxFormat.pop3c.txt] | | server as mail | +| | | storage. | ++-----------------------------+---------------+-------------------+-------------+ + +The *Tag* column indicates the tag which is used at the beginning of a <mailbox +location specification> [MailLocation.txt]. + +Mailbox formats *not* supported by Dovecot: ++-------------------------------+---------------------------------------------+ +| *Name* | *Description* | ++-------------------------------+---------------------------------------------+ +| <mbx> [MailboxFormat.mbx.txt] | UW-IMAP's old high performance mailbox | +| | format. One file contains all the mailboxes,| +| | so expunges may still be slow. | ++-------------------------------+---------------------------------------------+ +| <mix> [MailboxFormat.mix.txt] | UW-IMAP's new (2006) high performance | +| | mailbox format. Similar to multi-dbox. | ++-------------------------------+---------------------------------------------+ +| <mailstore> | A format created by Exim. | +| [MailboxFormat.mailstore.txt] | | ++-------------------------------+---------------------------------------------+ +| <MH> [MailboxFormat.MH.txt] | One file contains one message. Sort order of| +| | the folder determines the message ID and | +| | name. Actively used by projects such as | +| | MH-E, NMH, exmh. Experimentally supported | +| | by UW-IMAP | +| | [https://www.washington.edu/imap/]. | ++-------------------------------+---------------------------------------------+ +| <MMDF> [MailboxFormat.MMDF.txt]| Similar to mbox, but instead of From-line | +| | separators it uses four '^A' characters | ++-------------------------------+---------------------------------------------+ +| <Cyrus> | One file contains one message, plus there | +| [MailboxFormat.Cyrus.txt] | are a couple of index/cache files. Commonly | +| | referred to as being maildir-like, although | +| | they have only a single thing in common. | ++-------------------------------+---------------------------------------------+ + +Adding support for new formats for Dovecot isn't very difficult, although it +can be time consuming. Dovecot exposes a nice and simple API which needs to be +implemented. Use Cydir format as an example. + +Software Support +---------------- + ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| *Format/Software* | *Dovecot | *UW-IMAP | *Courier-IMAP | *Exim | *Postfix | *PINE | *mutt | *procmail | *maildrop | +| | [https://www.dovecot.org/]* | [https://www.washington.edu/imap/]* | [https://www.courier-mta.org/imap/]* | [https://www.exim.org/]* | [https://www.postfix.org/]* | [https://www.washington.edu/pine/]* | [https://www.mutt.org/]* | [https://www.procmail.org/]* | [https://www.courier-mta.org/maildrop/]* | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <mbox> [MailboxFormat.mbox.txt]| Yes | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <mbx> [MailboxFormat.mbx.txt] | No | Yes | No | Yes | No | Yes | No | No | No | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <maildir> | Yes | No | Yes | Yes | Yes | No | Yes | Yes (3.22) | Yes | +| [MailboxFormat.Maildir.txt] | | | | | | | | | | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <mailstore> | No | No | No | Yes | No | No | No | No | No | +| [MailboxFormat.mailstore.txt] | | | | | | | | | | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <dbox> [MailboxFormat.dbox.txt]| Yes | No | No | No | No | No | No | No | No | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ +| <MH> [MailboxFormat.MH.txt] | No | Yes | No | No | No | Yes | Yes | Yes | No | ++-------------------------------+-----------------------------+-------------------------------------+--------------------------------------+--------------------------+-----------------------------+-------------------------------------+--------------------------+------------------------------+------------------------------------------+ + +Conversion Between Mailbox Formats +---------------------------------- + +See <Migration.MailFormat.txt>. + +References +---------- + + * Mutt mailbox formats: https://rucus.ru.ac.za/docs/mutt/manual58.html + * Article on mailbox formats: + https://www.livejournal.com/users/rfunk/1571.html + * Mbox and maildir comparison: + https://www.linuxmail.info/mbox-maildir-mail-storage-formats/ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MailboxSettings.txt b/doc/wiki/MailboxSettings.txt new file mode 100644 index 0000000..3e94581 --- /dev/null +++ b/doc/wiki/MailboxSettings.txt @@ -0,0 +1,81 @@ +Mailbox settings +================ + +Since Dovecot v2.1 one can assign SPECIAL-USE RFC 6154 +[http://www.faqs.org/rfcs/rfc6154.html] tags and specify, which mailboxes to +create and/or subscribe to automatically. + +The autocreated mailboxes are created lazily to disk only when accessed for the +first time. The autosubscribed mailboxes aren't written to subscriptions file, +unless SUBSCRIBE command is explicitly used for them. + +The mailbox section name specifies the mailbox name. If it has spaces, you can +put it in "quotes". The mailbox settings are: + + * auto: Autocreate/subscribe mailbox? + * no: Neither + * create: Autocreate, but don't autosubscribe + * subscribe: Autocreate and autosubscribe + * special_use: Space-separated list of SPECIAL-USE flags to use for the + mailbox. There are no validity checks, so you could specify anything you + want in here, but it's not a good idea to use other than the standard ones + specified in the RFC. + * NOTE: Due to a bug in Dovecot v2.2.30+ if special-use flags are used, + SPECIAL-USE needs to be added to post-login CAPABILITY response as RFC + 6154 mandates. You can do this with 'imap_capability = +SPECIAL-USE' + * autoexpunge=<time>: (v2.2.20+) Automatically at user deinitialization + expunge all mails in this mailbox whose saved-timestamp is older than<time> + (e.g. autoexpunge=30d). This removes the need for <expire plugin> + [Plugins.Expire.txt] if you don't care that the expunging may not always + happen in time. + * For IMAP and POP3 this happens after the client is already disconnected. + * For LMTP this happens when the user's mail delivery is finished. Note + that if there are multiple recipients this may delay delivering the mails + to the other recipients. + * Also doveadm and other processes verify this, which may be unnecessary. + So it may be better to explicitly enable this only inside protocol imap, + pop3 and maybe lmtp. You can do this with e.g.:'protocol imap { namespace + inbox { mailbox Spam { autoexpunge = 10d } } }' + * mailbox_list_index=yes is highly recommended when using this setting, as + it avoids actually opening the mailbox to see if anything needs to be + expunged. + * autoexpunge_max_mails=<number>: (v2.2.25+) Mails are expunged until mail + count is at autoexpunge_max_mails or below. After these messages are + removed, autoexpunge will then try to expunge mails based on the + 'autoexpunge' setting. + +---%<------------------------------------------------------------------------- +namespace inbox { + #prefix = INBOX. # the namespace prefix isn't added again to the mailbox +names. + inbox = yes + # ... + + mailbox Trash { + auto = no + special_use = \Trash + } + mailbox Drafts { + auto = no + special_use = \Drafts + } + mailbox Sent { + auto = subscribe # autocreate and autosubscribe the Sent mailbox + special_use = \Sent + } + mailbox "Sent Messages" { + auto = no + special_use = \Sent + } + mailbox Spam { + auto = create # autocreate Spam, but don't autosubscribe + special_use = \Junk + } + mailbox virtual/All { # if you have a virtual "All messages" mailbox + auto = no + special_use = \All + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Makefile.am b/doc/wiki/Makefile.am new file mode 100644 index 0000000..13b0939 --- /dev/null +++ b/doc/wiki/Makefile.am @@ -0,0 +1,282 @@ +if BUILD_DOCS +wikidir = $(docdir)/wiki +wiki_DATA = $(wikifiles) +endif + +EXTRA_DIST = \ + $(wikifiles) + +wikifiles = ACL.txt \ + AixPluginsSupport.txt \ + AttachmentIndicator.txt \ + AuthDatabase.CheckPassword.txt \ + AuthDatabase.Dict.txt \ + AuthDatabase.LDAP.AuthBinds.txt \ + AuthDatabase.LDAP.PasswordLookups.txt \ + AuthDatabase.LDAP.Userdb.txt \ + AuthDatabase.LDAP.txt \ + AuthDatabase.Lua.txt \ + AuthDatabase.Passwd.txt \ + AuthDatabase.PasswdFile.txt \ + AuthDatabase.SQL.txt \ + AuthDatabase.VPopMail.txt \ + AuthDatabase.txt \ + Authentication.Caching.txt \ + Authentication.Kerberos.txt \ + Authentication.MasterUsers.txt \ + Authentication.Mechanisms.DigestMD5.txt \ + Authentication.Mechanisms.NTLM.txt \ + Authentication.Mechanisms.Winbind.txt \ + Authentication.Mechanisms.txt \ + Authentication.MultipleDatabases.txt \ + Authentication.PasswordSchemes.txt \ + Authentication.Penalty.txt \ + Authentication.Policy.txt \ + Authentication.RestrictAccess.txt \ + Authentication.txt \ + BasicConfiguration.txt \ + Chrooting.txt \ + Clients.NegativeUIDs.txt \ + Clients.txt \ + CompilingSource.txt \ + ConfigFile.txt \ + Debugging.Authentication.txt \ + Debugging.ProcessTracing.txt \ + Debugging.Rawlog.txt \ + Debugging.Thunderbird.txt \ + Design.Arrays.txt \ + Design.AuthProcess.txt \ + Design.AuthProtocol.txt \ + Design.Buffers.txt \ + Design.Code.txt \ + Design.Dcrypt.txt \ + Design.DoveadmProtocol.HTTP.txt \ + Design.DoveadmProtocol.txt \ + Design.Dsync.txt \ + Design.Events.txt \ + Design.Indexes.Cache.txt \ + Design.Indexes.MailIndexApi.txt \ + Design.Indexes.MainIndex.txt \ + Design.Indexes.TransactionLog.txt \ + Design.Indexes.txt \ + Design.InputStreams.txt \ + Design.Lua.txt \ + Design.MailProcess.txt \ + Design.Memory.txt \ + Design.OutputStreams.txt \ + Design.ParameterForwarding.txt \ + Design.Plugins.txt \ + Design.Processes.txt \ + Design.Storage.ErrorHandling.txt \ + Design.Storage.Mail.txt \ + Design.Storage.MailNamespace.txt \ + Design.Storage.MailStorage.txt \ + Design.Storage.MailUser.txt \ + Design.Storage.Mailbox.Save.txt \ + Design.Storage.Mailbox.Search.txt \ + Design.Storage.Mailbox.Sync.txt \ + Design.Storage.Mailbox.Transaction.txt \ + Design.Storage.Mailbox.txt \ + Design.Storage.MailboxList.txt \ + Design.Storage.Plugins.txt \ + Design.Strings.txt \ + Design.txt \ + Dict.txt \ + Dictionary.txt \ + Director.txt \ + DomainLost.txt \ + Errors.ChgrpNoPerm.txt \ + Events.txt \ + FindMailLocation.txt \ + FinishBasicConfiguration.txt \ + HAProxy.txt \ + HowTo.AntispamWithSieve.txt \ + HowTo.EximAndDovecotSASL.txt \ + HowTo.ImapcProxy.txt \ + HowTo.PopBSMTPAndDovecot.txt \ + HowTo.PopRelay.txt \ + HowTo.PostfixAndDovecotSASL.txt \ + HowTo.Rootless.txt \ + HowTo.SimpleVirtualInstall.txt \ + HowTo.WriteConfiguration.txt \ + HowTo.txt \ + IMAPServer.Hibernation.txt \ + IMAPServer.txt \ + ImapMetadata.txt \ + IndexFiles.txt \ + LDA.Exim.txt \ + LDA.Indexing.txt \ + LDA.Postfix.txt \ + LDA.Qmail.txt \ + LDA.Sendmail.txt \ + LDA.txt \ + LMTP.Exim.txt \ + LMTP.txt \ + Logging.txt \ + LoginProcess.txt \ + MDA.txt \ + MTA.txt \ + MailLocation.LocalDisk.txt \ + MailLocation.Maildir.txt \ + MailLocation.SharedDisk.txt \ + MailLocation.dbox.txt \ + MailLocation.mbox.txt \ + MailLocation.txt \ + MailboxFormat.Cydir.txt \ + MailboxFormat.MH.txt \ + MailboxFormat.Maildir.txt \ + MailboxFormat.dbox.txt \ + MailboxFormat.imapc.txt \ + MailboxFormat.mailstore.txt \ + MailboxFormat.mbox.txt \ + MailboxFormat.mbx.txt \ + MailboxFormat.txt \ + MailboxSettings.txt \ + MboxChildFolders.txt \ + MboxLocking.txt \ + MboxProblems.txt \ + Migration.BincIMAP.txt \ + Migration.Courier.txt \ + Migration.Cyrus.txt \ + Migration.Dsync.txt \ + Migration.Gmail.txt \ + Migration.Linuxconf.txt \ + Migration.MailFormat.txt \ + Migration.Online.txt \ + Migration.Teapop.txt \ + Migration.UW.txt \ + Migration.Vm-pop3d.txt \ + Migration.txt \ + MissingMailboxes.txt \ + Mountpoints.txt \ + NFS.txt \ + Namespaces.txt \ + OSCompatibility.txt \ + POP3Server.txt \ + PasswordDatabase.BSDAuth.txt \ + PasswordDatabase.ExtraFields.AllowNets.txt \ + PasswordDatabase.ExtraFields.Host.txt \ + PasswordDatabase.ExtraFields.NoDelay.txt \ + PasswordDatabase.ExtraFields.NoLogin.txt \ + PasswordDatabase.ExtraFields.Proxy.txt \ + PasswordDatabase.ExtraFields.User.txt \ + PasswordDatabase.ExtraFields.txt \ + PasswordDatabase.IMAP.txt \ + PasswordDatabase.PAM.txt \ + PasswordDatabase.Shadow.txt \ + PasswordDatabase.Static.txt \ + PasswordDatabase.oauth2.txt \ + PasswordDatabase.txt \ + PerformanceTuning.txt \ + Pigeonhole.Installation.txt \ + Pigeonhole.ManageSieve.Clients.txt \ + Pigeonhole.ManageSieve.Configuration.txt \ + Pigeonhole.ManageSieve.Install.txt \ + Pigeonhole.ManageSieve.Troubleshooting.txt \ + Pigeonhole.ManageSieve.txt \ + Pigeonhole.Sieve.Configuration.Dict.txt \ + Pigeonhole.Sieve.Configuration.File.txt \ + Pigeonhole.Sieve.Configuration.LDAP.txt \ + Pigeonhole.Sieve.Configuration.txt \ + Pigeonhole.Sieve.Examples.txt \ + Pigeonhole.Sieve.Extensions.Duplicate.txt \ + Pigeonhole.Sieve.Extensions.Editheader.txt \ + Pigeonhole.Sieve.Extensions.Include.txt \ + Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt \ + Pigeonhole.Sieve.Extensions.Vacation.txt \ + Pigeonhole.Sieve.Extensions.Variables.txt \ + Pigeonhole.Sieve.Extensions.txt \ + Pigeonhole.Sieve.Plugins.Extdata.txt \ + Pigeonhole.Sieve.Plugins.Extprograms.txt \ + Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt \ + Pigeonhole.Sieve.Plugins.IMAPSieve.txt \ + Pigeonhole.Sieve.Plugins.Pipe.txt \ + Pigeonhole.Sieve.Plugins.txt \ + Pigeonhole.Sieve.Troubleshooting.txt \ + Pigeonhole.Sieve.Usage.txt \ + Pigeonhole.Sieve.txt \ + Pigeonhole.txt \ + Plugins.Apparmor.txt \ + Plugins.Autocreate.txt \ + Plugins.CharsetAlias.txt \ + Plugins.Compress.txt \ + Plugins.Expire.txt \ + Plugins.FTS.Lucene.txt \ + Plugins.FTS.Solr.txt \ + Plugins.FTS.Squat.txt \ + Plugins.FTS.txt \ + Plugins.LastLogin.txt \ + Plugins.Lazyexpunge.txt \ + Plugins.Listescape.txt \ + Plugins.MailCrypt.txt \ + Plugins.MailFilter.txt \ + Plugins.MailLog.txt \ + Plugins.MailboxAlias.txt \ + Plugins.Notify.txt \ + Plugins.NotifyStatus.txt \ + Plugins.PushNotification.txt \ + Plugins.QuotaClone.txt \ + Plugins.Snarf.txt \ + Plugins.Stats.txt \ + Plugins.Trash.txt \ + Plugins.VarExpandCrypt.txt \ + Plugins.Virtual.txt \ + Plugins.Welcome.txt \ + Plugins.Zlib.txt \ + Plugins.txt \ + PostLoginScripting.txt \ + PreAuth.txt \ + QuickConfiguration.txt \ + Quota.Configuration.txt \ + Quota.Count.txt \ + Quota.Dict.txt \ + Quota.Dirsize.txt \ + Quota.FS.txt \ + Quota.Maildir.txt \ + Quota.txt \ + Replication.txt \ + RunningDovecot.txt \ + SSL.CertificateClientImporting.txt \ + SSL.CertificateCreation.txt \ + SSL.DovecotConfiguration.txt \ + SSL.SNIClientSupport.txt \ + SSL.txt \ + Sasl.txt \ + SecurityTuning.txt \ + Services.txt \ + SharedMailboxes.ClusterSetup.txt \ + SharedMailboxes.Permissions.txt \ + SharedMailboxes.Public.txt \ + SharedMailboxes.Shared.txt \ + SharedMailboxes.Symlinks.txt \ + SharedMailboxes.txt \ + SocketUnavailable.txt \ + Statistics.Old.txt \ + Statistics.txt \ + Submission.txt \ + SystemUsers.txt \ + TestInstallation.txt \ + TestPop3Installation.txt \ + TimeMovedBackwards.txt \ + Timeouts.txt \ + Upgrading.1.0.txt \ + Upgrading.1.1.txt \ + Upgrading.1.2.txt \ + Upgrading.2.0.txt \ + Upgrading.2.1.txt \ + Upgrading.2.2.txt \ + Upgrading.2.3.txt \ + Upgrading.txt \ + UserDatabase.ExtraFields.txt \ + UserDatabase.NSS.txt \ + UserDatabase.Prefetch.txt \ + UserDatabase.Static.txt \ + UserDatabase.txt \ + UserIds.txt \ + Variables.txt \ + VirtualUsers.Home.txt \ + VirtualUsers.txt \ + WhyDoesItNotWork.txt \ + maildrop.txt \ + mutt.txt \ + uw2dovecot.sh.txt diff --git a/doc/wiki/Makefile.in b/doc/wiki/Makefile.in new file mode 100644 index 0000000..6aa234e --- /dev/null +++ b/doc/wiki/Makefile.in @@ -0,0 +1,920 @@ +# 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 = doc/wiki +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 $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +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)$(wikidir)" +DATA = $(wiki_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +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@ +@BUILD_DOCS_TRUE@wikidir = $(docdir)/wiki +@BUILD_DOCS_TRUE@wiki_DATA = $(wikifiles) +EXTRA_DIST = \ + $(wikifiles) + +wikifiles = ACL.txt \ + AixPluginsSupport.txt \ + AttachmentIndicator.txt \ + AuthDatabase.CheckPassword.txt \ + AuthDatabase.Dict.txt \ + AuthDatabase.LDAP.AuthBinds.txt \ + AuthDatabase.LDAP.PasswordLookups.txt \ + AuthDatabase.LDAP.Userdb.txt \ + AuthDatabase.LDAP.txt \ + AuthDatabase.Lua.txt \ + AuthDatabase.Passwd.txt \ + AuthDatabase.PasswdFile.txt \ + AuthDatabase.SQL.txt \ + AuthDatabase.VPopMail.txt \ + AuthDatabase.txt \ + Authentication.Caching.txt \ + Authentication.Kerberos.txt \ + Authentication.MasterUsers.txt \ + Authentication.Mechanisms.DigestMD5.txt \ + Authentication.Mechanisms.NTLM.txt \ + Authentication.Mechanisms.Winbind.txt \ + Authentication.Mechanisms.txt \ + Authentication.MultipleDatabases.txt \ + Authentication.PasswordSchemes.txt \ + Authentication.Penalty.txt \ + Authentication.Policy.txt \ + Authentication.RestrictAccess.txt \ + Authentication.txt \ + BasicConfiguration.txt \ + Chrooting.txt \ + Clients.NegativeUIDs.txt \ + Clients.txt \ + CompilingSource.txt \ + ConfigFile.txt \ + Debugging.Authentication.txt \ + Debugging.ProcessTracing.txt \ + Debugging.Rawlog.txt \ + Debugging.Thunderbird.txt \ + Design.Arrays.txt \ + Design.AuthProcess.txt \ + Design.AuthProtocol.txt \ + Design.Buffers.txt \ + Design.Code.txt \ + Design.Dcrypt.txt \ + Design.DoveadmProtocol.HTTP.txt \ + Design.DoveadmProtocol.txt \ + Design.Dsync.txt \ + Design.Events.txt \ + Design.Indexes.Cache.txt \ + Design.Indexes.MailIndexApi.txt \ + Design.Indexes.MainIndex.txt \ + Design.Indexes.TransactionLog.txt \ + Design.Indexes.txt \ + Design.InputStreams.txt \ + Design.Lua.txt \ + Design.MailProcess.txt \ + Design.Memory.txt \ + Design.OutputStreams.txt \ + Design.ParameterForwarding.txt \ + Design.Plugins.txt \ + Design.Processes.txt \ + Design.Storage.ErrorHandling.txt \ + Design.Storage.Mail.txt \ + Design.Storage.MailNamespace.txt \ + Design.Storage.MailStorage.txt \ + Design.Storage.MailUser.txt \ + Design.Storage.Mailbox.Save.txt \ + Design.Storage.Mailbox.Search.txt \ + Design.Storage.Mailbox.Sync.txt \ + Design.Storage.Mailbox.Transaction.txt \ + Design.Storage.Mailbox.txt \ + Design.Storage.MailboxList.txt \ + Design.Storage.Plugins.txt \ + Design.Strings.txt \ + Design.txt \ + Dict.txt \ + Dictionary.txt \ + Director.txt \ + DomainLost.txt \ + Errors.ChgrpNoPerm.txt \ + Events.txt \ + FindMailLocation.txt \ + FinishBasicConfiguration.txt \ + HAProxy.txt \ + HowTo.AntispamWithSieve.txt \ + HowTo.EximAndDovecotSASL.txt \ + HowTo.ImapcProxy.txt \ + HowTo.PopBSMTPAndDovecot.txt \ + HowTo.PopRelay.txt \ + HowTo.PostfixAndDovecotSASL.txt \ + HowTo.Rootless.txt \ + HowTo.SimpleVirtualInstall.txt \ + HowTo.WriteConfiguration.txt \ + HowTo.txt \ + IMAPServer.Hibernation.txt \ + IMAPServer.txt \ + ImapMetadata.txt \ + IndexFiles.txt \ + LDA.Exim.txt \ + LDA.Indexing.txt \ + LDA.Postfix.txt \ + LDA.Qmail.txt \ + LDA.Sendmail.txt \ + LDA.txt \ + LMTP.Exim.txt \ + LMTP.txt \ + Logging.txt \ + LoginProcess.txt \ + MDA.txt \ + MTA.txt \ + MailLocation.LocalDisk.txt \ + MailLocation.Maildir.txt \ + MailLocation.SharedDisk.txt \ + MailLocation.dbox.txt \ + MailLocation.mbox.txt \ + MailLocation.txt \ + MailboxFormat.Cydir.txt \ + MailboxFormat.MH.txt \ + MailboxFormat.Maildir.txt \ + MailboxFormat.dbox.txt \ + MailboxFormat.imapc.txt \ + MailboxFormat.mailstore.txt \ + MailboxFormat.mbox.txt \ + MailboxFormat.mbx.txt \ + MailboxFormat.txt \ + MailboxSettings.txt \ + MboxChildFolders.txt \ + MboxLocking.txt \ + MboxProblems.txt \ + Migration.BincIMAP.txt \ + Migration.Courier.txt \ + Migration.Cyrus.txt \ + Migration.Dsync.txt \ + Migration.Gmail.txt \ + Migration.Linuxconf.txt \ + Migration.MailFormat.txt \ + Migration.Online.txt \ + Migration.Teapop.txt \ + Migration.UW.txt \ + Migration.Vm-pop3d.txt \ + Migration.txt \ + MissingMailboxes.txt \ + Mountpoints.txt \ + NFS.txt \ + Namespaces.txt \ + OSCompatibility.txt \ + POP3Server.txt \ + PasswordDatabase.BSDAuth.txt \ + PasswordDatabase.ExtraFields.AllowNets.txt \ + PasswordDatabase.ExtraFields.Host.txt \ + PasswordDatabase.ExtraFields.NoDelay.txt \ + PasswordDatabase.ExtraFields.NoLogin.txt \ + PasswordDatabase.ExtraFields.Proxy.txt \ + PasswordDatabase.ExtraFields.User.txt \ + PasswordDatabase.ExtraFields.txt \ + PasswordDatabase.IMAP.txt \ + PasswordDatabase.PAM.txt \ + PasswordDatabase.Shadow.txt \ + PasswordDatabase.Static.txt \ + PasswordDatabase.oauth2.txt \ + PasswordDatabase.txt \ + PerformanceTuning.txt \ + Pigeonhole.Installation.txt \ + Pigeonhole.ManageSieve.Clients.txt \ + Pigeonhole.ManageSieve.Configuration.txt \ + Pigeonhole.ManageSieve.Install.txt \ + Pigeonhole.ManageSieve.Troubleshooting.txt \ + Pigeonhole.ManageSieve.txt \ + Pigeonhole.Sieve.Configuration.Dict.txt \ + Pigeonhole.Sieve.Configuration.File.txt \ + Pigeonhole.Sieve.Configuration.LDAP.txt \ + Pigeonhole.Sieve.Configuration.txt \ + Pigeonhole.Sieve.Examples.txt \ + Pigeonhole.Sieve.Extensions.Duplicate.txt \ + Pigeonhole.Sieve.Extensions.Editheader.txt \ + Pigeonhole.Sieve.Extensions.Include.txt \ + Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt \ + Pigeonhole.Sieve.Extensions.Vacation.txt \ + Pigeonhole.Sieve.Extensions.Variables.txt \ + Pigeonhole.Sieve.Extensions.txt \ + Pigeonhole.Sieve.Plugins.Extdata.txt \ + Pigeonhole.Sieve.Plugins.Extprograms.txt \ + Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt \ + Pigeonhole.Sieve.Plugins.IMAPSieve.txt \ + Pigeonhole.Sieve.Plugins.Pipe.txt \ + Pigeonhole.Sieve.Plugins.txt \ + Pigeonhole.Sieve.Troubleshooting.txt \ + Pigeonhole.Sieve.Usage.txt \ + Pigeonhole.Sieve.txt \ + Pigeonhole.txt \ + Plugins.Apparmor.txt \ + Plugins.Autocreate.txt \ + Plugins.CharsetAlias.txt \ + Plugins.Compress.txt \ + Plugins.Expire.txt \ + Plugins.FTS.Lucene.txt \ + Plugins.FTS.Solr.txt \ + Plugins.FTS.Squat.txt \ + Plugins.FTS.txt \ + Plugins.LastLogin.txt \ + Plugins.Lazyexpunge.txt \ + Plugins.Listescape.txt \ + Plugins.MailCrypt.txt \ + Plugins.MailFilter.txt \ + Plugins.MailLog.txt \ + Plugins.MailboxAlias.txt \ + Plugins.Notify.txt \ + Plugins.NotifyStatus.txt \ + Plugins.PushNotification.txt \ + Plugins.QuotaClone.txt \ + Plugins.Snarf.txt \ + Plugins.Stats.txt \ + Plugins.Trash.txt \ + Plugins.VarExpandCrypt.txt \ + Plugins.Virtual.txt \ + Plugins.Welcome.txt \ + Plugins.Zlib.txt \ + Plugins.txt \ + PostLoginScripting.txt \ + PreAuth.txt \ + QuickConfiguration.txt \ + Quota.Configuration.txt \ + Quota.Count.txt \ + Quota.Dict.txt \ + Quota.Dirsize.txt \ + Quota.FS.txt \ + Quota.Maildir.txt \ + Quota.txt \ + Replication.txt \ + RunningDovecot.txt \ + SSL.CertificateClientImporting.txt \ + SSL.CertificateCreation.txt \ + SSL.DovecotConfiguration.txt \ + SSL.SNIClientSupport.txt \ + SSL.txt \ + Sasl.txt \ + SecurityTuning.txt \ + Services.txt \ + SharedMailboxes.ClusterSetup.txt \ + SharedMailboxes.Permissions.txt \ + SharedMailboxes.Public.txt \ + SharedMailboxes.Shared.txt \ + SharedMailboxes.Symlinks.txt \ + SharedMailboxes.txt \ + SocketUnavailable.txt \ + Statistics.Old.txt \ + Statistics.txt \ + Submission.txt \ + SystemUsers.txt \ + TestInstallation.txt \ + TestPop3Installation.txt \ + TimeMovedBackwards.txt \ + Timeouts.txt \ + Upgrading.1.0.txt \ + Upgrading.1.1.txt \ + Upgrading.1.2.txt \ + Upgrading.2.0.txt \ + Upgrading.2.1.txt \ + Upgrading.2.2.txt \ + Upgrading.2.3.txt \ + Upgrading.txt \ + UserDatabase.ExtraFields.txt \ + UserDatabase.NSS.txt \ + UserDatabase.Prefetch.txt \ + UserDatabase.Static.txt \ + UserDatabase.txt \ + UserIds.txt \ + Variables.txt \ + VirtualUsers.Home.txt \ + VirtualUsers.txt \ + WhyDoesItNotWork.txt \ + maildrop.txt \ + mutt.txt \ + uw2dovecot.sh.txt + +all: all-am + +.SUFFIXES: +$(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 doc/wiki/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign doc/wiki/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): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-wikiDATA: $(wiki_DATA) + @$(NORMAL_INSTALL) + @list='$(wiki_DATA)'; test -n "$(wikidir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(wikidir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(wikidir)" || 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_DATA) $$files '$(DESTDIR)$(wikidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(wikidir)" || exit $$?; \ + done + +uninstall-wikiDATA: + @$(NORMAL_UNINSTALL) + @list='$(wiki_DATA)'; test -n "$(wikidir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(wikidir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +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 $(DATA) +installdirs: + for dir in "$(DESTDIR)$(wikidir)"; 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 mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-wikiDATA + +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 Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-wikiDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool 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-ps install-ps-am \ + install-strip install-wikiDATA installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags-am uninstall uninstall-am uninstall-wikiDATA + +.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/doc/wiki/MboxChildFolders.txt b/doc/wiki/MboxChildFolders.txt new file mode 100644 index 0000000..4c3bde4 --- /dev/null +++ b/doc/wiki/MboxChildFolders.txt @@ -0,0 +1,187 @@ +Mail folders containing both messages and sub-folders +----------------------------------------------------- + +Under mbox, it is not normally possible to have a mail folder which contains +both messages and sub-folders. This is because there would be a filesystem name +collision between the name of the mbox file containing the messages and the +name of the directory containing the sub-folders, for example: + + * Mail folder "foo" containing messages would be stored in a file at + '~/mail/foo'. + * Mail folder "foo/bar" containing messages would be stored in a file at + '~/mail/foo/bar', but this cannot happen because this relies on the + existence of a directory '~/mail/foo/' which can't exist because there is + already a file with that name. + +If however there is a requirement to be able to have a mail folder which +contains both messages and sub-folders, then there are a couple of ways to do +it: + + 1. Maildir++ layout + 2. Messages in named file + +These approaches are described in more detail below. + +Maildir++ layout +---------------- + +Under mbox, Dovecot normally stores mail folders in "filesystem" layout. In +this layout, mail folders are stored in mbox files (potentially under +subdirectories) with the same relative path as the mail folder path, for +example: + + * '~/mail/foo' - mbox file containing mail for mail folder "foo"; can not + create any mail sub-folders of "foo" + * '~/mail/bar/baz' - mbox file containing mail for mail folder "bar/baz"; can + not create any mail sub-folders of "bar/baz" + * ('~/mail/inbox' - mbox file containing mail for INBOX) + +However, Dovecot can be configured to keep mbox mail in a Maildir++-like +layout. This makes Dovecot keep mail in mbox files where all the mailbox folder +naming levels are separated with dots (with a leading dot), for example: + + * '~/mail/.foo' - mbox file containing mail for mail folder "foo" + * '~/mail/.foo.bar' - mbox file containing mail for mail folder "foo/bar". We + can now do this. + * '~/mail/.bar.baz' - mbox file containing mail for mail folder "bar/baz" + * ('~/mail/inbox' - mbox file containing mail for INBOX) + +This can be enabled by adding ':LAYOUT=maildir++' to the mail location, for +example: + +---%<------------------------------------------------------------------------- +# Incomplete example. Do not use! +mail_location = mbox:~/mail:LAYOUT=maildir++ +---%<------------------------------------------------------------------------- + +However there is a problem. Under mbox, setting 'LAYOUT=maildir++' alone leaves +Dovecot unable to place index files, which would likely result in performance +issues. So when using 'LAYOUT=maildir++' with mbox, it is advisable to also +configure 'INDEX'. Now, mail files (other than 'inbox') all have names +beginning with a dot, so if we like we can store other things in the '~/mail' +directory by using names which do not begin with a dot. So we could think to +use 'INDEX' to indexes at '~/mail/index/', for example: + +---%<------------------------------------------------------------------------- +# Incomplete example. Do not use! +mail_location = mbox:~/mail:LAYOUT=maildir++:INDEX=~/mail/index +---%<------------------------------------------------------------------------- + +If we do this, then indexes will be kept at '~/mail/index/' and this will not +clash with any names used for mail folders. There is one more thing we may want +to consider though. By default Dovecot will maintain a list of subscribed +folders in a file '.subscriptions' under the mail location root. In this case +that means it would end up at '~/mail/.subscriptions'. This would then mean +that it would be impossible to create a mail folder called "subscriptions". We +can get around this by using the 'CONTROL' parameter to move the +'.subscriptions' file somewhere else, for example into the directory +'~/mail/control' (again choosing a name which doesn't begin with a dot so we +don't collide with the names of mbox files storing mail folders). That gives +us: + +---%<------------------------------------------------------------------------- +# Trick mbox configuration which allows a mail folder which contains both +# messages and sub-folders +mail_location = +mbox:~/mail:LAYOUT=maildir++:INDEX=~/mail/index:CONTROL=~/mail/control +---%<------------------------------------------------------------------------- + +This then allows mail folders which contains both messages and sub-folders +without possibility of naming collisions between mail folders and other data. + +There is one further wrinkle. Specifying ':LAYOUT=maildir++' for mbox changes +the default hierarchy separator from a slash to a dot. This should not be a +problem for IMAP clients as the hierarchy separator is exposed through IMAP. +However anything which expects to just "know" that the hierarchy separator is a +slash may get confused. This can be worked around by using a <namespace> +[Namespaces.txt] to set the folder separator back to a slash again. + +Messages in named file +---------------------- + +Under mbox, Dovecot normally stores mail folders in "filesystem" layout. In +this layout, mail folders are stored in mbox files (potentially under +subdirectories) with the same relative path as the mail folder path, for +example: + + * '~/mail/foo' - mbox file containing mail for mail folder "foo"; can not + create any mail sub-folders of "foo" + * '~/mail/bar/baz' - mbox file containing mail for mail folder "bar/baz"; can + not create any mail sub-folders of "bar/baz" + * ('~/mail/inbox' - mbox file containing mail for INBOX) + +In the example above, we can't create any sub-folders of "foo" because there is +a file 'foo' in the way. So we could think to get rid of that file and put a +directory there instead. But if we do that then we need somewhere to put the +messages for folder "foo". We could think to put them in a specially-named file +in the directory 'foo/'. Then if we wanted to create a sub-folder of "foo" we +would be fine because we could then do that. The rule would then be that +messages go into the specially-named file in the directory corresponding to the +mail folder name. We want want to choose a special name which would be unlikely +to collide with a folder name. We could think to use something like +'mBoX-MeSsAgEs'. Now, it turns out that you can configure Dovecot to do this +using the 'DIRNAME' parameter. For example, using a configuration of: + +---%<------------------------------------------------------------------------- +# Incomplete example. Do not use! +mail_location = mbox:~/mail:DIRNAME=mBoX-MeSsAgEs +---%<------------------------------------------------------------------------- + +we would get a layout like this: + + * '~/mail/inbox' - mbox file containing mail for INBOX + * '~/mail/foo/mBoX-MeSsAgEs' - mbox file containing mail for mail folder "foo" + + * '~/mail/foo/bar/mBoX-MeSsAgEs' - mbox file containing mail for mail folder + "foo/bar" + +However there is a problem. Under mbox, setting 'DIRNAME' alone leaves Dovecot +unable to place index files, which would likely result in performance issues, +or worse, if the index directory gets created first, this will obstruct the +creation of the mbox file. So when using 'DIRNAME' with mbox, it is also +necessary to configure 'INDEX'. The question then arises where to put index +files. + +Any directory under the '~/mail' directory could be considered as a mail +folder. We could think to use a name beginning with a dot, for example +'~/mail/.index' but that would then mean that it would not be possible to +create a mail folder called ".index"; unlikely, but it would be nice to have as +few implementation-specific restrictions as possible. + +In addition, by default, Dovecot will create a file '.subscriptions' at the +mail location root to hold a list of mailbox subscriptions. This would make it +impossible to create a mail folder called ".subscriptions". But we can move the +'.subscriptions' file to another directory by using the 'CONTROL' parameter. To +get round these issues, we can add another directory layer which separates +these purposes. For example, using the configuration: + +---%<------------------------------------------------------------------------- +# Trick mbox configuration which allows a mail folder which contains both +# messages and sub-folders +mail_location = +mbox:~/mail/mailboxes:DIRNAME=mBoX-MeSsAgEs:INDEX=~/mail/index:CONTROL=~/mail/control +---%<------------------------------------------------------------------------- + +would result in the following layout: + + * '~/mail/mailboxes/foo/mBoX-MeSsAgEs' - mbox file containing messages for + mail folder "foo" + * '~/mail/mailboxes/foo/bar/mBoX-MeSsAgEs' - mbox file containing messages for + mail folder "foo/bar" + * '~/mail/mailboxes/inbox' - mbox file containing messages for INBOX + * '~/mail/control/.subscriptions' - file containg list of subscribed mailboxes + + * '~/mail/index/INBOX/dovecot.index.*' - index files for INBOX + * '~/mail/index/foo/dovecot.index.*' - index files for mail folder "foo" + * '~/mail/index/foo/bar/dovecot.index.*' - index files for mail folder + "foo/bar" + * '~/mail/index/dovecot.mailbox.log' - other index files + +Restrictions on mail folder names are then minimised; we can't have mail +folders with the names "mBoX-M ''eSsAgEs", "dovecot.index.*, or +"dovecot.mailbox.log". + +Unlike the Maildir++ layout approach above, because we are still using +"filesystem" layout, the hierarchy separator remains as a slash. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MboxLocking.txt b/doc/wiki/MboxLocking.txt new file mode 100644 index 0000000..47c7c4e --- /dev/null +++ b/doc/wiki/MboxLocking.txt @@ -0,0 +1,70 @@ +Mbox Locking +============ + +The only standard way to lock an mbox is using a method called "dotlock". This +means that a file named '<mailbox-name>.lock' is created in the same directory +as the mailbox being locked. This works pretty well when the mbox is locked for +writing, but for reading it's very inefficient. That's why other locking +methods have been used. + +*It's important that all software that's reading or writing to mboxes use the +same locking settings.* If they use different methods, they might read/write to +an mbox while another process is modifying it, and see corrupted mails. If they +use the same methods but in a different order, they can both end up in a +deadlock. + +If you want to know more details about locking, see <the mbox format page> +[MailboxFormat.mbox.txt]. + +For Dovecot you can configure locking using the 'mbox_read_locks' and +'mbox_write_locks' settings. The defaults are: + +---%<------------------------------------------------------------------------- +mbox_read_locks = fcntl +mbox_write_locks = dotlock fcntl +---%<------------------------------------------------------------------------- + +Here's a list of how to find out the locking settings for other software: + +Procmail +-------- + +---%<------------------------------------------------------------------------- +# procmail -v 2>&1|grep Locking +Locking strategies: dotlocking, fcntl() +---%<------------------------------------------------------------------------- + +Postfix +------- + +Postfix has two different ways to deliver to mboxes. One is the "mailbox" +transport and another one is the "virtual" transport. + +---%<------------------------------------------------------------------------- +# postconf mailbox_delivery_lock +mailbox_delivery_lock = fcntl, dotlock +# postconf virtual_mailbox_lock +virtual_mailbox_lock = fcntl +---%<------------------------------------------------------------------------- + +In the above case, if you used the "mailbox" transport, you'd have to change +Dovecot's configuration to 'mbox_write_locks = fcntl dotlock' or vice versa for +Postfix. + +If you used the "virtual" transport, it doesn't really matter if the "dotlock" +is missing, since the "fcntl" is common with Dovecot and Postfix. + +mutt +---- + +---%<------------------------------------------------------------------------- +mutt -v|grep -i lock +---%<------------------------------------------------------------------------- + +Debian +------ + +Debian's policy specifies that all software should use "fcntl and then dotlock" +locking, but this probably applies only to most commonly used software. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MboxProblems.txt b/doc/wiki/MboxProblems.txt new file mode 100644 index 0000000..3b646b3 --- /dev/null +++ b/doc/wiki/MboxProblems.txt @@ -0,0 +1,134 @@ +mbox problems +============= + +External modifications +---------------------- + +In general Dovecot doesn't mind if you modify the mbox file externally. It's +fine if external software expunges messages or appends new ones. However moving +around existing messages, inserting messages in the middle of the file or +modifying existing messages isn't allowed. + +Especially modifying existing messages (eg. removing attachments) may cause all +kinds of problems. If you do that, at the minimum go and delete +'dovecot.index.cache' file from the mailbox, otherwise weird things may happen. +However IMAP protocol guarantees that messages don't change at all, and +deleting Dovecot's cache file doesn't clear clients' local caches, so it still +may not work right. + +If you insert messages, or if you "undelete" messages (eg. replace mbox from a +backup), you may see errors in Dovecot's logs: + +---%<------------------------------------------------------------------------- +mbox sync: UID inserted in the middle of mailbox /home/tss/mail/inbox (817 > +787, seq=18, idx_msgs=32) +---%<------------------------------------------------------------------------- + +This is normal. Dovecot just assigned new UIDs for the messages. See below for +other reasons why UID insertions could happen. + +Debugging UID insertions +------------------------ + +The above error message can be read as: "18th message in the mbox file +contained X-UID: 787 header, however the index file at that position told the +message was supposed to have UID 817. There are 32 messages currently in the +index file." + +There are four possibilities why the error message could happen: + + 1. Message with a X-UID: 787 header really was inserted in the mbox file. For + example you replaced mbox from a backup. + 2. Something changed the X-UID headers. I don't think any existing software + can cause this. + 3. The message was expunged from the index file, but for some reason it wasn't + expunged from the mbox file. The index file is updated only after a + successful mbox file modification, so this shouldn't really happen either. + 4. If this problem happens constantly, it could mean that you're sharing the + same index file for multiple different mboxes! + * This could happen if you let Dovecot do mailbox autodetection and it + sometimes uses '/var/mail/%u' (when it exists) and other times + '~/mail/inbox'. Use an explicit <mail_location> [MailLocation.txt] + setting to make sure the same INBOX is used. + * Another possibility is that you're sharing index files between multiple + users. Each user must have their own home directory. + +It's possible that broken X-UID headers in mails and 'mbox_lazy_writes=yes' +combination has some bugs. If you're able to reproduce such an error, please +let me know how. Dovecot versions earlier than 1.0.rc27 have some known bugs. + +UIDVALIDITY changes +------------------- + +UIDVALIDITY is stored in X-IMAPbase: or X-IMAP: header of the first message in +mbox file. This is done by both Dovecot and UW-IMAP (and Pine). It's also +stored in 'dovecot.index' file. It shouldn't normally change, because if it +does it means that client has to download all the messages for the mailbox +again. + +If the UIDVALIDITY in mbox file doesn't match the one in 'dovecot.index' file, +Dovecot logs an error: + +---%<------------------------------------------------------------------------- +UIDVALIDITY changed (1100532544 -> 1178155834) in mbox file +/home/user/mail/mailbox +---%<------------------------------------------------------------------------- + +This can happen when the following happens: + + 1. Dovecot accesses the mailbox saving the current UIDVALIDITY to + 'dovecot.index' file. + 2. The UIDVALIDITY gets lost from the mbox file + * X-IMAP: or X-IMAPbase: header gets lost because something else than + Dovecot or UW-IMAP deletes the first message + * The whole file gets truncated + * Something else than Dovecot deletes or renames the mbox + 3. The mailbox is accessed (or created if necessary) by UW-IMAP or Pine. It + notices that the mailbox is missing UIDVALIDITY, so it assigns a new + UIDVALIDITY and writes the X-IMAPbase: or X-IMAP: header. + * Also Dovecot that's configured to not use index files behaves the same. + 4. Dovecot accesses again the mailbox. UIDVALIDITY in the mbox file's header + doesn't match the one in 'dovecot.index' file. It logs an error and updates + the UIDVALIDITY in the index file to the new one. + +Crashes +------- + +Dovecot's mbox code is a bit fragile because of the way it works. However +instead of just corrupting the mbox file, it usually assert-crashes whenever it +notices an inconsistency. You may see crashes such as: + +---%<------------------------------------------------------------------------- +Panic: mbox /home/user/mail/mailbox: seq=2 uid=45 uid_broken=0 originally +needed 12 bytes, now needs 27 bytes +---%<------------------------------------------------------------------------- + +This is a bit difficult problem to fix. Usually this crash has been related to +Dovecot rewriting some headers that were broken. If you see these crashes, it +would really help if you were able to reproduce the crash. + +If you have such a mailbox which crashes every time when it's tried to be +opened, please put the mbox through mbox anonymizer +[http://dovecot.org/tools/mbox-anonymize.pl] and send it, the mailbox's +'dovecot.index' and 'dovecot.index.log' files to tss@iki.fi. None of those +files contain any actual message contents so it's be safe to send them. + +Avoiding crashes and errors +--------------------------- + +Since the problems usually have been related to broken headers, you should be +able to avoid them by filtering out all the Dovecot's internal metadata +headers. This is a good idea to do in any case. If you use <Dovecot LDA> +[LDA.txt] it does this filtering automatically. Otherwise you could do this in +your SMTP server. The headers that you should filter out are: + + * Content-Length + * Status + * X-IMAP + * X-IMAPbase + * X-Keywords + * X-Status + * X-UID + * X-UIDL (if you're using 'pop3_reuse_xuidl=yes') + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.BincIMAP.txt b/doc/wiki/Migration.BincIMAP.txt new file mode 100644 index 0000000..6a42ba3 --- /dev/null +++ b/doc/wiki/Migration.BincIMAP.txt @@ -0,0 +1,349 @@ +Binc IMAP +========= + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +If you're using only Binc IMAP, it's possible to do a transparent Dovecot +migration. + +Binc IMAP v1.2 and later +------------------------ + +binc2dovecot.pl attempts to do as perfect migration as possible. Basically it +reads Binc's uidlist files from the specified maildir and it's (sub-)folders +and generates 'dovecot-uidlist' files out of them. It also converts Binc's +subscription file. This script hasn't been tested with Binc IMAP< 1.2. + +If Binc has been used with the IMAPdir depot format, it need to be converted to +Maildir++ with the script IMAPdir2Maildir++ before running binc2dovecot.pl. + +IMAPdir2Maildir++ + +---%<------------------------------------------------------------------------- +#!/bin/bash +# BINC mailbox definition for the example parameters below +# Mailbox { +# depot = "IMAPdir", +# type = "Maildir", +# path = "Maildir", +# } + +# +# Parameters: set according to your local system settings +# + +# Path to the IMAPdir +IMAPdirName="${1}/Maildir" + +# Path to the new Maildir++ directory +maildirName="${1}/Maildir" + +# Name used for the inbox with IMAPdir +inboxName="INBOX" + +# the character . is invalid for Maildir++ +# What string shall it be replaced with? +dotReplacementString="_cdot_" + +# +# Below here nothing should need to be adjusted +# + +# Initialise some variables and settings +shopt -s dotglob +orgDir=$(pwd) + +# loop through all file names according to the pattern in $FILES +cd $IMAPdirName +FILES="*" +for file in $FILES +do + # Skip over Maildir++ directories + if [[ ${file:0:1} = "." && -e ${file}/maildirfolder ]] + then + continue + fi + # Skip over non-directory file names + if [[ ! -d $file ]] + then + continue + fi + + # Move INBOX contents according to Maildir++ specification + if [[ $file = $inboxName ]] + then + mv ${file}/* $maildirName + rmdir $file + continue + fi + + # create Maildir++ compliant new folder name + newFile=${file//\\\\/\\} + newFile=${newFile//\\./$dotReplacementString} + newFile=${newFile/#./$dotReplacementString} + newFile=.$newFile + + # rename folder name according to Maildir++ specification & add maildirfolder +file + mv "$file" "${maildirName}/$newFile" + owner=$(stat -c %u "${maildirName}/$newFile") + group=$(stat -c %g "${maildirName}/$newFile") + touch "${maildirName}/$newFile/maildirfolder" + chown $owner:$group "${maildirName}/$newFile/maildirfolder" + chmod 600 "${maildirName}/$newFile/maildirfolder" +done + +# Adapt subscriptions file +mv .bincimap-subscribed "${maildirName}/.bincimap-subscribed" +sed -i "s/\./$dotReplacementString/g" "${maildirName}/.bincimap-subscribed" + +# Return to original working directory +cd $orgDir +---%<------------------------------------------------------------------------- + +Usage: ./IMAPdir2Maildir++ /path/to/user + +binc2dovecot.pl + +---%<------------------------------------------------------------------------- +#!/usr/bin/perl + +use IO::File; +use IO::Dir; +use File::stat; +use File::Basename; +use strict; + +### Parameters to adapt to local cofiguration +# Name of the Maildir++ directory relative to the path passed as argument +my $mailbox = $ARGV[0]."/Maildir"; +# Name space used by BINC for private folders, with IMAPdir often = "" +our $namespace = "INBOX."; + +### Nothing should need to be changed below here +our $indent = 0; + +die("Mailbox doesn't exist") + if (!-d $mailbox); +parse_mailbox($mailbox); + +# Sanity check for namespace +my $subscriptionsSize = -s $mailbox.'/subscriptions'; +if ($subscriptionsSize == 0) { + print $/; + print $/; + print "WARNING: Your new subscriptions file is empty. Are you using the +correct namespace? If not re-run script with correct namespace parameter.", $/; +} + +sub parse_mailbox +{ + my ($mailbox) = @_; + print " " x $indent, "Parsing ", $mailbox, " ...", $/; + $indent += 2; + + my $mb = IO::Dir->new($mailbox) + or die("Unable to open mailbox $mailbox"); + while(my $file = $mb->read()) + { + my $absfile = $mailbox."/".$file; + next + if ($file eq "." || $file eq ".."); + if ($file eq ".bincimap-subscribed" && -f $absfile) + { + convert_subscribtions($absfile); + } + elsif ($file eq "bincimap-cache" && -f $absfile) + { + convert_cache($absfile); + } + elsif (substr($file, 0, 1) eq "." && -d $absfile && -e +$absfile."/maildirfolder") + { + parse_mailbox($absfile); + } + } + $mb->close(); + + $indent -= 2; + return 1; +} + +sub convert_cache +{ + my ($infile) = @_; + my $dir = dirname($infile); + my %uids = (); + + print " " x $indent, "Converting cache...", $/; + my $in = IO::File->new("<".$infile) + or die("Unable to open cache file $infile"); + my ($blockopen, $uid) = (0, 0); + my $id = ""; + while(my $line = $in->getline()) + { + if ($line =~ /^\d+\s{$/) + { + $blockopen = 1; + $uid = 0; + $id = ""; + next; + } + elsif ($blockopen && $line =~ /^}$/) + { + $blockopen = 0; + next; + } + elsif ($blockopen && $line =~ /^\t_UID\s=\s(\d+),?$/) + { + $uid = $1; + } + elsif ($blockopen && $line =~ /^\t_ID\s=\s"?(.*?)"?,?$/) + { + $id = $1; + } + if ($uid > 0 && length($id) > 0) + { + $uids{$uid} = $id; + $uid = 0; + $id = ""; + next; + } + } + $in->close(); + + if (scalar(keys(%uids)) <= 0) + { + print " " x $indent, "Empty uidlist. Skipping...", $/; + return 1; + } + + my $uidvalfile = $dir."/bincimap-uidvalidity"; + my ($uidvalidity, $uidnext) = (0, 0); + die("Error: File $uidvalfile doesn't exist") + if (!-f $uidvalfile); + $in = IO::File->new("<".$uidvalfile) + or die("Unable to open file: $uidvalfile"); + while(my $line = $in->getline()) + { + if ($line =~ /^\t_uidvalidity\s=\s(\d+),?$/) + { + $uidvalidity = $1; + } + elsif ($line =~ /^\t_uidnext\s=\s(\d+),?$/) + { + $uidnext = $1; + } + } + $in->close(); + + die("Error: either uidnext ($uidnext) or uidvalidity ($uidvalidity) is +invalid") + if ($uidnext <= 0 || $uidvalidity <= 0); + + my $version = 1; + my $outfile = $dir."/dovecot-uidlist";; + my $out = IO::File->new(">".$outfile) + or die("Unable to create cache file $outfile"); + $out->print($version, " ", $uidvalidity, " ", $uidnext, $/); + foreach my $uid (sort{$a <=> $b} (keys(%uids))) + { + $out->print($uid, " ", $uids{$uid}, $/); + } + $out->close(); + + my $stat = stat($infile); + chown($stat->uid, $stat->gid, $outfile); + chmod(0600, $outfile); + + return 1; +} + +sub convert_subscribtions +{ + my ($infile) = @_; + my $dir = dirname($infile); + my @cache = (); + + print " " x $indent, "Converting subscriptions...", $/; + my $in = IO::File->new("<".$infile) + or die("Unable to open file: $infile"); + while(my $line = $in->getline()) + { + next + if ($line !~ /^$namespace/); + $line =~ s/^$namespace?//; + $line =~ s/\n$//; + $line =~ s/\r$//; + $line =~ s/\//\./g; + next + if (length($line) <= 0); + next + if (!-d $dir."/.".$line); + push(@cache, $line) + if (scalar(grep{$_ eq $line}(@cache)) <= 0); + } + $in->close(); + + my $outfile = $dir."/subscriptions"; + my $out = IO::File->new(">".$outfile) + or die("Unable to create subscriptions file: $outfile"); + foreach my $subscription (@cache) + { + $out->print($subscription, $/); + } + $out->close(); + + my $stat = stat($infile); + chown($stat->uid, $stat->gid, $outfile); + chmod(0600, $outfile); + + return 1; +} +---%<------------------------------------------------------------------------- + +Usage: ./binc2dovecot.pl /path/to/user + +NOTE: /path/to/user/Maildir MUST exist. If "./Maildir" isn't your default +maildir-name, you can edit this at the top of the script. + +---%<------------------------------------------------------------------------- +Example 1: +# find /var/pop -mindepth 1 -maxdepth 1 -type d -exec +/path/to/binc2dove.pl {} \; + +Example 2: +# find /usr/local/vpopmail/domains -mindepth 2 -maxdepth 2 -type d -exec +/path/to/binc2dove.pl {} \; +---%<------------------------------------------------------------------------- + +Dovecot configuration +--------------------- + +Binc IMAP by default uses "INBOX/" as the IMAP namespace for private mailboxes. +If you want a transparent migration, you'll need to configure Dovecot to use a +namespace with "INBOX/" prefix as well. + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +namespace { + separator = / + prefix = INBOX/ + inbox = yes +} +---%<------------------------------------------------------------------------- + +Manual conversion +----------------- + + * Binc's '.bincimap-subscribed' file is compatible with Dovecot's + 'subscriptions' file, but you need to remove the "INBOX/" prefixes from the + mailboxes. + * Binc's 'bincimap-cache + bincimap-uidvalidity' are NOT compatible with + Dovecot's 'dovecot-uidlist' file. See file format documention or above + script for conversion. + * Binc's message flags are compatible with Dovecot (as they are specified by + the Maildir specification) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Courier.txt b/doc/wiki/Migration.Courier.txt new file mode 100644 index 0000000..5e87ab5 --- /dev/null +++ b/doc/wiki/Migration.Courier.txt @@ -0,0 +1,87 @@ +Courier IMAP/POP3 +================= + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +Courier v0.43 and later to Dovecot v1.1+ +---------------------------------------- + +courier-dovecot-migrate.pl +[https://dovecot.org/tools/courier-dovecot-migrate.pl] does a perfect migration +from Courier IMAP and POP3, preserving IMAP UIDs and POP3 UIDLs. It reads +Courier's 'courierimapuiddb' and 'courierpop3dsizelist' files and produces +'dovecot-uidlist' file from it. + +Before doing the actual conversion you can run the script and see if it +complains about any errors and such, for example: + +---%<------------------------------------------------------------------------- +# ./courier-dovecot-migrate.pl --to-dovecot --recursive /home +Finding maildirs under /home +/home/user/Maildir/dovecot-uidlist already exists, not overwritten +/home/user/Maildir2: No imap/pop3 uidlist files +Total: 69 mailboxes / 6 users + 0 errors +No actual conversion done, use --convert parameter +---%<------------------------------------------------------------------------- + +The actual conversion can be done for all users at once by running the script +with '--convert --recursive' parameters. Make sure the conversion worked by +checking that 'dovecot-uidlist' files were created to all maildirs (including +to subfolders). + +The '--recursive' option goes through only one level down in directory +hierarchies. This means that if you have some kind of a directory hashing +scheme (or even domain/username/), it won't convert all of the files. + +You can also convert each user as they log in for the first time, using +<PostLoginScripting.txt> with a script something like: + +---%<------------------------------------------------------------------------- +#!/bin/sh +# WARNING: Be sure to use mail_drop_priv_before_exec=yes, +# otherwise the files are created as root! + +courier-dovecot-migrate.pl --quiet --to-dovecot --convert Maildir +# This is for imap, create a similar script for pop3 too +exec /usr/local/libexec/dovecot/imap +---%<------------------------------------------------------------------------- + +FIXME: The script should rename also folder names that aren't valid mUTF-7. +Dovecot can't otherwise access such folders. + +Dovecot configuration +--------------------- + +Courier by default uses "INBOX." as the IMAP namespace for private mailboxes. +If you want a transparent migration, you'll need to configure Dovecot to use a +namespace with "INBOX." prefix as well. + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir + +namespace { + prefix = INBOX. + separator = . + inbox = yes +} +---%<------------------------------------------------------------------------- + +See also <Namespaces#Backwards Compatibility: Courier IMAP> [Namespaces.txt]. + +Manual conversion +----------------- + + * Courier's 'courierimapsubscribed' file is compatible with Dovecot's + 'subscriptions' file, but you need to remove the "INBOX." prefixes from the + mailboxes./This is true even if you set namespace prefix to "INBOX." as + described above./ + * Courier's 'courierimapuiddb' file is compatible with Dovecot's + 'dovecot-uidlist' file, just rename it. + * Courier's message flags are compatible with Dovecot (as they are specified + by the Maildir specification) + * Courier's message keywords implementation isn't Dovecot compatible. There + doesn't exist a simple way to convert the keywords manually. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Cyrus.txt b/doc/wiki/Migration.Cyrus.txt new file mode 100644 index 0000000..874c4bb --- /dev/null +++ b/doc/wiki/Migration.Cyrus.txt @@ -0,0 +1,81 @@ +Cyrus +===== + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +For POP3 UIDL compatibility, use one of: + +Cyrus versions up to v2.1.3: + ---%<----------------------------------------------------------------------- + # Cyrus (old format - up to v2.1.3) + pop3_uidl_format = %u + ---%<----------------------------------------------------------------------- + +Cyrus versions v2.1.4 and newer: + ---%<----------------------------------------------------------------------- + # Cyrus (new format - v2.1.4 and above) + pop3_uidl_format = %v.%u + ---%<----------------------------------------------------------------------- + +Mail storage migration +---------------------- + +There exists several scripts which can be used to convert Cyrus mail storages +to Maildir. They all read the Cyrus mail directories directly, so they don't +need a running Cyrus installation. + + * cyrus2dovecot [https://github.com/a-schild/cyrus2dovecot] (originally + [http://cyrus2dovecot.sw.fu-berlin.de/] by Freie Universität Berlin) allows + you to perform a server transition which is fully transparent to both POP + and IMAP users, as virtually all available metadata is preserved during the + conversion. This includes message UIDs, INTERNALDATEs, IMAP folder + subscriptions, the UIDVALIDITY and UIDNEXT values for each folder, as well + as all IMAP flags (including the first 26 user-defined keywords). Messages + marked as "delayed expunge" won't be migrated over. It also has support for + sieve migration and virtual domain support.Cyrus2Dovecot is supposed to work + with all Cyrus releases up to (at least) version 2.3.x. So far, it has been + tested with Cyrus 1.4, 2.1.18, 2.2.12, 2.3.12p2, 2.3.1. + * cyrus2courier [http://madness.at/projects/] is Dovecot-compatible. A + non-official v1.6ts release [http://dovecot.org/tools/] works up to Cyrus + v2.3.9. It should be able to preserve message UIDs, INTERNALDATEs, flags and + the first 26 keywords. It works only with the supported Cyrus versions, so + if Cyrus once again changes its internal formats this tool might break + again. + * cyrus2maildir.py [http://www.majid.info/mylos/weblog/2006/03/08-1.html] (for + Cyrus v2.2) preserves (only) INTERNALDATEs and \Seen flags. + * cyrus2dovecot [http://trukenmueller.de/cyrus2dovecot] (by Trukenmüller) + doesn't preserve timestamps or flags. + +You can also do the <migration via IMAP protocol using dsync> +[Migration.Dsync.txt]. + +Migration of passwords +---------------------- + +Some installations of Cyrus store passwords using /Cyrus/ SASL (not to be +confused with other SASL implementations). Passwords are stored in +'/etc/sasldb2', in Berkeley DB format. On Debian, the command 'db4.2_dump -p +/etc/sasldb2' may allow you access to the passwords. This could be +incorporated into a script to copy the passwords to an LDAP directory for use +with other mail servers (e.g. Dovecot). + +For Fedora Core 3 (and probably other versions) the command is just 'db_dump -p +/etc/sasldb2'. + +Namespaces +---------- + +Cyrus uses one of the following namespace configurations depending on the +altnamespace and unixhierarchysep options: + +---%<------------------------------------------------------------------------- +namespace inbox { + prefix = INBOX. # no altnamespace + #prefix = "" # altnamespace + separator = . # no unixhierarchysep + #separator = / # unixhierarchysep +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Dsync.txt b/doc/wiki/Migration.Dsync.txt new file mode 100644 index 0000000..cd3e9a7 --- /dev/null +++ b/doc/wiki/Migration.Dsync.txt @@ -0,0 +1,165 @@ +Migrating from any IMAP/POP3 server to Dovecot via dsync +======================================================== + +You need Dovecot v2.1.4+ for this. + +This page describes how to migrate mails to Dovecot from a remote IMAP/POP3 +server, preserving the IMAP UIDs, POP3 UIDLs and everything else. + +We'll assume that you can log in with master user "master" that has a password +"masteruser-secret". If you can't use master users, you'll need the users' +plaintext passwords and change the appropriate configuration to use them. + +See also server-specific details: + + * <Gmail> [Migration.Gmail.txt] + +Generic configuration +--------------------- + +dsync can be configured with features and workarounds. This is done by using +dsync_features setting in config file, such as + +---%<------------------------------------------------------------------------- +dsync_features = empty-header-workaround +---%<------------------------------------------------------------------------- + + * empty-header-workaround - enables dsync to cope with broken (Zimbra) servers + that sometimes send FETCH replies that are missing all the headers, even + though the mail actually has headers and another FETCH might return them. In + this situation dsync simply assumes for existing mails that the mails are a + match. (v2.2.25.3+) + +In v2.2.30+ dsync can avoid creating a single huge transaction that can fail +all at once. In case of failures the sync can be then done incrementally. + +---%<------------------------------------------------------------------------- +dsync_commit_msgs_interval = 100 # default in v2.2.30+ +---%<------------------------------------------------------------------------- + +In v2.2.33+ you can specify which email headers are used in incremental syncing +for checking whether the local email matches the remote email. This should only +include headers that can be efficiently downloaded from the remote server. The +default is: + +---%<------------------------------------------------------------------------- +dsync_hashed_headers = Date Message-ID +---%<------------------------------------------------------------------------- + +IMAP migration configuration +---------------------------- + +Set up configuration for the IMAP server you wish to migrate from: + +---%<------------------------------------------------------------------------- +imapc_host = imap.example.com + +# Authenticate as masteruser / masteruser-secret, but use a separate login +user. +# If you don't have a master user, remove the imapc_master_user setting. +imapc_user = %u +imapc_master_user = masteruser +imapc_password = masteruser-secret + +imapc_features = rfc822.size +# If you have Dovecot v2.2.8+ you may get a significant performance improvement +with fetch-headers: +imapc_features = $imapc_features fetch-headers +# Read multiple mails in parallel, improves performance +mail_prefetch_count = 20 + +# If the old IMAP server uses INBOX. namespace prefix, set: +#imapc_list_prefix = INBOX + +# for SSL: +#imapc_port = 993 +#imapc_ssl = imaps +#ssl_client_ca_dir = /etc/ssl +#imapc_ssl_verify = yes +# for <2.2.0: change ssl_client_ca_dir=/etc/ssl to imapc_ssl_ca_dir=/etc/ssl +---%<------------------------------------------------------------------------- + +POP3 migration configuration +---------------------------- + +Set up configuration for the POP3 server you wish to migrate from: + +---%<------------------------------------------------------------------------- +pop3c_host = pop3.example.com + +# Authenticate as masteruser / masteruser-secret, but use a separate login +user. +# If you don't have a master user, remove the pop3c_master_user setting. +pop3c_user = %u +pop3c_master_user = masteruser +pop3c_password = masteruser-secret + +# for SSL: +#pop3c_port = 995 +#pop3c_ssl = pop3s +# for <2.2.0: change ssl_client_ca_dir=/etc/ssl to pop3c_ssl_ca_dir=/etc/ssl +#ssl_client_ca_dir = /etc/ssl +#pop3c_ssl_verify = yes + +# make sure you have also the regular inbox namespace defined, e.g.: +#namespace inbox { +# inbox = yes +#} +namespace { + prefix = POP3-MIGRATION-NS/ + location = pop3c: + list = no + hidden = yes +} +protocol doveadm { + mail_plugins = $mail_plugins pop3_migration +} +plugin { + pop3_migration_mailbox = POP3-MIGRATION-NS/INBOX +} +---%<------------------------------------------------------------------------- + +The pop3-migration plugin is used to preserve POP3 UIDLs. When dsync is +handling IMAP INBOX and requests a POP3 UIDL, the plugin connects to the POP3 +server and figures out which IMAP messages match which POP3 messages and then +returns the appropriate POP3 UIDL. + +Running +------- + +Make sure destination is exactly as source, deleting/reverting any changes in +destination if necessary: + +---%<------------------------------------------------------------------------- +doveadm -o mail_fsync=never backup -R -u user@domain imapc: +---%<------------------------------------------------------------------------- + +or incremental one-way merge (it's ok to do changes on both sides): + +---%<------------------------------------------------------------------------- +doveadm -o mail_fsync=never sync -1 -R -u user@domain imapc: +---%<------------------------------------------------------------------------- + +(Fsyncing is disabled just for migration efficiency.) + +For per-user user/passwords use: + +---%<------------------------------------------------------------------------- +doveadm -o imapc_user=foo -o pop3c_user=foo -o imapc_password=bar -o +pop3c_password=bar backup -R -u user@domain imapc: +---%<------------------------------------------------------------------------- + +Once the users are migrated, remember to remove the pop3_migration plugin from +settings. + +Problems +-------- + + * POP3 message order (when it's different from IMAP message order) is + currently preserved only when destination is Maildir, sdbox or mdbox. + * If source POP3 server merges multiple IMAP mailboxes into one POP3 INBOX, + the migration won't be transparent. + * If source IMAP and POP3 servers return messages somehow differently, + pop3-migration plugin might not be able to match the messages + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Gmail.txt b/doc/wiki/Migration.Gmail.txt new file mode 100644 index 0000000..eccac1a --- /dev/null +++ b/doc/wiki/Migration.Gmail.txt @@ -0,0 +1,73 @@ +Migration from Gmail to Dovecot +=============================== + +You can use <dsync migration via IMAP> [Migration.Dsync.txt] protocol, but +there are a few things different with Gmail compared to other IMAP servers: + + * With Gmail when you delete a mail from POP3, the mail is only hidden from + future POP3 sessions, but it's still available via IMAP. If you wish to + preserve this functionality, there's a 'pop3_deleted_flag' setting in + Dovecot v2.2.2+. + * Gmail has labels. If a message has multiple labels, it shows up in multiple + IMAP folders, but it's still the same message and uses quota only once for + that message. Dovecot currently doesn't have such support, so the migration + will copy the message to multiple folders and each instance will use up + quota. There's currently no easy fix for this, although there are some + future plans to optionally not count message copies towards quota. + * Even though the quota is duplicated, it doesn't mean that the storage + usage has to be duplicated. Use the dsync -v parameter to avoid this. See + https://github.com/dovecot/core/commit/70df8f39fb3db7c49b18c855178f8172176a037a + * Gmail has virtual folders: "All Mail", "Starred" and "Important". From + migration point of view this means that the migration should skip most of + these folders, since their mails are in other folders anyway. With v2.2.3+ + you can tell dsync to skip these folders:'doveadm sync -x '\Flagged' -x + '\Important'' - by using the \flag parameters dsync finds the folders by + their SPECIAL-USE flag rather than their name (which may be different for + different user depending on their language). + * The "All Mail" folder actually contains also "archived mails" that don't + exist in any other folder. These mails need to be migrated. See below. + * Google requires that SSL/TLS be enabled to connect through IMAP. Make sure + that the following are enabled in your Dovecot configuration and set to + appropriate values based on your distribution (usually either one is + enough): + + ---%<---------------------------------------------------------------------- + ssl_client_ca_dir = (''your distribution's trusted TLS CA store (Fedora / + CentOS / Redhat uses /etc/pki/tls/ ))'' + ssl_client_ca_file = (''your distribution's trusted TLS CA file (Fedora / + CentOS / Redhat uses /etc/pki/tls/cert.pem ))'' + ---%<---------------------------------------------------------------------- + +GMail Migration Feature (v2.2.16+) +---------------------------------- + +There's a new 'imapc_features=gmail-migration' setting that helps with this +migration. It will: + + * Set the pop3_deleted_flag to mails that no longer exist in POP3 + * Return POP3 UIDL in GMail format so dsync can preserve it. + * Add a new $GmailHaveLabels keyword to archived mails in the \All mailbox, + which means those mails are not archived. You probably don't want to migrate + these mails. + * Note that mails in the \Important and \Flagged mailboxes are marked with + "\Important" and "\Starred" labels. If you don't migrate mails that have + $GmailHaveLabels then you must not exclude the \Flagged and \Important + mailboxes or some of the mails won't be migrated. + +For example use a command line: + +v2.2.16: + +---%<------------------------------------------------------------------------- +doveadm backup -a 'virtual/All' -F '-$GmailHaveLabels' -R -u user@domain imapc: +---%<------------------------------------------------------------------------- + +Unfortunately -F parameter isn't working in v2.2.17 & v2.2.18 because of +another parameter collision caused -F to be accidentally used for another +purpose. For v2.2.19+ use: + +---%<------------------------------------------------------------------------- +doveadm backup -a 'virtual/All' -O '-$GmailHaveLabels' -R -u user@domain imapc: +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Linuxconf.txt b/doc/wiki/Migration.Linuxconf.txt new file mode 100644 index 0000000..8c74d62 --- /dev/null +++ b/doc/wiki/Migration.Linuxconf.txt @@ -0,0 +1,64 @@ +Linuxconf Migration +=================== + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +For those of you who still remember it and use it, Linuxconf +[http://www.solucorp.qc.ca/linuxconf/] and its patched UW-IMAP companion VIMAP +[http://vimap.sourceforge.net/] had a really simple way of doing virtual +domains. They use standard passwd/shadow files, except each domain has its own +files, such as: + +---%<------------------------------------------------------------------------- +/etc/vmail/passwd.domain1.com +/etc/vmail/shadow.domain1.com +/etc/vmail/passwd.domain2.com +/etc/vmail/shadow.domain2.com +---%<------------------------------------------------------------------------- + +The mail is stored in <mbox format> [MailboxFormat.mbox.txt]. The INBOX exists +in '/var/spool/vmail/domain.com/user' and the other mailboxes in +'/vhome/domain.com/home/user'. + +To make Dovecot Linuxconf compatible, use these settings: + +---%<------------------------------------------------------------------------- +# passwd-like file for use with Linuxconf virtual domains +passdb { + driver = passwd-file + # Path for passwd-file + args = /etc/vmail/shadow.%d +} +userdb { + driver = passwd-file + # Path for passwd-file + args = /etc/vmail/passwd.%d +} + +mail_location = mbox:%h:INBOX=/var/spool/vmail/%d/%n +# Or if you want to place Dovecot's index/cache files to a separate directory +# to avoid adding them to backups: +#mail_location = +mbox:%h:INBOX=/var/spool/vmail/%d/%n:INDEX=/nobackup/imap-indexes/%d/%n +# Note that you may need to modify imap-indexes directory's permissions so +# that Dovecot can create the directories. +---%<------------------------------------------------------------------------- + +You also need to rename all the '.mailboxlist' files to '.subscriptions' to +preserve the mailbox subscriptions. + +The Linuxconf virtual email system is actually pretty good especially if you +are merging several existing single domain servers into one virtual domain +server. All you have to do is copy over your existing passwd/shadow files into +the /etc/vmail folder and rename them. You will need to do some editing on the +passwd file to point to where you wish to store your email. + +Exim works very well with this configuration. The Exim Wiki has a detailed +description of how to configure Exim [http://www.exim.org/eximwiki/Linuxconf] +to work with this virtual user structure. + +More information about Linuxconf can be found at their Home Site +[http://www.solucorp.qc.ca/linuxconf/]. Exim [http://www.exim.org] info here. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.MailFormat.txt b/doc/wiki/Migration.MailFormat.txt new file mode 100644 index 0000000..5fb1921 --- /dev/null +++ b/doc/wiki/Migration.MailFormat.txt @@ -0,0 +1,247 @@ +Converting between mailbox formats +================================== + +If you want a transparent migration, the biggest problem is preserving message +UIDs. See <Migration.txt> for the problems this may cause. If you do the +conversion with dsync, it preserves the UIDs. + +dsync +----- + +With dsync you can convert between any two mailbox formats that Dovecot +supports. As much of the mailbox state is preserved as possible. Typically it's +everything. See <Tools.Dsync.txt> for full documentation, here are only a +couple of examples: + + * mbox -> maildir migration. Set 'mail_location=maildir:~/Maildir' and run + 'dsync -u username mirror mbox:~/mail:INBOX=/var/mail/username' + * maildir -> mdbox migration. Set 'mail_location=mdbox:~/mdbox' and run 'dsync + -u username mirror maildir:~/Maildir' + * maildir -> sdbox migration. Set 'mail_location=sdbox:~/sdbox' and run 'dsync + -u username mirror maildir:~/Maildir' + +If you can successfully use dsync, you can skip the rest of this page. + +Converting from mbox to Maildir +------------------------------- + + * mb2md.pl with Dovecot modifications [http://dovecot.org/tools/mb2md.pl] can + convert mails, preserving UIDs and keywords. + * See also [attachment:migrateuser.sh script to drive the full migration + for a user]. + * This script requires patched 'mailutil' that supports Maildir. One + working 'mailutil' binary is RHEL4 PINE RPM + [http://dag.wieers.com/rpm/packages/pine/pine-4.64-3.el4.rf.i386.rpm] + from the DAG RPM Repository [http://dag.wieers.com/rpm/]. You could + also patch any version of pine/c-client and patch it with the Maildir + patches from + http://staff.washington.edu/chappa/pine/info/maildir.html. + * mb2md.py [http://dovecot.org/list/dovecot/2008-March/029736.html] can + convert also message UIDs. + * Yet another way to fix the UIDL migration problem. If you can generate an + uildlist ("messagenumber uidl" pairs), use my new -U uidllist option to + inject X-UILD: headers in the converted Maildir-file. The modified mb2md + script is avalable here:mb2md.xuidl.pl.gz + [http://www.chaos.dk/~sch/mb2md.xuidl/mb2md.xuidl.pl.gz]. I used this to + convert a cucipop installation to dovecot. pop3_reuse_xuidl=yes will do the + rest./-- <SoerenSchroeder.txt> 2009-02-13/ + +Check also the *User-Contributed Maildir Support* section on the qmail +community site [http://www.qmail.org/top.html#usersoft] for more choices. + +Example (user's mail in '~someuser/mail' and INBOX in '/var/mail/someuser'): + +---%<------------------------------------------------------------------------- +cd ~someuser +mb2md-3.20.pl -s mail -R +mb2md-3.20.pl -m -s /var/mail/someuser +mv mail mail.old +---%<------------------------------------------------------------------------- + +Now the mail will be in '~someuser/Maildir'. Do not forget to migrate the +subscriptions as well, otherwise the new maildir will seem to have only an +inbox when viewed through a mail client that supports them. This can be as +simple as copying the old '~someuser/mail/.subscriptions' file to +'~someuser/Maildir/subscriptions' (warning: I have not tested this extensively, +my subscription list and folder hierarchy was very simplistic). + +Hierarchy separator change +-------------------------- + +The default hierarchy separator with Maildir is '.' instead of '/' which is +common with mboxes. To keep the migration transparent to users, you can keep +the '/' separator by using <namespaces> [Namespaces.txt]. In any case you need +to replace the '/' with '.' in the subscriptions file: + + * ---%<---------------------------------------------------------------------- + sed 's:/:.:g' subscriptions > subscriptions.new + mv subscriptions.new subscriptions + ---%<---------------------------------------------------------------------- + +UW-IMAP's subscriptions file is in '~/.mailboxlist'. Dovecot's mbox +subscriptions is in '<mbox root dir>/.subscriptions'. Dovecot's Maildir +subscriptions is in '<maildir root>/subscriptions'. + +Also if you're migrating from UW-IMAP, you probably had "mail/" prefixes in the +mailbox names. You can again use <namespaces> [Namespaces.txt] to let clients +use the prefix, or you can tell your users to remove the namespace prefix from +their clients and change the subscriptions file: + +---%<------------------------------------------------------------------------- +sed 's/^mail\.//' subscriptions > subscriptions.new +mv subscriptions.new subscriptions +---%<------------------------------------------------------------------------- + +Note that because Maildir uses '.' as the hierarchy separator in filesystem, +it's not possible to have mailbox names containing '.' characters, even if you +changed the separator in namespaces. If you really want to have dots, the only +way to do this is by modifying the filesystem separator in 'MAILDIR_FS_SEP' and +'MAILDIR_FS_SEP_S' defines in 'src/lib-storage/index/maildir/maildir-storage.h' +file in the sources. Do not be tempted to change 'MAILDIR_FS_SEP' et al to +'/'; it won't work. + +Converting from Maildir to mbox +------------------------------- + +This is especially helpful if you want to archive your mail to a single file +for storage on a CD, a PC, etc. But it can also be helpful if you want to use +<mbox> [MailboxFormat.mbox.txt] with Dovecot. + +Use the reformail program that comes with maildrop +[http://www.courier-mta.org/maildrop/]. You can also use the formail program +that comes with procmail [http://www.procmail.org/]. Here is a simple script +showing how this works. + +To use it, adjust the script to invoke the right command according to your +system. + +Then 'cd' to the user's home directory (one level above 'Maildir') and run the +script with two arguments: the mailbox name (You can use "." for the top-level +folder), and the output mbox filename, for example: + +---%<------------------------------------------------------------------------- +cd ~hans +perl dw-maildirtombox.pl . >/tmp/hans-inbox +perl dw-maildirtombox.pl Sent >/tmp/hans-sent +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +#!/usr/bin/env perl +# dw-maildirtombox.pl +# dw = Dovecot Wiki :-) +# NOTE! The output file must not contain single quotes (')! +# figure out which program to run +$cmd="reformail -f1"; +system("$cmd </dev/null >/dev/null 2>/dev/null") == 0 or $cmd="formail"; +system("$cmd </dev/null >/dev/null 2>/dev/null") == 0 +or die "cannot find reformail or formail on your \$PATH!\nAborting"; +$dir=$ARGV[0]; +$outputfile=$ARGV[1]; +if (($outputfile eq '') || ($dir eq '')) +{ die "Usage: ./archivemail.pl mailbox outputfile\nAborting"; } +if (!stat("Maildir/$dir/cur") || !stat("Maildir/$dir/new")) +{ die "Maildir/$dir is not a maildir.\nAborting"; } +@files = (<Maildir/$dir/cur/*>,<Maildir/$dir/new/*>); +foreach $file (@files) { + next unless -f $file; # skip non-regular files + next unless -s $file; # skip empty files + next unless -r $file; # skip unreadable files + $file =~ s/'/'"'"'/; # escape ' (single quote) + $run = "cat '$file' | $cmd >>'$outputfile'"; + system($run) == 0 or warn "cannot run \"$run\"."; +} +---%<------------------------------------------------------------------------- + +Converting from MBX to Maildir +------------------------------ + +See the uw2dovecot.pl +[http://wiki.dovecot.org/Migration/UW?action=AttachFile&do=view&target=uw2dovecot.pl] +as mentioned on the <Migration.UW.txt> page. + +Converting from MBX to mbox +--------------------------- + +If you are using UW-IMAP and using the <MBX format> [MailboxFormat.mbx.txt], +you will need to convert it to <mbox> [MailboxFormat.mbox.txt] format. The +conversion process isn't pretty, but here is a script that works. You will need +to get and compile the mailutil program from the UW-IMAP web site +[http://www.washington.edu/imap/]. + +---%<------------------------------------------------------------------------- +#! /bin/sh +# Written by Marc Perkel - public domain +# overhauled by Matthias Andree, 2006 +# Usage: mbx-convert <filename> +# This code assumes there a user named "marc" with the primary group "marc". +# Change to any real user on your system. +# Yes - it look bizzare - but it gets the job done +# abort on error +set -e +user=marc +group=marc +homedir=/home/$user +if [ $# -ne 1 ] ; then + echo >&2 "Usage: $0 <filename>" + exit 1 +fi +# set up automatic cleanup +trap 'rm -f "${homedir}"/in.$$ "${homedir}"/out.$$' 0 +# First copy to users home dir and make the user the owner +cp "$1" "${homedir}/in.$$" +chown "$user":"$group" "${homedir}/in.$$" +# Run mailutil to convert as the user other than root +# mailutil requires this +su "$user" -c "mailutil copy in.$$ \#driver.unix/out.$$" +# create new file with same permissions/owner as old +cp -p "$1" "${1}.new" +# cat instead of copy leaves the original owner and permissions alone +if cat "${homedir}/out.$$" >"${1}.new" ; then + # cat succeeded, rename file into place + mv "${1}.new" "$1" +else + # cat failed, remove temp file + rm -f "${1}.new" + exit 1 +fi +---%<------------------------------------------------------------------------- + +Make a copy of some folders and test it first. Once you are satisfied that it +works then: + + * Write a script to convert all your files. + * Shut down your email system so files can't be modified + * Copy all your email to a backup location in case you have to revert + * Run the script + * Turn on Dovecot and test to verify it is working + * Important - make sure that you changed your SMTP configuration to write mbox + and not MBX. + * Turn on SMTP and verify it is all working + +*User comments:* + + * Is this hassle actually necessary? I have run mailutil as root like this + (mailutil as provided by the PINE 4.61 package for SUSE Linux + 10.0):'mailutil copy /tmp/foo.mbx.orig '#driver.unix//tmp/foo.test'' and did + not encounter any problems./-- <MatthiasAndree.txt>, 2006-05-18/ + * I did the same (using 'mailutil') but it doesn't maintain UIDs or + UIDVALIDITY. So I hacked[attachment:mbx2mbox.tgz this] together to do the + migration./-- <JulianFitzell.txt>, 2008-08-02/ + * Tried to do 'mailutil -v copy /tmp/foo '#driver.unix'/tmp/foo.unix', but + mailutil argues 'Can't open mailbox /tmp/foo: no such mailbox'. (mailutil as + from the Debian package uw-mailutils in Debian 5.0 Lenny) strace shows that + it searches for /tmp/foo/cur, i.e. a Maildir format mailbox. (WTF?) No idea + yet how to get this working. And I'm really glad when I got rid of MBX. -- + <AxelBeckert.txt>, 2009-06-19 + * As Mark Crispin always says: Don't use UW-IMAP with buggy (Maildir) + patches, compile your own. + * Same problem here - just reinstalled uw-imapd, used thunderbird to create + a "normal" mailfolder and copied the old folder contents - F.Fernandez + * At least with ubuntu mailutil from uw-mailutils it starts search from + root *ALWAYS* and if you start with slash it tries to convert from + maildir format 'mailutil -v copy /tmp/foo '#driver.unix'/tmp/foo.unix' = + convert maildir formated folder /tmp/foo/cur to mbox and 'mailutil -v + copy tmp/foo '#driver.unix'/tmp/foo.unix' = convert /tmp/foo file to mbox + - Manwe, 2010-03-09 + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Online.txt b/doc/wiki/Migration.Online.txt new file mode 100644 index 0000000..83d8bb8 --- /dev/null +++ b/doc/wiki/Migration.Online.txt @@ -0,0 +1,86 @@ +Online Mailbox Format Conversion +-------------------------------- + +This page aims to help with the tasks around planned mailbox migrations to e.g. +mdbox. To perform this exercise with minimum service interruption a Postfix +check can be implemented to put mail for the accounts to be migrated on HOLD: + +Postfix main.cf +--------------- + +---%<------------------------------------------------------------------------- +smtpd_recipient_restrictions = + [...] + check_recipient_access hash:/etc/postfix/recipient_maintenance, + permit_mynetworks, + reject_unauth_destination +---%<------------------------------------------------------------------------- + +/etc/postfix/recipient_maintenance +---------------------------------- + +---%<------------------------------------------------------------------------- +user@domain.tld HOLD Planned maintenance +user1@domain.tld HOLD Planned maintenance +user2@domain.tld HOLD Planned maintenance +[...] +---%<------------------------------------------------------------------------- + +Virtual Domain Aliases in Postfix can be easily used to populate the *List of +Recipients* to be converted (and to be queued on HOLD). The following basic +script helps populating the database and needs to be adapted to the actual +alias location: + +---%<------------------------------------------------------------------------- +#!/bin/bash +set -e +ALIASES="/etc/postfix/virtual" +MAINTALIASES="/etc/postfix/recipient_maintenance" + +doveadm user $1 || { echo 'user query failed.'; exit 1; } + +sed -e "s/\(.*\)$1/\1/;s/[ \t]*$//; s/$/ HOLD Planned maintenance: account=$1/" +$ALIASES >>$MAINTALIASES +grep $1 $MAINTALIASES +postmap $MAINTALIASES +echo '[ Complete ]' +---%<------------------------------------------------------------------------- + +Usage: + +---%<------------------------------------------------------------------------- +$ maintalias.sh user@domain.tld +---%<------------------------------------------------------------------------- + +Finally running *postmap recipient_maintenance* will create the database (in +case this part is not scripted). + +Actual Migration +---------------- + +Disable new logins for the users by adding 'allow_nets=' to their userdb +records, effectively disallowing ALL nets. Close open sessions if any: + +---%<------------------------------------------------------------------------- +$ doveadm who <user> +$ doveadm kick <user> +---%<------------------------------------------------------------------------- + +Convert the mailbox using the backup option: + +---%<------------------------------------------------------------------------- +$ dsync -u user@domain.tld backup mdbox:~/mdbox +---%<------------------------------------------------------------------------- + +Adjust userdb entries (if required) to reflect new 'mail_location'. Clear the +'recipient_maintenance' DB and undo 'allow_nets=' entries for the migrated +users. + +Finally release and requeue all mail previously held: + +---%<------------------------------------------------------------------------- +$ postsuper -r [ALL] +$ postqueue -f +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Teapop.txt b/doc/wiki/Migration.Teapop.txt new file mode 100644 index 0000000..c6498bb --- /dev/null +++ b/doc/wiki/Migration.Teapop.txt @@ -0,0 +1,73 @@ +Teapop 0.3.8 +============ + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +First at all sorry for my bad English. At work I had to migrate our existing +teapop/mbox setup to Dovecot/Maildir without change the UIDL. At first I think +I must set the option pop3_uidl_format to %Mf. But this doesn't work because +Teapop use different algorithm. So the only way I found was to set the X-UIDL +in the mbox and then use the mb2md script. My Co-worker Robert (many thanks for +programming the script) and I use the following script: + +---%<------------------------------------------------------------------------- +#!/usr/bin/perl +use Digest::MD5; +$context = Digest::MD5->new; +$gotmail = 0; +$counter = 1; +@mail = (); +while (<>) +{ + $line = $_; + if(/^From /) + { + if ($gotmail) + { + processMail (); + $counter++; + $context->reset(); + @mail = (); + } + $gotmail = 1; + } + push (@mail, $line); + next if ($line =~ /^(Status|X-Status|Lines|Content-Length): /); + $context->add($line); +} +if ($gotmail) +{ + processMail (); +} +else +{ + print STDERR "Mailbox is empty!\n"; +} +sub processMail () +{ + if ($#mail > 2) + { + print shift(@mail); + print shift(@mail); + print "X-UIDL: " . $context->hexdigest() . "\n"; + foreach $l (@mail) + { + print $l; + } + } + else + { + print STDERR "Email has less then 3 lines!\n"; + } +} +---%<------------------------------------------------------------------------- + +Usage: scriptname $mboxfile > $newbox + +The script read the mbox file and generate the MD5 sum, if the line don't start +with Status,X-Status,Lines and Content-Length, for each mail and insert the +X-UIDL: after the Return-Path line. After that you can use the mb2md +script.Important: You must set the 'pop3_reuse_xuidl=yes'. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.UW.txt b/doc/wiki/Migration.UW.txt new file mode 100644 index 0000000..5ba5e88 --- /dev/null +++ b/doc/wiki/Migration.UW.txt @@ -0,0 +1,137 @@ +UW-IMAP +======= + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +Namespaces +---------- + +By default UW-IMAP allows access to whole home directory. Since the home +directory may contain many other files as well, many people have chosen to +store their mails in the 'mail/' directory. This usually means that IMAP +clients have been configured to use 'mail/' as their "IMAP namespace prefix" +(the clients use different names for this). This doesn't work with Dovecot, +because Dovecot shows clients only the 'mail/' directory instead of the whole +home directory. So if the IMAP namespace was kept as 'mail/', Dovecot would try +to access the '~/mail/mail/' directory. + +There are three ways to fix this: + + 1. Remove the IMAP namespace prefix from the clients. + 2. Use namespaces to allow users to keep using the prefix. See "Backwards + Compatibility" in <Namespaces.txt> for an example configuration. + 3. Configure Dovecot to use home directory ('mail_location = + mbox:~/:INBOX=/var/mail/%u' and set 'mail_full_filesystem_access=yes'). The + latter is needed to make '~/mail' and '~user/mail' prefixes work. + +A typical mailbox location setting is: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +~/mbox file +----------- + +If a '~/mbox' file exists, UW-IMAP moves all the mails from '/var/mail/user' +into the '~/mbox' file. Currently Dovecot doesn't support this feature. There +are two possibilities to handle this: + + * Move everyone's mails to '~/mbox' and reconfigure your <MDA.txt> to deliver + new mails there by default. + * Move the existing mails from '~/mbox' back to '/var/mail/user'. + +Subscriptions +------------- + +UW-IMAP keeps the list of subscribed mailboxes in '~/.mailboxlist' file, while +Dovecot keeps them in '~/mail/.subscriptions' file. UW-IMAP's subscriptions +also contain the mailboxes with their prefixes, for example: + +---%<------------------------------------------------------------------------- +mail/box +~/mail/box2 +~user/mail/box3 +---%<------------------------------------------------------------------------- + + * If you removed the prefix from the IMAP clients, you'll also have to remove + these prefixes. + * You can use <uw2dovecot.sh.txt> script to copy all the users' '.mailboxlist' + files to '.subscriptions' files (without any prefix removal). + * It's possible to keep using the '.mailboxlist' filename (as long as it's in + the same directory) by modifying 'SUBSCRIPTION_FILE_NAME' define in + 'src/lib-storage/index/mbox/mbox-storage.h' + +UIDs, flags and keywords +------------------------ + +Dovecot uses UW-IMAP compatible metadata headers in mboxes, so it's possible to +migrate back and forth without losing any flags, keywords or cause IMAP UIDs to +change. + +Locking +------- + +UW-IMAP uses dotlock + flock() as the default locking combination, while +Dovecot uses dotlock + fcntl() by default. See <MboxLocking.txt> to determine +what are the correct lock settings for you. To use UW-IMAP compatible locking, +use: + +---%<------------------------------------------------------------------------- +mbox_read_locks = flock +mbox_write_locks = dotlock flock +---%<------------------------------------------------------------------------- + +DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA +------------------------------------------------- + +The first message in a mbox file may contain the subject "DON'T DELETE THIS +MESSAGE -- FOLDER INTERNAL DATA". This system message has information about the +mailbox and its state. + +Dovecot v1.0 uses these system messages. Keep them. + +Maildir conversion +------------------ + +If you're planning on migrating to Dovecot, you might also want to switch to +Maildir format as well. However it might be easier to first migrate from +UW-IMAP + mbox to Dovecot + mbox, and only then migrate the users to Maildir +format. + + * http://people.redhat.com/rkeech/maildir-migration.txt describes how to + migrate from UW-IMAP+mbox to Dovecot v0.99 + Maildir. Note that Dovecot + v0.99 has slightly different configuration file settings. + * <Migration.MailFormat.txt> has some migration scripts + * Here is a tool ([attachment:uw2dovecot.pl]) that will convert mbox, mbx, and + mix formatted UW-IMAP folders to Maildir/dovecot format. + +UW-POP3 (UW-IMAP's POP3 wrapper, ipop3d) +======================================== + +By default Dovecot generates POP3 UIDLs differently than UW-POP3, which causes +POP3 clients to redownload them as new messages. You can avoid this by setting: + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %08Xv%08Xu +---%<------------------------------------------------------------------------- + +To utilize the UW login conversion to lowecase, we recommend that you use the +following option: + +---%<------------------------------------------------------------------------- +auth_username_format = %Lu +---%<------------------------------------------------------------------------- + +You can confirm that the old and the new UIDLs match: + +---%<------------------------------------------------------------------------- +telnet localhost 110 +user test +pass test +uidl +quit +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.Vm-pop3d.txt b/doc/wiki/Migration.Vm-pop3d.txt new file mode 100644 index 0000000..550eafc --- /dev/null +++ b/doc/wiki/Migration.Vm-pop3d.txt @@ -0,0 +1,42 @@ +Vm-pop3d +======== + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read <Migration.txt> page first carefully.* + +Vm-pop3d uses the Message-ID: header data for UIDL, Dovecot does not support +this as it is not unique enough. The following Perl script will take the +Message-ID: data from all mails in a mbox and put the data into the X-UIDL: +header which Dovecot can use with the 'pop3_reuse_xuidl' setting: + +---%<------------------------------------------------------------------------- +#!/usr/bin/env perl +use Email::Simple; +my @totalmail=<STDIN>; +my $mail = join("",@totalmail); +my $email = Email::Simple->new($mail); +my $msg_id = $email->header("Message-Id"); +$msg_id =~ s#<##g; +$msg_id =~ s#>##g; +$email->header_set("X-UIDL", $msg_id); +print $email->as_string; +---%<------------------------------------------------------------------------- + +Requires email::simple, though the default setting in email::simple is to wrap +headers at 77 characters, which then causes problems when Outlook clients issue +UIDL, the workaround for this is to edit the Perl module, on Debian Etch this +involves editing '/usr/share/perl5/Email/Simple.pm', find "sub _fold" and +change {0,77} to a suitably higher value. On more recent versions of +email::simple, you may need to edit 'Headers.pm' instead, with the line to look +for being "_default_fold_at" + +You then run the script like so: + +---%<------------------------------------------------------------------------- +formail -q- -s perl script.pl < inbox > newinbox +---%<------------------------------------------------------------------------- + +When Dovecot now looks at newinbox, it will use the X-UIDL: header and clients +will not redownload mail. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Migration.txt b/doc/wiki/Migration.txt new file mode 100644 index 0000000..a1a5945 --- /dev/null +++ b/doc/wiki/Migration.txt @@ -0,0 +1,166 @@ +Migration to Dovecot +==================== + +*WARNING: Badly done migration will cause your IMAP and/or POP3 clients to +re-download all mails. Read this page carefully.* + +This page contains generic information related to migrating from another IMAP +or POP3 server to Dovecot. You should read this page, and then look at the +server-specific instructions: + + * <Migrating from any IMAP/POP3 server to Dovecot via dsync> + [Migration.Dsync.txt] - this is the recommended way to do all migrations + nowadays + * <UW-IMAP / UW-POP3> [Migration.UW.txt] + * <Linuxconf / VIMAP> [Migration.Linuxconf.txt] + * <Courier IMAP and POP3> [Migration.Courier.txt] + * <Cyrus IMAP and POP3> [Migration.Cyrus.txt] + * <vm-pop3d> [Migration.Vm-pop3d.txt] + * <teapop> [Migration.Teapop.txt] + * <Binc IMAP> [Migration.BincIMAP.txt] + * <Gmail> [Migration.Gmail.txt] + +Dovecot is one of the easiest IMAP servers to migrate to because of its +powerful configuration options. Dovecot can store email in both <mbox> +[MailboxFormat.mbox.txt] and <Maildir> [MailboxFormat.Maildir.txt] formats, +making it compatible with many existing servers. Dovecot is also very flexible +as to where it stores the email. It supports many different databases for +storing <passwords> [PasswordDatabase.txt] <user information> +[UserDatabase.txt]. + +Migration involves several separate tasks. You either need to convert your data +or make Dovecot read your existing data. Dovecot is very good at being +compatible and configurable, so it is likely to read your existing mailboxes +and user and password configurations. Tasks for conversion include: + + * <Where and how to store the email> [MailLocation.txt] + * <User authentication> [PasswordDatabase.txt] + * <User database configuration> [UserDatabase.txt] (home directory structure, + UID and GID) + +IMAP migration +-------------- + +When migrating mails from another IMAP server, you should make sure that these +are preserved: + + 1. Message flags + * Lost flags can be really annoying, you most likely want to avoid it. + 2. Message UIDs and UIDVALIDITY value + * If UIDs are lost, at the minimum clients' message cache gets cleaned and + messages are re-downloaded as new. + * Some IMAP clients store metadata by assigning it to specific UID, if + UIDs are changed these will be lost. + 3. Mailbox subscription list + * Users would be able to manually subscribe them again if you don't want + to mess with it. + +POP3 migration +-------------- + +When migrating mails from another POP3 server, you should try to preserve the +old UIDLs. If POP3 client is configured to keep mails in the server and the +messages' UIDLs change, all the messages are downloaded again as new messages. + +*Don't trust the migration scripts or anything you see in this wiki. Verify +manually that the UIDLs are correct before exposing real clients to Dovecot.* +You can do this by logging in using your old POP3 server, issuing UIDL command +and saving the output. Then log in using Dovecot and save its UIDL output as +well. Use e.g.'diff' command to verify that the lists are identical. Note that: + + * *If a client already saw changed UIDLs and decided to start re-downloading + mails, it's unlikely there is anything you can do to stop it. Even going + back to your old server is unlikely to help at that point.* + * Some (many?) POP3 clients also require that the message ordering is + preserved. + * Some clients re-download all mails if you change the hostname in the client + configuration. Be aware of this when testing. + +Some servers (UW, Cyrus) implementing both IMAP and POP3 protocols use the IMAP +UID and UIDVALIDITY values for generating the POP3 UIDL values. To preserve the +POP3 UIDL from such servers you'll need to preserve the IMAP UIDs and set +'pop3_uidl_format' properly. + +If the server doesn't use IMAP UIDs for the POP3 UIDL, you'll need to figure +out another way to do it. One way is to put the UIDL value into X-UIDL: header +in the mails and set 'pop3_reuse_xuidl=yes'. Some POP3 servers (QPopper) write +the X-UIDL: header themselves, making the migration easy. + +Some POP3 servers using Maildir uses the maildir base filename as the UIDL. You +can use 'pop3_uidl_format = %f' to do this. + +Here is a list of POP3 servers and how they generate their UIDs. Please update +if you know more: + + * UW-POP3: 'pop3_uidl_format = %08Xv%08Xu' + * qmail-pop3d: 'pop3_uidl_format = %f' + * Cyrus <= 2.1.3: 'pop3_uidl_format = %u' + * Cyrus >= 2.1.4: 'pop3_uidl_format = %v.%u' + * Citadel [http://www.citadel.org] (all versions): 'pop3_uidl_format = %u' + * Dovecot 0.99: 'pop3_uidl_format = %v.%u' + * tpop3d [http://www.ex-parrot.com/~chris/tpop3d/]: + * Maildir: 'pop3_uidl_format = %Mf' (MD5 sum of the maildir base filename + in hex) + * mbox: MD5 sum in hex of first 512 bytes of the message (or of the full + message if it's less than 512 bytes). + * popa3d [http://www.openwall.com/popa3d/] Generates MD5 sum from a couple of + headers. Dovecot uses compatible MD5 sums internally, but converts them into + UIDL strings in a bit different way. + * teapop [http://www.toontown.org/teapop/] 0.3.8: + * Maildir: 'pop3_uidl_format = %Mf' (MD5 sum of the maildir base filename + in hex) + * mbox: MD5 sum of the message without the following lines: + Status,X-Status,Lines and Content-Length. + * Cucipop mbox: v1.31 uses its own homebrew checksum based on headers and + body. Injection of X-UIDL: headers and pop3_reuse_xuidl=yes is the way to + go. + * qpopper: 'pop3_reuse_xuidl=yes' + * Courier: 'pop3_uidl_format = %f' + +IMAP <-> IMAP copying +--------------------- + +Note that you can do IMAP -> Dovecot migration using <dsync> +[Migration.Dsync.txt], which preserves IMAP UIDs and other metadata. This is +the recommended way of doing migrations. But there are also other options: + +If you don't care about preserving messages' UIDs, you can always migrate from +another IMAP server to Dovecot by downloading the messages via IMAP from the +old server and then uploading them to Dovecot via IMAP. + +There are several different tools for this, for example UW-IMAP +[http://www.washington.edu/imap/]'s mailutil, imapsync +[http://freshmeat.net/projects/imapsync], YippieMove +[http://www.yippiemove.com] and Larch [https://github.com/rgrove/larch]. + +imapsync +-------- + +Here's an example of how to run imapsync for a single user: + +---%<------------------------------------------------------------------------- +imapsync --syncinternaldates \ + --host1 192.168.1.57 --authmech1 LOGIN --user1 leah@example.com --password1 +secret \ + --host2 127.0.0.1 --authmech2 LOGIN --user2 leah@example.com --password2 +secret +---%<------------------------------------------------------------------------- + +It is quite easy to script this for a number of users, assuming you have their +passwords. Even if you do not, imapsync also supports logging in as an admin +user that has the ability to copy message for sub users, and a variety of other +authentication options. + +Larch +----- + +Here's an example of how to run Larch: + +---%<------------------------------------------------------------------------- +larch --from imap://mail1.example.com --to imap://mail2.example.com +---%<------------------------------------------------------------------------- + +When run it will ask you for usernames and passwords that will be used for +logging into servers, but you can also specify them on the command line. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/MissingMailboxes.txt b/doc/wiki/MissingMailboxes.txt new file mode 100644 index 0000000..752d5d4 --- /dev/null +++ b/doc/wiki/MissingMailboxes.txt @@ -0,0 +1,54 @@ +Missing mailboxes +================= + +Namespaces +---------- + +Dovecot by default doesn't use any "personal IMAP namespace prefix", which +clients often call either "IMAP namespace" or "IMAP prefix". With Courier you +probably had this set to "INBOX.", with UW-IMAP you might have set it to +"mail/". So, the solution is simply to set this field empty and restart your +IMAP client. If this helps, but you don't want to modify the clients' +configuration, see <Namespaces.txt>. + +Mail location +------------- + +If it didn't help, you might have <mail_location> [MailLocation.txt] setting +wrong. If it's unset, Dovecot tries to detect where your mail is stored by +looking at '~/Maildir', '~/mail', '/var/spool/mail/' and '/var/mail/' +directories. Depending on what you want, Dovecot might have guessed wrong. See +<TestInstallation.txt> for how to figure out what exactly is the problem. + +Missing INBOX (mbox) +-------------------- + +See if the mails are stored in '~/mbox' file. If '~/mbox' file exists, UW-IMAP +moves mails there from '/var/mail/user'. Dovecot supports this with <snarf +plugin> [Plugins.Snarf.txt]. + +Subscriptions +------------- + +Dovecot uses different filenames for list of mailbox subscriptions. You'll need +to rename these to ones that Dovecot wants (currently '.subscriptions' for mbox +and 'subscriptions' for Maildir). See <Migration.txt> for more information. + +Troubleshooting +--------------- + +If it's still not working, check first if the problem is with IMAP client or +server configuration. Easiest way to do this is to talk IMAP directly. (include +the A, B, C): + +---%<------------------------------------------------------------------------- +telnet imap.example.org 143 +A login username password +B list "" * +C logout +---%<------------------------------------------------------------------------- + +If you see a list of expected mailboxes, the problem is with your IMAP client. +If not, set 'mail_debug=yes' and look at the logs. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Mountpoints.txt b/doc/wiki/Mountpoints.txt new file mode 100644 index 0000000..1f920af --- /dev/null +++ b/doc/wiki/Mountpoints.txt @@ -0,0 +1,55 @@ +Mountpoints +=========== + +---%<------------------------------------------------------------------------- +master: Warning: /mnt/foo is no longer mounted. See +http://wiki2.dovecot.org/Mountpoints +---%<------------------------------------------------------------------------- + +Dovecot wants to keep track of mountpoints that might contain emails. If such a +mountpoint is suddenly not mounted, it's handled as an error condition rather +than as "this is a new user". This prevents other confusion that follows such a +situation. + +The list of mount points is maintained in the file /var/run/dovecot/mounts. + +Removing mountpoints +-------------------- + +If you permanently removed a mountpoint, you can tell Dovecot to forget about +it with: + +---%<------------------------------------------------------------------------- +doveadm mount remove /mnt/foo +---%<------------------------------------------------------------------------- + +Ignoring mountpoints +-------------------- + +Dovecot already internally filters out many mountpoints and filesystems that +are pretty much guaranteed not to contain any emails, but of course it can't +know about everything. This is especially problematic with filesystems that are +sometimes mounted and sometimes not. You can permanently tell Dovecot to ignore +a mountpoint with: + +---%<------------------------------------------------------------------------- +doveadm mount add /mnt/foo ignore +---%<------------------------------------------------------------------------- + +or ignore all mountpoints under '/mnt': + +---%<------------------------------------------------------------------------- +doveadm mount add '/mnt/*' ignore +---%<------------------------------------------------------------------------- + +Adding mountpoints +------------------ + +Mountpoints are added automatically when Dovecot starts up. If you mount a new +filesystem with mails while Dovecot is running you can also add it manually: + +---%<------------------------------------------------------------------------- +doveadm mount add /mnt/foo +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/NFS.txt b/doc/wiki/NFS.txt new file mode 100644 index 0000000..edd2ff6 --- /dev/null +++ b/doc/wiki/NFS.txt @@ -0,0 +1,161 @@ +NFS +=== + +NFS is commonly used in one of these ways: + + 1. Dovecot is run in a single computer. + 2. Dovecot is run in multiple computers, users are redirected more or less + randomly to different computers. + 3. Dovecot is run in multiple computers, each user is assigned a specific + computer which is used whenever possible. + +*The only way to reliably implement the 2nd setup is with the <director> +[Director.txt] service.* + +Dovecot configuration +--------------------- + +Single Dovecot server setup or <Dovecot director> [Director.txt] cluster setup: + +---%<------------------------------------------------------------------------- +mmap_disable = yes +#dotlock_use_excl = no # only needed with NFSv2, NFSv3+ supports O_EXCL and +it's faster +mail_fsync = always +mail_nfs_storage = no +mail_nfs_index = no +---%<------------------------------------------------------------------------- + +Multi-server setup that *tries* to flush NFS caches (increases NFS operations, +and *isn't fully reliable*), try not to use this: + +---%<------------------------------------------------------------------------- +mmap_disable = yes +#dotlock_use_excl = no # only needed with NFSv2, NFSv3+ supports O_EXCL and +it's faster +mail_fsync = always +# These settings slow things down and don't fully work, use director proxy +instead: +mail_nfs_storage = yes +mail_nfs_index = yes +---%<------------------------------------------------------------------------- + +Common issues +------------- + +Clock synchronization +--------------------- + +Run ntpd in the NFS server and all the NFS clients to make sure their clocks +are synchronized. If the clocks are more than one second apart from each others +and multiple computers access the same mailbox simultaneously, you may get +errors. + +NFS caching problems +-------------------- + +NFS caching is a big problem when multiple computers are accessing the same +mailbox simultaneously. The best fix for this is to prevent it from happening. +Configure your setup so that a user always gets redirected to the same server +(unless it's down). This also means that mail deliveries must be done by the +same server, or alternatively it shouldn't update index files. + +Dovecot flushes NFS caches when needed if you set 'mail_nfs_storage=yes', but +unfortunately this doesn't work 100%, so you can get random errors. + +Disabling NFS attribute cache helps a lot in getting rid of caching related +errors, but this makes the performance MUCH worse and increases the load on NFS +server. This can usually be done by giving 'actimeo=0' or 'noac' mount option. + +Index files +----------- + +If you keep the index files stored on NFS, you'll need to set +'mmap_disable=yes'. If you're not running lockd you'll have to set +'lock_method=dotlock', but this degrades performance. Note that some NFS +installations have problems with lockd. If you're beginning to get all kinds of +locking related errors, try if the problems go away with dotlocking. + +With mbox/Maildir formats (but not dbox!) it's also possible to store index +files on local disk instead of on NFS. If the user gets redirected to different +servers, the local indexes are automatically created/updated. If the user is +(nearly) always redirected to the same server this should be fine and you would +likely get higher performance than indexes stored on NFS, but if the server +changes it can be slow to recreate the index/cache files. + +Single computer setup +--------------------- + +This doesn't really differ from keeping mails stored locally. For better +performance you should keep index files stored in a local disk. + +Random redirects to multiple servers +------------------------------------ + +You should avoid this setup whenever possible. Besides the NFS cache problems +described above, mailbox contents can't be cached as well in the memory either. +This is more problematic with mbox than with maildir, but in both cases if a +client is redirected to a different server when reconnecting, the new server +will have to read some data via the NFS into memory, while the original server +might have had the data already cached. + +If you choose to use this setup, at the very least try to make connections from +a single IP redirected into the same server. This avoids the biggest problems +with clients that use multiple connections. + +Per-user redirects to multiple servers +-------------------------------------- + +This method performs a lot better than random redirects. It maximizes the +caching possibilities and prevents the problems caused by simultaneous mailbox +access. + +New mail deliveries are often still handled by different computers. This isn't +a problem with maildir as long as you're not using <LDA.txt> (i.e. +dovecot-uidlist file or index files shouldn't get updated). It shouldn't be a +problem with mboxes either as long as you're using fcntl locking. This problem +can be fully solved by using LMTP protocol to deliver the mails to the correct +server (possibly using Dovecot's LMTP proxy). + +NFS clients +=========== + +Here's a list of kernels that have been tried as NFS clients: + + * FreeBSD has a caching bug + [http://www.freebsd.org/cgi/query-pr.cgi?pr=123755] which causes problems + when mailbox is being accessed from different computers at the same time + * Linux 2.6.16: 'utime()' is buggy, fix in here + [http://client.linux-nfs.org/Linux-2.6.x/2.6.16/linux-2.6.16-007-fix_setattr_clobber.dif]. + With the fix applied, utime() seems to work perfectly. High-volume systems + may experience VFS lock sync issues and for these the complete patchset at + http://www.linux-nfs.org/Linux-2.6.x/2.6.16/linux-2.6.16-NFS_ALL.dif is + suggested and appears to work well in production. + * Linux 2.6.18: Seems to have intermittent caching issues. The same .config + with 2.6.20.1 has been tested and appears to work well. + * Linux 2.4.8: Has caching problems, don't know if they can be solved + * Solaris: If it's completely broken, see + http://dovecot.org/list/dovecot/2006-December/018145.html + * The Connectathon test suite is very useful to verify a healthy NFS setup, + see http://www.connectathon.org/nfstests.html + +Misc notes +========== + + * readdirplus isn't really needed by Dovecot and it can slow down some NFS + servers. Use "nordirplus" mount option to disable it. + * Dovecot doesn't care about root_squash setting, all the root-owned files are + in /var/run typically which is not in NFS + * In an environment using Debian (2.6.18) clients with Isilon NFS cluster + nodes - the following mount options were found to be the most + successful:'rsize=32768,wsize=32768,hard,fg,lock,nfsvers=3,tcp,retrans=0,nordirplus + 0 0' + * To learn more about NFS caching and other issues, mostly from a programmer's + point of view, see NFS Coding HOWTO + [http://iki.fi/tss/nfs-coding-howto.html] + * Use such permissions for the unmounted mount point root directory that + Dovecot can't create files under it. Otherwise if the NFS server isn't + mounted for any reason and user access mails, a new empty user mail + directory is created, which breaks things. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Namespaces.txt b/doc/wiki/Namespaces.txt new file mode 100644 index 0000000..3d05dac --- /dev/null +++ b/doc/wiki/Namespaces.txt @@ -0,0 +1,393 @@ +Namespaces +========== + +Contents + + + 1. Namespaces + + 1. Configuration + + 1. Namespace types + + 2. Hierarchy separators + + 3. Namespace settings + + 4. From userdb + + 2. Shared Mailboxes + + 3. Examples + + 1. Mixed mbox and Maildir + + 2. Backwards Compatibility: UW-IMAP + + 3. Backwards Compatibility: Courier IMAP + + 4. Per-user Namespace Location From SQL + + 5. Hidden subscription namespace + +Dovecot supports fully configurable namespaces. Their original and primary +purpose is to provide Namespace IMAP extension (RFC 2342 +[http://www.faqs.org/rfcs/rfc2342.html]) support, which allows giving IMAP +clients hints about where to locate mailboxes and whether they're private, +shared or public. Unfortunately most IMAP clients don't support this extension. + +Dovecot namespaces can be used for several other purposes too: + + * Changing the hierarchy separator + * Providing backwards compatibility when switching from another IMAP server + * Provides support for <public> [SharedMailboxes.Public.txt] and <shared> + [SharedMailboxes.Shared.txt] mailboxes + * Allows having mails in multiple different locations with possibly different + formats + +Configuration +------------- + +In v2.1+ there's a default inbox namespace added in '10-mail.conf'. If the +configuration doesn't explicitly specify a namespace (as was in v2.0 and older) +a default namespace is created automatically. + +The section name in namespaces (e.g. 'namespace sectionname { .. } ' is used +only internally within configuration. It's not required at all, but it allows +you to update an existing namespace (like how '15-mailboxes.conf' does) or have +userdb override namespace settings for specific users +('namespace/sectionname/prefix=foo/'). + +Namespace types +--------------- + +There are 3 types of namespaces: + + * private: Typically contains only user's own private mailboxes. + * shared: Contains other users' <shared mailboxes> + [SharedMailboxes.Shared.txt]. + * public: Contains <public mailboxes> [SharedMailboxes.Public.txt]. + +Hierarchy separators +-------------------- + +Hierarchy separator specifies the character that is used to separate a parent +mailbox from its child mailbox. For example if you have a mailbox "foo" with a +child mailbox "bar", the full path to the child mailbox would be "foo/bar" if +the separator was '/'. With a separator '.' it would be "foo.bar". + +IMAP clients, Sieve scripts and many parts of Dovecot configuration use the +configured separator when referring to mailboxes. This means that if you change +the separator, you may break things. + +However, changing the separator doesn't change the on-disk "layout separator". +For example: ++-----------------------------+--------+-----+----------+---------------------+ +| mail_location | Layout | NS | Mailbox | Directory | +| | sep | sep | name | | ++-----------------------------+--------+-----+----------+---------------------+ +| maildir:~/Maildir | . | . | foo.bar | ~/Maildir/.foo.bar/ | ++-----------------------------+--------+-----+----------+---------------------+ +| maildir:~/Maildir | . | / | foo/bar | ~/Maildir/.foo.bar/ | ++-----------------------------+--------+-----+----------+---------------------+ +| maildir:~/Maildir:LAYOUT=fs | / | . | foo.bar | ~/Maildir/foo/bar/ | ++-----------------------------+--------+-----+----------+---------------------+ +| maildir:~/Maildir:LAYOUT=fs | / | / | foo/bar | ~/Maildir/foo/bar/ | ++-----------------------------+--------+-----+----------+---------------------+ + +Note how the "namespace separator" changes only the "Mailbox name", but doesn't +change the directory where the mails are stored. The "layout separator" can +only be changed by changing the LAYOUT, which also affects the entire directory +structure. + +The layout separator also restricts the mailbox names. For example if the +layout separator is '.', you can't just set separator to '/' and create a +mailbox named "foo.bar". If you need to do this, you can use <listescape> +[Plugins.Listescape.txt] plugin to add escape the mailbox names as necessary. + +A commonly used separator is '/'. It probably causes the least amount of +trouble with different IMAP clients.'^' separator is troublesome with +Thunderbird.When '\' should be used it must be quoted, so one sets separator = +"\\" + +You should use the same hierarchy separator for all namespaces. All list=yes +namespaces must use the same separator, but if you find it necessary (e.g. for +backwards compatibility namespaces) you may use different separators for +list=no namespaces. + +Namespace settings +------------------ + + * type: See the "Namespace types" section above + * separator: See the "Hierarchy separators" section above + * prefix: The namespace prefix how it's visible in the NAMESPACE reply (if + hidden=no) and mailbox list (if list=yes). + * location: <Mailbox location> [MailLocation.txt]. The default is to use + 'mail_location' setting. + * inbox: "yes", if this namespace contains the user's INBOX. There is only one + INBOX, so only one namespace can have inbox=yes. + * hidden: "yes", if this namespace shouldn't be listed in NAMESPACE reply. + * list: "yes" (default), if this namespace and its mailboxes should be listed + by LIST command when the namespace prefix isn't explicitly specified as a + parameter. "children" means the namespace prefix list listed only if it has + child mailboxes. + * subscriptions: "yes" (default) if this namespace should handle its own + subscriptions. If "no", then the first parent namespace with + subscriptions=yes will handle it. For example if it's "no" for a namespace + with prefix=foo/bar/, Dovecot first sees if there's a prefix=foo/ namespace + with subscriptions=yes and then a namespace with an empty prefix. If neither + is found, an error is given. + * ignore_on_failure: Normally Dovecot fails if it can't successfully create a + namespace. Set this to "yes" to continue even if the namespace creation + fails (e.g. public namespace points to inaccessible location). + * disabled: Set to "yes" to quickly disable this namespace. Especially useful + when returned by a userdb lookup to give per-user namespaces. + * alias_for: If multiple namespaces point to the same location, they should be + marked as aliases against one primary namespace. This avoids duplicating + work for some commands (listing the same mailbox multiple times). The value + for alias_for is the primary namespace's prefix. For example if the primary + namespace has empty prefix, set 'alias_for=' for the alias namespace. Or if + primary has 'prefix=INBOX/', use 'alias_for=INBOX/'. + * mailbox { .. } settings can be used to autocreate/autosubscribe mailboxes + and set their SPECIAL-USE flags. + +From userdb +----------- + +To change namespace settings from userdb, you need to return +"namespace/<name>/setting=value". To create a namespace, make sure you first +return "namespace=<name>[,<name>,...]" and settings after this. Note that the +"namespace" setting must list all the namespaces that are used - there's +currently no way to simply "add" a namespace. + +---%<------------------------------------------------------------------------- +userdb { + driver = static + args = namespace=inbox,special +namespace/special/location=sdbox:/var/special/%u +namespace/special/prefix=special/ +} +---%<------------------------------------------------------------------------- + +Shared Mailboxes +---------------- + +See <SharedMailboxes.txt>. + +Examples +-------- + +Mixed mbox and Maildir +---------------------- + +If you have your INBOX as mbox in '/var/mail/username' and the rest of the +mailboxes in Maildir format under '~/Maildir', you can do this by creating two +namespaces: + +---%<------------------------------------------------------------------------- +namespace { + separator = / + prefix = "#mbox/" + location = mbox:~/mail:INBOX=/var/mail/%u + inbox = yes + hidden = yes + list = no +} +namespace { + separator = / + prefix = + location = maildir:~/Maildir +} +---%<------------------------------------------------------------------------- + +Without the 'list = no' setting in the first namespace, clients would see the +"#mbox" namespace as a non-selectable mailbox named "#mbox" but with child +mailboxes (the mbox files in the '~/mail' directory), ie. like a directory. So +specifically with 'inbox = yes', having 'list = no' is often desirable. + +Backwards Compatibility: UW-IMAP +-------------------------------- + +When switching from UW-IMAP and you don't want to give users full access to +filesystem, you can create hidden namespaces which allow users to access their +mails using their existing namespace settings in clients. + +---%<------------------------------------------------------------------------- +# default namespace +namespace inbox { + separator = / + prefix = + inbox = yes +} +# for backwards compatibility: +namespace compat1 { + separator = / + prefix = mail/ + hidden = yes + list = no + alias_for = +} +namespace compat2 { + separator = / + prefix = ~/mail/ + hidden = yes + list = no + alias_for = +} +namespace compat3 { + separator = / + prefix = ~%u/mail/ + hidden = yes + list = no + alias_for = +} +---%<------------------------------------------------------------------------- + +Backwards Compatibility: Courier IMAP +------------------------------------- + +*Recommended:* You can continue using the same INBOX. namespace as Courier: + +---%<------------------------------------------------------------------------- +namespace inbox { + separator = . + prefix = INBOX. + inbox = yes +} +---%<------------------------------------------------------------------------- + +*Alternatively:* Create the INBOX. as a compatibility name, so old clients can +continue using it while new clients will use the empty prefix namespace: + +---%<------------------------------------------------------------------------- +namespace inbox { + separator = / + prefix = + inbox = yes +} + +namespace compat { + separator = . + prefix = INBOX. + inbox = no + hidden = yes + list = no + alias_for = +} +---%<------------------------------------------------------------------------- + +The "separator=/" allows the INBOX to have child mailboxes. Otherwise with +"separator=." it wouldn't be possible to know if "INBOX.foo" means INBOX's +"foo" child or the root "foo" mailbox in "INBOX." compatibility namespace. With +"separator=/" the difference is clear with "INBOX/foo" vs. "INBOX.foo". + +The alternative configuration is not recommended, as it may introduce there +problems: + + * Although clients may do LIST INBOX.*, they may still do LSUB *, resulting in + mixed results. + * If clients used empty namespace with Courier, they now see the mailboxes + with different names, resulting in redownloading of all mails (except + INBOX). + * Some clients may have random errors auto-detecting the proper default + folders (Sent, Drafts etc) if the client settings refer to old paths while + the server lists new paths. + +See also <Migration.Courier.txt>. + +Per-user Namespace Location From SQL +------------------------------------ + +You need to give the namespace a name, for example "docs" below: + +---%<------------------------------------------------------------------------- +namespace docs { + type = public + separator = / + prefix = Public/ +} +---%<------------------------------------------------------------------------- + +Then you have an SQL table like: + +---%<------------------------------------------------------------------------- +CREATE TABLE Namespaces ( +.. + Location varchar(255) NOT NULL, +.. +) +---%<------------------------------------------------------------------------- + +Now if you want to set the namespace location from the Namespaces table, use +something like: + +---%<------------------------------------------------------------------------- +user_query = SELECT Location as 'namespace/docs/location' FROM Namespaces WHERE +.. +---%<------------------------------------------------------------------------- + +Hidden subscription namespace +----------------------------- + +If you follow some advice to separate your INBOX, shared/ and public/ +namespaces by choosing INBOX/ as your prefix for the inboxes you will see, that +you run into troubles with subscriptions.Thats, because there is no parent +namespace for shared/ and public/ if you set 'subscriptions = no' for those +namespaces.If you set 'subscriptions = yes' for shared/ and public/ you will +see yourself in the situation, that all users share the same subscription files +under the location of those mailboxes.One good solution is, to create a so +called "hidden subscription namespace" with subscriptions turned on and setting +'subscriptions = no' for the other namespaces: + +---%<------------------------------------------------------------------------- +namespace subscriptions { + subscriptions = yes + prefix = "" + list = no + hidden = yes +} + +namespace inbox { + inbox = yes + location = + subscriptions = no + mailbox Drafts { + auto = subscribe + special_use = \Drafts + } + mailbox Sent { + auto = subscribe + special_use = \Sent + } + mailbox "Sent Messages" { + special_use = \Sent + } + mailbox Spam { + auto = subscribe + special_use = \Junk + } + mailbox Trash { + auto = subscribe + special_use = \Trash + } + prefix = INBOX/ + separator = / +} +namespace { + type = shared + prefix = shared/%%u/ + location = mdbox:%%h/mdbox:INDEXPVT=%h/mdbox/shared + list = children + subscriptions = no +} +namespace { + type = public + separator = / + prefix = public/ + location = mdbox:/usr/local/mail/public/mdbox:INDEXPVT=%h + subscriptions = no + list = children +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/OSCompatibility.txt b/doc/wiki/OSCompatibility.txt new file mode 100644 index 0000000..57c21b5 --- /dev/null +++ b/doc/wiki/OSCompatibility.txt @@ -0,0 +1,51 @@ +Operating System Compatibility +============================== + +Dovecot is commonly used with Linux, Solaris, FreeBSD, OpenBSD, NetBSD and Mac +OS X. The following operating systems have also worked at least at some point +in Dovecot's existence: + + * BSD/OS 4.2 + * AIX 4.3 + * HP-UX 11i (Dovecot v1.1+) + * Tru64 ?.? + * UnixWare 7.1.4 + * IRIX 6.5 compiles, but SCM_RIGHTS seems to be broken. + * Cygwin apparently doesn't work nowadays. + * MidnightBSD (ports) + +If there are compiling problems with any OS, please send a bug report that +includes the error messages. + +SCM_RIGHTS +---------- + +There is one slightly problematic feature that Dovecot requires for +implementing privilege separation:*SCM_RIGHTS*. If it doesn't work correctly, +you'll get errors on 'fd_send()' or 'fd_read()' such as: + +---%<------------------------------------------------------------------------- +imap-login: fd_send(X) failed: Bad file number +---%<------------------------------------------------------------------------- + +If this happens, you can still use inetd and mailfront +[http://untroubled.org/mailfront/], which executes Dovecot's post-login IMAP or +POP3 binary. You can also try defining 'BUGGY_CMSG_MACROS' in +'src/lib/fdpass.c' to see if it helps. + +Compilers +--------- + +Dovecot should compile with any ANSI-C99 compiler. Dovecot has been known to +compile (at least once in its lifetime) with the following compilers: + + * GCC + * Clang + * Intel CC [http://www.intel.com/software/products/compilers/clin/] + * Tiny CC [http://www.tinycc.org] + * Sun Studio 11 + * Sun Studio 12 + * AIX xlC + * HP-UX cc + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/POP3Server.txt b/doc/wiki/POP3Server.txt new file mode 100644 index 0000000..1c389a7 --- /dev/null +++ b/doc/wiki/POP3Server.txt @@ -0,0 +1,166 @@ +Dovecot as a POP3 server +======================== + +Dovecot was primarily designed to be an IMAP server, so although it works fine +as a POP3 server, it's not really optimized for that. + +Maildir Performance +------------------- + +The main problem with Dovecot's POP3 implementation with Maildir is how to get +messages' size fast enough. The POP3 specification requires that the sizes are +reported exactly, not just approximately. This means that linefeeds must be +counted as CR+LF characters. Normally with Maildir the linefeeds are stored as +plain LF characters, which means that simply getting the file size would +produce the wrong POP3 message size. Some Maildir POP3 servers do this anyway +and violate the POP3 specification. + +Dovecot returns correct message sizes by reading the entire message and +counting the linefeeds correctly. After this is done, the "virtual size" is +stored into dovecot-uidlist file and future calculations can be avoided by +simply looking up the cached value. + +You can also avoid the initial message size calculation by storing the size +directly into the filename. You can do this by appending ,W=<size> at the end +of the base filename. For example '1199932653.M583975P6568.host,W=2211:2,' is a +file whose virtual size is 2211 bytes (and real size somewhat smaller). Note +that this must not be done for existing files, only to newly delivered mails. + +If Dovecot's LDA is used, dovecot-uidlist and the index files are updated upon +message arrival, therefore there will be no message-size performance issues. + +'pop3_fast_size_lookups=yes' setting in v2.0.5+ uses the virtual message sizes +when they're already available, but fallbacks to using the physical message +sizes (violating POP3 specifications, but then again a lot of POP3 servers do +that). + +mbox Performance +---------------- + +Index files are quite useless if your users don't keep mails in the server. +They get first updated when the POP3 session starts to include all the +messages, and after the user has deleted all the mails, they again get updated +to contain zero mails. With this kind of a session the index reads and writes +could have been avoided if the index files had just been completely disabled. + +You may want to try how performance changes if you disable indexes for POP3 +users. You can also try preserving indexes but try different values for +'mbox_min_index_size' setting. + +Do not disable indexing if there are users that do not delete messages after +downloading them. Also, if you use Dovecot LDA, indexes may be helpful to have +fast access to the message sizes. + +Session locking +--------------- + +By default Dovecot allows multiple POP3 connections to the same mailbox. This +is (was?) especially useful for dialup connections which die in the middle of +the download, because the half-dead connections won't keep the mailbox locked. + +Setting 'pop3_lock_session=yes' makes Dovecot lock the mailbox for the whole +session. This is also what the POP3 RFC [http://www.ietf.org/rfc/rfc1939.txt] +specifies that should be done. If another connection comes while the mailbox is +locked, Dovecot waits until the locking times out (2 minutes with +Maildir,'mbox_lock_timeout' with mbox). In future there will be a separate +'pop3_lock_timeout' setting which allows timing out sooner. + +Flag changes +------------ + +By default when a message is RETRed, \Seen flag is added to it. POP3 itself +doesn't support flags, but if the mailbox is opened with IMAP (eg. from +webmail) it's shown as seen. You can disable this (to get better performance) +with 'pop3_no_flag_updates=yes'. + +POP3 client workarounds +----------------------- + +'pop3_client_workarounds' setting allows you to set some workarounds to avoid +POP3 clients breaking with some broken mails. + +Following are supported + + * outlook-no-nuls - Converts 0x0 in data to 0x80 + * oe-ns-eoh - Add missing end of header line + +UIDL format +----------- + +UIDLs are used by POP3 clients to keep track of what messages they've +downloaded, typically only if you've enabled "keep messages in server" option. +If the UIDL changes, the existing messages are re-downloaded as new messages, +which the users don't really appreciate. + +Dovecot supports multiple different ways to set the UIDL format, mostly to make +migrations from other POP3 servers transparent by preserving the old UIDL +values. See <Migration.txt> for how to set the UIDLs to be compatible with your +previous POP3 server. + +For new POP3 servers, the easiest way to set up UIDLs is to use IMAP's +UIDVALIDITY and UID values. The default in Dovecot v1.1+ is: + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %08Xu%08Xv +---%<------------------------------------------------------------------------- + +Another good default is to use the message's global UID: + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %g +---%<------------------------------------------------------------------------- + +However, note that GUIDs may not be unique, as the GUID does not change when a +message is copied. (While copying is not possible using only POP3, it can be +done using IMAP, Sieve, or doveadm.) + +Some formats, such as the previous default '%v.%u', seem to have problems with +Outlook 2003. + +MD5 UIDL format (mbox-only) +--------------------------- + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %m +---%<------------------------------------------------------------------------- + +This works by getting the MD5 sum of a couple of message headers that uniquely +identify the message. The one good thing about MD5 format is that it doesn't +rely on the IMAP UID or UIDVALIDITY value. This allows you to modify the mbox +files in ways that Dovecot doesn't like, without causing the UIDLs to change. +For example: + + * Inserting messages in the middle of mbox files (eg. restoring mbox files + from backups can cause "Expunged message reappeared" errors) + * Reordering messages inside mbox + * <Other random problems> [MboxProblems.txt] causing UID renumbering (although + you should figure out why they're happening) + +The MD5 summing method however doesn't work well if you receive two identical +messages. Usually the MD5 sum is taken from these headers: + + * The first Received: header + * Delivered-To: header + +Normally there won't be a problem, because the MTA adds a unique identifier to +the first Received: header. If the same message is sent to multiple users in +one delivery, the Delivered-To: header is still different, making the MD5 sum +different. + +Except the MTA can be configured to support aliases, so for example sending the +mail to both root@ and webmail@ aliases causes the message to be delivered to +the same user, with identical Received: and Delivered-To: headers. The messages +really are identical, so their MD5 sums are also identical, and that can cause +some POP3 clients to keep downloading the messages over and over again, never +deleting them. + +To avoid this, there's also a 3rd header that is included in the MD5 sum +calculation: + + * X-Delivery-ID: header + +If you use <Dovecot's deliver> [LDA.txt] or IMAP APPEND and 'pop3_uidl_format = +%m', it always appends the X-Delivery-ID: header to saved mailbox. Any existing +X-Delivery-ID: headers in the saved mails are dropped. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.BSDAuth.txt b/doc/wiki/PasswordDatabase.BSDAuth.txt new file mode 100644 index 0000000..c13b800 --- /dev/null +++ b/doc/wiki/PasswordDatabase.BSDAuth.txt @@ -0,0 +1,7 @@ +BSDAuth +======= + +This is similar to <PAM> [PasswordDatabase.PAM.txt], but used by OpenBSD. It +supports 'cache_key' parameter the same way as PAM. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.AllowNets.txt b/doc/wiki/PasswordDatabase.ExtraFields.AllowNets.txt new file mode 100644 index 0000000..5c80fa4 --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.AllowNets.txt @@ -0,0 +1,43 @@ +Allow_nets extra field +---------------------- + +The allow_nets field is a comma separated list of IP addresses and/or networks +where the user is allowed to log in from. If the user tries to log in from +elsewhere, the authentication will fail the same way as if a wrong password was +given. + +Example: 'allow_nets=127.0.0.0/8,192.168.0.0/16,1.2.3.4,4.5.6.7'. + +IPv6 addresses are also allowed. IPv6 mapped IPv4 addresses (eg. +'::ffff:1.2.3.4') are converted to standard IPv4 addresses before matching. +Example:'allow_nets=::1,2001:abcd:abcd::0:0/80,1.2.3.4' + +passwd-file example +------------------- + +---%<------------------------------------------------------------------------- +user:{plain}password::::::allow_nets=192.168.0.0/24 +---%<------------------------------------------------------------------------- + +Keyword 'local' +--------------- + +The keyword 'local' is accepted for Non-IP connections like Unix socket. For +example, with a Postfix/LMTP delivery setup, you must include 'local' for +Postfix to verify the email account: + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = password=test allow_nets=local,127.0.0.1/32 +} +---%<------------------------------------------------------------------------- + +Otherwise, you will see this error in the log: + +---%<------------------------------------------------------------------------- +[/var/run/dovecot/lmtp] said: 550 5.1.1 <test2@example.com> User doesn't exist: +test2@example.com (in reply to RCPT TO command)) +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.Host.txt b/doc/wiki/PasswordDatabase.ExtraFields.Host.txt new file mode 100644 index 0000000..3a822c2 --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.Host.txt @@ -0,0 +1,75 @@ +Login referrals +=============== + +Login referrals are an IMAP extension specified by RFC 2221 +[https://tools.ietf.org/html/rfc2221]. Their purpose is to redirect clients to +an different IMAP4 server in case of hardware failures or organizational +changes. No client action is needed to invoke the LOGIN-REFERRALS capability: +the redirection is triggered by the server and occurs transparently. + +A security consideration is in order. As also stated by RFC 2221, a man in the +middle attack may use a rogue 'password catching' server to collectlogin data +and redirect your clients to their own rogue IMAP4 server. Although this would +be avoided by enforcing SSL/TLS. Login referrals are not supported by many +clients, so you probably don't want to use them anyway. + +Dovecot does not use login referrals by default. + +Configuration +------------- + +Note that the "host" field is also used by <proxying> +[PasswordDatabase.ExtraFields.Proxy.txt]. Login referrals are used only if the +proxy field isn't set. + +Login referrals can be used in two ways: + + 1. Tell the client to log into another server without allowing to log in + locally. + 2. Suggest the client to log into another server, but log it in anyway. + +The following fields can be used to configure login referrals: + + * 'host=s': The destination server's hostname. This field is required for + login referrals to be used. + * 'port=s': The destination server's port. The default is 143. + * 'destuser=s': Tell client to use a different username when logging in. + * 'reason=s': Optional reason to use as the reply to the login command. The + default is "Logged in, but you should use this server instead." + +Using the above settings you can suggest client to log in elsewhere. To require +it, you'll also have to return: + + * 'nologin': User is not allowed to log in. + * 'reason=s': Optional reason. The default is "Try this server instead.". + +Client support +-------------- + +The following clients are known to support login referrals: + + * Pine + * Outlook (but not Outlook Express) + +Examples +-------- + +Forward user to another server after successful authentication: + +---%<------------------------------------------------------------------------- +password_query = SELECT password, host, 'Y' as nologin FROM users WHERE userid += '%u' +---%<------------------------------------------------------------------------- + +Forward all users to another server without authentication: + +---%<------------------------------------------------------------------------- +password_query = \ + SELECT NULL AS password, 'Y' AS nopassword \ + 'imap2.example.com' AS host, \ + 'This server is down, try another one.' AS reason, \ + 'Y' AS nologin, \ + 'Y' AS nodelay +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.NoDelay.txt b/doc/wiki/PasswordDatabase.ExtraFields.NoDelay.txt new file mode 100644 index 0000000..96b0948 --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.NoDelay.txt @@ -0,0 +1,13 @@ +Nodelay extra field +=================== + +If the authentication fails, Dovecot typically waits 0-2 seconds before sending +back the "authentication failed" reply. If this field is set, no such delay is +done. This is commonly used with <proxying> +[PasswordDatabase.ExtraFields.Proxy.txt] and <login referrals> +[PasswordDatabase.ExtraFields.Host.txt]. + +Note that if PAM is used as the passdb, it adds an extra delay which can't be +removed. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.NoLogin.txt b/doc/wiki/PasswordDatabase.ExtraFields.NoLogin.txt new file mode 100644 index 0000000..fa7ea03 --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.NoLogin.txt @@ -0,0 +1,22 @@ +Nologin extra field +=================== + +User isn't allowed to log in even if the password matches. Commonly used with +<proxying> [PasswordDatabase.ExtraFields.Proxy.txt] and <login referrals> +[PasswordDatabase.ExtraFields.Host.txt], but may also be used standalone. One +way to use this would be perhaps: + + * 'nologin=y' + * 'reason=System is being upgraded, please try again later.' + +Unfortunately many clients don't show the reason to the user at all and just +assume that the password was given wrong, so it might not be a good idea to use +this unless the system will be down for days and you don't have a better way to +notify the users. + +Note: if you want to entirely block the user from logging in (i.e. account is +suspended), with no IMAP referral information provided, you must ensure that +neither 'proxy' nor 'host' are defined as one of the passdb extra fields. The +order of preference is:'proxy', 'host', then 'nologin'. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.Proxy.txt b/doc/wiki/PasswordDatabase.ExtraFields.Proxy.txt new file mode 100644 index 0000000..e86d27d --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.Proxy.txt @@ -0,0 +1,307 @@ +Proxying +======== + +Dovecot supports proxying IMAP, POP3, <Submission.txt> (v2.3+), <LMTP.txt>, and +<ManageSieve> [Pigeonhole.ManageSieve.txt] connections to other hosts. The +proxying can be done for all users, or only for some specific users. There are +two ways to do the authentication: + + 1. Forward the password to the remote server. The proxy may or may not perform + authentication itself. This requires that the client uses only plaintext + authentication, or alternatively the proxy has access to users' passwords + in plaintext. + 2. Let Dovecot proxy perform the authentication and login to remote server + using the proxy's <master password> [MasterPassword.txt]. This allows + client to use also non-plaintext authentication. + +The proxy is configured pretty much the same way as <login referrals> +[PasswordDatabase.ExtraFields.Host.txt], with the addition of 'proxy' field. +The common fields to use for both proxying ways are: + + * 'proxy' and 'proxy_maybe': Enables the proxying. Either one of these fields + is required. + * 'proxy_maybe' can be used to implement "automatic proxying". If the proxy + destination matches the current connection, the user gets logged in + normally instead of being proxied. If the same happens with 'proxy', the + login fails with "Proxying loops" error. + * 'proxy_maybe' with LMTP requires v2.1.0+ + * 'proxy_maybe' with 'host=<dns name>' requires v2.1.2+. + * 'auth_proxy_self' setting in dovecot.conf can be used to specify extra + IPs that are also considered to be the proxy's own IPs. (v2.1.2+) + * 'proxy_always' can be used with 'proxy_maybe' to conditionally do + proxying to specified remote host (host isn't self) or to let director + assign a backend host (host is self). So basically this setting just + always sends the 'proxy' extra field to login process, but not + necessarily the 'host'. Useful when dividing users across multiple + director clusters. + * 'host=s': The destination server's *IP address*. This field is required. + * 'source_ip=s': The source IP address to use for outgoing connections. + (v2.2.14+) + * 'port=s': The destination server's port. The default is 143 with IMAP and + 110 with POP3. + * 'protocol=s': The protocol to use for the connection to the destination + server. This field is currently only relevant for LMTP: it can be used to + select either "lmtp" or "smtp". + * 'destuser=s': Tell client to use a different username when logging in. + * 'proxy_mech=s': Tell client to use this SASL authentication mechanism when + logging in. + * 'proxy_timeout': Abort connection after this many seconds. + * 'proxy_nopipelining': Don't pipeline IMAP commands. This is a workaround for + broken IMAP servers that hang otherwise. (v2.2.11+) + * 'proxy_not_trusted': IMAP/POP3 proxying never sends the ID/XCLIENT command + to remote. (v2.2.27+) + +You can use SSL/TLS connection to destination server by returning: + + * 'ssl=yes': Use SSL and require a valid verified remote certificate. + *WARNING: Unless used carefully, this is an insecure setting!* Before + v2.0.16/v2.1.beta1 the host name isn't checked in any way against the + certificate's CN. The only way to use this securely is to only use and allow + your own private CA's certs, anything else is exploitable by a + man-in-the-middle attack. + * Note that 'ssl_client_ca_dir' or 'ssl_client_ca_file' aren't currently + used for verifying the remote certificate, although ideally they will be + in a future Dovecot version. For now you need to add the trusted remote + certificates to 'ssl_ca'. + * *NOTE:* LMTP proxying supports SSL/TLS only since v2.3.1 - for older + versions any ssl/starttls extra field is ignored. + * *NOTE:* doveadm proxying doesn't support SSL/TLS currently - any + ssl/starttls extra field is ignored. + * 'ssl=any-cert': Use SSL, but don't require a valid remote certificate. + * 'starttls=yes': Use STARTTLS command instead of doing SSL handshake + immediately after connected. + * 'starttls=any-cert': Combine starttls and ssl=any-cert. + * Additionally you can also tell Dovecot to send SSL client certificate to the + remote server using 'ssl_client_cert' and 'ssl_client_key' settings in + 'dovecot.conf' (v2.0.17+). + +Set 'login_trusted_networks' to point to the proxies in the backends. This way +you'll get the clients' actual IP addresses logged instead of the proxy's. + +The destination servers don't need to be running Dovecot, but you should make +sure that the Dovecot proxy doesn't advertise more capabilities than the +destination server can handle. For IMAP you can do this by changing +'imap_capability' setting. For POP3 you'll have to modify Dovecot's sources for +now ('src/pop3/capability.h'). Dovecot also automatically sends updated +untagged CAPABILITY reply if it detects that the remote server has different +capabilities than what it already advertised to the client, but some clients +simply ignore the updated CAPABILITY reply. + +v2.2.14+: If your proxy handles a lot of connections (~64k) to the same +destination IP you may run out of TCP ports. The only way to work around this +is to use either multiple destination IPs or ports, or multiple source IPs. +Multiple source IPs can be easily used by adding them to the 'login_source_ips' +setting in 'dovecot.conf'. You can also use hostnames which expand to multiple +IPs. By prefixing the setting with "?" (e.g.'login_source_ips = +?proxy-sources.example.com') Dovecot will use only those IPs that actually +exist in the server, allowing you to share the same config file with multiple +servers. It's probably better not to include the server's default outgoing IP +address in the setting, as explained here +[https://idea.popcount.org/2014-04-03-bind-before-connect/]. + +v2.2.19+: To avoid reconnection load spikes when a backend server dies, you can +tell proxy to spread the client disconnections over a longer time period (after +the server side of the connection is already +disconnected).'login_proxy_max_disconnect_delay' setting in 'dovecot.conf' +controls this (disabled by default). + +v2.2.29+: You can forward arbitratry variables by returning them prefixed with +'forward_'. Dovecot will use protocol dependant way to forward these variables +forward and they will appear on the other side as 'forward_variable' Currently +IMAP/POP3 only feature. This feature requires that the sending host is in +login_trusted_networks. For IMAP the feature works by providing the variables +as part of ID command, such as 'i ID ( ... "x-forward-var" "value")'. For POP3 +the forwarding mecahism uses 'XCLIENT' with 'FORWARD=<base64 encoded blob of +forwarded variables>' + +See <Design.ParameterForwarding.txt> for more details on forwarding. + +Moving users between backends/clusters (v2.2.25+) +------------------------------------------------- + +A safe way to move users from one cluster to another is to do it like: + + * Set delay_until=<timestamp> <passdb extra field> + [PasswordDatabase.ExtraFields.txt] where <timestamp> is the current + timestamp plus some seconds into future (e.g. 31s). You may also want to + append e.g. "+5" for some load balancing if a lot of users are moved at + once. + * Set host=<new host> passdb extra field. This update should be atomic + together with the delay_until field. + * Use "doveadm proxy kick" or "doveadm director kick" to kick the user's + existing connections. + * The processes may still continue running in the backend for a longer + time. If you want to be absolutely sure, you could also run a script to + kill -9 all processes for the user in the backend. This of course has its + own problems. + +The idea here is that while the user's connections are being kicked and the +backend processes are finishing up and shutting down, new connections are being +delayed in the proxy. This delay should be long enough that the user's existing +processes are expected to die, but not so large that clients get connection +timeouts. A bit over 30 seconds is likely a good value. Once the delay_until +timestamp is reached, the connections continue to the new host. + +If you have a lot of users, it helps to group some of them together and do the +host/delay_until updates on a per-group basis rather than per-user basis. + +ID command forwarding (v2.2.29+) +-------------------------------- + +If you want to forward, for some reason, the IMAP ID command provided by the +client, set + +---%<------------------------------------------------------------------------- +imap_id_retain=yes +---%<------------------------------------------------------------------------- + +This will also enable client_id variable in variable expansions for auth +requests, which will contain the ID command as IMAP arglist. + +Password forwarding +------------------- + +If you don't want proxy itself to do authentication, you can configure it to +succeed with any given password. You can do this by returning an empty password +and 'nopassword' field. + +Master password +--------------- + +This way of forwarding requires the destination server to support master user +feature. The users will be normally authenticated in the proxy and the common +proxy fields are returned, but you'll need to return two fields specially: + + * 'master=s': This contains the master username (e.g. "proxy"). It's used as + SASL auhentication ID. + * Alternatively you could return 'destuser=user*master' and set + 'auth_master_user_separator = *'. + * 'pass=s': This field contains the master user's password. + +See <Authentication.MasterUsers.txt> for more information how to configure +this. + +OAuth2 forwarding +----------------- + +If you want to forward <OAuth2> [PasswordDatabase.oauth2.txt] tokens, return +field proxy_mech=%m as extra field. + +Example password forwarding static DB configuration +--------------------------------------------------- + +See <PasswordDatabase.Static.txt> + +Example password forwarding SQL configuration +--------------------------------------------- + +Create the SQL table: + +---%<------------------------------------------------------------------------- +CREATE TABLE proxy ( + user varchar(255) NOT NULL, + host varchar(16) default NULL, + destuser varchar(255) NOT NULL default '', + PRIMARY KEY (user) +); +---%<------------------------------------------------------------------------- + +Insert data to SQL corresponding your users. + +Working data could look like this: ++------+-------------+-----------------+ +| user | host | destuser | ++------+-------------+-----------------+ +| john | 192.168.0.1 | | ++------+-------------+-----------------+ +| joe | 192.168.0.2 | joe@example.com | ++------+-------------+-----------------+ + +The important parts of 'dovecot.conf': + +---%<------------------------------------------------------------------------- +# If you want to trade a bit of security for higher performance, change these +settings: +service imap-login { + service_count = 0 +} +service pop3-login { + service_count = 0 +} + +# If you are not moving mailboxes between hosts on a daily basis you can +# use authentication cache pretty safely. +auth_cache_size = 4096 + +auth_mechanisms = plain +passdb { + driver = sql + args = /usr/local/etc/dovecot/dovecot-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +The important parts of 'dovecot-sql.conf.ext': + +---%<------------------------------------------------------------------------- +driver = mysql +connect = host=sqlhost1 host=sqlhost2 dbname=mail user=dovecot password=secret +password_query = SELECT NULL AS password, 'Y' as nopassword, host, destuser, +'Y' AS proxy FROM proxy WHERE user = '%u' +---%<------------------------------------------------------------------------- + +Example proxy_maybe SQL configuration +------------------------------------- + +Create the SQL table: + +---%<------------------------------------------------------------------------- +CREATE TABLE users ( + user varchar(255) NOT NULL, + domain varchar(255) NOT NULL, + password varchar(100) NOT NULL, + host varchar(16) NOT NULL, + home varchar(100) NOT NULL, + PRIMARY KEY (user) +); +---%<------------------------------------------------------------------------- + +The important parts of 'dovecot.conf': + +---%<------------------------------------------------------------------------- +# user/group who owns the message files: +mail_uid = vmail +mail_gid = vmail + +auth_mechanisms = plain + +passdb { + driver = sql + args = /usr/local/etc/dovecot/dovecot-sql.conf.ext +} +userdb sql { + driver = sql + args = /usr/local/etc/dovecot/dovecot-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +The important parts of 'dovecot-sql.conf.ext': + +---%<------------------------------------------------------------------------- +driver = mysql + +password_query = \ + SELECT concat(user, '@', domain) AS user, password, host, 'Y' AS proxy_maybe +\ + FROM users WHERE user = '%n' AND domain = '%d' + +user_query = SELECT user AS username, domain, home \ + FROM users WHERE user = '%n' AND domain = '%d' +---%<------------------------------------------------------------------------- + +Example proxy LDAP configuration +-------------------------------- + +see: <PasswordDatabase.ExtraFields.txt> for more information, and a worked out +example + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.User.txt b/doc/wiki/PasswordDatabase.ExtraFields.User.txt new file mode 100644 index 0000000..5c191e6 --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.User.txt @@ -0,0 +1,27 @@ +User extra field +================ + +This is mostly useful in case-insensitive username lookups to get the username +returned back using the same casing always. Otherwise depending on your +configuration it may cause problems, such as '/var/mail/user' and +'/var/mail/User' mailboxes created for the same user. + +An example 'password_query' in 'dovecot-sql.conf.ext' would be: + +---%<------------------------------------------------------------------------- +password_query = \ + SELECT concat(user, '@', domain) AS user, password \ + FROM users \ + WHERE user = '%n' and domain = '%d' +---%<------------------------------------------------------------------------- + +You can also update "username" and "domain" fields separately: + +---%<------------------------------------------------------------------------- +password_query = \ + SELECT user AS username, domain, password \ + FROM users \ + WHERE user = '%n' and domain = '%d' +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.ExtraFields.txt b/doc/wiki/PasswordDatabase.ExtraFields.txt new file mode 100644 index 0000000..bffebfb --- /dev/null +++ b/doc/wiki/PasswordDatabase.ExtraFields.txt @@ -0,0 +1,105 @@ +Password database extra fields +============================== + +The primary purpose of a password database lookup is to return the password for +a given user. It may however also return other fields which are treated +specially: + + * * <user> [PasswordDatabase.ExtraFields.User.txt]*: Change the username (eg. + lowercase it). + * *login_user*: Master passdb can use this to change the username. (v2.2.13+) + * * <allow_nets> [PasswordDatabase.ExtraFields.AllowNets.txt]*: Allow user to + log in from only specified IPs (checks against remote client IP). + * *allow_real_nets*: Allow user's network connection to log in from only + specified IPs (checks against /real/ remote IP, e.g. a Dovecot proxy). + * * <proxy and proxy_maybe> [PasswordDatabase.ExtraFields.Proxy.txt]*: Proxy + the connection to another IMAP/POP3 server. + * * <host> [PasswordDatabase.ExtraFields.Host.txt]*: Send login referral to + client (if proxy=y field isn't set). + * * <nologin> [PasswordDatabase.ExtraFields.NoLogin.txt]*: User isn't actually + allowed to log in even if the password matches, with optionally a different + reason given as the authentication failure message. + * * <nodelay> [PasswordDatabase.ExtraFields.NoDelay.txt]*: Don't delay reply + to client in case of an authentication failure. + * *nopassword*: If you want to allow all passwords, use an empty password and + this field. + * *fail*: If set, explicitly fails the passdb lookup. (v2.2.22+) + * *k5principals*: if using "auth_mechanisms = gssapi", may contain Kerberos v5 + principals allowed to map to the current user, bypassing the internal call + to krb5_kuserok(). The database must support credentials lookup. (v2.2+) + * *delay_until*=<UNIX timestamp>[+<max random secs>]: Delay login until this + time. The timestamp must be less than 5 minutes into future or the login + will fail with internal error. The extra random seconds can be used to avoid + a load spike of everybody getting logged in at exactly the same time. + (v2.2.25+) + * *noauthenticate*: Do not perform any authentication, just store extra fields + if user is found. (v2.2.26+/v2.3) + * *forward_<anything>*: In proxy/director, pass the variable to next hop as + forward_<anything>. (v2.2.29+/v2.3) + +How to return these extra fields depends on the password database you use. See +the <password database> [PasswordDatabase.txt] pages on how to do it. Some +passdbs however don't support returning them at all, such as <PAM> +[PasswordDatabase.PAM.txt]. + +The password database may also return fields prefixed with 'userdb_'. These +fields are only saved and used later as if they came from the <user database> +[UserDatabase.txt]'s extra fields. Typically this is done only when using +<prefetch userdb> [UserDatabase.Prefetch.txt]. + +Note that boolean fields are true always if the field exists. So 'nodelay', +'nodelay=yes', 'nodelay=no' and 'nodelay=0' all mean that the nodelay field is +true. With SQL the field is considered to be non-existent if its value is NULL. + +The following suffixes added to a field name are handled specially: + + * *:protected*: Set this field only if it hasn't been set before. + * *:remove*: Remove this field entirely. + +Examples +-------- + +SQL +--- + +*dovecot-sql.conf.ext*: + +---%<------------------------------------------------------------------------- +password_query = SELECT userid as user, password, 'Y' as proxy, host \ + FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +LDAP +---- + +*dovecot-ldap.conf*: + +---%<------------------------------------------------------------------------- +pass_attrs = \ + =user=%{ldap:user}, \ + =password=%{ldap:userPassword}, + =proxy=%{ldap:proxyEnabled}, \ + =host=%{ldap:hostName} +---%<------------------------------------------------------------------------- + +Note about the "proxy", "proxy_maybe" and any other boolean type fields: these +represent an existence test. Currently this translates to "will proxy (or +proxy_maybe) if this attribute exists". This allows the proxy behaviour to be +selectable per user. To have it "always" on, use a template, e.g.: + +---%<------------------------------------------------------------------------- +pass_attrs = \ + =user=%{ldap:user}, \ + =password=%{ldap:userPassword}, + =proxy=y, \ + =host=%{ldap:hostName} +---%<------------------------------------------------------------------------- + +passwd-file +----------- + +---%<------------------------------------------------------------------------- +user:{plain}pass::::::proxy=y host=127.0.0.1 +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.IMAP.txt b/doc/wiki/PasswordDatabase.IMAP.txt new file mode 100644 index 0000000..02f3db8 --- /dev/null +++ b/doc/wiki/PasswordDatabase.IMAP.txt @@ -0,0 +1,32 @@ +Authentication via remote IMAP server +===================================== + +Available driver settings: + + * host=<template> : IP address or hostname. Allows <%variables> + [Variables.txt] (e.g.'host=imap.%d') + * port=<port> + * username=<template> : The default is %u, but this could be changed to for + example '%n@example.com' + * ssl=imaps / ssl=starttls + * ssl_ca_dir=<path> + * ssl_ca_file=<path> (v2.2.30+) + * allow_invalid_cert=yes|no : Whether to allow authentication even if the + certificate isn't trusted. For v2.2 it defaults to "yes". (v2.2.30+) + * rawlog_dir=<path> + +See also <HowTo.ImapcProxy.txt> for how to combine this with imapc storage. + +Example +------- + +Authenticates users against remote IMAP server in IP address 192.168.1.123: + +---%<------------------------------------------------------------------------- +passdb { + driver = imap + args = host=192.168.1.123 +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.PAM.txt b/doc/wiki/PasswordDatabase.PAM.txt new file mode 100644 index 0000000..29646cf --- /dev/null +++ b/doc/wiki/PasswordDatabase.PAM.txt @@ -0,0 +1,234 @@ +PAM - Pluggable Authentication Modules +====================================== + +This is the most common way to authenticate system users nowadays. PAM is not +itself a password database, but rather its configuration tells the system how +exactly to do the authentication. Usually this means using the 'pam_unix.so' +module, which authenticates user from the system's shadow password file. + +Because PAM is not an actual database, only plaintext authentication mechanisms +can be used with PAM. PAM cannot be used as a user database either (although +static user templates could be used to provide the same effect). Usually PAM is +used with <passwd> [AuthDatabase.Passwd.txt] (NSS) or <static> +[UserDatabase.Static.txt] user databases. + +Dovecot should work with Linux PAM, Solaris PAM, OpenPAM (FreeBSD) and ApplePAM +(Mac OS X). + +Service name +------------ + +The PAM configuration is usually in the '/etc/pam.d/' directory, but some +systems may use a single file,'/etc/pam.conf'. By default Dovecot uses +'dovecot' as the PAM service name, so the configuration is read from +'/etc/pam.d/dovecot'. You can change this by giving the wanted service name in +the 'args' parameter. You can also set the service to '%s' in which case +Dovecot automatically uses either 'imap' or 'pop3' as the service, depending on +the actual service the user is logging in to. Here are a few examples: + + * Use '/etc/pam.d/imap' and '/etc/pam.d/pop3': + + ---%<---------------------------------------------------------------------- + passdb { + driver = pam + args = %s + } + ---%<---------------------------------------------------------------------- + + * Use '/etc/pam.d/mail': + + ---%<---------------------------------------------------------------------- + passdb { + driver = pam + args = mail + } + ---%<---------------------------------------------------------------------- + +PAM sessions +------------ + +By giving a 'session=yes' parameter, you can make Dovecot open a PAM session +and close it immediately. Some PAM plugins need this, for instance +'pam_mkhomedir'. With this parameter, 'dovecot.conf' might look something like +this: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = session=yes dovecot +} +---%<------------------------------------------------------------------------- + +PAM credentials +--------------- + +By giving a 'setcred=yes' parameter, you can make Dovecot create PAM +credentials. Some PAM plugins need this. The credentials are never deleted +however, so using this might cause problems with other PAM plugins. + +Limiting the number of PAM lookups +---------------------------------- + +Usually in other software PAM is used to do only a single lookup in a process, +so PAM plugin writers haven't done much testing on what happens when multiple +lookups are done. Because of this, many PAM plugins leak memory and possibly +have some other problems when doing multiple lookups. If you notice that PAM +authentication stops working after some time, you can limit the number of +lookups done by the auth worker process before it dies: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = max_requests=100 +} +---%<------------------------------------------------------------------------- + +The default max_requests value is 100. + +Username changing +----------------- + +A PAM module can change the username. + +Making PAM plugin failure messages visible +------------------------------------------ + +You can replace the default "Authentication failed" reply with PAM's failure +reply by setting: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = failure_show_msg=yes +} +---%<------------------------------------------------------------------------- + +This can be useful with e.g. pam_opie to find out which one time password +you're supposed to give: + +---%<------------------------------------------------------------------------- +1 LOGIN username otp +1 NO otp-md5 324 0x1578 ext, Response: +---%<------------------------------------------------------------------------- + +Restrict IP-Addresses allowed to connect via PAM +------------------------------------------------ + +You can restrict the IP-Addresses allowed to connect via PAM: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + override_fields = allow_nets=10.1.100.0/23,2001:db8:a0b:12f0::/64 +} +---%<------------------------------------------------------------------------- + +Caching +------- + +Dovecot supports caching password lookups by setting 'auth_cache_size' to +non-zero value. For this to work with PAM, you'll also have to give 'cache_key' +parameter. Usually the user is authenticated only based on the username and +password, but PAM plugins may do all kinds of other checks as well, so this +can't be relied on. For this reason the 'cache_key' must contain all the +<variables> [Variables.txt] that may affect authentication. The commonly used +variables are: + + * '%u' - Username. You'll most likely want to use this. + * '%s' - Service. If you use '*' as the service name you'll most likely want + to use this. + * '%r' - Remote IP address. Use this if you do any IP related checks. + * '%l' - Local IP address. Use this if you do any checks based on the local IP + address that was connected to. + +Examples: + +---%<------------------------------------------------------------------------- +# 1MB auth cache size +auth_cache_size = 1024 +passdb { + driver = pam + # username and service + args = cache_key=%u%s * +} +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +# 1MB auth cache size +auth_cache_size = 1024 +passdb { + driver = pam + # username, remote IP and local IP + args = cache_key=%u%r%l dovecot +} +---%<------------------------------------------------------------------------- + +Examples +-------- + +Linux +----- + +Here is an example '/etc/pam.d/dovecot' configuration file which uses standard +UNIX authentication: + +---%<------------------------------------------------------------------------- +auth required pam_unix.so nullok +account required pam_unix.so +---%<------------------------------------------------------------------------- + +Solaris +------- + +For Solaris you will have to edit '/etc/pam.conf'. Here is a working Solaris +example (using 'args = *' instead of the default 'dovecot' service): + +---%<------------------------------------------------------------------------- +imap auth requisite pam_authtok_get.so.1 +imap auth required pam_unix_auth.so.1 +imap account requisite pam_roles.so.1 +imap account required pam_unix_account.so.1 +imap session required pam_unix_session.so.1 +pop3 auth requisite pam_authtok_get.so.1 +pop3 auth required pam_unix_auth.so.1 +pop3 account requisite pam_roles.so.1 +pop3 account required pam_unix_account.so.1 +pop3 session required pam_unix_session.so.1 +---%<------------------------------------------------------------------------- + +Mac OS X +-------- + +On Mac OS X, the '/etc/pam.d/dovecot' file might look like this: + +---%<------------------------------------------------------------------------- +auth required pam_opendirectory.so try_first_pass +account required pam_nologin.so +account required pam_opendirectory.so +password required pam_opendirectory.so +---%<------------------------------------------------------------------------- + +...which, as the equivalent of '/etc/pam.d/login' on OS X 10.9. For very old +versions of OS X (e.g. 10.4), can be represented (where?) as the following in +the on that OS: + +---%<------------------------------------------------------------------------- +passdb { + driver = pam + args = login +} +---%<------------------------------------------------------------------------- + +On older versions of Mac OS X, "passwd" can be used as a userdb to fill in UID, +GID, and homedir information after PAM was used as a passdb, even though +Directory Services prevents "passdb passwd" from working as a username/password +authenticator. This will provide full system user authentication with true +homedir mail storage, without resorting to a single virtual mail user or LDAP: + +---%<------------------------------------------------------------------------- +userdb { + driver = passwd +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.Shadow.txt b/doc/wiki/PasswordDatabase.Shadow.txt new file mode 100644 index 0000000..f103260 --- /dev/null +++ b/doc/wiki/PasswordDatabase.Shadow.txt @@ -0,0 +1,38 @@ +Shadow +====== + +Works at least with Linux and Solaris, but nowadays <PAM> +[PasswordDatabase.PAM.txt] is usually preferred to this. + +This uses auth-worker processes: + +---%<------------------------------------------------------------------------- +passdb { + driver = shadow +} +---%<------------------------------------------------------------------------- + +By default the auth-worker processes are run as "dovecot" user though, which +normally doesn't have access to '/etc/shadow'. If this is a problem, you can +fix it with: + +---%<------------------------------------------------------------------------- +service auth-worker { + # This should be enough: + group = shadow + # If not, just give full root permissions: + #user = root +} +---%<------------------------------------------------------------------------- + +If there are only a few users and you're using '/etc/shadow' file, there's +really no need to use auth-workers. You can disable them with: + +---%<------------------------------------------------------------------------- +passdb { + driver = shadow + args = blocking=no +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.Static.txt b/doc/wiki/PasswordDatabase.Static.txt new file mode 100644 index 0000000..21852e2 --- /dev/null +++ b/doc/wiki/PasswordDatabase.Static.txt @@ -0,0 +1,27 @@ +Static Password Database +======================== + +Static password database is typically used only for testing, proxying setups +and perhaps some other special kind of setups. Static passdb allows all users +to log in with any username. For password you return either: + + * password=secret: All users have "secret" as password. + * nopassword: Users can log in with any password. + +You can return any other <extra fields> [PasswordDatabase.ExtraFields.txt]. You +can use the standard <variables> [Variables.txt] everywhere. + +Example +------- + +Using <Director.txt>: + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = nopassword=y + default_fields = proxy=y host=127.0.0.1 +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.oauth2.txt b/doc/wiki/PasswordDatabase.oauth2.txt new file mode 100644 index 0000000..5928cf5 --- /dev/null +++ b/doc/wiki/PasswordDatabase.oauth2.txt @@ -0,0 +1,192 @@ +Open Authentication v2.0 database +================================= + +Since v2.2.28. This database works with a oauth2 provider such as google or +facebook. You are recommended to use xoauth2 or oauthbearer <authentication +mechanisms> [Authentication.Mechanisms.txt] with this. The responses from +endpoints must be JSON objects. + +Configuration +------------- + +Common +------ + +In dovecot.conf put + +---%<------------------------------------------------------------------------- +auth_mechanisms = $auth_mechanisms oauthbearer xoauth2 + +passdb { + driver = oauth2 + mechanisms = xoauth2 oauthbearer + args = /etc/dovecot/dovecot-oauth2.conf.ext +} +---%<------------------------------------------------------------------------- + +Backend +------- + +Configuration file example for Google +[https://developers.google.com/identity/protocols/OAuth2] + +---%<------------------------------------------------------------------------- +tokeninfo_url = https://www.googleapis.com/oauth2/v3/tokeninfo?access_token= +introspection_url = https://www.googleapis.com/oauth2/v2/userinfo +#force_introspection = yes +username_attribute = email +tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt +---%<------------------------------------------------------------------------- + +Configuration file example for WSO2 Identity Server +[http://wso2.com/identity-and-access-management] + +---%<------------------------------------------------------------------------- +introspection_mode = post +introspection_url = +https://adminuser:adminpass@server.name:port/oauth2/introspect +username_attribute = username +tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt +active_attribute = active +active_value = true +---%<------------------------------------------------------------------------- + +Proxy +----- + +If you want to forward oauth2 authentication to your backend, you can use +various ways + +Without proxy authentication + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = nopasssword=y proxy=y proxy_mech=%m ... +} +---%<------------------------------------------------------------------------- + +or with proxy authentication, put into dovecot-oauth2.conf.ext + +---%<------------------------------------------------------------------------- +pass_attrs = proxy=y proxy_mech=%m +---%<------------------------------------------------------------------------- + +Proxy with password grant (since v2.3.6) +---------------------------------------- + +If you want to configure proxy to get token and pass it to backend + +passdb settings + +---%<------------------------------------------------------------------------- +passdb { + driver = oauth2 + mechanisms = oauthbearer xoauth2 + args = /usr/local/etc/dovecot/dovecot-oauth2.token.conf.ext +} + +passdb { + driver = oauth2 + mechanisms = plain login + args = /usr/local/etc/dovecot/dovecot-oauth2.plain.conf.ext +} +---%<------------------------------------------------------------------------- + +put into dovecot-oauth2.token.conf.ext + +---%<------------------------------------------------------------------------- +grant_url = http://localhost:8000/token +client_id = verySecretClientId +client_secret = verySecretSecret +tokeninfo_url = http://localhost:8000/oauth2?oauth= +introspection_url = http://localhost:8000/introspect +introspection_mode = post +use_grant_password = no +debug = yes +username_attribute = username +pass_attrs = pass=%{oauth2:access_token} +---%<------------------------------------------------------------------------- + +put into dovecot-oauth2.plain.conf.ext + +---%<------------------------------------------------------------------------- +grant_url = http://localhost:8000/token +client_id = verySecretClientId +client_secret = verySecretSecret +introspection_url = http://localhost:8000/introspect +introspection_mode = post +use_grant_password = yes +debug = yes +username_attribute = username +pass_attrs = host=127.0.0.1 proxy=y proxy_mech=xoauth2 +pass=%{oauth2:access_token} +---%<------------------------------------------------------------------------- + +Full config file +---------------- + +---%<------------------------------------------------------------------------- +### OAuth2 password database configuration + +## url for verifying token validity. Token is appended to the URL +# tokeninfo_url = http://endpoint/oauth/tokeninfo?access_token= + +## introspection endpoint, used to gather extra fields and other information. +# introspection_url = http://endpoint/oauth/me + +## How introspection is made, valid values are +## auth = GET request with Bearer authentication +## get = GET request with token appended to URL +## post = POST request with token=bearer_token as content +# introspection_mode = auth + +## Force introspection even if tokeninfo contains wanted fields +## Set this to yes if you are using active_attribute +# force_introspection = no + +## wanted scope of validity (optional) +# scope = something + +## username attribute in response (default: email) +# username_attribute = email + +## username normalization format (default: %Lu) +# username_format = %Lu + +## Attribute name for checking whether account is disabled (optional) +# active_attribute = + +## Expected value in active_attribute (empty = require present, but anything +goes) +# active_value = + +## Extra fields to set in passdb response (in passdb static style) +# pass_attrs = + +## Timeout in milliseconds +# timeout_msecs = 0 + +## Enable debug logging +# debug = no + +## Max parallel connections (how many simultaneous connections to open) +# max_parallel_connections = 1 + +## Max pipelined requests (how many requests to send per connection, requires +server-side support) +# max_pipelined_requests = 1 + +## HTTP request raw log directory +# rawlog_dir = /tmp/oauth2 + +## TLS settings +# tls_ca_cert_file = /path/to/ca-certificates.txt +# tls_ca_cert_dir = /path/to/certs/ +# tls_cert_file = /path/to/client/cert +# tls_key_file = /path/to/client/key +# tls_cipher_suite = HIGH:!SSLv2 +# tls_allow_invalid_cert = FALSE +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PasswordDatabase.txt b/doc/wiki/PasswordDatabase.txt new file mode 100644 index 0000000..f41a93e --- /dev/null +++ b/doc/wiki/PasswordDatabase.txt @@ -0,0 +1,182 @@ +Password Databases +================== + +Dovecot authenticates users against password databases. It can also be used to +configure things like <proxies> [PasswordDatabase.ExtraFields.Proxy.txt]. + +You can use multiple databases, so if the password doesn't match in the first +database, Dovecot checks the next one. This can be useful if you want to easily +support having both virtual users and also local system users (see +<Authentication.MultipleDatabases.txt>). + +Success/failure databases +------------------------- + +These databases simply verify if the given password is correct for the user. +Dovecot doesn't get the correct password from the database, it only gets a +"success" or a "failure" reply. This means that these databases can't be used +with non-plaintext <authentication mechanisms> [Authentication.Mechanisms.txt]. + +Databases that belong to this category are: + + * <PAM> [PasswordDatabase.PAM.txt]: Pluggable Authentication Modules. + * <BSDAuth> [PasswordDatabase.BSDAuth.txt]: BSD authentication. + * <CheckPassword> [AuthDatabase.CheckPassword.txt]: External checkpassword + program without Dovecot extensions. + * <IMAP> [PasswordDatabase.IMAP.txt]: Authenticate against remote IMAP server. + + * <OAuth2> [PasswordDatabase.oauth2.txt]: Authenticate against oauth2 provider + (v2.2.29+) + +Lookup databases +---------------- + +Dovecot does a lookup based on the username and possibly other information +(e.g. IP address) and verifies the password validity itself. Fields that the +lookup can return: + + * * <password> [Authentication.PasswordSchemes.txt]*: User's password. + * *password_noscheme*: Like "password", but if a password begins with "{", + assume it belongs to the password itself instead of treating it as a + <scheme> [Authentication.PasswordSchemes.txt] prefix. This is usually + needed only if you use plaintext passwords. + * * <user> [PasswordDatabase.ExtraFields.User.txt]*: Returning a user field + can be used to change the username. Typically used only for case changes + (e.g. "UseR" -> "user"). + * *username*: Like user, but doesn't drop existing domain name (e.g. + "username=foo" for "user@domain" gives "foo@domain"). + * *domain*: Updates the domain part of the username. + * Other special <extra fields> [PasswordDatabase.ExtraFields.txt]. + +Databases that support looking up only passwords, but no user or extra fields: + + * <Passwd> [AuthDatabase.Passwd.txt]: System users (NSS, '/etc/passwd', or + similiar). + * <Shadow> [PasswordDatabase.Shadow.txt]: Shadow passwords for system users + (NSS,'/etc/shadow' or similiar). + * Dovecot supports reading all <password schemes> + [Authentication.PasswordSchemes.txt] from passwd and shadow databases (if + prefix is specified), but that is of course incompatible with all other + tools using/modifying the passwords. + * <VPopMail> [AuthDatabase.VPopMail.txt]: External software used to handle + virtual domains. + +Databases that support looking up everything: + + * <Passwd-file> [AuthDatabase.PasswdFile.txt]: '/etc/passwd'-like file in + specified location. + * <LDAP> [AuthDatabase.LDAP.txt]: Lightweight Directory Access Protocol. + * <SQL> [AuthDatabase.SQL.txt]: SQL database (PostgreSQL, MySQL, SQLite). + * <Dict> [AuthDatabase.Dict.txt]: Dict key-value database (Redis, memcached, + etc.) + * <CheckPassword> [AuthDatabase.CheckPassword.txt]: External checkpassword + program when used with Dovecot extensions. + * <Static> [PasswordDatabase.Static.txt]: Static passdb for simple + configurations + * <Lua> [AuthDatabase.Lua.txt]: Lua script for authentication (v2.3.0+) + +Passdb settings +--------------- + +An example passdb passwd-file with its default settings: + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = scheme=ssha256 /usr/local/etc/passwd.replica + default_fields = + override_fields = + + deny = no + master = no + pass = no + skip = never + mechanisms = + username_filter = + + result_failure = continue + result_internalfail = continue + result_success = return-ok + + # v2.2.24+ + auth_verbose = default +} +---%<------------------------------------------------------------------------- + +First we have the settings that provide content for the passdb lookup: + + * driver: The passdb backend name + * args: Arguments for the passdb backend. The format of this value depends on + the passdb driver. Each one uses different args. + * default_fields: Passdb fields (and <extra fields> + [PasswordDatabase.ExtraFields.txt]) that are used, unless overwritten by the + passdb backend. They are in format 'key=value key2=value2 ...'. The values + can contain <%variables> [Variables.txt]. + * override_fields: Same as default_fields, but instead of providing the + default values, these values override what the passdb backend returned. + * auth_verbose: If this is explicitly set to yes or no, it overrides the + global auth_verbose setting. (However, auth_debug=yes overrides the + auth_verbose setting.) (v2.2.24+) + +Then we have the settings which specify when the passdb is used: + + * deny: If "yes", used to provide "denied users database". If the user is + found from the passdb, the authentication will fail. + * master: If "yes", used to provide <master users database> + [Authentication.MasterUsers.txt]. The users listed in the master passdb can + log in as other users. + * pass: This is an alias for 'result_success = continue' as described + below. This was commonly used together with master passdb to specify that + even after a successful master user authentication, the authentication + should continue to the actual non-master passdb to lookup the user. + * skip: Do we sometimes want to skip over this passdb? + * never + * authenticated: Skip if an earlier passdb already authenticated the user + successfully. + * unauthenticated: Skip if user hasn't yet been successfully authenticated + by the previous passdbs. + * mechanisms: Skip, if non-empty and the current auth mechanism is not listed + here. Space or comma-separated list of auth mechanisms (e.g. "PLAIN LOGIN"). + Also "none" can be used to match for a non-authenticating passdb lookup. + (v2.2.30+) + * username_filter: Skip, if non-empty and the username doesn't match the + filter. This is mainly used to assign specific passdbs to specific domains. + Space or comma-separated list of username filters that can have "*" or "?" + wildcards. If any of the filters matches, the filter succeeds. However, + there can also be negative matches preceded by "!". If any of the negative + filters matches, the filter won't succeed. For example if the filter is + "*@example.com *@example2.com !user@example.com", "any@example.com" or + "user@example2.com" matches but "user@example.com" won't match. (v2.2.30+) + +And finally we can control what happens when we're finished with this passdb: + + * result_success: What to do if the authentication succeeded (default: + return-ok) + * result_failure: What to do if authentication failed (default: continue) + * result_internalfail: What to do if the passdb lookup had an internal failure + (default: continue). If any of the passdbs had an internal failure and the + final passdb also returns "continue", the authentication will fail with + "internal error".*WARNING*: If multiple passdbs are required (results are + merged), it's important to set result_internalfail=return-fail to them, + otherwise the authentication could still succeed but not all the intended + extra fields are set. + +The result values that can be used: + + * return-ok: Return success, don't continue to the next passdb. + * return-fail: Return failure, don't continue to the next passdb. + * return: Return earlier passdb's success or failure, don't continue to the + next passdb. If this was the first passdb, return failure. + * continue-ok: Set the current authentication state to success, and continue + to the next passdb. The following passdbs will skip password verification. + * continue-fail: Set the current authentication state to failure, and continue + to the next passdb. The following passdbs will still verify the password. + * continue: Continue to the next passdb without changing the authentication + state. The initial state is failure. If this was set in result_success, the + following passdbs will skip password verification. + +*NOTICE*: when using "continue*" values on a *master* passdb (master = yes), +execution will jump to the first *non-master* passdb instead of continuing with +the next master passdb (verified at lest up to v2.2.27). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PerformanceTuning.txt b/doc/wiki/PerformanceTuning.txt new file mode 100644 index 0000000..80e7fca --- /dev/null +++ b/doc/wiki/PerformanceTuning.txt @@ -0,0 +1,69 @@ +Dovecot performance tuning +========================== + +Disk I/O optimization +--------------------- + +Usually heavily loaded IMAP and POP3 servers don't use much CPU, but they use +all the disk I/O they can get. So reducing disk I/O is probably the most useful +optimization you can do. + + * See <MailLocation.LocalDisk.txt> for generic disk I/O optimizations. + * See <MailLocation.Mbox.txt> for mbox-specific optimizations. + * See <MailLocation.Maildir.txt> for Maildir-specific optimizations. + * See <dbox> [MailboxFormat.dbox.txt] for Dovecot's own high-performance + mailbox format. It usually gives much better performance than mbox/Maildir. + * See <full text search indexes> [Plugins.FTS.txt] for optimizing IMAP SEARCH + command. + * See <POP3Server.txt> for POP3 optimizations, especially + 'pop3_no_flag_updates=yes' + * 'mailbox_list_index=yes' can help a lot by replying to IMAP STATUS (and + similar) lookups from a single index without having to open each mailbox + index separately. This is the default in v2.3+. + * Also 'mailbox_list_index_very_dirty_syncs=yes' makes Dovecot assume that + the list index is up-to-date. + * 'mail_prefetch_count' setting may be helpful with some mailbox formats + * 'mail_location = ...:VOLATILEDIR=/tmp/dovecot-volatile/%2.256Nu/%u' moves + e.g. lock files to the volatile directory. This is helpful especially if + mail_location otherwise points to a remote filesystem like NFS. (v2.2.32+) + * If acl plugin is used, but only global ACLs are needed, set + 'acl_globals_only=yes' (v2.2.31+) + +CPU usage optimization +---------------------- + + * See <LoginProcess.txt> for optimizing CPU usage caused by logins + * See 'auth_cache_size' setting for caching passdb and userdb lookups + * To distribute password hash calculations to multiple CPU cores (via + auth-worker processes), set 'auth_cache_verify_password_with_worker=yes' + (v2.2.34+) + * Services having client_limit>1 and process_limit>1, set process_min_avail to + the number of CPU cores + * To reduce forks by reusing existing processes for new requests increase + 'service { service_count }' from 1 to higher (e.g. 100) for imap and pop3 + services. It's better not to set it too high or unlimited (0), because + different users use different amounts of memory, and it's wasteful when a + lot of processes end up having a lot of "free" memory. + +Memory usage optimization +------------------------- + +There aren't many settings which affect Dovecot's memory usage. In general +Dovecot uses as much memory as it needs, which is usually quite little. + + * 'auth_cache_size' controls maximum memory size for caching passdb/userdb + lookups + * <High-performance mode for login processes> [LoginProcess.txt]. + * 'imap_hibernate_timeout' controls when to move IDLEing IMAP connections to + wait for changes in a shared imap-hibernate process. This frees up the imap + process. + +Note that these settings do not directly affect the memory usage: + + * 'service { vsz_limit } ': These are simply safe guards against potential + memory leaks. If the process's virtual size reaches the limit, the process + is killed by the kernel. + * 'service { process_limit, client_limit } ': These are mostly to avoid DoS + attacks using up all your memory. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Installation.txt b/doc/wiki/Pigeonhole.Installation.txt new file mode 100644 index 0000000..78b2c56 --- /dev/null +++ b/doc/wiki/Pigeonhole.Installation.txt @@ -0,0 +1,159 @@ +Pigeonhole Installation +======================= + +Contents + + + 1. Pigeonhole Installation + + 1. Getting the sources + + 2. Compiling + + 3. Prebuilt Binaries + + 1. Alpine Linux + + 2. ArchLinux + + 3. RHEL 6 + clones (CentOS, Scientific Linux, ...) + + 4. Debian + + 5. openSUSE + + 6. FreeBSD + + 7. OpenBSD + +Getting the sources +------------------- + +You can download the latest released sources from the Pigeonhole download page +[http://pigeonhole.dovecot.org/download.html]. + +Alternatively, you can get the sources, including the most recent unreleased +changes, from the the Mercurial repository: + +---%<------------------------------------------------------------------------- +hg clone http://hg.rename-it.nl/dovecot-2.0-pigeonhole +---%<------------------------------------------------------------------------- + +Compiling +--------- + +If you downloaded the sources using Mercurial, you will need to execute +'./autogen.sh' first to build the automake structure in your source tree. This +process requires autotools and libtool to be installed. + +If you installed Dovecot from sources, Pigeonhole's configure script should be +able to find the installed 'dovecot-config' automatically: + +---%<------------------------------------------------------------------------- +./configure +make +sudo make install +---%<------------------------------------------------------------------------- + +If this doesn't work, you can use '--with-dovecot=<path>' configure option, +where the path points to a directory containing 'dovecot-config' file. This can +point to an installed file: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=/usr/local/lib/dovecot +make +sudo make install +---%<------------------------------------------------------------------------- + +or to Dovecot source directory that is already compiled: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=../dovecot-2.0.0/ +make +sudo make install +---%<------------------------------------------------------------------------- + +*IMPORTANT*: You need to recompile Pigeonhole when you upgrade Dovecot to a new +version, because otherwise the Sieve interpreter plugin will fail to load with +a version error. + +Prebuilt Binaries +----------------- + +Alpine Linux +------------ + +Pigeonhole can be installed from packages by running: + +---%<------------------------------------------------------------------------- +apk add dovecot-pigeonhole-plugin +---%<------------------------------------------------------------------------- + +ArchLinux +--------- + +Pidgeonhole is available in the community repositories, and can be installed by +running: + +---%<------------------------------------------------------------------------- +pacman -S pigeonhole +---%<------------------------------------------------------------------------- + +RHEL 6 + clones (CentOS, Scientific Linux, ...) +----------------------------------------------- + +Pidgeonhole is available in the main repository, and can be installed by +running: + +---%<------------------------------------------------------------------------- +yum install dovecot-pigeonhole +---%<------------------------------------------------------------------------- + +Debian +------ + +Starting with Debian Wheezy, Pigeonhole binaries are distributed in separate +packages:'dovecot-sieve' for the <Sieve interpreter> [Pigeonhole.Sieve.txt] and +'dovecot-managesieved' for the <ManageSieve service> +[Pigeonhole.ManageSieve.txt]. You can install these by running: + +---%<------------------------------------------------------------------------- +apt-get install dovecot-sieve dovecot-managesieved +---%<------------------------------------------------------------------------- + +Older Debian releases have Sieve and ManageSieve support included in the main +'dovecot-common' package, meaning that this is always available for those +releases once Dovecot is installed. + +openSUSE +-------- + +It is part of the dovecot (dovecot21) rpm. There is no need to install +additional packages. + +FreeBSD +------- + +Pigeonhole can be installed from ports by running: + +---%<------------------------------------------------------------------------- +cd /usr/ports/mail/dovecot-pigeonhole +make install clean +---%<------------------------------------------------------------------------- + +It can be also be installed from packages by running: + +---%<------------------------------------------------------------------------- +pkg install dovecot-pigeonhole +---%<------------------------------------------------------------------------- + +OpenBSD +------- + +Pigeonhole can be installed from packages by running: + +---%<------------------------------------------------------------------------- +pkg_add dovecot-pigeonhole +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.ManageSieve.Clients.txt b/doc/wiki/Pigeonhole.ManageSieve.Clients.txt new file mode 100644 index 0000000..250f0d5 --- /dev/null +++ b/doc/wiki/Pigeonhole.ManageSieve.Clients.txt @@ -0,0 +1,61 @@ +ManageSieve Client Issues +========================= + +Although this ManageSieve server should comply with the draft specification of +theManageSieve protocol, quite a few clients don't. This page lists the known +client problems. + + * *The TLS problem*: + * The core of the TLS problem is that a ManageSieve server is required to send + an unsolicited CAPABILITY response right after successful TLS negotiation. + Older Cyrus servers did not do this and many clients incorporated this + protocol error as the standard, meaning that these do not expect the + CAPABILITY response and thus fail with subsequent commands. However, now + that Cyrus' Timsieved has changed its behaviour towards protocol compliance, + all those clients will follow eventually. The following clients are known to + have this TLS issue: + + Thunderbird Sieve add-on: + TLS broken for old versions. Starting with version 0.1.5 the Thunderbird + Sieve add-on properly supports TLS. + + KMail + kio_sieve: + TLS broken for old versions. This issue is fixed at least in kmail 1.9.9 / + kde 3.5.9. + + SquirrelMail/AvelSieve: + For some users the !Avelsieve client stores scripts but fails to retrieve + them later. This problem is directly caused byAvelSieve's TLS support. A + quick way to fix this is not to enable TLS forManageSieve. AvelSieve + stable (v1.0.1) does not have TLS support at all, so you will see this + happen only with the development or SVN versions. Another issue is that + (at least with avelsieve-1.9.7) it is impossible to delete the last rule + of a script. For avelsieve-1.9.7 you find a patch that fixes these two + issues here + [http://pigeonhole.dovecot.org/client-patches/avelsieve-1.9.7-dovecot.patch]. + + * *Smartsieve, Websieve*: + * These clients are specifically written for Cyrus timsieved and fail on + multiple stages of the protocol when connected to PigeonholeManageSieve. + * /(Stephan Bosch)/: I intend to look at these in the future, but currently + these are very much unavailable for use with Dovecot. But, feel free to + fix these yourself:) + * /(Steffen "Stefreak" Neubauer)/: I've fixed the problems for smartsieve. + Just replace your lib/Managesieve.php with this + here:https://www.commail.org/sieve/lib/Managesieve.phps - HAVE FUN! + * /(Mark Titorenko)/: Stephan provides an updated link to Steffen's + ManageSieve patch in this Dovecot mailing list post dated 2009-09-01 + [http://www.mail-archive.com/dovecot@dovecot.org/msg21862.html] + * /(Stephan Bosch)/: Links moved here + [http://pigeonhole.dovecot.org/patches/] + * *Ruby/Managesieve*: Ruby command line client and library to managesieve + works fine Ruby/Managesieve [http://managesieve.rubyforge.org/] + * *Ruby/Sieve-Parser*: Ruby library for sieve parsing Sieve-Parser + [http://rubygems.org/gems/sieve-parser/] + +*NOTE*: If you add new issues to this list, notify the author or send an e-mail +to the Dovecot mailing list [http://dovecot.org/mailinglists.html]. In any +case, you must make sure that the issue is properly explained and that the +author can contact you for more information. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.ManageSieve.Configuration.txt b/doc/wiki/Pigeonhole.ManageSieve.Configuration.txt new file mode 100644 index 0000000..bf40848 --- /dev/null +++ b/doc/wiki/Pigeonhole.ManageSieve.Configuration.txt @@ -0,0 +1,258 @@ +ManageSieve Configuration +========================= + +*NOTE*: If you have used the Sieve plugin before and you have '.dovecot.sieve' +files in user directories, you are advised to *make a backup first*. Although +theManageSieve daemon takes care to move these files to the Sieve storage +before it is substituted with a symbolic link, this is not a very well tested +operation, meaning that there is a possibility that existing Sieve scripts get +lost. + +The ManageSieve configuration consists of ManageSieve protocol settings and +<Sieve interpreter> [Pigeonhole.Sieve.txt]-related settings. The Sieve +interpreter settings are shared with settings of the <Sieve plugin> +[Pigeonhole.Sieve.txt] for Dovecot's <Local Delivery Agent (LDA)> [LDA.txt] and +<LMTP.txt>. First, the ManageSieve protocol settings are outlined and then the +relevant Sieve settings are described. + +Protocol Configuration +---------------------- + +Along with all other binaries that Dovecot uses, the managesieve and +managesieve-login binaries are installed during 'make install' of the +<Pigeonhole.txt> package. The only thing you need to do to activate the +ManageSieve protocol support in Dovecot is to add 'sieve' to the 'protocols=' +configuration line in your dovecot.conf. The managesieve daemon will listen on +port 4190 by default. As the implementation of the managesieve daemon is +largely based on the original IMAP implementation, it is very similar in terms +of configuration. In addition to most mail daemon config settings, the +managesieve daemon accepts a few more. The following settings can be configured +in the 'protocol sieve' section: + +managesieve_max_line_length = 65536: + The maximum ManageSieve command line length in bytes. This setting is + directly borrowed from IMAP. But, since long command lines are very unlikely + withManageSieve, changing this will not be very useful. + +managesieve_logout_format = bytes=%i/%o: + Specifies the string pattern used to compose the logout message of an + authenticated session. The following substitutions are available: + +: + ---%<----------------------------------------------------------------------- + %i - total number of bytes read from client + %o - total number of bytes sent to client + ---%<----------------------------------------------------------------------- + +managesieve_implementation_string = Dovecot Pigeonhole: + To fool ManageSieve clients that are focused on CMU's timesieved you can + specify the IMPLEMENTATION capability that the Dovecot reports to clients + (e.g. 'Cyrus timsieved v2.2.13'). + +managesieve_max_compile_errors = 5: + The maximum number of compile errors that are returned to the client upon + script upload or script verification. + +managesieve_sieve_capability =, managesieve_notify_capability = : + Respectively the SIEVE and NOTIFY capabilities reported by the ManageSieve + service before authentication. If left unassigned, these will be assigned + dynamically according to what the Sieve interpreter supports by default + (after login this may differ depending on the authenticated user). + +Sieve Interpreter Configuration +------------------------------- + +The part of the <Sieve interpreter> [Pigeonhole.Sieve.txt] configuration that +is relevant forManageSieve mainly consists of the settings that specify where +the user's scripts are stored and where the active script is located. +TheManageSieve service primarily uses the following Sieve interpreter setting +in the 'plugin' section of the Dovecot configuration: + +sieve = file:~/sieve;active=~/.dovecot.sieve : + This specifies the <location> [Pigeonhole.Sieve.Configuration.txt] where the + scripts that are uploaded throughManageSieve are stored. During delivery, the + LDA Sieve plugin uses this location setting to find the active script for + Sieve filtering. The Sieve include extension uses this location for + retrieving ":personal" scripts. If the location type does not allow uploading + scripts, theManageSieve service cannot be used. Currently, only the ' <file> + [Pigeonhole.Sieve.Configuration.File.txt]' <location type> + [Pigeonhole.Sieve.Configuration.txt] supports ManageSieve. + +: + For the ' <file> [Pigeonhole.Sieve.Configuration.File.txt]' <location type> + [Pigeonhole.Sieve.Configuration.txt]: + + * The location is the path to the storage directory for all the user's + personal Sieve scripts. Scripts are stored as separate files with + extension '.sieve'. All other files are ignored when scripts are listed by + aManageSieve client. The storage directory is always generated + automatically if it does not exist (as far as the system permits the user + to do so; no root privileges are used). This is similar to the behavior of + the mail daemons regarding the 'mail_location' configuration. + * ManageSieve maintains a symbolic link pointing to the currently active + script (the script executed at delivery). The location of this symbolic + link can be configured using the ';active=<path>' option. If a regular + file already exists at the location specified by in the ';active=<path>' + location option, it is moved to the storage directory before the symbolic + link is installed. It is renamed to 'dovecot.orig.sieve' and therefore + listed as 'dovecot.orig' by a ManageSieve client. *Note:* It is not wise + to place this active symbolic link inside your mail store, as it may be + mistaken for a mail folder. Inside a maildir for instance, the default + '.dovecot.sieve' would show up as phantom folder //dovecot/sieve/ in your + IMAP tree. + +: + For Pigeonhole versions before v0.3.1, this setting can only be a filesystem + path pointing to a script file, or - whenManageSieve is used - it is the + location of the symbolic link pointing to the active script in the storage + directory. That storage directory is then configured using the deprecated + 'sieve_dir' setting. + +Quota Support +------------- + +By default, users can manage an unlimited number of Sieve scripts on the server +throughManageSieve. However, ManageSieve can be configured to enforce limits on +the number of personal Sieve scripts per user and/or the amount of disk storage +used by these scripts. The maximum size of individual uploaded scripts is +dictated by the configuration of the <Sieve interpreter> +[Pigeonhole.Sieve.txt]. The limits are configured in the plugin section of the +Dovecot configuration as follows: + +sieve_max_script_size = 1M: + The maximum size of a Sieve script. + +sieve_quota_max_scripts = 0: + The maximum number of personal Sieve scripts a single user can have. + +sieve_quota_max_storage = 0: + The maximum amount of disk storage a single user's scripts may occupy. + +A value of 0 for these settings means that no limit is enforced. + +Examples +-------- + +The following provides example configurations for ManageSieve in dovecot.conf +for the various versions. Only sections relevant toManageSieve and the Sieve +plugin are shown. Refer to 20-managesieve.conf in +doc/dovecot/example-config/conf.d, but don't forget to add 'sieve' to the +'protocols' setting if you use it. + +---%<------------------------------------------------------------------------- +... +service managesieve-login { + #inet_listener sieve { + # port = 4190 + #} + + #inet_listener sieve_deprecated { + # port = 2000 + #} + + # Number of connections to handle before starting a new process. Typically + # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0 + # is faster. <doc/wiki/LoginProcess.txt> + #service_count = 1 + + # Number of processes to always keep waiting for more connections. + #process_min_avail = 0 + + # If you set service_count=0, you probably need to grow this. + #vsz_limit = 64M +} + +service managesieve { + # Max. number of ManageSieve processes (connections) + #process_limit = 1024 +} + +# Service configuration + +protocol sieve { + # Maximum ManageSieve command line length in bytes. ManageSieve usually does + # not involve overly long command lines, so this setting will not normally +need + # adjustment + #managesieve_max_line_length = 65536 + + # Maximum number of ManageSieve connections allowed for a user from each IP +address. + # NOTE: The username is compared case-sensitively. + #mail_max_userip_connections = 10 + + # Space separated list of plugins to load (none known to be useful so far). +Do NOT + # try to load IMAP plugins here. + #mail_plugins = + + # MANAGESIEVE logout format string: + # %i - total number of bytes read from client + # %o - total number of bytes sent to client + #managesieve_logout_format = bytes=%i/%o + + # To fool ManageSieve clients that are focused on CMU's timesieved you can +specify + # the IMPLEMENTATION capability that the dovecot reports to clients. + # For example: 'Cyrus timsieved v2.2.13' + #managesieve_implementation_string = Dovecot Pigeonhole + + # Explicitly specify the SIEVE and NOTIFY capability reported by the server +before + # login. If left unassigned these will be reported dynamically according to +what + # the Sieve interpreter supports by default (after login this may differ +depending + # on the user). + #managesieve_sieve_capability = + #managesieve_notify_capability = + + # The maximum number of compile errors that are returned to the client upon +script + # upload or script verification. + #managesieve_max_compile_errors = 5 + + # Refer to 90-sieve.conf for script quota configuration and configuration of + # Sieve execution limits. +} + +plugin { + # Used by both the Sieve plugin and the ManageSieve protocol + sieve = file:~/sieve;active=~/.dovecot.sieve +} +---%<------------------------------------------------------------------------- + +Proxy +----- + +Like Dovecot's imapd, the ManageSieve login daemon supports proxying to +multiple backend servers. The <proxy configuration wiki page> +[PasswordDatabase.ExtraFields.Proxy.txt] for POP3 and IMAP applies +automatically toManageSieve as well. + +Migration from Dovecot v1.x ManageSieve +--------------------------------------- + +The following has changed since the ManageSieve releases for Dovecot v1.x: + + * For Dovecot v1.0 and v1.1, the 'sieve_dir' setting used by ManageSieve was + called 'sieve_storage'. Also, the 'sieve' and 'sieve_storage' settings were + located inside the 'protocol managesieve' section of the configuration. As + per Dovecot v1.2 these settings are shared with the Sieve plugin and located + in the 'plugin' section of the configuration. Make sure you have updated the + name of the 'sieve_dir' setting and the location of both these settings if + you are upgrading fromManageSieve for Dovecot v1.0/v1.1. + * Pigeonhole ManageSieve does not use the 'mail_location' configuration as a + fall-back anymore to determine a default location for storing Sieve scripts. + It always uses the 'sieve_dir' setting, with default value '~/sieve'. + * The Pigeonhole ManageSieve service now binds to TCP port 4190 by default due + to the IANA port assignment for theManageSieve service. When upgrading from + v1.x, this should be taken into account. For a smooth transition, the + service can be configured manually to listen on both port 2000 and port + 4190, as demonstrated in the example section. + * The Dovecot configuration now calls the ManageSieve protocol 'sieve' instead + of 'managesieve' because it is registered as such with IANA. The binaries + and the services are still called 'managesieve' and 'managesieve-login'. The + example section demonstrates how this affects the configuration. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.ManageSieve.Install.txt b/doc/wiki/Pigeonhole.ManageSieve.Install.txt new file mode 100644 index 0000000..b9f67ad --- /dev/null +++ b/doc/wiki/Pigeonhole.ManageSieve.Install.txt @@ -0,0 +1,2 @@ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.ManageSieve.Troubleshooting.txt b/doc/wiki/Pigeonhole.ManageSieve.Troubleshooting.txt new file mode 100644 index 0000000..d19bd18 --- /dev/null +++ b/doc/wiki/Pigeonhole.ManageSieve.Troubleshooting.txt @@ -0,0 +1,201 @@ +ManageSieve Troubleshooting +=========================== + +Like Dovecot itself, *the ManageSieve service always logs a detailed error +message* if something goes wrong at the server (refer to <Dovecot Logging> +[Logging.txt] for more details): the logs are the first place to look if you +suspect something is wrong. To get additional debug messages in your log file, +you should set 'mail_debug=yes' in dovecot.conf (inside 'protocol sieve {...} +'if you want to enable this forManageSieve only). + +If the client commits protocol violations or sends invalid scripts, an error +response is provided to the client which is not necessarily logged on the +server. A goodManageSieve client presents such error messages to the user. + +Keep in mind that the the ManageSieve service only provides the Sieve +/protocol/, which may be somewhat confusing. This protocol can only be used to +/upload/ Sieve scripts and /activate/ them for execution. Performing the steps +below therefore only verifies that this functionality is working and *not* +whether Sieve scripts are correctly being executed upon delivery. The execution +of Sieve scripts is performed by the Dovecot <Local Delivery Agent (LDA)> +[LDA.txt] or its <LMTP service> [LMTP.txt] using the <LDA Sieve plugin> +[Pigeonhole.Sieve.txt]. If you have problems with Sieve script execution upon +delivery, you are referred to the <Sieve Troubleshooting page> +[Pigeonhole.Sieve.Troubleshooting.txt]. + +Manual Login and Script Upload +------------------------------ + +If you fail to login or upload scripts to the server, it is not necessarily +caused by Dovecot or your configuration. It is often best to test +yourManageSieve server manually first. This also provides you with the direct +error messages from the server without intermission of your client. If you do +not use TLS, you can connect using a simple 'telnet' or 'netcat' connection to +the configured port (typically 4190 or 2000 for older setups). Otherwise you +must use a TLS-capable text protocol client like 'gnutls-cli' as described +below. Upon connection, the server presents the initial greeting with its +capabilities: + +---%<------------------------------------------------------------------------- +"IMPLEMENTATION" "dovecot" +"SASL" "PLAIN" +"SIEVE" "comparator-i;ascii-numeric fileinto reject vacation imapflags notify +include envelope body relational regex subaddress copy" +"STARTTLS" +OK "Dovecot ready." +---%<------------------------------------------------------------------------- + +Note that the reported 'STARTTLS' capability means that the server accepts TLS, +but, since you are using telnet/netcat, you cannot use this (refer to Manual +TLS Login below). The 'SASL' capability lists the available SASL authentication +mechanisms. If this list is empty and 'STARTTLS' is available, it probably +means that the server forces you to initiate TLS first (as dictated by +''disable_plaintext_auth=yes'' in dovecot.conf). + +Now you need to log in. Although potentially multiple SASL mechanisms are +available, only 'PLAIN' is described here. Authentication is performed using +theManageSieve 'AUTHENTICATE' command. This command typically looks as follows +when the 'PLAIN' mechanism is used: + +---%<------------------------------------------------------------------------- +AUTHENTICATE "PLAIN" "<base64-encoded credentials>" +---%<------------------------------------------------------------------------- + +The credentials are the base64-encoded version of the string +'"\0<username>\0<password"' (in which '\0' represents the ASCII NUL character). +Generating this is cumbersome and a bit daunting for the novice user, so for +convenience a simple Perl script is provided to generate the 'AUTHENTICATE' +command for you. It is available here +[http://pigeonhole.dovecot.org/utilities/sieve-auth-command.pl] and used as +follows: + +---%<------------------------------------------------------------------------- +sieve-auth-command.pl <username> <password> +---%<------------------------------------------------------------------------- + +The command is written to stdout and you can paste this to your protocol +session, e.g.: + +---%<------------------------------------------------------------------------- +AUTHENTICATE "PLAIN" "AHVzZXJuYW1lAHBhc3N3b3Jk" +OK "Logged in." +---%<------------------------------------------------------------------------- + +Now that you are logged in, you can upload a script. This is done using the +'PUTSCRIPT' command. Its first argument is the name for the script and its +second argument is a string literal. A string literal starts with a length +specification ''{<bytes>+}'' followed by a newline. Thereafter the server +expects '<bytes>' bytes of script data. The following uploads a trivial 6 byte +long sieve script that keeps every message (6th byte is the newline character): + +---%<------------------------------------------------------------------------- +PUTSCRIPT "hutsefluts" {6+} +keep; +OK "Putscript completed." +---%<------------------------------------------------------------------------- + +Upon successful upload, you should find a file called 'hutsefluts.sieve' in +your 'sieve_dir' directory. The script should also be listed by the server as +follows when the 'LISTSCRIPTS' command is issued: + +---%<------------------------------------------------------------------------- +LISTSCRIPTS +"hutsefluts" +OK "Listscripts completed." +---%<------------------------------------------------------------------------- + +You can check whether your script is uploaded correctly by downloading it using +the 'GETSCRIPT' command. This command accepts the name of the downloaded script +as its only parameter: + +---%<------------------------------------------------------------------------- +GETSCRIPT "hutsefluts" +{6} +keep; +OK "Getscript completed." +---%<------------------------------------------------------------------------- + +To let the Sieve plugin use your newly uploaded script, you must activate it +using the 'SETACTIVE' command (only one script can be active at any time). The +active script is indicated 'ACTIVE' in the 'LISTSCRIPTS' output, e.g.: + +---%<------------------------------------------------------------------------- +SETACTIVE "hutsefluts" +OK "Setactive completed." +LISTSCRIPTS +"hutsefluts" ACTIVE +OK "Listscripts completed. +---%<------------------------------------------------------------------------- + +The symbolic link configured with the 'sieve' setting should now point to the +activated script in the 'sieve_dir' directory. If no script is active, this +symbolic link is absent. + +Manual TLS Login +---------------- + +When TLS needs to be used during manual testing, 'gnutls-cli' provides the +means to do so. This command-line utility is part of the GNUTLS distribution +and on most systems this should be easy to install. It is used to connect +toManageSieve as follows: + +---%<------------------------------------------------------------------------- +gnutls-cli --starttls -p <port> <host> +---%<------------------------------------------------------------------------- + +This starts the client in plain text mode first. As shown in the previous +section, the server presents a greeting with all capabilities of the server. If +'STARTTLS' is listed, you can issue the 'STARTTLS' command as follows: + +---%<------------------------------------------------------------------------- +STARTTLS +OK "Begin TLS negotiation now." +---%<------------------------------------------------------------------------- + +If an OK response is given by the server you can press 'Ctrl-D' to make +'gnutls-cli' start the TLS negotiation. Upon pressing 'Ctrl-D', 'gnutls-cli' +will show information on the negotiated TLS session and finally the first +response of the server is shown: + +---%<------------------------------------------------------------------------- +"IMPLEMENTATION" "dovecot" +"SASL" "PLAIN" +"SIEVE" "comparator-i;ascii-numeric fileinto reject vacation imapflags notify +include envelope body relational regex subaddress copy" +OK "TLS negotiation successful." +---%<------------------------------------------------------------------------- + +Hereafter, you can continue to authenticate and upload a script as described in +the previous section. + +Client Problems +--------------- + +If manual efforts to upload a script are successful, but your client still +fails, you need to obtain a view on what the client communicates with the +server. A common method is to sniff the client protocol session using a tool +like 'ngrep'. However, this will not work when TLS is active. If the problem is +not specific to TLS, you are advised to temporarily turn off TLS and sniff the +plain text protocol. If TLS is part of the issue, you can use Dovecot's +<rawlog> [Debugging.Rawlog.txt] facility to see what is going on if the client +is logged in. If the authentication is the problem, there is no real nice way +to obtain a transcript of the protocol. One way is to run managesieve from +inetd, wrapping it into a script that writes the protocol messages somewhere +(*FIXME*: This needs some checking and explanation). Alternatively, if +possible, the client can be altered to write its protocol messages somewhere. + +Refer to the <ManageSieve Clients page> [Pigeonhole.ManageSieve.Clients.txt] +for information on known client problems. + +Known Server Issues and Protocol Deviations +------------------------------------------- + + * The ANONYMOUS authentication mechanism is currently not supported and + explicitly denied. + +*NOTE*: If you add new issues to this list, notify the author or send an e-mail +to the Dovecot mailing list [http://dovecot.org/mailinglists.html]. In any +case, you must make sure that the issue is properly explained and that the +author can contact you for more information. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.ManageSieve.txt b/doc/wiki/Pigeonhole.ManageSieve.txt new file mode 100644 index 0000000..e025f00 --- /dev/null +++ b/doc/wiki/Pigeonhole.ManageSieve.txt @@ -0,0 +1,27 @@ +Pigeonhole ManageSieve Server +============================= + +The <Pigeonhole project> [Pigeonhole.txt] provides Sieve [http://sieve.info] +support for Dovecot, which allows users to filter incoming messages by writing +scripts specified in the Sieve language (RFC 5228). The PigeonholeManageSieve +service is used to manage a user's Sieve script collection. It has the +following advantages over doing it directly via filesystem: + + * No need to let users log in via FTP/SFTP/etc, which could be difficult + especially with virtual users. + * ManageSieve is a standard protocol [http://tools.ietf.org/html/rfc5804], so + users can manage their scripts using (hopefully) user-friendlyManageSieve + clients. Many webmails already include aManageSieve client. + * Scripts are compiled before they are installed, which guarantees that the + uploaded script is valid. This prevents a user from inadvertently installing + a broken Sieve script. + +Configuration and Use +--------------------- + + * <Download and Installation> [Pigeonhole.Installation.txt] + * <Configuration> [Pigeonhole.ManageSieve.Configuration.txt] + * <Troubleshooting> [Pigeonhole.ManageSieve.Troubleshooting.txt] + * <Client Issues> [Pigeonhole.ManageSieve.Clients.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Configuration.Dict.txt b/doc/wiki/Pigeonhole.Sieve.Configuration.Dict.txt new file mode 100644 index 0000000..6ec686f --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Configuration.Dict.txt @@ -0,0 +1,187 @@ +Pigeonhole Sieve: Dict Lookup for Sieve Scripts +=============================================== + +Sieve scripts can be obtained from a number of different <types of locations> +[Pigeonhole.Sieve.Configuration.txt]. This page shows how to retrieve them from +a Dovecot dictionary [http://wiki2.dovecot.org/Dictionary] (abbreviated as +'dict'), which can have either a file or database backend. + +To retrieve a Sieve script from the dict database, two lookups are performed. +First, the name of the Sieve script is queried from the dict path +'/priv/sieve/name/<name>'. If the Sieve script exists, this yields a data ID +which in turn points to the actual script text. The script text is subsequently +queried from the dict path '/priv/sieve/data/<dict-id>'. + +The second query is only necessary when no compiled binary is available or when +the script has changed and needs to be recompiled. The data ID is used to +detect changes in the dict's underlying database. Changing a Sieve script in +the database must be done by first making a new script data item with a new +data ID. Then, the mapping from name to data ID must be changed to point to the +new script text, thereby changing the data ID returned from the name lookup, +i.e. the first query mentioned above. Script binaries compiled from Sieve +scripts contained in a dict database record the data ID. While the data ID +contained in the binary is identical to the one returned from the dict lookup, +the binary is assumed up-to-date. When the returned data ID is different, the +new script text is retrieved using the second query and compiled into a new +binary containing the updated data ID. + +Note that, by default, compiled binaries are not stored at all for Sieve +scripts retrieved from a dict database. The ';bindir=<path>' option needs to be +specified in the <location specification> [Pigeonhole.Sieve.Configuration.txt]. + +Configuration +------------- + +The script location syntax is specified as follows: + +---%<------------------------------------------------------------------------- +sieve = dict:<dict-uri>[;<option>[=<value>][;...]] +---%<------------------------------------------------------------------------- + +The following additional options are recognized: + +user=<username> : + Overrides the user name used for the dict lookup. Normally, the name of the + user running the Sieve interpreter is used. + +If the name of the Script is left unspecified and is not otherwise provided by +the Sieve interpreter, the name defaults to `default'. + +Examples +-------- + +Using a flat file backend +------------------------- + +Flat file example 1 +------------------- + +To retrieve the Sieve script named "keep" from the dict file +/etc/dovecot/sieve.dict: + +---%<------------------------------------------------------------------------- +sieve = dict:file:/etc/dovecot/sieve.dict;name=keep +---%<------------------------------------------------------------------------- + +The file /etc/dovecot/sieve.dict might look like this. Note that with the above +configuration, only the "keep" script will be used. + +---%<------------------------------------------------------------------------- +priv/sieve/name/keep +1 +priv/sieve/name/discard +2 +priv/sieve/data/1 +keep; +priv/sieve/data/2 +discard; +---%<------------------------------------------------------------------------- + +Flat file example 2 +------------------- + +Following on from example 1, a more advanced script. This notifies an external +email address when new mail has arrived. Note that the script all needs to be +on one line. + +---%<------------------------------------------------------------------------- +priv/sieve/name/notify +5 +priv/sieve/data/5 +require ["enotify", "variables"]; if header :matches "From" "*" { set "from" +"${1}";} notify :importance "3" :message "New email from ${from}" +"mailto:other@domain.com?body=New%20email%20has%20arrived."; +---%<------------------------------------------------------------------------- + +Using a SQL backend +------------------- + +For greater flexibility, it's possible to use a SQL backend for your dict +scripts. First, set up a configuration file (such as +/etc/dovecot/dict-sieve-sql.conf) with your database configuration. This should +consist of the following parts: + +---%<------------------------------------------------------------------------- +# The database connection params +connect = host=localhost dbname=dovecot user=dovecot password=password + +# The name mapping that yields the ID of the Sieve script +map { + pattern = priv/sieve/name/$script_name # The name of the script, as per +the "sieve" config parameter + table = user_sieve_scripts # The database table + username_field = username # The field in the table to query +on + value_field = id # The field which contains the +return value of the script ID + fields { + script_name = $script_name # FIXME: The other database field +to query? + } +} + +# The name mapping that yields the script content from ID +{ + pattern = priv/sieve/data/$id # The ID, obtained from above + table = user_sieve_scripts # The database table + username_field = username # The field in the table to query + value_field = script_data # The field which contains the +script + fields { + id = $id # FIXME: The other database field +to query? + } +} +---%<------------------------------------------------------------------------- + +Next, create a dict proxy service. Normally in /etc/dovecot/dovecot.conf: + +---%<------------------------------------------------------------------------- +dict { + sieve = pgsql:/etc/dovecot/dict-sieve-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +Finally, configure Sieve to check the dict (e.g. in +/etc/dovecot/conf.d/90-sieve.conf). This looks up a script called "active" in +the database. + +---%<------------------------------------------------------------------------- +plugin { + sieve = dict:proxy::sieve;name=active +} +---%<------------------------------------------------------------------------- + +As with the flat file, the database query will need to return the Sieve script +all in one line, otherwise the subsequent lines will be ignored. + +Note: you might need to <configure the proxy permissions> [Dict.txt] + +Caching the compiled Sieve binaries +----------------------------------- + +With the configuration described above, the Sieve binaries will be compiled +each time they are called. To improve performance, it is preferable to cache +them, which can be done using the bindir parameter, which is added to the Sieve +configuration. For example: + +---%<------------------------------------------------------------------------- +{ + sieve = dict:file:/etc/dovecot/sieve.dict;name=keep;bindir=~/.sieve-bin +} +---%<------------------------------------------------------------------------- + +Or: + +---%<------------------------------------------------------------------------- +{ + sieve = +dict:file:/etc/dovecot/sieve.dict;name=keep;bindir=/var/sieve-scripts/%u +} +---%<------------------------------------------------------------------------- + +*Note:* Sieve uses the ID number as its cache index and to detect the need to +compile. Therefore, if a script is changed, then its ID must also be changed +for it to be reloaded. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Configuration.File.txt b/doc/wiki/Pigeonhole.Sieve.Configuration.File.txt new file mode 100644 index 0000000..0b95abb --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Configuration.File.txt @@ -0,0 +1,85 @@ +Pigeonhole Sieve: File Location for Sieve Scripts +================================================= + +The 'file' <location type> [Pigeonhole.Sieve.Configuration.txt] is used to +retrieve Sieve scripts from the file system. This is the default type if the +type specifier is omitted from the location specification. The location can +either point to a directory or to a regular file. If the location points to a +directory, a script called 'name' is retrieved by reading a file from that +directory with the file name 'name.sieve'. + +When this location type is involved in a 'sieve_before' or 'sieve_after' script +sequence and the location points to a directory, all files in that directory +with a '.sieve' extension are part of the sequence. The sequence order of the +scripts in that directory is determined by the file names, using a normal 8bit +per-character comparison. + +Unless overridden using the ';bindir=<path>' location option, compiled binaries +for scripts retrieved from the 'file' location type are by default stored in +the same directory as where the script file was found if possible. + +Configuration +------------- + +The script location syntax is specified as follows: + +---%<------------------------------------------------------------------------- +location = file:<path>[;<option>[=<value>][;...]] +---%<------------------------------------------------------------------------- + +The following additional options are recognized: + +active=<path> : + When <ManageSieve> [Pigeonhole.ManageSieve.txt] is used, one script in the + storage can be active; i.e., evaluated at delivery. For the 'file' location + type, the active script in the storage directory is pointed to by a symbolic + link. This option configures where this symbolic link is located. If the + 'file' location path points to a regular file, this setting has no effect + (andManageSieve cannot be used). + +Example +------- + +---%<------------------------------------------------------------------------- +plugin { + ... + sieve = file:~/sieve;active=~/.dovecot.sieve + + sieve_default = file:/var/lib/dovecot/;name=default +} +---%<------------------------------------------------------------------------- + +On <Pigeonhole.Sieve.txt> 2.2.13-12~deb8u4 combined with <ManageSieve> +[Pigeonhole.ManageSieve.txt] on Debian the active option didn't worked and it +lead to following errors/warnings: + +---%<------------------------------------------------------------------------- +Warning: sieve-storage: Active sieve script symlink /var/mail/xxx/xxx/xxx/sieve +is no symlink +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +Error: sieve: sieve file backend: invalid option `active=~/.dovecot.sieve' +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +managesieve(<MAILBOX>): Error: sieve-storage: Active sieve script file +'/var/mail/xxx/xxx/xxx/sieve' is no symlink nor a regular file. This needs to +be fixed manually. +---%<------------------------------------------------------------------------- + +Therefore we just used it without the active option as follows and then it +worked: + +(We adjusted of course the file paths to our needs) + +---%<------------------------------------------------------------------------- +plugin { + ... + sieve = file:~/sieve; + + sieve_default = file:/var/lib/dovecot/;name=default +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Configuration.LDAP.txt b/doc/wiki/Pigeonhole.Sieve.Configuration.LDAP.txt new file mode 100644 index 0000000..e122156 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Configuration.LDAP.txt @@ -0,0 +1,131 @@ +Pigeonhole Sieve: LDAP Lookup for Sieve Scripts +=============================================== + +The 'ldap' <location type> [Pigeonhole.Sieve.Configuration.txt] is used to +retrieve Sieve scripts from an LDAP database. To retrieve a Sieve script from +the LDAP database, at most two lookups are performed. First, the LDAP entry +containing the Sieve script is searched using the specified LDAP search filter. +If the LDAP entry changed since it was last retrieved (or it was never retieved +before), the attribute containing the actual Sieve script is retrieved in a +second lookup. In the first lookup, a special attribute is read and checked for +changes. Usually, this is the 'modifyTimestamp' attribute, but an alternative +can be configured. + +Note that, by default, compiled binaries are not stored at all for Sieve +scripts retrieved from an LDAP database. The ';bindir=<path>' option needs to +be specified in the <location specification> +[Pigeonhole.Sieve.Configuration.txt]. + +Depending on how Pigeonhole was configured and compiled (refer to INSTALL file +for more information), LDAP support may only be available when a plugin called +'sieve_storage_ldap' is loaded. + +Configuration +------------- + +If support for the 'ldap' location type is compiled as a plugin, it needs to be +added to the sieve_plugins setting before it can be used, e.g.: + +---%<------------------------------------------------------------------------- +sieve_plugins = sieve_storage_ldap +---%<------------------------------------------------------------------------- + +The 'ldap' script location syntax is specified as follows: + +---%<------------------------------------------------------------------------- +location = ldap:<config-file>[;<option>[=<value>][;...]] +---%<------------------------------------------------------------------------- + +The '<config-file>' is a filesystem path that points to a configuration file +containing the actual configuration for this 'ldap' script location. + +The following additional location options are recognized: + +user=<username> : + Overrides the user name used for the lookup. Normally, the name of the user + running the Sieve interpreter is used. + +If the name of the Script is left unspecified and not otherwise provided by the +Sieve interpreter, the name defaults to `'default''. + +The configuration file is based on the auth userdb/passdb LDAP configuration +[http://wiki2.dovecot.org/AuthDatabase/LDAP]. The following options are +specific to the Sieve ldap location type: + +sieve_ldap_filter = (&(objectClass=posixAccount)(uid=%u)) : + The LDAP search filter that is used to find the entry containing the Sieve + script. + +sieve_ldap_script_attr = mailSieveRuleSource : + The name of the attribute containing the Sieve script itself. + +sieve_ldap_mod_attr = modifyTimestamp : + The name of the attribute used to detect modifications to the LDAP entry. + +Example +------- + +The dovecot configuration: + +---%<------------------------------------------------------------------------- +plugin { + sieve = ldap:/etc/dovecot/sieve-ldap.conf;bindir=~/.sieve-bin/ +} +---%<------------------------------------------------------------------------- + +The contents of sieve-ldap.conf: + +---%<------------------------------------------------------------------------- +# This file needs to be accessible by the Sieve interpreter running in +LDA/LMTP. +# This requires acces by the mail user. Don't use privileged LDAP credentials +# here as these may likely leak. Only search and read access is required. + +# Space separated list of LDAP hosts to use. host:port is allowed too. +hosts = localhost + +# Distinguished Name - the username used to login to the LDAP server. +# Leave it commented out to bind anonymously. +dn = cn=sieve,ou=Programs,dc=example,dc=org + +# Password for LDAP server, if dn is specified. +dnpass = secret + +# Simple binding. +sasl_bind = no + +# No TLS +tls = no + +# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. +# -1 = everything. You may need to recompile OpenLDAP with debugging enabled +# to get enough output. +debug_level = 0 + +# LDAP protocol version to use. Likely 2 or 3. +ldap_version = 3 + +# LDAP base +base = dc=mail,dc=example,dc=org + +# Dereference: never, searching, finding, always +deref = never + +# Search scope: base, onelevel, subtree +scope = subtree + +# Filter for user lookup. Some variables can be used: +# %u - username +# %n - user part in user@domain, same as %u if there's no domain +# %d - domain part in user@domain, empty if there's no domain +# %{name} - name of the Sieve script +sieve_ldap_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Attribute containing the Sieve script +sieve_ldap_script_attr = mailSieveRuleSource + +# Attribute used for modification tracking +sieve_ldap_mod_attr = modifyTimestamp +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Configuration.txt b/doc/wiki/Pigeonhole.Sieve.Configuration.txt new file mode 100644 index 0000000..c54a0a8 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Configuration.txt @@ -0,0 +1,643 @@ +Pigeonhole Sieve Configuration +============================== + +Contents + + + 1. Pigeonhole Sieve Configuration + + 1. Script Locations + + 2. Basic Configuration + + 3. Configurable Limits + + 4. Extension-specific Configuration + + 5. Per-user Sieve script location + + 6. Executing Multiple Scripts Sequentially + + 7. Visible Default Script + + 8. Trace Debugging + + 9. Deprecated Settings + + 10. Migration + + 1. General Dovecot 2.0 changes + + 2. From CMUSieve (Dovecot v1.0/v1.1) + + 3. From Dovecot Sieve v0.1.x (Dovecot v1.2) + +Script Locations +---------------- + +The Sieve interpreter can retrieve Sieve scripts from several types of +locations. The default 'file' location type is a directory containing one or +more Sieve script files with a symlink pointing to the active one. More complex +setups can use other location types such as 'ldap' or 'dict' to fetch Sieve +scripts from remote databases. + +All settings that specify the location of one or more Sieve scripts accept the +following syntax:: + +---%<------------------------------------------------------------------------- +<setting> = [<type>:]path[;<option>[=<value>][;...]] +---%<------------------------------------------------------------------------- + +The following script location types are implemented by default: + +file : + The location path is a file system path pointing to a directory containing + one or more script files with names structured as '<script-name>.sieve' with + the active option (default ~/.dovecot.sieve) specifying a symlink to the one + that will be used, or without the active option specified, it may be a script + file instead of a directory. Read <this wiki page> + [Pigeonhole.Sieve.Configuration.File.txt] for more information and examples. + +dict : + The location path is a Dovecot dict uri. Read <this wiki page> + [Pigeonhole.Sieve.Configuration.Dict.txt] for more information and examples. + +ldap : + LDAP database lookup. The location path is a configuration file with LDAP + options. Read <this wiki page> [Pigeonhole.Sieve.Configuration.LDAP.txt] for + more information and examples. + +If the type prefix is omitted, the script location type is 'file' and the +location is interpreted as a local filesystem path pointing to a Sieve script +file or directory. + +The following options are defined for all location types: + +name=<script-name> : + Set the name of the Sieve script that this location points to. If the name of + the Sieve script is not contained in the location path and the location of a + single script is specified, this option is required (e.g. for 'dict' + locations that must point to a particular script). If the name of the script + is contained in the location path, the value of the name option overrides the + name retrieved from the location. If the Sieve interpreter explicitly queries + for a specific name (e.g. to let the Sieve include extension + [http://tools.ietf.org/html/draft-ietf-sieve-include-05] retrieve a script + from the 'sieve_global=' location), this option has no effect. + +bindir=<dirpath> : + Points to the directory where the compiled binaries for this script location + are stored. This directory is created automatically if possible. If this + option is omitted, the behavior depends on the location type. For 'file' type + locations, the binary is then stored in the same directory as where the + script file was found if possible. For `dict' type locations, the binary is + not stored at all in that case. Don't specify the same directory for + different script locations, as this will result in undefined behavior. + Multiple mail users can share a single script directory if the script + location is the same and all users share the same system credentials (uid, + gid). + +*NOTE*: Pigeonhole versions before v0.3.1 do not support the location syntax +described here. These versions only support bare filesystem paths pointing to +files or directores as script storage location. Also, in that case a few +additional <deprecated settings> [Pigeonhole.Sieve.Configuration.txt] are +needed for configuration. + +Basic Configuration +------------------- + +To use Sieve, you will first need to make sure you are using Dovecot <LDA.txt> +or <LMTP.txt> for delivering incoming mail to users' mailboxes. Then, you need +to enable the Pigeonhole Sieve plugin in your configuration: + +---%<------------------------------------------------------------------------- +protocol lda { + mail_plugins = $mail_plugins sieve +} +protocol lmtp { + mail_plugins = $mail_plugins sieve +} +---%<------------------------------------------------------------------------- + +The sieve plugin recognizes the following configuration options in the 'plugin' +section of the config file (default values are shown if applicable): + +sieve = file:~/sieve;active=~/.dovecot.sieve : + The location of the user's main Sieve script or script storage. The + <LDA.txt> Sieve plugin uses this to find the active script for Sieve + filtering at delivery. The Sieve include extension + [http://tools.ietf.org/html/draft-ietf-sieve-include-05] uses this location + for retrieving ":personal" scripts. + +: + This location is also where the <ManageSieve> [Pigeonhole.ManageSieve.txt] + service will store the user's scripts, if supported by the location type. For + the 'file' location type, the location will then be the path to the storage + directory for all the user's personal Sieve scripts. <ManageSieve> + [Pigeonhole.ManageSieve.txt] maintains a symbolic link pointing to the + currently active script (the script executed at delivery). The location of + this symbolic link can be configured using the ';active=<path>' option. + +: + For Pigeonhole versions before v0.3.1, this setting can only be a filesystem + path pointing to a script file, or - when <ManageSieve> + [Pigeonhole.ManageSieve.txt] is used - it is the location of the symbolic + link pointing to the active script in the storage directory. That storage + directory is then configured using the deprecated 'sieve_dir' setting. + +sieve_default = (v0.3+) : + The location of the default personal sieve script file which gets executed + ONLY if user's private Sieve script does not exist, + e.g.'file:/var/lib/dovecot/default.sieve' (check the <multiscript section> + [Pigeonhole.Sieve.Configuration.txt] for instructions on running global Sieve + scripts before and after the user's personal script). This is usually a + global script, so be sure to pre-compile the specified script manually in + that case using the 'sievec' command line tool, as explained <here> + [Pigeonhole.Sieve.Usage.txt]. This setting used to be called + 'sieve_global_path', but that name is now deprecated. + +sieve_default_name = (v0.4.8+) : + The name by which the default Sieve script is visible to <ManageSieve> + [Pigeonhole.ManageSieve.txt] clients. Normally, it is not visible at all. + Refer to the <visible default script section> + [Pigeonhole.Sieve.Configuration.txt] for more information. + +sieve_global = : + Location for :global include scripts for the Sieve include extension + [http://tools.ietf.org/html/draft-ietf-sieve-include-05]. This setting used + to be called 'sieve_global_dir', but that name is now deprecated. + +sieve_discard = (v0.4.16+) : + The location of a Sieve script that is run for any message that is about to + be discarded; i.e., it is not delivered anywhere by the normal Sieve + execution. This only happens when the "implicit keep" is canceled, by e.g. + the "discard" action, and no actions that deliver the message are executed. + This "discard script" can prevent discarding the message, by executing + alternative actions. If the discard script does nothing, the message is still + discarded as it would be when no discard script is configured. + +sieve_extensions = : + Which Sieve language extensions are available to users. By default, all + supported extensions are available, except for deprecated extensions, + extensions that add the ability to change messages, extensions that require + explicit configuration or extensions that are still under development. Some + system administrators may want to disable certain Sieve extensions or enable + those that are not available by default. All supported extensions are listed + <here> [Pigeonhole.Sieve.txt]. Normally, all enabled extensions must be + listed for this setting, but starting with Sieve version 0.1.7, this setting + can use '+' and '-' to specify differences relative to the default. For + example 'sieve_extensions = +imapflags' will enable the deprecated imapflags + extension [http://tools.ietf.org/html/draft-melnikov-sieve-imapflags-03] in + addition to all extensions enabled by default. + +sieve_global_extensions = (v0.3+) : + Which Sieve language extensions are ONLY avalable in global scripts. This can + be used to restrict the use of certain Sieve extensions to administrator + control, for instance when these extensions can cause security concerns. This + setting has higher precedence than the 'sieve_extensions' setting (above), + meaning that the extensions enabled with this setting are never available to + the user's personal script no matter what is specified for the + 'sieve_extensions' setting. The syntax of this setting is similar to the + 'sieve_extensions' setting, with the difference that extensions are enabled + or disabled for exclusive use in global scripts. Currently, no extensions are + marked as such by default. + +sieve_implicit_extensions = (v0.4.13+) : + Which Sieve language extensions are implicitly available to users. The + extensions listed in this setting do not need to be enabled explicitly using + the Sieve "require" command. This behavior directly violates the Sieve + standard, but can be necessary for compatibility with some existing + implementations of Sieve (notably jSieve). Do not use this setting unless you + really need to! The syntax and semantics of this setting are otherwise + identical to the 'sieve_extensions' setting. + +sieve_plugins = : + The Pigeonhole Sieve interpreter can have plugins of its own. Using this + setting, the used plugins can be specified. Check the <Sieve plugins page> + [Pigeonhole.Sieve.Plugins.txt] for available plugins. + +sieve_user_email = (v0.4.14+) : + The primary e-mail address for the user. This is used as a default when no + other appropriate address is available for sending messages. If this setting + is not configured, either the postmaster or null "<>" address is used as a + sender, depending on the action involved. This setting is important when + there is no message envelope to extract addresses from, such as when the + script is executed in IMAP. + +sieve_user_log = : + The path to the file where the user log file is written. If not configured, a + default location is used. If the main user's personal Sieve (as configured + with 'sieve=') is a file, the logfile is set to '<filename>.log' by default. + If it is not a file, the default user log file is '~/.dovecot.sieve.log'. + +recipient_delimiter = +: + The separator that is expected between the :user and :detail address parts + introduced by the subaddress extension [http://tools.ietf.org/html/rfc5233/]. + This may also be a sequence of characters (e.g. '--'). The current + implementation looks for the separator from the left of the localpart and + uses the first one encountered. The :user part is left of the separator and + the :detail part is right. This setting is also used by Dovecot's <LMTP.txt> + service with identical semantics. + +sieve_redirect_envelope_from = sender (v0.4.4+): + Specifies what envelope sender address is used for redirected messages. + Normally, the Sieve "redirect" command copies the sender address for the + redirected message from the processed message. So, the redirected message + appears to originate from the original sender. The following values are + supported for this setting: + "sender" : + The sender address is used (default) + + "recipient" : + The final recipient address is used + + "orig_recipient" : + The original recipient is used + + "user_email" (v0.4.14+): + The user's primary address is used. This is configured with the + "sieve_user_email" setting. If that setting is not configured, "user_mail" + is equal to "sender" (the default). + + "postmaster" : + The postmaster_address configured for LDA/LMTP. + + "<user@domain>" : + Redirected messages are always sent from user@domain. The angle brackets + are mandatory. The null "<>" address is also supported. + +: + When the envelope sender of the processed message is the null address "<>", + the envelope sender of the redirected message is also always "<>", + irrespective of what is configured for this setting. + +For example: + +---%<------------------------------------------------------------------------- +plugin { +... + # The location of the user's main script storage. The active script + # in this storage is used as the main user script executed during + # delivery. The include extension fetches the :personal scripts + # from this location. When ManageSieve is used, this is also where + # scripts are uploaded. This example uses the file system as + # storage, with all the user's scripts located in the directory + # `~/sieve' and the active script (symbolic link) located at + # `~/.dovecot.sieve'. + sieve = file:~/sieve;active=~/.dovecot.sieve + + # If the user has no personal active script (i.e. if the location + # indicated in sieve= does not exist or has no active script), use + # this one: + sieve_default = /var/lib/dovecot/sieve/default.sieve + + # The include extension fetches the :global scripts from this + # location. + sieve_global = /var/lib/dovecot/sieve/global/ +} +---%<------------------------------------------------------------------------- + +Configurable Limits +------------------- + +sieve_max_script_size = 1M : + The maximum size of a Sieve script. The compiler will refuse to compile any + script larger than this limit. If set to 0, no limit on the script size is + enforced. + +sieve_max_actions = 32 : + The maximum number of actions that can be performed during a single script + execution. If set to 0, no limit on the total number of actions is enforced. + +sieve_max_redirects = 4 : + The maximum number of redirect actions that can be performed during a single + script execution. The meaning of 0 differs based on your version. For + versions v0.3.0 and beyond this means that redirect is prohibited. For older + versions, however, this means that the number of redirects is /unlimited/, so + be careful. + +Extension-specific Configuration +-------------------------------- + +The following Sieve language extensions have specific configuration +options/needs: + + * <duplicate> [Pigeonhole.Sieve.Extensions.Duplicate.txt] + * <editheader> [Pigeonhole.Sieve.Extensions.Editheader.txt] (configuration + required) + * <imapsieve> [Pigeonhole.Sieve.Plugins.IMAPSieve.txt] (plugin configuration + required) + * <include> [Pigeonhole.Sieve.Extensions.Include.txt] + * <spamtest and virustest> [Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt] + (configuration required) + * <vacation and vacation-seconds> [Pigeonhole.Sieve.Extensions.Vacation.txt] + * <variables> [Pigeonhole.Sieve.Extensions.Variables.txt] + +Per-user Sieve script location +------------------------------ + +By default, the Dovecot Sieve plugin looks for the user's Sieve script file in +the user's home directory ('~/.dovecot.sieve'). This requires that the <home +directory> [VirtualUsers.txt] is set for the user. + +If you want to store the script elsewhere, you can override the default using +the 'sieve' setting, which specifies the path to the user's script file. This +can be done in two ways: + + 1. Define the 'sieve' setting in the plugin section of 'dovecot.conf'. + 2. Return 'sieve' extra field from <userdb extra fields> + [UserDatabase.ExtraFields.txt]. + +For example, to use a Sieve script file named '<username>.sieve' in +'/var/sieve-scripts', use: + +---%<------------------------------------------------------------------------- +plugin { +... + + sieve = /var/sieve-scripts/%u.sieve +} +---%<------------------------------------------------------------------------- + +You may use templates like %u, as shown in the example. See all <variables> +[Variables.txt]. + +A relative path (or just a filename) will be interpreted to point under the +user's home directory. + +Executing Multiple Scripts Sequentially +--------------------------------------- + +The Dovecot Sieve plugin allows executing multiple Sieve scripts sequentially. +The extra scripts can be executed before and after the user's private script. +For example, this allows executing global Sieve policies before the user's +script. This is not possible using the 'sieve_default' setting, because that is +only used when the user's private script does not exist. The following settings +in the 'plugin' section of the Dovecot config file control the execution +sequence: + +sieve_before = : + +sieve_before2 = : + +sieve_before3 = (etc..) : + Location Sieve of scripts that need to be executed before the user's personal + script. If a 'file' location path points to a directory, all the Sieve + scripts contained therein (with the proper '.sieve' extension) are executed. + The order of execution within that directory is determined by the file names, + using a normal 8bit per-character comparison. Multiple script locations can + be specified by appending an increasing number to the setting name. The Sieve + scripts found from these locations are added to the script execution sequence + in the specified order. Reading the numbered sieve_before settings stops at + the first missing setting, so no numbers may be skipped. + +sieve_after = : + +sieve_after2 = : + +sieve_after3 = (etc..) : + Identical to 'sieve_before', but the specified scripts are executed after the + user's script (only when keep is still in effect, as explained below). + +The script execution ends when the currently executing script in the sequence +does not yield a "keep" result: when the script terminates, the next script is +only executed if an implicit or explicit "keep" is in effect. Thus, to end all +script execution, a script must not execute keep and it must cancel the +implicit keep, e.g. by executing "'discard; stop;'". This means that the +command "'keep;'" has different semantics when used in a sequence of scripts. +For normal Sieve execution, "'keep;'" is equivalent to "'fileinto "INBOX";'", +because both cause the message to be stored in INBOX. However, in sequential +script execution, it only controls whether the next script is executed. Storing +the message into INBOX (the default folder) is not done until the last script +in the sequence executes (implicit) keep. To force storing the message into +INBOX earlier in the sequence, the fileinto command can be used (with "':copy'" +or together with "'keep;'"). + +Apart from the keep action, all actions triggered in a script in the sequence +are executed before continuing to the next script. This means that when a +script in the sequence encounters an error, actions from earlier executed +scripts are not affected. The sequence is broken however, meaning that the +script execution of the offending script is aborted and no further scripts are +executed. An implicit keep is executed in stead. + +Just as for executing a single script the normal way, the Dovecot Sieve plugin +takes care never to duplicate deliveries, forwards or responses. When vacation +actions are executed multiple times in different scripts, the usual error is +not triggered: the subsequent duplicate vacation actions are simply discarded. + +For example: + +---%<------------------------------------------------------------------------- +plugin { +... + # Global scripts executed before the user's personal script. + # E.g. handling messages marked as dangerous + sieve_before = /var/lib/dovecot/sieve/discard-virusses.sieve + + # Domain-level scripts retrieved from LDAP + sieve_before2 = ldap:/etc/dovecot/sieve-ldap.conf;name=ldap-domain + + # User-specific scripts executed before the user's personal script. + # E.g. a vacation script managed through a non-ManageSieve GUI. + sieve_before3 = /var/vmail/%d/%n/sieve-before + + # User-specific scripts executed after the user's personal script. + # (if keep is still in effect) + # E.g. user-specific default mail filing rules + sieve_after = /var/vmail/%d/%n/sieve-after + + # Global scripts executed after the user's personal script + # (if keep is still in effect) + # E.g. default mail filing rules. + sieve_after2 = /var/lib/dovecot/sieve/after.d/ +} +} +---%<------------------------------------------------------------------------- + +*IMPORTANT*: Be sure to manually pre-compile the scripts specified by +'sieve_before' and 'sieve_after' using the 'sievec' tool, as explained <here> +[Pigeonhole.Sieve.Usage.txt]. + +Visible Default Script +---------------------- + +The 'sieve_default=' setting specifies the location of a default script that is +executed when the user has no active personal script. Normally, this default +script is invisible to the user; i.e., it is not listed in <ManageSieve> +[Pigeonhole.ManageSieve.txt]. To give the user the ability to see and read the +default script, it is possible to make it visible under a specific configurable +name using the 'sieve_default_name' setting. This feature is only supported for +Pigeonhole versions 0.4.8 and higher. + +ManageSieve will magically list the default script under that name, even though +it does not actually exist in the user's normal script storage location. This +way, theManageSieve client can see that it exists and it can retrieve its +contents. If no normal script is active, the default is always listed as +active. The user can replace the default with a custom script, by uploading it +under the default script's name. If that custom script is ever deleted, the +default script will reappear from the shadows implicitly. + +This way, ManageSieve clients will not need any special handling for this +feature. If the name of the default script is equal to the name the client uses +for the main script, it will initially see and read the default script when the +user account is freshly created. The user can edit the script, and when the +edited script is saved through theManageSieve client, it will will override the +default script. If the user ever wants to revert to the default, the user only +needs to delete the edited script and the default will reappear. + +The name by which the default script will be known is configured using the +'sieve_default_name' setting. Of course, the 'sieve_default' setting needs to +point to a valid script location as well for this to work. If the default +script does not exist at the indicated location, it is not shown. + +For example: + +---%<------------------------------------------------------------------------- +plugin { +... + sieve = file:~/sieve;active=~/.dovecot.sieve + + sieve_default = /var/lib/dovecot/sieve/default.sieve + sieve_default_name = roundcube +} +---%<------------------------------------------------------------------------- + +Trace Debugging +--------------- + +Trace debugging provides detailed insight in the operations performed by the +Sieve script. Messages about what the Sieve script is doing are written to the +specified directory. This feature is only supported for Pigeonhole versions +0.4.14 and higher. + +*WARNING*: On a busy server, this functionality can quickly fill up the trace +directory with a lot of trace files. Enable this only temporarily and as +selective as possible; e.g., enable this only for a few users by returning the +settings below from userdb as <userdb extra fields> +[UserDatabase.ExtraFields.txt], rather than enabling these for everyone. + +The following settings apply to both the LDA/LMTP Sieve plugin and the +<IMAPSieve> [Pigeonhole.Sieve.Plugins.IMAPSieve.txt] plugin: + +sieve_trace_dir = : + The directory where trace files are written. Trace debugging is disabled if + this setting is not configured or if the directory does not exist. If the + path is relative or it starts with "~/" it is interpreted relative to the + current user's home directory. + +sieve_trace_level = : + The verbosity level of the trace messages. Trace debugging is disabled if + this setting is not configured. Possible values are: + "actions" : + Only print executed action commands, like keep, fileinto, reject and + redirect. + + "commands" : + Print any executed command, excluding test commands. + + "tests" : + Print all executed commands and performed tests. + + "matching" : + Print all executed commands, performed tests and the values matched in + those tests. + +sieve_trace_debug = no : + Enables highly verbose debugging messages that are usually only useful for + developers. + +sieve_trace_addresses = no : + Enables showing byte code addresses in the trace output, rather than only the + source line numbers. + +Deprecated Settings +------------------- + +These settings are deprecated in newer versions, but still recognized: + +sieve_global_path = (< v0.2): + The deprecated name for the 'sieve_default' setting. + +sieve_dir = ~/sieve (< v0.3.1): + Directory for :personal include scripts for the include extension + [http://tools.ietf.org/html/draft-ietf-sieve-include-05]. The Sieve + interpreter only recognizes files that end with a '.sieve' extension, so the + include extension expects a file called 'name.sieve' to exist in the + 'sieve_dir' directory for a script called 'name'. When using <ManageSieve> + [Pigeonhole.ManageSieve.txt], this is also the directory where scripts are + uploaded. For recent Pigeonhole versions, this location is configured as part + of the 'sieve' setting. + +sieve_global_dir = (< v0.3.1): + Directory for :global include scripts for the include extension + [http://tools.ietf.org/html/draft-ietf-sieve-include-05]. The Sieve + interpreter only recognizes files that end with a '.sieve' extension, so the + include extension expects a file called 'name.sieve' to exist in the + 'sieve_global_dir' directory for a script called 'name'. For recent + Pigeonhole versions, a more generic version of this setting is called + 'sieve_global' and allows locations other than file system directories. + +Migration +--------- + +General Dovecot 2.0 changes +--------------------------- + + * Note that the Dovecot v2.0 <LDA.txt> does not create mailfolders + automatically by default anymore. If your configuration relies on this, you + need to enable the 'lda_mailbox_autocreate' setting for <LDA.txt> or start + using the Sieve mailbox extension's ':create' tag for *fileinto* commands. + * Dovecot v2.0 adds support for <LMTP.txt>. Much like the <Dovecot LDA> + [LDA.txt], it can make use of the Pigeonhole Sieve plugin. Since the + <LMTP.txt> service has its own 'prototocol lmtp' section in the config file, + you need to add the Sieve plugin to the 'mail_plugins' setting there too + when you decide to use <LMTP.txt>. + +From CMUSieve (Dovecot v1.0/v1.1) +--------------------------------- + +For the most part, migration from CMUSieve to Pigeonhole Sieve is just a matter +of changing the used plugin name from *cmusieve* to *sieve* in the +'mail_plugins' option in the 'protocol lda' section of the config file (as +explained <above> [Pigeonhole.Sieve.Configuration.txt]). However, there are a +few important differences in the supported Sieve language features: + + * The *imapflags* extension is now called *imap4flags*. The CMUSieve + implementation is based on an old draft specification + [http://tools.ietf.org/html/draft-melnikov-sieve-imapflags-03] that is not + completely compatible with the new version + [http://tools.ietf.org/html/rfc5232/]. Particularly, the *mark* and *unmark* + commands were removed from the new specification. For backwards + compatibility, support for the old imapflags extension can be enabled using + the 'sieve_extensions' setting (as explained <above> + [Pigeonhole.Sieve.Configuration.txt]). This is disabled by default. + * The *notify* extension is now called *enotify*. The CMUSieve implementation + is based on an old draft specification + [http://tools.ietf.org/html/draft-martin-sieve-notify-01] that is not + completely compatible with the new version + [http://tools.ietf.org/html/rfc5435/]. Particularly, the *denotify* command + and *$text$* substitutions were removed from the new specification. For + backwards compatibility, support for the old imapflags extension can be + enabled using the 'sieve_extensions' setting (as explained <above> + [Pigeonhole.Sieve.Configuration.txt]). This is disabled by default. + * The include extension [http://tools.ietf.org/html/draft-ietf-sieve-include] + now requires your script /file/ names to end with ".sieve". This means that + 'include :personal "myscript"' won't work unless your script file is called + "'myscript.sieve'" on disk. Also note that the "'.sieve'" extension has no + special meaning within the Sieve script; if you 'include "myscript.sieve"', + the Sieve interpreter will look for a script file called + 'myscript.sieve.sieve' and not 'myscript.sieve'. + * Be sure to use *UTF8* for the mailbox argument of the *fileinto* command. + Older CMUSieve installations used modified UTF7 (as IMAP does) for the + mailbox parameter. If not adjusted, the Pigeonhole Sieve plugin will use the + wrong folder name for storing the message. + +From Dovecot Sieve v0.1.x (Dovecot v1.2) +---------------------------------------- + + * The 'sieve_subaddress_sep' setting for the Sieve subaddress extension + [http://tools.ietf.org/html/rfc5233/] is now known as 'recipient_delimiter'. + Although 'sieve_subaddress_sep' is still recognized for backwards + compatibility, it is recommended to update the setting to the new name, + since the <LMTP.txt> service also uses the 'recipient_delimiter' setting. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Examples.txt b/doc/wiki/Pigeonhole.Sieve.Examples.txt new file mode 100644 index 0000000..fb578df --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Examples.txt @@ -0,0 +1,423 @@ +Pigeonhole Sieve examples +========================= + +Contents + + + 1. Pigeonhole Sieve examples + + 1. Mail filtering by various headers + + 2. Flagging or Highlighting your mail + + 3. Spam/Virus rules + + 1. Direct filtering using message header + + 2. Filtering using the spamtest and virustest extensions + + 4. Plus Addressed mail filtering + + 5. Vacation auto-reply + + 6. Include scripts + + 7. Archiving a Mailinglist by Date + + 8. Emulating lmtp_save_to_detail_mailbox=yes + + 9. Translation from Procmail + +Below are some simple Sieve code examples, more can be found at +http://sieve.info/examplescripts. + +Mail filtering by various headers +--------------------------------- + +Use if/elsif/else to store messages into various folders/subfolders: + + * ---%<---------------------------------------------------------------------- + require ["fileinto", "envelope"]; + if address :is "to" "dovecot@dovecot.org" { + fileinto "Dovecot-list"; + } elsif envelope :is "from" "owner-cipe-l@inka.de" { + fileinto "lists.cipe"; + } elsif anyof (header :contains "X-listname" "lugog@cip.rz.fh-offenburg.de", + header :contains "List-Id" "Linux User Group Offenburg") { + fileinto "ml.lugog"; + } else { + # The rest goes into INBOX + # default is "implicit keep", we do it explicitly here + keep; + } + ---%<---------------------------------------------------------------------- + + "anyof" means logical OR, "allof" is AND. + +Forward mails with "order" or "buy" in their subject to another address: + + * ---%<---------------------------------------------------------------------- + if header :contains "subject" ["order", "buy"] { + redirect "orders@company.dom"; + } + ---%<---------------------------------------------------------------------- + +Message-ID and recipient of forwarded message are stored in a +'.dovecot.lda-dupes' at users home directory to prevent mail loops. + +Flagging or Highlighting your mail +---------------------------------- + +Some mail readers use these flags: + +---%<------------------------------------------------------------------------- +require "imap4flags"; +require "regex"; +if anyof (exists "X-Cron-Env", + header :regex ["subject"] [".* security run output", + ".* monthly run output", + ".* daily run output", + ".* weekly run output"]) { + addflag "$label1"; # ie 'Important'/red label within Thunderbird + +# Other flags: +# addflag "$label1"; # Important: #ff0000 => red +# addflag "$label2"; # Work: #ff9900 => orange +# addflag "$label3"; # personal: #009900 => green +# addflag "$label4"; # todo: #3333ff => blue +# addflag "$label5"; # later: #993399 => violet +# +} +---%<------------------------------------------------------------------------- + +Local copy of your emails: + +---%<------------------------------------------------------------------------- +require ["envelope", "imap4flags"]; +if envelope "from" "my_address@my_domain.com" +{ + setflag "\\seen"; +} +---%<------------------------------------------------------------------------- + +/Useful, when you want sieve to manage your incoming *and* outgoing email (you +must ask your mail reader to Bcc your mail to your dovecot in this case)./ + +Spam/Virus rules +---------------- + +Most spam and virus scanners add a special header to mail messages, so that +users can apply filtering accordingly. Depending on how the Sieve interpreter +is configured, filtering can either be performed by evaluating these headers +directly, or using the spamtest and virustest extensions. + +Direct filtering using message header +------------------------------------- + +Evaluating the headers directly is always possible as long as the headers are +actually added to the messages by the scanner software. For example, to +fileSpamAssassin-tagged mails into a folder called "Spam": + +---%<------------------------------------------------------------------------- +require "fileinto"; +if header :contains "X-Spam-Flag" "YES" { + fileinto "Spam"; +} +---%<------------------------------------------------------------------------- + +The following example discards SpamAssassin-tagged mails with level higher than +or equal to 10: + +---%<------------------------------------------------------------------------- +if header :contains "X-Spam-Level" "**********" { + discard; + stop; +} +---%<------------------------------------------------------------------------- + +Some spam scanners only produce a numeric score in a header. Then, the test +becomes more involved: + +---%<------------------------------------------------------------------------- +require ["comparator-i;ascii-numeric","relational"]; +if allof ( + not header :matches "x-spam-score" "-*", + header :value "ge" :comparator "i;ascii-numeric" "x-spam-score" "10" ) +{ + discard; + stop; +} +---%<------------------------------------------------------------------------- + +*NOTE:* Be very careful when matching against spam score headers using the +relational extension and the i;ascii-numeric comparator. This comparator can +only be used to match unsigned integers. Strings that do not begin with a digit +character represent positive infinity and will therefore always be larger than +any score mentioned in your rule! That is why the above example first checks +the minus sign explicitly. + +Filtering using the spamtest and virustest extensions +----------------------------------------------------- + +When the spamtest [http://tools.ietf.org/html/rfc5235#section-3.2] and +virustest [http://tools.ietf.org/html/rfc5235#section-3.3] extensions are +configured on the server ( <here> +[Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt] is explained how), users +(and GUIs) can have a much easier way to filter spam and virus messages +respectively. To filter spam, the spamtest extension can for example be used as +follows: + +---%<------------------------------------------------------------------------- +require "spamtestplus"; +require "fileinto"; +require "relational"; +require "comparator-i;ascii-numeric"; + +/* If the spamtest fails for some reason, e.g. spam header is missing, file + * file it in a special folder. + */ +if spamtest :value "eq" :comparator "i;ascii-numeric" "0" { + fileinto "Unclassified"; + +/* If the spamtest score (in the range 1-10) is larger than or equal to 3, + * file it into the spam folder: + */ +} elsif spamtest :value "ge" :comparator "i;ascii-numeric" "3" { + fileinto "Spam"; + +/* For more fine-grained score evaluation, the :percent tag can be used. The + * following rule discards all messages with a percent score + * (relative to maximum) of more than 85 %: + */ +} elsif spamtest :value "gt" :comparator "i;ascii-numeric" :percent "85" { + discard; +} + +/* Other messages get filed into INBOX */ +---%<------------------------------------------------------------------------- + +The virustest extension can be used in a similar manner: + +---%<------------------------------------------------------------------------- +require "virustest"; +require "fileinto"; +require "relational"; +require "comparator-i;ascii-numeric"; + +/* Not scanned ? */ +if virustest :value "eq" :comparator "i;ascii-numeric" "0" { + fileinto "Unscanned"; + +/* Infected with high probability (value range in 1-5) */ +} if virustest :value "eq" :comparator "i;ascii-numeric" "4" { + /* Quarantine it in special folder (still somewhat dangerous) */ + fileinto "Quarantine"; + +/* Definitely infected */ +} elsif virustest :value "eq" :comparator "i;ascii-numeric" "5" { + /* Just get rid of it */ + discard; +} +---%<------------------------------------------------------------------------- + +Plus Addressed mail filtering +----------------------------- + +Using the subaddress [http://tools.ietf.org/html/rfc5233/] extension, it is +possible to match against the 'detail' part of an e-mail address, e.g. a +''+tag'' suffix to the local part of the address. This is for example useful +when you don't want just any +tag to create a directory, but you want to use +tagged addresses such as with amavisd-new. This example would place email +addressed to user+spam@example.com into user's Spam folder. + +---%<------------------------------------------------------------------------- +require ["fileinto", "envelope", "subaddress"]; +if envelope :detail "to" "spam"{ + fileinto "Spam"; +} +---%<------------------------------------------------------------------------- + +The following more advanced example uses the subaddress +[http://tools.ietf.org/html/rfc5233/] extension to handle recipient addresses +structured as 'sales+<name>@company.com' in a special way. The '<name>' part is +extracted from the address using variables +[http://tools.ietf.org/html/rfc5229/] extension, transformed into a format with +the first letter in upper case and subsequently used to create the folder name +where the message is stored. The folder name is structured as 'users/<name>'. +If the '+<name>' detail is omitted from the recipient address, the message is +filed in the 'sales' folder. + +---%<------------------------------------------------------------------------- +require ["variables", "envelope", "fileinto", "subaddress"]; + +if envelope :is :user "to" "sales" { + if envelope :matches :detail "to" "*" { + /* Save name in ${name} in all lowercase except for the first letter. + * Joe, joe, jOe thus all become 'Joe'. + */ + set :lower :upperfirst "name" "${1}"; + } + + if string :is "${name}" "" { + /* Default case if no detail is specified */ + fileinto "sales"; + } else { + /* For sales+joe@ this will become users/Joe */ + fileinto "users/${name}"; + } +} +---%<------------------------------------------------------------------------- + +To work with Postfix, this requires that the envelope "to" still contains the +full address, so pass it with the -a flag. + +---%<------------------------------------------------------------------------- +dovecot unix - n n - - pipe + flags=DRhu user=mail:mail argv=/usr/local/libexec/dovecot/dovecot-lda + -f ${sender} -d ${user}@${nexthop} -a ${original_recipient} +---%<------------------------------------------------------------------------- + +or + +---%<------------------------------------------------------------------------- +mailbox_command = /usr/lib/dovecot/dovecot-lda -a "$RECIPIENT" +---%<------------------------------------------------------------------------- + +Vacation auto-reply +------------------- + +Auto-responder functionality is implemented using the vacation +[http://tools.ietf.org/html/rfc5230/] extension. The following script sends +out-of-office replies when the message is not spam: + +---%<------------------------------------------------------------------------- +require ["fileinto", "vacation"]; +# Move spam to spam folder +if header :contains "X-Spam-Flag" "YES" { + fileinto "spam"; + # Stop here so that we do not reply on spams + stop; +} +vacation + # Reply at most once a day to a same sender + :days 1 + :subject "Out of office reply" + # List of additional recipient addresses which are included in the auto +replying. + # If a mail's recipient is not the envelope recipient and it's not on this +list, + # no vacation reply is sent for it. + :addresses ["j.doe@company.dom", "john.doe@company.dom"] +"I'm out of office, please contact Joan Doe instead. +Best regards +John Doe"; +---%<------------------------------------------------------------------------- + +It's also possible to include the original subject using the variables +[http://tools.ietf.org/html/rfc5229/] extension: + +---%<------------------------------------------------------------------------- +require ["variables", "vacation"]; +# Store old Subject line so it can be used in vacation message +if header :matches "Subject" "*" { + set "subjwas" ": ${1}"; +} +vacation + :days 1 + :subject "Out of office reply${subjwas}" + :addresses ["j.doe@company.dom", "john.doe@company.dom"] +"I'm out of office, please contact Joan Doe instead. +Best regards +John Doe"; +---%<------------------------------------------------------------------------- + +Include scripts +--------------- + +It's possible to include other Sieve scripts in your script: + +---%<------------------------------------------------------------------------- +require ["include"]; +include :global "global-spam"; +include :personal "my-own-spam"; +---%<------------------------------------------------------------------------- + +The lookup directories can be specified with: + +---%<------------------------------------------------------------------------- +plugin { + # Directory for :personal include scripts. The default is to use home +directory. + sieve_dir = %h/sieve + + # Directory for :global include scripts (not to be confused with +sieve_global_path). + # If unset, the include fails. + sieve_global_dir = /etc/dovecot/sieve/ +} +---%<------------------------------------------------------------------------- + +Both 'sieve_dir' and 'sieve_global_dir' may also be overridden by <userdb extra +fields> [UserDatabase.ExtraFields.txt]. + +It's not currently possible to use subdirectories for the scripts. Having a '/' +character in the script name always fails the include. This is just an extra +check to avoid potential problems with including scripts within mail +directories. + +Archiving a Mailinglist by Date +------------------------------- + +You can archive messages from mailing lists in a date-structured folder tree as +follows: + +---%<------------------------------------------------------------------------- +require ["variables","date","fileinto","mailbox"]; + +# Extract date info +if currentdate :matches "year" "*" { set "year" "${1}"; } +if currentdate :matches "month" "*" { set "month" "${1}"; } + +# Archive Dovecot mailing list items by year and month. +# Create folder when it does not exist. +if header :is "list-id" "dovecot.dovecot.org" { + fileinto :create "INBOX.Lists.${year}.${month}.dovecot"; +} +---%<------------------------------------------------------------------------- + +For example, in March 2013 this puts messages from the Dovecot mailing list in +a folder called 'INBOX.Lists.2013.03.dovecot'. It combines the date +[http://tools.ietf.org/html/rfc5260#section-4] and variables +[http://tools.ietf.org/html/rfc5229/] extensions to extract the required date +strings. Using the ':create' argument for the 'fileinto' command, the indicated +folder is created automatically if it doesn't exist. The ':create' argument is +provided by the mailbox [http://tools.ietf.org/html/rfc5490#section-3] +extension. + +Emulating lmtp_save_to_detail_mailbox=yes +----------------------------------------- + +If you can't turn this option on, you can emulate the behaviour to some extent +with following code. + +---%<------------------------------------------------------------------------- +require ["variables", "fileinto", "envelope", "subaddress", "mailbox"]; + +if envelope :matches :detail "to" "*" { + # you can prefix with INBOX/ or INBOX. if necessary + # remove :create if you want to permit only existing mailboxes + fileinto :create "${1}"; +} +---%<------------------------------------------------------------------------- + +Translation from Procmail +------------------------- + +There exists a script which attempts to translate simple Procmail rules into +Sieve rules:http://www.earth.ox.ac.uk/~steve/sieve/procmail2sieve.pl +(dovecot.org mirror [http://dovecot.org/tools/procmail2sieve.pl]) + +Here's the original post announcing it: +http://dovecot.org/list/dovecot/2007-March/020895.html + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.Duplicate.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.Duplicate.txt new file mode 100644 index 0000000..dbd0c28 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.Duplicate.txt @@ -0,0 +1,47 @@ +Pigeonhole Sieve: Duplicate Extension +===================================== + +The *duplicate* extension RFC 7353 [http://tools.ietf.org/html/rfc7352] adds a +new test command called 'duplicate' to the Sieve language. This test adds the +ability to detect duplications. The main application for this new test is +handling duplicate deliveries commonly caused by mailing list subscriptions or +redirected mail addresses. The detection is normally performed by matching the +message ID to an internal list of message IDs from previously delivered +messages. For more complex applications, the 'duplicate' test can also use the +content of a specific header field or other parts of the message. + +Previously, this extension was Dovecot-specific and available under the name +'vnd.dovecot.duplicate'. Specification for old version available here +[http://hg.rename-it.nl/dovecot-2.1-pigeonhole/raw-file/tip/doc/rfc/spec-bosch-sieve-duplicate.txt]. +That implementation differs significantly from what is now published as RFC +7353 [http://tools.ietf.org/html/rfc7352], but the original extension is still +supported for backwards compatibility. + +Configuration +------------- + +The *duplicate* extension is available by default. The *duplicate* extension +has its own specific settings. The following settings are available (default +values are indicated): + +sieve_duplicate_default_period = 14d : + +sieve_duplicate_max_period = 7d : + These options respectively specify the default and the maximum value for the + period after which tracked values are purged from the duplicate tracking + database. The period is specified in s(econds), unless followed by a d(ay), + h(our) or m(inute) specifier character. + +Example +------- + +---%<------------------------------------------------------------------------- +plugin { + sieve = ~/.dovecot.sieve + + sieve_duplicate_default_period = 1h + sieve_duplicate_max_period = 1d +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.Editheader.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.Editheader.txt new file mode 100644 index 0000000..f7b3869 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.Editheader.txt @@ -0,0 +1,61 @@ +Pigeonhole Sieve: Editheader Extension +====================================== + +The *editheader* extension (RFC5293 [http://tools.ietf.org/html/rfc5293/]) +enables Sieve scripts to delete and add message header fields, thereby allowing +interaction with other components that consume or produce header fields. + +Configuration +------------- + +The *editheader* extension is not available by default and needs to be enabled +explicitly by adding it to the 'sieve_extensions' setting. + +The following settings can be configured for the *editheader* extension +(default values are indicated): + +sieve_editheader_max_header_size = 2048 : + The maximum size in bytes of a header field value passed to the 'addheader' + command. The minimum value for this setting is 1024 bytes. The value is in + bytes, unless followed by a k(ilo). + +sieve_editheader_forbid_add = : + A space-separated list of headers that cannot be added to the message header. + Addition of the 'Subject:' header cannot be prohibited, as required by the + RFC specification. Therefore, adding this header to this setting has no + effect. + +sieve_editheader_forbid_delete = : + A space-separated list of headers that cannot be deleted from the message + header. Deleting the 'Received:' and 'Auto-Submitted:' fields is always + forbidden, while removing the 'Subject:' header cannot be prohibited, as + required by the RFC specification. Therefore, adding one of these headers to + this setting has no effect. + +sieve_editheader_protected = : + A space-separated list of headers that cannot be added to or deleted from the + message header. This setting is provided for backwards compatibility. It is a + combination of the 'sieve_editheader_forbid_add' and + 'sieve_editheader_forbid_delete' settings. The same limitations apply. + +Invalid values for the settings above will make the Sieve interpreter log a +warning and revert to the default values. + +Example +------- + +---%<------------------------------------------------------------------------- +plugin { + # Use editheader + sieve_extensions = +editheader + + # Header fiels must not exceed one kilobyte + sieve_editheader_max_header_size = 1k + + # Protected special headers + sieve_editheader_forbid_add = X-Verified + sieve_editheader_forbid_delete = X-Verified X-Seen +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.Include.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.Include.txt new file mode 100644 index 0000000..e5b820b --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.Include.txt @@ -0,0 +1,28 @@ +Pigeonhole Sieve: Include Extension +=================================== + +The Sieve *include* extension (RFC 6609 [http://tools.ietf.org/html/rfc6609]) +permits users to include one Sieve script into another. This can make managing +large scripts or multiple sets of scripts much easier, and allows a site and +its users to build up libraries of scripts. Users are able to include their own +personal scripts or site-wide scripts. + +Included scripts can include more scripts of their own, yielding a tree of +included scripts with the main script (typically the user's personal script) at +its root. + +Configuration +------------- + +The *include* extension is available by default. The *include* extension has +its own specific settings. The following settings can be configured for the +*include* extension (default values are indicated): + +sieve_include_max_includes = 255 : + The maximum number of scripts that may be included. This is the total number + of scripts involved in the include tree. + +sieve_include_max_nesting_depth = 10 : + The maximum nesting depth for the include tree. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt new file mode 100644 index 0000000..fbc7225 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt @@ -0,0 +1,146 @@ +Pigeonhole Sieve: Spamtest and Virustest Extensions +=================================================== + +Using the *spamtest* and *virustest* extensions (RFC 5235 +[http://tools.ietf.org/html/rfc5235/]), the Sieve language provides a uniform +and standardized command interface for evaluating spam and virus tests +performed on the message. Users no longer need to know what headers need to be +checked and how the scanner's verdict is represented in the header field value. +They only need to know how to use the *spamtest* (*spamtestplus*) and +*virustest* extensions. This also gives GUI-based Sieve editors the means to +provide a portable and easy to install interface for spam and virus filter +configuration. The burden of specifying which headers need to be checked and +how the scanner output is represented falls onto the Sieve administrator. + +Configuration +------------- + +The *spamtest*, *spamtestplus* and *virustest* extensions are not enabled by +default and thus need to be enabled explicitly using the 'sieve_extensions' +setting. + +The following settings need to be configured for using the *spamtest* and +*spamtestplus* extensions. The *virustest* extension has identical +configuration settings, but with a ''sieve_virustest_'' prefix instead of a +''sieve_spamtest_'' prefix: + +sieve_spamtest_status_type = "score" / "strlen" / "text": + This specifies the type of status result that the spam/virus scanner + produces. This can either be a numeric score ('score'), a string of identical + characters ('strlen'), e.g. ''*******'', or a textual description ('text'), + e.g.'{{{Spam}}}' or ''Not Spam''. + +sieve_spamtest_status_header = <header-field> [ ":" <regexp> ]: + This specifies the header field that contains the result information of the + spam scanner and it may express the syntax of the content of the header. If + no matching header is found in the message, the spamtest command will match + against "0". + +: + This is a structured setting. The first part specifies the header field name. + Optionally, a POSIX regular expression follows the header field name, + separated by a colon. Any white space directly following the colon is not + part of the regular expression. If the regular expression is omitted, any + header content is accepted and the full header value is used. When a regular + expression is used, it must specify one match value (inside brackets) that + yields the desired spam scanner result. If the header does not match the + regular expression or if no value match is found, the 'spamtest' test will + match against "0" during Sieve script execution. + +sieve_spamtest_max_value =: + This statically specifies the maximum value a numeric spam score can have. + +sieve_spamtest_max_header = <header-field> [ ":" <regexp> ]: + Some spam scanners include the maximum score value in one of their status + headers. Using this setting, this maximum can be extracted from the message + itself in stead of specifying the maximum manually using the setting + 'sieve_spamtest_max_value' explained above. The syntax is identical to the + 'sieve_spamtext_status_header' setting. + +sieve_spamtest_text_valueX =: + When the 'sieve_spamtest_status_type' setting is set to 'text', these + settings specify that the 'spamtest' test will match against the value "'X'" + when the specified string is equal to the text (extracted) from the status + header. For *spamtest* and *spamtestplus*, values of X between 0 and 10 are + recognized, while *virustest* only uses values between 0 and 5. + +Examples +-------- + +This section shows several configuration examples. Each example shows a +specimen of valid virus/spam test headers that the given configuration willwork +on. + +Example 1 +--------- + +Spam header: 'X-Spam-Score: No, score=-3.2' + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_type = score + sieve_spamtest_status_header = \ + X-Spam-Score: [[:alnum:]]+, score=(-?[[:digit:]]+\.[[:digit:]]) + sieve_spamtest_max_value = 5.0 +} +---%<------------------------------------------------------------------------- + +Example 2 +--------- + +Spam header: 'X-Spam-Status: Yes' + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_type = text + sieve_spamtest_status_header = X-Spam-Status + sieve_spamtest_text_value1 = No + sieve_spamtest_text_value10 = Yes +} +---%<------------------------------------------------------------------------- + +Example 3 +--------- + +Spam header: 'X-Spam-Score: sssssss' + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +spamtest +spamtestplus + + sieve_spamtest_status_header = X-Spam-Score + sieve_spamtest_status_type = strlen + sieve_spamtest_max_value = 5 +} +---%<------------------------------------------------------------------------- + +Example 4 +--------- + +Spam header: 'X-Spam-Score: status=3.2 required=5.0' + +Virus header: 'X-Virus-Scan: Found to be clean.' + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +spamtest +spamtestplus +virustest + + sieve_spamtest_status_type = score + sieve_spamtest_status_header = \ + X-Spam-Score: score=(-?[[:digit:]]+\.[[:digit:]]).* + sieve_spamtest_max_header = \ + X-Spam-Score: score=-?[[:digit:]]+\.[[:digit:]] +required=([[:digit:]]+\.[[:digit:]]) + + sieve_virustest_status_type = text + sieve_virustest_status_header = X-Virus-Scan: Found to be (.+)\. + sieve_virustest_text_value1 = clean + sieve_virustest_text_value5 = infected +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.Vacation.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.Vacation.txt new file mode 100644 index 0000000..16bf772 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.Vacation.txt @@ -0,0 +1,106 @@ +Pigeonhole Sieve: Vacation Extension +==================================== + +The Sieve vacation extension (RFC5230 [http://tools.ietf.org/html/rfc5230/]) +defines a mechanism to generate automatic replies to incoming email messages. +It takes various precautions to make sure replies are only sent when +appropriate. Script authors can specify how often replies can be sent to a +particular contact. In the original vacation extension, this interval is +specified in days with a minimum of one day. When more granularity is necessary +and particularly when replies must be sent more frequently than one day, the +vacation-seconds extension (RFC6131 [http://tools.ietf.org/html/rfc5230/]) can +be used. This allows specifying the minimum reply interval in seconds with a +minimum of zero (a reply is then always sent), depending on administrator +configuration. + +Configuration +============= + +The *vacation* extension is available by default. In contrast, the +*vacation-seconds* extension - which implies the vacation extension when used - +is not available by default and needs to be enabled explicitly by adding it to +the 'sieve_extensions' setting. The configuration also needs to be adjusted +accordingly to allow a non-reply period of less than a day. + +The *vacation* and *vacation-seconds* extensions have their own specific +settings. The settings that specify a period (currently all of them) are +specified in *s*(econds), unless followed by a *d*(ay), *h*(our) or *m*(inute) +specifier character. + +The following settings can be configured for the vacation extension in the +'plugin' section (default values are indicated): + +sieve_vacation_min_period = 1d : + This specifies the minimum period that can be specified for the :days and + :seconds tags of the vacation command. A minimum of 0 indicates that users + are allowed to make the Sieve interpreter send a vacation response message + for every incoming message that meets the other reply criteria (refer to + RFC5230). A value of zero is however not recommended. + +sieve_vacation_max_period = 0 : + This specifies the maximum period that can be specified for the :days tag of + the vacation command. The configured value must be larger than the + sieve_vacation_min_period setting. A value of 0 has a special meaning: it + indicates that there is no upper limit. + +sieve_vacation_default_period = 7d : + This specifies the default period that is used when no :days or :seconds tag + is specified. The configured value must lie between the + sieve_vacation_min_period and sieve_vacation_max_period. + +sieve_vacation_use_original_recipient = no : + This specifies whether the original envelope recipient should be used in the + check for implicit delivery. The vacation command checks headers of the + incoming message, such as To: and Cc: for the address of the recipient, to + verify that the message is explicitly addressed at the recipient. If the + recipient address is not found, the vacation action will not trigger a + response to prevent sending a reply when it is not appropriate. Normally only + the final recipient address is used in this check. This setting allows + including the original recipient specified in the SMTP session if available. + This is useful to handle mail accounts with aliases. Use this option with + caution: if you are using aliases that point to more than a single account, + senders can get multiple vacation responses for a single message. Use the + <LDA.txt> '-a' option or the <LMTP.txt>/ <LDA.txt> + 'lda_original_recipient_header' setting to make the original SMTP recipient + available to Sieve. + +sieve_vacation_dont_check_recipient = no : + This disables the checks for implicit delivery entirely. This means that the + vacation command does not verify that the message is explicitly addressed at + the recipient. Use this option with caution. Specifying 'yes' will violate + the Sieve standards and can cause vacation replies to be sent for messages + not directly addressed at the recipient. + +sieve_vacation_send_from_recipient = no : + This setting determines whether vacation messages are sent with the SMTP MAIL + FROM envelope address set to the recipient address of the Sieve script owner. + Normally this is set to<>, which is the default as recommended in the + specification. This is meant to prevent mail loops. However, there are + situations for which a valid sender address is required and this setting can + be used to accommodate for those. + +Invalid values for the settings above will make the Sieve interpreter log a +warning and revert to the default values. + +See also <how vacation auto-reply uses addresses> [Pigeonhole.Sieve.Usage.txt]. + +Example +------- + +---%<------------------------------------------------------------------------- +plugin { + # Use vacation-seconds + sieve_extensions = +vacation-seconds + + # One hour at minimum + sieve_vacation_min_period = 1h + + # Ten days default + sieve_vacation_default_period = 10d + + # Thirty days at maximum + sieve_vacation_max_period = 30d +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.Variables.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.Variables.txt new file mode 100644 index 0000000..ee7a7f7 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.Variables.txt @@ -0,0 +1,26 @@ +Pigeonhole Sieve: Variables Extension +===================================== + +The Sieve *variables* extension (RFC5229 [http://tools.ietf.org/html/rfc5229/]) +adds the concept of variables to the Sieve language. + +Configuration +============= + +The *variables* extension is available by default. The *variables* extension +has its own specific settings. The following settings can be configured for the +*variables* extension (default values are indicated): + +sieve_variables_max_scope_size = 255 (v0.5.0+) : + The maximum number of variables that can be declared in a scope. There are + currently two variable scopes: the normal script scope and the global scope + created by the "include" extension. The minimum value for this setting is + 128. + +sieve_variables_max_variable_size = 4k (v0.5.0+) : + The maximum allowed size for the value of a variable. If exceeded at runtime, + the value is always truncated to the configured maximum. The minimum value + for this setting is 4000 bytes. The value is in bytes, unless followed by a + k(ilo). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Extensions.txt b/doc/wiki/Pigeonhole.Sieve.Extensions.txt new file mode 100644 index 0000000..1c0cd1d --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Extensions.txt @@ -0,0 +1,14 @@ +Pigeonhole Sieve Extensions +=========================== + +The following Sieve language extensions have a dedicated wiki page with +specific configuration and usage information: + + * <duplicate> [Pigeonhole.Sieve.Extensions.Duplicate.txt] + * <editheader> [Pigeonhole.Sieve.Extensions.Editheader.txt] + * <include> [Pigeonhole.Sieve.Extensions.Include.txt] + * <spamtest and virustest> [Pigeonhole.Sieve.Extensions.SpamtestVirustest.txt] + + * <vacation and vacation-seconds> [Pigeonhole.Sieve.Extensions.Vacation.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.Extdata.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.Extdata.txt new file mode 100644 index 0000000..1b7ecdb --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.Extdata.txt @@ -0,0 +1,155 @@ +Pigeonhole Sieve Extdata Plugin +=============================== + +The extdata plugin adds the *vnd.dovecot.extdata* extension to the Sieve +language. It allows a Sieve script to lookup information from a datasource +external to the script. This makes use of Dovecot's dict mechanism in a +read-only manner, meaning that scripts cannot update dict data sources. + +Getting the sources +------------------- + +Currently, the sources of the extdata plugin are not released, but you can get +them from the their Git repository. + +For Pigeonhole v0.4: + +---%<------------------------------------------------------------------------- +git clone -b core-0.4 https://github.com/stephanbosch/sieve-extdata-plugin.git +---%<------------------------------------------------------------------------- + +For Pigeonhole v0.5: + +---%<------------------------------------------------------------------------- +git clone -b core-0.5 https://github.com/stephanbosch/sieve-extdata-plugin.git +---%<------------------------------------------------------------------------- + +Compiling +--------- + +If you downloaded the sources of this plugin using Git, you will need to +execute './autogen.sh' first to build the automake structure in your source +tree. This process requires autotools and libtool to be installed. + +If you installed Dovecot from sources, the plugin's configure script should be +able to find the installed 'dovecot-config' automatically, along with the +Pigeonhole development headers: + +---%<------------------------------------------------------------------------- +./configure +make +sudo make install +---%<------------------------------------------------------------------------- + +If this doesn't work, you can use '--with-dovecot=<path>' configure option, +where the path points to a directory containing 'dovecot-config' file. This can +point to an installed file: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=/usr/local/lib/dovecot +make +sudo make install +---%<------------------------------------------------------------------------- + +The above example should also find the necessary Pigeonhole development headers +implicitly. You can also compile by pointing to compiled Dovecot and Pigeonhole +source trees: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=../dovecot-2.3.2/ +--with-pigeonhole=../dovecot-2.3-pigeonhole-0.5.2 +make +sudo make install +---%<------------------------------------------------------------------------- + +Configuration +------------- + +This package builds and installs the sieve_extdata plugin for Pigeonhole Sieve. +The plugin is activated by adding it to the sieve_plugins setting + +---%<------------------------------------------------------------------------- +sieve_plugins = sieve_extdata +---%<------------------------------------------------------------------------- + +The following configuration settings are used: + +sieve_extdata_dict_uri = : + Specifies the uri of the dict that is used for extdata lookups. + +Example: + +---%<------------------------------------------------------------------------- +plugin { + + sieve = ~/.dovecot.sieve + sieve_plugins = sieve_extdata + + sieve_extdata_dict_uri = file:/etc/dovecot/pigeonhole-sieve.dict +} +---%<------------------------------------------------------------------------- + +Usage +----- + +Sieve scripts can use the new 'vnd.dovecot.extdata' extension as follows: + +---%<------------------------------------------------------------------------- +require ["variables", "vacation", "vnd.dovecot.extdata"]; + +vacation :days 30 :subject "${extdata.vacation_subject}" +"${extdata.vacation_message}"; +keep; +---%<------------------------------------------------------------------------- + +where "priv/vacation_subject" & "priv/vacation_message" would be looked up in +the Dovecot dict. See below for some example dicts: + +Dict with flat file backend +--------------------------- + +To use a flat file backend for the above example, create a dict file with the +following format (for example /etc/dovecot/sieve-extdata-lookup.dict): + +---%<------------------------------------------------------------------------- +priv/vacation_message +Sorry I am out of the office +---%<------------------------------------------------------------------------- + +Dict with a SQL backend +----------------------- + +To use a SQL backend for the above example, first set up a dict proxy. In +/etc/dovecot.conf: + +---%<------------------------------------------------------------------------- +dict { + sieve = mysql:/etc/dovecot/pigeonhole-sieve.dict +} +---%<------------------------------------------------------------------------- + +And in /etc/dovecot/pigeonhole-sieve.dict: + +---%<------------------------------------------------------------------------- +connect = host=localhost dbname=dovecot user=dovecot password=password + +map { + pattern = priv/vacation_message # The dict value to lookup + table = virtual_users # The SQL table to perform the lookup in + username_field = email # The username field to search on in the +table + value_field = vacation_msg # The database value to return +} +---%<------------------------------------------------------------------------- + +Finally configure extdata to use the proxy: + +---%<------------------------------------------------------------------------- +sieve_extdata_dict_uri = proxy::sieve +---%<------------------------------------------------------------------------- + +Read the (preliminary) specification +[https://github.com/stephanbosch/sieve-extdata-plugin/blob/core-0.5/doc/rfc/spec-bosch-sieve-external-data.txt] +for more information. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.Extprograms.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.Extprograms.txt new file mode 100644 index 0000000..78ffcdc --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.Extprograms.txt @@ -0,0 +1,337 @@ +Pigeonhole Sieve Extprograms Plugin +=================================== + +The "sieve_extprograms" plugin provides an extension to the Sieve filtering +language [http://www.sieve.info] adding new action commands for invoking a +predefined set of external programs. Messages can be piped to or filtered +through those programs and string data can be input to and retrieved from those +programs. To mitigate the security concerns, the external programs cannot be +chosen arbitrarily; the available programs are restricted through administrator +configuration. + +This plugin is only available for <Pigeonhole.txt> v0.3 and higher (available +for Dovecot v2.1). For <Pigeonhole.txt> v0.4 this plugin is part of the +release. This an evolution of the <Pipe plugin> +[Pigeonhole.Sieve.Plugins.Pipe.txt] for Pigeonhole v0.2 and now provides the +"filter" and "execute" commands (and corresponding extensions) in addition to +the "pipe" command that was provided earlier by the Pipe plugin. + +Getting the sources +------------------- + +Starting with Pigeonhole v0.4 for Dovecot v2.2, the plugin is included in the +release and therefore it is implicitly compiled and installed with Pigeonhole +itself. + +For Pigeonhole v0.3, the plugin was never released, but you can get the sources +from its Mercurial repository: + +---%<------------------------------------------------------------------------- +hg clone http://hg.rename-it.nl/pigeonhole-0.3-sieve-extprograms/ +---%<------------------------------------------------------------------------- + +Compiling for Pigeonhole v0.3 +----------------------------- + +If you downloaded the sources of this plugin using Mercurial, you will need to +execute './autogen.sh' first to build the automake structure in your source +tree. This process requires autotools and libtool to be installed. + +If you installed Dovecot from sources, the plugin's configure script should be +able to find the installed 'dovecot-config' automatically, along with the +Pigeonhole development headers: + +---%<------------------------------------------------------------------------- +./configure +make +sudo make install +---%<------------------------------------------------------------------------- + +If this doesn't work, you can use '--with-dovecot=<path>' configure option, +where the path points to a directory containing 'dovecot-config' file. This can +point to an installed file: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=/usr/local/lib/dovecot +make +sudo make install +---%<------------------------------------------------------------------------- + +The above example should also find the necessary Pigeonhole development headers +implicitly. You can also compile by pointing to compiled Dovecot and Pigeonhole +source trees: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=../dovecot-2.1.0/ +--with-pigeonhole=../dovecot-2.1-pigeonhole-0.3.0 +make +sudo make install +---%<------------------------------------------------------------------------- + +Configuration +------------- + +The plugin is activated by adding it to the sieve_plugins setting: + +---%<------------------------------------------------------------------------- +sieve_plugins = sieve_extprograms +---%<------------------------------------------------------------------------- + +This plugin registers the 'vnd.dovecot.pipe', 'vnd.dovecot.filter' and +'vnd.dovecot.execute' extensions with the Sieve interpreter. However, these +extensions are not enabled by default and thus need to be enabled explicitly. +It is recommended to restrict the use of these extensions to global context by +adding these to the 'sieve_global_extensions' setting. If personal user scripts +also need to directly access external programs, the extensions need to be added +to the 'sieve_extensions' setting. + +The commands introduced by the Sieve language extensions in this plugin can +directly pipe a message or string data to an external program (typically a +shell script) by forking a new process. Alternatively, these can connect to a +unix socket behind which a Dovecot script service is listening to start the +external program, e.g. to execute as a different user or for added security. + +The program name specified for the new Sieve 'pipe', 'filter' and 'execute' +commands is used to find the program or socket in a configured directory. +Separate directories are specified for the sockets and the directly executed +binaries. The socket directory is searched first. Since the use of "/" in +program names is prohibited, it is not possible to build a hierarchical +structure. + +Directly forked programs are executed with a limited set of environment +variables:'HOME', 'USER', 'SENDER', 'RECIPIENT' and 'ORIG_RECIPIENT'. Programs +executed through the script-pipe socket service currently have no environment +set at all. + +If a shell script is expected to read a message or string data, it must fully +read the provided input until the data ends with EOF, otherwise the Sieve +action invoking the program will fail. The action will also fail when the shell +script returns a nonzero exit code. Standard output is available for returning +a message (for the filter command) or string data (for the execute command) to +the Sieve interpreter. Standard error is written to the LDA log file. + +The three extensions introduced by this plugin - 'vnd.dovecot.pipe', +'vnd.dovecot.filter' and 'vnd.dovecot.execute' - each have separate but similar +configuration. The following configuration settings are used, for which +"<extension>" in the setting name is replaced by either 'pipe', 'filter' or +'execute' depending on which extension is being configured: + +sieve_<extension>_socket_dir = : + Points to a directory relative to the Dovecot base_dir where the plugin looks + for script service sockets. + +sieve_<extension>_bin_dir = : + Points to a directory where the plugin looks for programs (shell scripts) to + execute directly and pipe messages to. + +sieve_<extension>_exec_timeout = 10s : + Configures the maximum execution time after which the program is forcibly + terminated. + +sieve_<extension>_input_eol = crlf : + Determines the end-of-line character sequence used for the data piped to + external programs. The default is currently "crlf", which represents a + sequence of the carriage return (CR) and line feed (LF) characters. This + matches the Internet Message Format (RFC5322) and what Sieve itself uses as a + line ending. Set this setting to "lf" to use a single LF character instead. + +Configuration Example 1: socket service for "pipe" and "execute" +---------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_extprograms + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute + + # pipe sockets in /var/run/dovecot/sieve-pipe + sieve_pipe_socket_dir = sieve-pipe + + # execute sockets in /var/run/dovecot/sieve-execute + sieve_execute_socket_dir = sieve-execute +} + +service sieve-pipe-script { + # This script is executed for each service connection + executable = script /usr/lib/dovecot/sieve-extprograms/sieve-pipe-action.sh + + # use some unprivileged user for execution + user = dovenull + + # socket name is program-name in Sieve (without sieve-pipe/ prefix) + unix_listener sieve-pipe/sieve-pipe-script { + } +} + +service sieve-execute-action { + # This script is executed for each service connection + executable = script +/usr/lib/dovecot/sieve-extprograms/sieve-execute-action.sh + + # use some unprivileged user for execution + user = dovenull + + # socket name is program-name in Sieve (without sieve-execute/ prefix) + unix_listener sieve-execute/sieve-execute-action { + } +} +---%<------------------------------------------------------------------------- + +Configuration Example 2: direct execution for "pipe" and "filter" +----------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_extprograms + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.filter + + # This directory contains the scripts that are available for the pipe +command. + sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe + + # This directory contains the scripts that are available for the filter + # command. + sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter +} +---%<------------------------------------------------------------------------- + +Usage +----- + +Read the specification (v0.3 plugin +[http://hg.rename-it.nl/pigeonhole-0.3-sieve-extprograms/raw-file/tip/doc/rfc/spec-bosch-sieve-extprograms.txt]/v0.4+ +[https://github.com/dovecot/pigeonhole/blob/master/doc/rfc/spec-bosch-sieve-extprograms.txt]) +for detailed information on how to use the new language extensions. + +Full Examples +------------- + +Example 1 +--------- + +This simple example shows how to use the "vnd.dovecot.execute" extension to +perform some sort of test on the incoming message. + +Relevant configuration: + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +vnd.dovecot.execute + + sieve_plugins = sieve_extprograms + sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute +} +---%<------------------------------------------------------------------------- + +The sieve script: + +---%<------------------------------------------------------------------------- +require "vnd.dovecot.execute"; + +if not execute :pipe "hasfrop.sh" { + discard; + stop; +} +---%<------------------------------------------------------------------------- + +At the location '/usr/lib/dovecot/sieve-execute', create the executable script +'hasfrop.sh'. In this example, the 'hasfrop.sh' checks whether the message +contains the literal text "FROP" anywhere in the message. The Sieve script +shown above discards the message if this scripts ends with an exit code other +than 0, which happens when "FROP" was found. + +---%<------------------------------------------------------------------------- +# Something that reads the whole message and inspects it for some +# property. Not that the whole message needs to be read from input! +N=`cat | grep -i "FROP"` # Check it for the undesirable text "FROP" +if [ ! -z "$N" ]; then + # Result: deny + exit 1; +fi + +# Result: accept +exit 0 +---%<------------------------------------------------------------------------- + +Example 2 +--------- + +This example shows how to use the "vnd.dovecot.execute" extension for +querying/updating a MySQL database. This is used to redirect messages only once +every 300s for a particular sender. Note that this particular use case could +also be implemented using the Sieve " <duplicate> +[Pigeonhole.Sieve.Extensions.Duplicate.txt]" extension + +Relevant configuration: + +---%<------------------------------------------------------------------------- +plugin { + sieve_extensions = +vnd.dovecot.execute + + sieve_plugins = sieve_extprograms + sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute +} +---%<------------------------------------------------------------------------- + +The sieve script: + +---%<------------------------------------------------------------------------- +require ["variables", "copy", "envelope", "vnd.dovecot.execute"]; + +# put the envelope-from address in a variable +if envelope :matches "from" "*" { set "from" "${1}"; } + +# execute the vacationcheck.sh program and redirect the message based on its +exit code +if execute :output "vacation_message" "vacationcheck.sh" ["${from}","300"] +{ + redirect + :copy "foo@bar.net"; +} +---%<------------------------------------------------------------------------- + +At the location '/usr/lib/dovecot/sieve-execute', create the executable script +'vacationcheck.sh'. In this example, the 'vacationcheck.sh' script needs two +parameters: the sender address and a time interval specified in seconds. The +time interval is used to specify the minimum amount of time that needs to have +passed since the sender was last seen. If the script returns exit code 0, then +message is redirected in the Sieve script shown above. + +---%<------------------------------------------------------------------------- +USER=postfixadmin +PASS=pass +DATABASE=postfixadmin + +# DB STRUCTURE +#CREATE TABLE `sieve_count` ( +# `from_addres` varchar(254) NOT NULL, +# `date` datetime NOT NULL +#) ENGINE=InnoDB DEFAULT CHARSET=latin1; +# +#ALTER TABLE `sieve_count` +# ADD KEY `from_addres` (`from_addres`); + +MAILS=$(mysql -u$USER -p$PASS $DATABASE --batch --silent -e "SELECT count(*) as +ile FROM sieve_count WHERE from_addres='$1' AND DATE_SUB(now(),INTERVAL $2 +SECOND) < date;") +ADDRESULT=$(mysql -u$USER -p$PASS $DATABASE --batch --silent -e "INSERT INTO +sieve_count (from_addres, date) VALUES ('$1', NOW());") + +# uncoment below to debug +# echo Uset $1 sent $MAILS in last $2 s >> +/usr/lib/dovecot/sieve-pipe/output.txt +# echo Add result : $ADDRESULT >> /usr/lib/dovecot/sieve-pipe/output.txt +# echo $MAILS + +if [ "$MAILS" = "0" ] +then +exit 0 +fi + +exit 1 +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt new file mode 100644 index 0000000..d9f111a --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt @@ -0,0 +1,49 @@ +Pigeonhole IMAP FILTER=SIEVE Plugin +=================================== + +Normally, Sieve filters can either be applied at initial mail delivery or +triggered by certain events in the Internet Message Access Protocol +('IMAPSIEVE';RFC 6785 [http://tools.ietf.org/html/rfc6785]). The user can +configure which Sieve scripts to run at these instances, but it is not possible +to trigger the execution of Sieve scripts manually. However, this could be very +useful; e.g, to test new Sieve rules and to re-filter messages that were +erroneously handled by an earlier version of the Sieve scripts involved. + +<Pigeonhole.txt> provides the 'imap_filter_sieve' plugin, which provides a +vendor-defined IMAP extension called 'FILTER=SIEVE'. This adds a new 'FILTER' +command that allows applying a mail filter (a Sieve script) on a set of +messages that match the specified IMAP searching criteria. + +The latest draft of the specification for this IMAP capability is available +here +[https://github.com/dovecot/pigeonhole/blob/master/doc/rfc/draft-bosch-imap-filter-sieve-00.txt]. +This plugin is experimental and the specification is likely to change. Use the +specification included in your current release to obtain the matching +specification for your release. + +This plugin is available for <Pigeonhole.txt> v0.4.24 and higher (available for +Dovecot v2.2.36), and v0.5.2 and higher (available for Dovecot v2.3.2). The +plugins are included in the Pigeonhole package and are therefore implicitly +compiled and installed with Pigeonhole itself. + +Configuration +------------- + +The IMAP FILTER Sieve plugin is activated by adding it to the mail_plugins +setting for the imap protocol: + +---%<------------------------------------------------------------------------- +protocol imap { + mail_plugins = $mail_plugins imap_filter_sieve +} +---%<------------------------------------------------------------------------- + +Note that enabling this plugin allows users to specify the Sieve script content +as a parameter to the FILTER command, not just run existing stored scripts. + +Currently, no other settings specific to this plugin are defined. It uses the +normal configuration settings used by the LDA Sieve plugin at delivery. + +The sieve_before and sieve_after scripts are currently ignored by this plugin. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPSieve.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPSieve.txt new file mode 100644 index 0000000..7a04bc7 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.IMAPSieve.txt @@ -0,0 +1,109 @@ +Pigeonhole IMAPSieve Plugins +============================ + +As defined in the base specification (RFC 5228 +[http://tools.ietf.org/html/rfc5228]), the Sieve language is used only during +delivery. However, in principle, it can be used at any point in the processing +of an email message.RFC 6785 [http://tools.ietf.org/html/rfc6785] defines the +use of Sieve filtering in IMAP, operating when messages are created or their +attributes are changed. This feature extends both Sieve and IMAP. Therefore, +Pigeonhole provides both an IMAP plugin and a Sieve plugin. + +The 'sieve_imapsieve' plugin implements the 'imapsieve' extension for the Sieve +filtering language, adding functionality for using Sieve scripts from within +IMAP. The 'imap_sieve' plugin for IMAP adds the 'IMAPSIEVE' capability to the +'imap' service. The basic 'IMAPSIEVE' capability allows attaching a Sieve +script to a mailbox for any mailbox by setting a special IMAP METADATA entry. +This way, users can configure Sieve scripts that are run for IMAP events in +their mailboxes. + +Beyond the standard, the Pigeonhole implementation also adds the ability for +administrators to configure Sieve scripts outside the user's control, that are +run either before or after a user's script if there is one. + +This plugin is available for <Pigeonhole.txt> v0.4.14 and higher (available for +Dovecot v2.2.24). The plugins are included in the Pigeonhole package and are +therefore implicitly compiled and installed with Pigeonhole itself. + +Configuration +------------- + +The IMAP plugin is activated by adding it to the mail_plugins setting for the +imap protocol: + +---%<------------------------------------------------------------------------- +protocol imap { + mail_plugins = $mail_plugins imap_sieve +} +---%<------------------------------------------------------------------------- + +This will only enable support for administrator scripts. User scripts are only +supported when additionally a Sieve URL is configured using the imapsieve_url +plugin setting. This URL points to the <ManageSieve> +[Pigeonhole.ManageSieve.txt] server that users need to use to upload their +Sieve scripts. This URL will be shown to the client in the IMAP CAPABILITY +response as 'IMAPSIEVE=<URL>'. + +The Sieve plugin is activated by adding it to the sieve_plugins setting: + +---%<------------------------------------------------------------------------- +sieve_plugins = sieve_imapsieve +---%<------------------------------------------------------------------------- + +This plugin registers the 'imapsieve' extension with the Sieve interpreter. +This extension is enabled implicitly, which means that it does not need to be +added to the 'sieve_extensions' setting. + +Note that the 'imapsieve' extension can only be used in a Sieve script that is +invoked from IMAP. When it is used in the active delivery script, it will cause +runtime errors. To make a Sieve script suitable for both delivery and IMAP, the +availability of the extension can be tested using the 'ihave' test (RFC 5463 +[http://tools.ietf.org/html/rfc5463]) as usual. + +The following settings are recognized the "imap_sieve" plugin: + +imapsieve_url = : + If configured, this setting enables support for user Sieve scripts in IMAP. + So, leave this unconfigured if you don't want users to have the ability to + associate Sieve scripts with mailboxes. This has no effect on the + administrator-controlled Sieve scripts explained below. The value is an URL + pointing to the <ManageSieve> [Pigeonhole.ManageSieve.txt] server that users + must use to upload their Sieve scripts; e.g.,'sieve://sieve.example.com'. + +imapsieve_mailboxXXX_name = : + This setting configures the name of a mailbox for which administrator scripts + are configured. The `XXX' in this setting is a sequence number, which allows + configuring multiple associations between Sieve scripts and mailboxes. The + settings defined hereafter with matching sequence numbers apply to the + mailbox named by this setting. The sequence of configured mailboxes ends at + the first missing 'imapsieve_mailboxXXX_name' setting. This setting supports + wildcards with a syntax compatible with the IMAP LIST command, meaning that + this setting can apply to multiple or even all ("*") mailboxes. + +imapsieve_mailboxXXX_before = : + +imapsieve_mailboxXXX_after = : + When an IMAP event of interest occurs, these sieve scripts are executed + before and after any user script respectively. These settings each specify + the location of a single sieve script. The semantics of these settings are + very similar to the 'sieve_before' and 'sieve_after' settings: the specified + scripts form a sequence together with the user script in which the next + script is only executed when an (implicit) keep action is executed. + +imapsieve_mailboxXXX_causes = : + Only execute the administrator Sieve scripts for the mailbox configured with + 'imapsieve_mailboxXXX_name' when one of the listed 'IMAPSIEVE' causes + [https://tools.ietf.org/html/rfc6785#section-4.3] apply (currently either + 'APPEND', 'COPY', or 'FLAG'. This has no effect on the user script, which is + always executed no matter the cause. + +imapsieve_mailboxXXX_from = : + Only execute the administrator Sieve scripts for the mailbox configured with + 'imapsieve_mailboxXXX_name' when the message originates from the indicated + mailbox. This setting supports wildcards with a syntax compatible with the + IMAP LIST command + +See <Replacing antispam plugin with IMAPSieve> [HowTo.AntispamWithSieve.txt] as +example on how to use this. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.Pipe.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.Pipe.txt new file mode 100644 index 0000000..b307037 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.Pipe.txt @@ -0,0 +1,187 @@ +Pigeonhole Sieve Pipe Plugin +============================ + +The sieve_pipe plugin adds the vnd.dovecot.pipe extension to the Sieve language +[http://www.sieve.info]. The extension adds a new action command for piping +messages to a pre-defined set of external programs. To mitigate the security +concerns, the external programs cannot be chosen arbitrarily; the available +programs are restricted through administrator configuration. + +This plugin is available for <Pigeonhole.txt> v0.2. This plugin is superseded +by the <Extprograms> [Pigeonhole.Sieve.Plugins.Extprograms.txt] plugin for +Pigeonhole v0.3 and beyond. + +Getting the sources +------------------- + +Currently, the sources of the sieve_pipe plugin are not released, but you can +get them from the the Mercurial repository: + +---%<------------------------------------------------------------------------- +hg clone http://hg.rename-it.nl/pigeonhole-0.2-sieve-pipe/ +---%<------------------------------------------------------------------------- + +Compiling +--------- + +If you downloaded the sources of this plugin using Mercurial, you will need to +execute './autogen.sh' first to build the automake structure in your source +tree. This process requires autotools and libtool to be installed. + +If you installed Dovecot from sources, the plugin's configure script should be +able to find the installed 'dovecot-config' automatically, along with the +Pigeonhole development headers: + +---%<------------------------------------------------------------------------- +./configure +make +sudo make install +---%<------------------------------------------------------------------------- + +If this doesn't work, you can use '--with-dovecot=<path>' configure option, +where the path points to a directory containing 'dovecot-config' file. This can +point to an installed file: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=/usr/local/lib/dovecot +make +sudo make install +---%<------------------------------------------------------------------------- + +The above example should also find the necessary Pigeonhole development headers +implicitly. You can also compile by pointing to compiled Dovecot and Pigeonhole +source trees: + +---%<------------------------------------------------------------------------- +./configure --with-dovecot=../dovecot-2.0.0/ +--with-pigeonhole=../dovecot-2.0-pigeonhole-0.2.0 +make +sudo make install +---%<------------------------------------------------------------------------- + +Configuration +------------- + +This package builds and installs the sieve_pipe plugin for Pigeonhole Sieve. +The plugin is activated by adding it to the sieve_plugins setting: + +---%<------------------------------------------------------------------------- +sieve_plugins = sieve_pipe +---%<------------------------------------------------------------------------- + +The plugin can directly pipe a message to an external program (typically a +shell script) by forking a new process. Alternatively, it can connect to a Unix +socket behind which a Dovecot script service is listening to start the external +program, e.g. to execute as a different user or for added security. + +The program name specified for the Sieve "pipe" command is used to find the +program or socket in a configured directory. Separate directories are specified +for the sockets and the directly executed binaries. The socket directory is +searched first. Since the Sieve "pipe" command refuses "/" in program names, it +is not possible to build a hierarchical structure. + +Directly forked programs are executed with a limited set of environment +variables: HOME, USER, SENDER, RECIPIENT and ORIG_RECIPIENT. Programs executed +through the script-pipe socket service currently have no environment set at +all. + +The following configuration settings are used by the sieve_pipe plugin: + +sieve_pipe_socket_dir = : + Points to a directory relative to the Dovecot base_dir where the sieve_pipe + plugin looks for the sockets. + +sieve_pipe_bin_dir = : + Points to a directory where the sieve_pipe plugin looks for programs (shell + scripts) to execute directly and pipe messages to. + +Example of socket service + +---%<------------------------------------------------------------------------- +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_pipe + + sieve_pipe_socket_dir = sieve-pipe +} + +service sieve-custom-action { + executable = script-pipe /usr/lib/dovecot/sieve-pipe/sieve-custom-action.sh + + # use some unprivileged user for execution + user = dovenull + + # socket name is program-name in Sieve (without sieve-pipe/ prefix) + unix_listener sieve-pipe/sieve-custom-action { + } +} +---%<------------------------------------------------------------------------- + +Example of direct execution + +---%<------------------------------------------------------------------------- +plugin { + sieve = ~/.dovecot.sieve + + sieve_plugins = sieve_pipe + + # This directory contains the scripts that are available. + sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe +} +---%<------------------------------------------------------------------------- + +Usage +----- + +Sieve scripts can use the new 'vnd.dovecot.pipe' extension as follows: + +---%<------------------------------------------------------------------------- +require ["vnd.dovecot.pipe"]; + +pipe "external-program"; +---%<------------------------------------------------------------------------- + +Read the full specification +[http://hg.rename-it.nl/pigeonhole-0.2-sieve-pipe/raw-file/tip/doc/rfc/spec-bosch-sieve-pipe.txt] +for more information. + +Examples +-------- + +Example of a jabber notification notify.sieve: + +---%<------------------------------------------------------------------------- +require [ "vnd.dovecot.pipe", "copy", "variables" ]; +if header :matches "subject" "*" { set "subject" "${1}"; } +if header :matches "from" "*" { set "from" "${1}"; } +pipe :args [ "USER@DOMAIN.TLD", "${from}", "${subject}" ] :copy :try +"jabber_notify.sh" ; +---%<------------------------------------------------------------------------- + +The jabber_notify.sh: + +---%<------------------------------------------------------------------------- +USER="$1" +FROM="$2" +SUBJECT="$3" +# clix accepts this as a config search directory +# you can use clix - lua based +# http://code.matthewwild.co.uk/clix/summary +# or use any other jabber cmd line client that can send things +export XDG_CONFIG_HOME=/srv/mail +/srv/mail/clix.bin send -q --account=default --to="$USER" "New mail from +${FROM} about ${SUBJECT}" +# we don't care about the exit status in this case +exit 0 +---%<------------------------------------------------------------------------- + +The $XDG_CONFIG_HOME/.clixrc: + +---%<------------------------------------------------------------------------- +[default] +jid=USER@DOMAIN.TLD +password=PASSWORD +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Plugins.txt b/doc/wiki/Pigeonhole.Sieve.Plugins.txt new file mode 100644 index 0000000..3028b75 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Plugins.txt @@ -0,0 +1,45 @@ +Pigeonhole Sieve Plugins +======================== + +The Pigeonhole Sieve interpreter can be dynamically extended with new features +by means of plugins. Plugins can be configured using the 'sieve_plugins' +setting in the 'plugin' section of the Dovecot configuration, as explained on +the <Pigeonhole Sieve Configuration page> [Pigeonhole.Sieve.Configuration.txt]. + +The following plugins are currently available for the Pigeonhole Sieve +interpeter: + + * <Extdata> [Pigeonhole.Sieve.Plugins.Extdata.txt] /(custom language + extension, experimental)/ + * This plugin adds support for the Dovecot-specific 'vnd.dovecot.extdata' + extension, which allows access to external string data. Any type of Dovecot + dict lookup can be specified as data source. + * <Extprograms> [Pigeonhole.Sieve.Plugins.Extprograms.txt] [*Pigeonhole v0.3* + and beyond]/(custom language extensions)/ + * This plugin adds support for the Dovecot-specific 'vnd.dovecot.pipe', + 'vnd.dovecot.filter' and 'vnd.dovecot.execute' extensions. These extensions + add new action commands for invoking a predefined set of external programs + (typically shell scripts. Messages can be piped to or filtered through those + programs and string data can be input to and retrieved from those programs. + * <IMAPSieve> [Pigeonhole.Sieve.Plugins.IMAPSieve.txt] [*Pigeonhole v0.4.14* + and beyond]/(standard language extension, RFC 6785 + [https://tools.ietf.org/html/rfc6785])/ + * This set of plugins adds support for the 'imapsieve' extension in sieve and + the 'IMAPSIEVE' capability in IMAP. With these plugins it is possible to use + Sieve filtering in IMAP, operating when messages are created or their + attributes are changed. + * <IMAP FILTER=SIEVE> [Pigeonhole.Sieve.Plugins.IMAPFilterSieve.txt] + [*Pigeonhole v0.4.24* and beyond, *Pigeonhole v0.5.2* and beyond] /(custom + language extension, experimental)/ + * This plugin provides a vendor-defined IMAP extension called FILTER=SIEVE. It + adds a new FILTER command that allows applying a mail filter (a Sieve + script) on a set of messages that match the specified IMAP searching + criteria. + * <Pipe> [Pigeonhole.Sieve.Plugins.Pipe.txt] [*Pigeonhole v0.2*] /(custom + language extension, deprecated)/ + * This plugin adds support for the Dovecot-specific 'vnd.dovecot.pipe' + extension, which allows piping messages to a pre-defined set of external + programs. For Pigeonhole v0.3, the same functionality (and more) is provided + by the extprograms plugin. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Troubleshooting.txt b/doc/wiki/Pigeonhole.Sieve.Troubleshooting.txt new file mode 100644 index 0000000..758690d --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Troubleshooting.txt @@ -0,0 +1,143 @@ +Pigeonhole Sieve Troubleshooting +================================ + +This page explains how to approach problems with the <Sieve interpreter> +[Pigeonhole.Sieve.txt]. + +Contents + + + 1. Pigeonhole Sieve Troubleshooting + + 1. Troubleshooting Approach + + 2. Common Problems + + 1. Sieve Scripts are not Executed + + 2. Mailbox Names with non-ASCII Characters Cause Problems + +Troubleshooting Approach +------------------------ + +/This section should contain a step-wise approach to troubleshooting./ + +Common Problems +--------------- + +Common configuration problems and their solutions are described here. + +Sieve Scripts are not Executed +------------------------------ + +When Sieve scripts are not being executed, there are several possibilities: + +Your MTA is not using Dovecot LDA or LMTP : + Sieve scripts are executed by the Dovecot <LDA (Local Delivery Agent)> + [LDA.txt] and/or the Dovecot <LMTP.txt> service. That is why you first need + to check whether LDA or LMTP are actually being used. At least one of these + is supposed to be called/accessed from your <MTA.txt>, e.g. Exim or Postfix, + for local message delivery. Most MTAs have their own local delivery agent, + and without explicit configuration this is what is used. In that case, your + Sieve scripts are simply ignored. When you set 'mail_debug=yes' in your + configuration, your logs will show details of LDA and/or LMTP execution. The + following is an example of the first few log lines of an LDA delivery: + +: + ---%<----------------------------------------------------------------------- + dovecot: lda: Debug: Loading modules from directory: /usr/lib/dovecot/modules + dovecot: lda: Debug: Module loaded: + /usr/lib/dovecot/modules/lib90_sieve_plugin.so + dovecot: lda(hendrik): Debug: Effective uid=1000, gid=1000, + home=/home/hendrik + dovecot: lda(hendrik): Debug: Namespace inbox: type=private, prefix=, sep=, + inbox=yes, hidden=no, list=yes, subscriptions=yes location= + ---%<----------------------------------------------------------------------- + +: + The first lines show that LDA has found and loaded the Sieve plugin module. + Then it shows for what user it is delivering and where his INBOX is located. + LMTP produces similar log lines. If you don't see lines such as the above, + your MTA is probably not using Dovecot for local delivery. You can verify + whether Dovecot is working correctly by executing 'dovecot-lda' manually. + +The Sieve plugin is not enabled : + The Dovecot <LDA.txt> and <LMTP.txt> services do not provide Sieve support by + default. Sieve support is provided as a separate plugin that needs to be + enabled by adding it to the 'mail_plugins' setting in the 'protocol lda {...} + ' section for the LDA and the 'protocol lmtp {...} ' section for LMTP. If + this is omitted, Sieve scripts are ignored. Check the <configuration page> + [Pigeonhole.Sieve.Configuration.txt] for more information. When you set + 'mail_debug=yes' in your configuration, your logs will show details of Sieve + execution. The following is an example of the log lines produced for a simple + Sieve execution: + +: + ---%<----------------------------------------------------------------------- + dovecot: lda(hendrik): Debug: sieve: using sieve path for user's script: + /home/hendrik/.dovecot.sieve + dovecot: lda(hendrik): Debug: sieve: opening script + /home/hendrik/.dovecot.sieve + dovecot: lda(hendrik): Debug: sieve: binary save: not saving binary + /home/hendrik/.dovecot.svbin, because it is already stored + dovecot: lda(hendrik): Debug: sieve: executing script from + /home/hendrik/.dovecot.svbin + dovecot: lda(hendrik): sieve: msgid=2234234@host.example.com: stored mail + into mailbox 'INBOX' + ---%<----------------------------------------------------------------------- + + Without actually running LDA, you can also check if 'doveconf -f service=lda + mail_plugins' includes "sieve". + +The Sieve plugin is misconfigured or the involved Sieve scripts contain errors + : + If there is a configuration error or when a Sieve script cannot be compiled + and executed, an error is always logged. + +Mailbox Names with non-ASCII Characters Cause Problems +------------------------------------------------------ + +This problem most often manifests with the following error message: + +---%<------------------------------------------------------------------------- +error: msgid=<234234.234234@example.com>: failed to store into mailbox +'INBOX/Co&APY-rdineren' (INBOX/Co&-APY-rdineren): Mailbox doesn't exist: +INBOX.Co&-APY-rdineren. +---%<------------------------------------------------------------------------- + +The Sieve script causing this error contained the following command: + +---%<------------------------------------------------------------------------- +fileinto "INBOX/Co&APY-rdineren"; +---%<------------------------------------------------------------------------- + +The specified mailbox contains the non-ASCII character 'ö'. Unfortunately, the +author of this script used the wrong encoding. This is modified UTF-7 such as +used by IMAP. However, Sieve expects UTF-8 for mailbox names. Depending on +version and configuration, Dovecot uses modified UTF-7 internally. The Sieve +interpreter expects UTF-8 and converts that to UTF-7 when necessary. When the +mailbox is encoded in UTF-7 by the user, the '&' will just be escaped into '&-' +during the UTF-7 conversion, yielding an erroneous mailbox name for Dovecot. +That is what causes the error message presented above. Instead, the 'fileinto' +command should have looked as follows: + +---%<------------------------------------------------------------------------- +fileinto "INBOX/Coördineren"; +---%<------------------------------------------------------------------------- + +The old CMUSieve plugin did use UTF-7 for folder names. Therefore, this problem +could have emerged after migrating from CMUSieve to Pigeonhole. In that case +you should carefully read the migration instructions +[http://wiki.dovecot.org/LDA/Sieve/Dovecot#Migration_from_CMUSieve] again. + +Often the 'author' of such scripts is an older or misconfigured Sieve GUI +editor. For example, the SieveRules +[https://github.com/JohnDoh/Roundcube-Plugin-SieveRules-Managesieve#readme] +plugin for the RoundCube webmail IMAP client [http://roundcube.net/] has a +configuration option to enable the correct behavior: + +---%<------------------------------------------------------------------------- +$sieverules_config['folder_encoding'] = 'UTF-8'; +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.Usage.txt b/doc/wiki/Pigeonhole.Sieve.Usage.txt new file mode 100644 index 0000000..98f49b4 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.Usage.txt @@ -0,0 +1,130 @@ +Pigeonhole Sieve Usage +====================== + +Mailbox Names +------------- + +Regarding separators, you need to specify mailbox names in Sieve scripts the +same way as IMAP clients see them. For example if you want to deliver mail to +the "Customers" mailbox which exists under "Work" mailbox: + + * Namespace with 'prefix=""', 'separator=.' (Maildir default): + +---%<------------------------------------------------------------------------- +require "fileinto"; +fileinto "Work.Customers"; +---%<------------------------------------------------------------------------- + + * Namespace with 'prefix=INBOX.', 'separator=.' (Courier migration): + +---%<------------------------------------------------------------------------- +require "fileinto"; +fileinto "INBOX.Work.Customers"; +---%<------------------------------------------------------------------------- + + * Namespace with 'prefix=""', 'separator=/' (mbox, dbox default): + +---%<------------------------------------------------------------------------- +require "fileinto"; +fileinto "Work/Customers"; +---%<------------------------------------------------------------------------- + +However, Sieve uses UTF8 encoding for mailbox names, while IMAP uses modified +UTF7. This means that non-ASCII characters contained in mailbox names are +represented differently between IMAP and Sieve scripts. + +Vacation auto-reply +------------------- + +Vacation uses envelope sender and envelope recipient. They're taken from: + + * Envelope sender: -f parameter to dovecot-lda if given, otherwise + Return-Path: header in the message. + * Envelope recipient: -a parameter to dovecot-lda if given, otherwise -d + parameter to dovecot-lda. If neither is given (delivering to system users), + the $USER environment is used. + +The vacation replies are sent to the envelope sender. + +List of autoreplied senders is stored in '.dovecot.lda-dupes' file in user's +home directory. When you're testing the vacation feature, it's easy to forget +that the reply is sent only once in the number of configured days. If you've +problems getting the vacation reply, try deleting this file. If that didn't +help, make sure the problem isn't related to sending mails in general by trying +the "reject" Sieve command. + +The automatic replies aren't sent if any of the following is true: + + * The envelope sender is not available (equal to <>) + * The envelope sender and envelope recipient are the same + * The sender recently (within :days days; default 7) got a reply from the same + vacation command + * The message contains at least one of the mailing list headers "list-id", + "list-owner", "list-subscribe", "list-post", "list-unsubscribe", + "list-help", or "list-archive" + * Auto-Submitted: header exists with any value except "no" + * Precedence: header exists with value "junk", "bulk" or "list" + * The envelope sender is considered a system address, which either: + * begins with "MAILER-DAEMON" (case-insensitive), + * begins with "LISTSERV" (case-insensitive), + * begins with "majordomo" (case-insensitive), + * contains the string "-request" anywhere within it (case-sensitive), or + * begins with "owner-" (case-sensitive) + * The envelope recipient and alternative addresses specified with the vacation + command's :addresses tag are not found in the message's To:, Cc:, Bcc:, + Resent-To:, Resent-Cc: or Resent-Bcc: fields. + +Manually Compiling Sieve Scripts +-------------------------------- + +When the Sieve plugin executes a script for the first time (or after it has +been changed), it is compiled and stored in binary form (byte code) to avoid +compiling the script again for each subsequent mail delivery. The Pigeonhole +Sieve implementation uses the '.svbin' extension to store compiled Sieve +scripts (e.g.'.dovecot.svbin'). To store the binary, the plugin needs write +access in the directory in which the script is located. + +A problem occurs when a global script is encountered by the plugin. For +security reasons, global script directories are not supposed to be writable by +the user. Therefore, the plugin cannot store the binary when the script is +first compiled. Note that this doesn't mean that the old compiled version of +the script is used when the binary cannot be written: it compiles and uses the +current script version. The only real problem is that the plugin will not be +able to update the binary on disk, meaning that the global script needs to be +recompiled each time it needs to be executed, i.e. for every incoming message, +which is inefficient. + +To mitigate this problem, the administrator must manually pre-compile global +scripts using the 'sievec' command line tool. For example: + +---%<------------------------------------------------------------------------- +sievec /var/lib/dovecot/sieve/global/ +---%<------------------------------------------------------------------------- + +This is necessary for scripts listed in the 'sieve_global_path', 'sieve_before' +and 'sieve_after' settings. For global scripts that are only included in other +scripts using the Sieve include extension, this step is not necessary, since +included scripts are incorporated into the binary produced for the main script. + +Compile and Runtime Logging +--------------------------- + +Log messages produced during script compilation or during script execution are +written to two locations by the LDA Sieve plugin: + + * A log file is written in the same directory as the user's main private + script (as specified by the 'sieve' setting). This log file bears the name + of that script file appended with ".log", e.g.'.dovecot.sieve.log'. If there + are errors or warnings in the script, the messages are appended to that log + file until it eventually grows too large (>10 kB currently). When that + happens, the old log file is moved to a ".log.0" file and an empty log file + is started. Informational messages are not written to this log file and the + log file is not created until messages are actually logged, i.e. when an + error or warning is produced. + * Messages that could be of interest to the system administrator are also + written to the Dovecot logging facility (usually syslog). This includes + informational messages that indicate what actions are executed on incoming + messages. Compile errors encountered in the user's private script are not + logged here. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.Sieve.txt b/doc/wiki/Pigeonhole.Sieve.txt new file mode 100644 index 0000000..43e9578 --- /dev/null +++ b/doc/wiki/Pigeonhole.Sieve.txt @@ -0,0 +1,290 @@ +Pigeonhole Sieve Interpreter +============================ + +The <Pigeonhole project> [Pigeonhole.txt] provides Sieve support as a plugin +for Dovecot's <Local Delivery Agent (LDA)> [LDA.txt] and also for its +<LMTP.txt> service. The plugin implements a Sieve [http://www.sieve.info] +interpreter, which filters incoming messages using a script specified in the +Sieve language (RFC 5228 [http://tools.ietf.org/html/rfc5228/]). The Sieve +script is provided by the user and, using that Sieve script, the user can +customize how incoming messages are handled. Messages can be delivered to +specific folders, forwarded, rejected, discarded, etc. + +Configuration and Use +--------------------- + + * <Download and Installation> [Pigeonhole.Installation.txt] + * <Sieve Interpreter Configuration> [Pigeonhole.Sieve.Configuration.txt] + * <Sieve Usage Information> [Pigeonhole.Sieve.Usage.txt] + * <Sieve Script Examples> [Pigeonhole.Sieve.Examples.txt] + * <Sieve Interpreter Plugins> [Pigeonhole.Sieve.Plugins.txt] + * <Sieve Troubleshooting> [Pigeonhole.Sieve.Troubleshooting.txt] + +Supported Features +------------------ + +Sieve language has various <extensions> [Pigeonhole.Sieve.Extensions.txt]. You +can find more information about the extensions from the Sieve Mail Filtering +Language Charter [http://www.ietf.org/html.charters/sieve-charter.html] or the +Sieve.info wiki page [http://www.sieve.info/]. + +Note that Sieve doesn't support running external programs. + +The Pigeonhole Sieve interpreter recognizes the following Sieve extensions: + + * ++-----------------------------------------------------------------+------------+----------+----------------+ +| *Extension* | *Support | *Default | *Purpose* | +| | Status* | Enabled* | | ++-----------------------------------------------------------------+------------+----------+----------------+ +| body [http://tools.ietf.org/html/rfc5173/] | supported | yes | Allows | +| | | | evaluating the | +| | | | body of a | +| | | | message | ++-----------------------------------------------------------------+------------+----------+----------------+ +| copy [http://tools.ietf.org/html/rfc3894/] | supported | yes | Allows storing | +| | | | and forwarding | +| | | | messages | +| | | | without | +| | | | canceling the | +| | | | implicit keep | ++-----------------------------------------------------------------+------------+----------+----------------+ +| date [http://tools.ietf.org/html/rfc5260#section-4] | supported | yes | Adds the | +| | (v0.1.12+) | | ability to test| +| | | | date and time | +| | | | values in | +| | | | various ways | ++-----------------------------------------------------------------+------------+----------+----------------+ +| duplicate [http://tools.ietf.org/html/rfc7352] | supported | yes | Allows | +| | (v0.4.3+) | | detecting | +| | | | duplicate | +| | | | message | +| | | | deliveries | ++-----------------------------------------------------------------+------------+----------+----------------+ +| editheader [http://tools.ietf.org/html/rfc5293/] | supported | no | Adds the | +| | (v0.3.0+) | | ability to add | +| | | | and remove | +| | | | message header | +| | | | fields | ++-----------------------------------------------------------------+------------+----------+----------------+ +| encoded-character | supported | yes | Allows encoding| +| [http://tools.ietf.org/html/rfc5228#section-2.4.2.4] | | | special | +| | | | characters | +| | | | numerically | ++-----------------------------------------------------------------+------------+----------+----------------+ +| enotify [http://tools.ietf.org/html/rfc5435/] | supported | yes | Provides the | +| | (v0.1.3+) | | ability to send| +| | | | notifications | +| | | | by various | +| | | | means | +| | | | (currently only| +| | | | mailto) | ++-----------------------------------------------------------------+------------+----------+----------------+ +| envelope [http://tools.ietf.org/html/rfc5228#section-5.4] | supported | yes | Allows | +| | | | evaluating | +| | | | envelope parts,| +| | | | i.e. sender and| +| | | | recipient | ++-----------------------------------------------------------------+------------+----------+----------------+ +| environment [http://tools.ietf.org/html/rfc5183/] | supported | yes | Allows testing | +| | (v0.4.0+) | | against various| +| | | | labeled values | +| | | | from the | +| | | | execution | +| | | | environment | ++-----------------------------------------------------------------+------------+----------+----------------+ +| fileinto [http://tools.ietf.org/html/rfc5228#section-4.1] | supported | yes | Allows storing | +| | | | messages in | +| | | | folders other | +| | | | than INBOX | ++-----------------------------------------------------------------+------------+----------+----------------+ +| foreverypart [http://tools.ietf.org/html/rfc5703#section-3] | supported | yes | Allows | +| | (v0.4.14+) | | iterating | +| | | | through the | +| | | | message's MIME | +| | | | parts | ++-----------------------------------------------------------------+------------+----------+----------------+ +| ihave [http://tools.ietf.org/html/rfc5463/] | supported | yes | Adds the | +| | (v0.2.4+) | | ability to test| +| | | | for support of | +| | | | Sieve | +| | | | extensions and | +| | | | dynamically | +| | | | invoke their use| ++-----------------------------------------------------------------+------------+----------+----------------+ +| imap4flags [http://tools.ietf.org/html/rfc5232/] | supported | yes | Allows adding | +| | | | IMAP flags to | +| | | | stored messages| ++-----------------------------------------------------------------+------------+----------+----------------+ +| imapsieve [http://tools.ietf.org/html/rfc6785/] | supported | no | Provides access| +| | (v0.4.14+) | (plugin) | to special | +| | | | environment | +| | | | items when | +| | | | executing at | +| | | | IMAP events | ++-----------------------------------------------------------------+------------+----------+----------------+ +| include [http://tools.ietf.org/html/rfc6609/] | supported | yes | Allows | +| | (v0.4.0+) | | including other| +| | | | Sieve scripts | ++-----------------------------------------------------------------+------------+----------+----------------+ +| index [http://tools.ietf.org/html/rfc5260#section-6] | supported | yes | Allows matching| +| | (v0.4.7+) | | specific header| +| | | | field instances| +| | | | by index | ++-----------------------------------------------------------------+------------+----------+----------------+ +| mailbox [http://tools.ietf.org/html/rfc5490#section-3] | supported | yes | Provides a | +| | (v0.1.10+) | | mailbox | +| | | | existence check| +| | | | and allows | +| | | | creating | +| | | | mailboxes upon | +| | | | fileinto | ++-----------------------------------------------------------------+------------+----------+----------------+ +| mboxmetadata [http://tools.ietf.org/html/rfc5490] | supported | no | Provides access| +| | (v0.4.7+) | | to mailbox | +| | | | METADATA entries| ++-----------------------------------------------------------------+------------+----------+----------------+ +| mime [http://tools.ietf.org/html/rfc5703#section-4] | supported | yes | Allows testing | +| | (v0.4.14+) | | parts of | +| | | | structured MIME| +| | | | header fields | ++-----------------------------------------------------------------+------------+----------+----------------+ +| extracttext [http://tools.ietf.org/html/rfc5703#section-7] | supported | yes | Allows | +| | (v0.4.14+) | | extracting text| +| | | | from individual| +| | | | message MIME | +| | | | parts | ++-----------------------------------------------------------------+------------+----------+----------------+ +| regex | supported | yes | Provides | +| [http://tools.ietf.org/html/draft-murchison-sieve-regex-08/] | | | regular | +| | | | expression | +| | | | match support | ++-----------------------------------------------------------------+------------+----------+----------------+ +| reject [http://tools.ietf.org/html/rfc5429#section-2.2] | supported | yes | Allows | +| | | | rejecting | +| | | | messages with a| +| | | | rejection | +| | | | bounce message | ++-----------------------------------------------------------------+------------+----------+----------------+ +| relational [http://tools.ietf.org/html/rfc5231/] | supported | yes | Provides | +| | | | relational | +| | | | match support | ++-----------------------------------------------------------------+------------+----------+----------------+ +| servermetadata [http://tools.ietf.org/html/rfc5490] | supported | no | Provides access| +| | (v0.4.7+) | | to server | +| | | | METADATA entries| ++-----------------------------------------------------------------+------------+----------+----------------+ +| spamtest [http://tools.ietf.org/html/rfc5235/] | supported | no | Implements a | +| | (v0.1.16+) | | uniform way to | +| | | | test against | +| | | | headers added | +| | | | by spam filters| ++-----------------------------------------------------------------+------------+----------+----------------+ +| subaddress [http://tools.ietf.org/html/rfc5233/] | supported | yes | Allows testing | +| | | | against | +| | | | delimited | +| | | | elements of the| +| | | | local part of | +| | | | addresses | ++-----------------------------------------------------------------+------------+----------+----------------+ +| vacation [http://tools.ietf.org/html/rfc5230/] | supported | yes | Provides | +| | | | auto-responder | +| | | | functionality, | +| | | | e.g. for when | +| | | | the user is on | +| | | | vacation | ++-----------------------------------------------------------------+------------+----------+----------------+ +| vacation-seconds [http://tools.ietf.org/html/rfc6131/] | supported | no | Extends | +| | (0.2.3+) | | vacation | +| | | | extension with | +| | | | the ability to | +| | | | send vacation | +| | | | responses with | +| | | | intervals of | +| | | | seconds rather | +| | | | than days | ++-----------------------------------------------------------------+------------+----------+----------------+ +| variables [http://tools.ietf.org/html/rfc5229/] | supported | yes | Adds variables | +| | | | support to the | +| | | | language | ++-----------------------------------------------------------------+------------+----------+----------------+ +| virustest [http://tools.ietf.org/html/rfc5235/] | supported | no | Implements a | +| | (v0.1.16+) | | uniform way to | +| | | | test against | +| | | | headers added | +| | | | by virus | +| | | | scanners | ++-----------------------------------------------------------------+------------+----------+----------------+ +| imapflags(obsolete draft | deprecated | no | Old version of | +| [http://tools.ietf.org/html/draft-melnikov-sieve-imapflags-03]) | | | imap4flags (for| +| | | | backwards | +| | | | compatibility | +| | | | with CMU Sieve)| ++-----------------------------------------------------------------+------------+----------+----------------+ +| notify (obsolete draft | deprecated | no | Old version of | +| [http://tools.ietf.org/html/draft-martin-sieve-notify-01]) | | | enotify (for | +| | | | backwards | +| | | | compatibility | +| | | | with CMU Sieve)| ++-----------------------------------------------------------------+------------+----------+----------------+ + +The following Dovecot-specific Sieve extensions are available for the +Pigeonhole Sieve interpreter: + + * ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| *Extension* | *Support Status* | *Default | *Purpose* | +| | | Enabled* | | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.debug | supported (v0.3.0+) | no | Allows logging debug messages | +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-debug.txt] | | | | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.environment | supported (v0.4.14+) | no | Extends the standard "environment" | +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-dovecot-environment.txt] | | | extension with extra items and a | +| | | | variables namespace for direct access | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.execute | <plugin> | no | Implements executing a pre-defined set | +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-extprograms.txt] | [Pigeonhole.Sieve.Plugins.Extprograms.txt] | | of external programs with the option to| +| | (v0.3+) | | process string data through the | +| | | | external program | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.extdata | <plugin> | no | Allows a Sieve script to lookup | +| [http://hg.rename-it.nl/pigeonhole-0.2-sieve-extdata/raw-file/tip/doc/rfc/spec-bosch-sieve-external-data.txt] | [Pigeonhole.Sieve.Plugins.Extdata.txt] | | information from a datasource external | +| | | | to the script | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.filter | <plugin> | no | Implements filtering messages through a| +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-extprograms.txt] | [Pigeonhole.Sieve.Plugins.Extprograms.txt] | | pre-defined set of external programs | +| | (v0.3+) | | | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.pipe | <plugin> | no | Implements piping messages to a | +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-extprograms.txt] | [Pigeonhole.Sieve.Plugins.Pipe.txt] (v0.2),| | pre-defined set of external programs | +| | <plugin> | | | +| | [Pigeonhole.Sieve.Plugins.Extprograms.txt] | | | +| | (v0.3+) | | | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ +| vnd.dovecot.report | supported (v0.4.14+) | no | Implements sending Messaging Abuse | +| [https://raw.githubusercontent.com/dovecot/pigeonhole/master/doc/rfc/spec-bosch-sieve-report.txt] | | | Reporting Format (MARF) reports (RFC | +| | | | 5965 | +| | | | [http://tools.ietf.org/html/rfc5965/]) | ++----------------------------------------------------------------------------------------------------------------+--------------------------------------------+----------+----------------------------------------+ + +Please note that not all extensions are enabled by default, as shown in the +table above. Deprecated extensions, extensions that add the ability to change +messages, extensions that require explicit configuration and extensions that +are still under development are not enabled without explicit <configuration> +[Pigeonhole.Sieve.Configuration.txt]. This means that the 'sieve_extensions' or +'sieve_global_extensions' settings need to be adjusted accordingly. Also, for +<plugins> [Pigeonhole.Sieve.Plugins.txt] it is not enough to add the plugin +name to the 'sieve_plugins' setting; the extensions introduced by the plugin +also need to be enabled explicitly. + +ManageSieve server +------------------ + +To give users the ability to upload their own Sieve scripts to your server, +i.e. without the need for shell or FTP access, you can use the Manage ''Sieve +protocol. This is also provided by the <Pigeonhole.txt> project. It is +available as a separate Dovecot service. Its configuration and use is explained +on the <Pigeonhole ManageSieve page> [Pigeonhole.ManageSieve.txt]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Pigeonhole.txt b/doc/wiki/Pigeonhole.txt new file mode 100644 index 0000000..7666b25 --- /dev/null +++ b/doc/wiki/Pigeonhole.txt @@ -0,0 +1,45 @@ +Pigeonhole Sieve support +======================== + +Introduction +------------ + +The <Pigeonhole project> [Pigeonhole.txt] provides mail filtering facilities at +time of final message delivery using the Sieve (RFC 5228 +[https://www.ietf.org/rfc/rfc5228.txt]) language. By writing Sieve scripts, +users can customize how messages are delivered, e.g. whether they are forwarded +or stored in special folders. The Sieve language is meant to be simple, +extensible and system independent. And, unlike most other mail filtering script +languages, it does not allow users to execute arbitrary programs. This is +particularly useful to prevent virtual users from having full access to the +mail store. The intention of the language is to make it impossible for users to +do anything more complex (and dangerous) than write simple mail filters. See +Sieve wiki [https://sieve.info/] for more comprehensive information about the +Sieve language itself. + +Installation +------------ + +Refer to the <installation page> [Pigeonhole.Installation.txt]. + +Configuration and Use +--------------------- + +The Pigeonhole package provides the following items: + + * The <Sieve interpreter plugin> [Pigeonhole.Sieve.txt] for Dovecot's <Local + Delivery Agent (LDA)> [LDA.txt] or its <LMTP.txt> server: This facilitates + the actual Sieve filtering upon delivery. + * The <ManageSieve Service> [Pigeonhole.ManageSieve.txt]: This implements the + ManageSieve protocol through which users can remotely manage Sieve scripts + on the server. + +Contact Info +------------ + + * Author: Stephan Bosch, stephan@rename-it.nl + * IRC: Freenode [https://freenode.net/], #dovecot, S[r]us + * Please use the Dovecot mailing list [https://www.dovecot.org/mailing-lists] + for questions about the Pigeonhole. You don't have to subscribe to it. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Apparmor.txt b/doc/wiki/Plugins.Apparmor.txt new file mode 100644 index 0000000..d68f05d --- /dev/null +++ b/doc/wiki/Plugins.Apparmor.txt @@ -0,0 +1,34 @@ +Apparmor plugin +=============== + +A simple plugin which allows changing "hat" (apparmor context) when user is +loaded. Context is changed back to default on user deinit. Multiple hats are +supported, and passed to apparmor_change_hatv function. Since v2.2.32. + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins apparmor + +plugin { + apparmor_hat = hat_name + apparmor_hat2 = another_hat +} +---%<------------------------------------------------------------------------- + +You can also specify hats from user or password database. If you provide from +passdb, use userdb_apparmor_hat=hat and subsequent hats as userdb_apparmor_hat2 +and so forth. From userdb, you can omit the userdb_ prefix. + +It's also possible to combine these, so that you can provide some of the hats +from config and some from passdb/userdb configuration. If you want to provide +apparmor_hat2 from config, make sure you provide apparmor_hat from userdb or +passdb always, otherwise apparmor_hat2 won't be seen. + +Debugging +--------- + +Set mail_debug=yes to see context changes. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Autocreate.txt b/doc/wiki/Plugins.Autocreate.txt new file mode 100644 index 0000000..e1b2eee --- /dev/null +++ b/doc/wiki/Plugins.Autocreate.txt @@ -0,0 +1,28 @@ +Autocreate plugin (v2.0 and older) +================================== + +With v2.1+ you don't need this plugin. Use <mailbox { auto } setting> +[MailboxSettings.txt] instead. + +This plugin allows administrator to specify mailboxes that must always exist +for all users. They can optionally also be subscribed. The mailboxes are +created and subscribed always after user logs in. Namespaces are fully +supported, so namespace prefixes need to be used where necessary. + +Example: + +---%<------------------------------------------------------------------------- +protocol imap { + mail_plugins = $mail_plugins autocreate +} +plugin { + autocreate = Trash + autocreate2 = Spam + #autocreate3 = ..etc.. + autosubscribe = Trash + autosubscribe2 = Spam + #autosubscribe3 = ..etc.. +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.CharsetAlias.txt b/doc/wiki/Plugins.CharsetAlias.txt new file mode 100644 index 0000000..b62e151 --- /dev/null +++ b/doc/wiki/Plugins.CharsetAlias.txt @@ -0,0 +1,20 @@ +Charset Alias plugin +==================== + +Requires v2.2.34+. This plugin allows treating the specified source charset as +a different charset when decoding to UTF-8. For instance, when decoding from +shift_jis to UTF-8, using cp932 (or sjis-win) instead of shift_jis may be +preferable to handle Microsoft extended chars properly. + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins charset_alias +plugin { + charset_aliases = shift_jis=sjis-win euc-jp=eucjp-win +iso-2022-jp=iso-2022-jp-3 +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Compress.txt b/doc/wiki/Plugins.Compress.txt new file mode 100644 index 0000000..d3cbd80 --- /dev/null +++ b/doc/wiki/Plugins.Compress.txt @@ -0,0 +1,16 @@ +IMAP COMPRESS plugin +==================== + +The goal of the extension is to reduce the bandwidth usage of IMAP. + +Configuration: + +---%<------------------------------------------------------------------------- +#mail_plugins = $mail_plugins zlib # Required for v2.1 and older only + +protocol imap { + mail_plugins = $mail_plugins imap_zlib +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Expire.txt b/doc/wiki/Plugins.Expire.txt new file mode 100644 index 0000000..12b9f08 --- /dev/null +++ b/doc/wiki/Plugins.Expire.txt @@ -0,0 +1,354 @@ +Expire plugin +============= + +(See also <autoexpunge> [MailboxSettings.txt] setting, which partially +obsoletes this plugin.) + +Typically this plugin is used to optimize expunging old mails from users' +mailboxes. For example: + +---%<------------------------------------------------------------------------- +doveadm expunge -A mailbox Trash savedbefore 30d +---%<------------------------------------------------------------------------- + +Note that: + + * *This command runs fine even without the expire plugin.* Then it just goes + through all users rather than those users who have something to actually + expunge. + * The plugin actually works for all doveadm mail commands, not just expunge. + So for testing you could use e.g.'doveadm search -A ...' to see which + messages it matches. + * The optimization is done only when -A parameter is used to go through all + users. If you use -u parameter to separately go through users, the plugin + does nothing. + * The optimization is done only when "savedbefore" is used in the search + query. It's possible to have further restrictions also, but the user + filtering is based only on the "savedbefore" timestamp. + * The optimization is done only when the given mailbox or mailboxes match the + list of expire mailboxes specified in 'plugin { expire* } ' settings. + +So the expire plugin's job is to reduce disk I/O when figuring out which users +have work to do. Unless you have thousands of users, you probably shouldn't +bother with this plugin. + +Details +------- + +When expire plugin is enabled, it keeps track of the "oldest mail's saved +timestamp" for the specified mailboxes. When doveadm command uses "savedbefore" +search key, the timestamps in the database can be used to figure out which +users have matching mails. + +Expire plugin tracks/optimizes only "savedbefore" search query, i.e. the date +when message was *saved or copied to the mailbox* (*NOT the time message was +originally received*) while expire plugin was loaded. If mailbox contained +existing messages before the plugin was loaded for the first time, they'll get +expunged eventually when the first message saved/copied after expire plugin was +enabled gets expunged. + +The save/copy date may not be exact if it's not cached in +'dovecot.index.cache': + + * mbox: The current lookup time is used and added to cache. + * maildir: File's ctime is used. + * dbox: Save/copy time is taken from the dbox file if it exists (it normally + should), fallbacking to file's ctime if not. + +You need to configure a list of mailboxes that are tracked. Mailbox patterns +can contain IMAP LIST command-compatible wildcards: + + * "*" works in a standard way: It matches any number of characters. + * "%" works by matching any number of characters, but it stops at the + hierarchy separator. Currently the separator is hardcoded to "/", so it + doesn't work correctly if you've configured separator to something else + (e.g. "." is the default for Maildir). + +Example configuration +--------------------- + +Make sure you enable the plugin globally, not just for specific protocols. + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins expire + +plugin { + expire = Trash + expire2 = Trash/* + expire3 = Spam + + # Enable caching of dict value in dovecot.index file. This significantly +reduces + # the number of dict lookups. It makes initial testing more confusing though, +so + # it's better to enable it only after you've verified that the expire plugin +is + # working as wanted. (v2.2.16+) + expire_cache = yes +} +---%<------------------------------------------------------------------------- + + * See <Dict.txt> for more information about how to use dict service, + especially about permission issues. + * You need to get 'doveadm -A' working using your userdb. See iterate settings + for <SQL> [AuthDatabase.SQL.txt] and <LDAP> [AuthDatabase.LDAP.txt]. + +MySQL Backend +------------- + +dovecot.conf: + +---%<------------------------------------------------------------------------- +plugin { + expire_dict = proxy::expire +} +dict { + expire = mysql:/etc/dovecot/dovecot-dict-expire.conf.ext +} +---%<------------------------------------------------------------------------- + +Create the table like this: + +---%<------------------------------------------------------------------------- +CREATE TABLE expires ( + username varchar(75) not null, + mailbox varchar(255) not null, + expire_stamp integer not null, + primary key (username, mailbox) +); +---%<------------------------------------------------------------------------- + +dovecot-dict-expire.conf.ext: + +---%<------------------------------------------------------------------------- +connect = host=localhost dbname=mails user=sqluser password=sqlpass + +map { + pattern = shared/expire/$user/$mailbox + table = expires + value_field = expire_stamp + + fields { + username = $user + mailbox = $mailbox + } +} +---%<------------------------------------------------------------------------- + +PostgreSQL Backend +------------------ + +Like MySQL configuration above, but you'll also need to create a trigger: + +---%<------------------------------------------------------------------------- +CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS $$ +BEGIN + UPDATE expires SET expire_stamp = NEW.expire_stamp + WHERE username = NEW.username AND mailbox = NEW.mailbox; + IF FOUND THEN + RETURN NULL; + ELSE + RETURN NEW; + END IF; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER mergeexpires BEFORE INSERT ON expires + FOR EACH ROW EXECUTE PROCEDURE merge_expires(); +---%<------------------------------------------------------------------------- + +SQLite Backend +-------------- + +Like MySQL configuration above, but you'll also need to create a trigger: + +---%<------------------------------------------------------------------------- +CREATE TRIGGER mergeexpires BEFORE INSERT ON expires FOR EACH ROW +BEGIN + UPDATE expires SET expire_stamp=NEW.expire_stamp + WHERE username = NEW.username AND mailbox = NEW.mailbox; + SELECT raise(ignore) + WHERE (SELECT 1 FROM expires WHERE username = NEW.username AND +mailbox = NEW.mailbox) IS NOT NULL; +END; +---%<------------------------------------------------------------------------- + +Vpopmail (+MySQL) +----------------- + +Configure expire plugin like MySQL configuration. From here, there are two +cases: + +If you are using the mysql database for authentication directly, you only need +to make iterate work for <MySQL> [AuthDatabase.SQL.txt]. + +When using Vpopmail backend, doveadm -A won't work. To be able to use the +expire database, you can use a bash script like this: + +---%<------------------------------------------------------------------------- +#!/bin/bash + +# SQL connection data +HOST="localhost" +USER="dovecot" +PWD="yourpassword" +DBNAME="vpopmail" +TBLNAME="expires" +# expunge messages older than this (days) +TTL=30 + +expiredsql=`cat <<EOF + USE $DBNAME; + SELECT CONCAT(username, "~", mailbox) + FROM $TBLNAME + WHERE expire_stamp>0 AND expire_stamp<UNIX_TIMESTAMP()-86400*$TTL; +EOF` + +for row in `echo "$expiredsql" | mysql -h $HOST -u $USER -p$PWD -N`; do + username=`echo $row | cut -d"~" -f1` + mailbox=`echo $row | cut -d"~" -f2-` + + # Check if mailbox name is empty. Just in case. + if [ -n $mailbox ]; then + echo "Expunging: "$row + doveadm expunge -u $username mailbox "$mailbox" savedbefore $TTL"d" + fi +done +---%<------------------------------------------------------------------------- + +Example #1 timeline +------------------- + +FIXME: expire-tool no longer exists, update these examples. Let's say Trash is +configured to expire in 7 days and today is 2009-07-10. Initially the database +and the Trash mailbox is empty. + +User moves the first message to Trash. The expires table is updated: + +---%<------------------------------------------------------------------------- +mysql> select mailbox, from_unixtime(expire_stamp), username from expires; ++---------+-----------------------------+----------+ +| mailbox | from_unixtime(expire_stamp) | username | ++---------+-----------------------------+----------+ +| Trash | 2009-07-17 15:57:36 | tss | ++---------+-----------------------------+----------+ +---%<------------------------------------------------------------------------- + +The expire_stamp contains the date when expire-tool will look into that mailbox +and try to find messages to expunge. Until then it skips the mailbox. + +A day later user moves another message to Trash. The expire_stamp isn't +updated, because the second message's save date is newer than the first one's. +Checking Trash's contents via IMAP you can see something like: + +---%<------------------------------------------------------------------------- +1 fetch 1:* (internaldate x-savedate) +* 1 FETCH (INTERNALDATE "16-Dec-2008 09:52:38 -0500" X-SAVEDATE "10-Jul-2009 +15:57:36 -0400") +* 2 FETCH (INTERNALDATE "29-Jun-2003 23:20:09 -0400" X-SAVEDATE "11-Jul-2009 +16:03:11 -0400") +1 OK Fetch completed. +---%<------------------------------------------------------------------------- + +Note how the message's INTERNALDATE (received date) can be very old compared to +the save date. Now, running expire-tool --test: + +---%<------------------------------------------------------------------------- +Info: tss/Trash: stop, expire time in future: Fri Jul 17 15:57:36 2009 +---%<------------------------------------------------------------------------- + +So it does nothing, because the expire time is in future. Fast forward 6 more +days into future. Running expire-tool --test: + +---%<------------------------------------------------------------------------- +Info: tss/Trash: seq=1 uid=1: Expunge +Info: tss/Trash: timestamp 1247860656 (Fri Jul 17 15:57:36 2009) -> 1247947391 +(Sat Jul 18 16:03:11 2009) +---%<------------------------------------------------------------------------- + +The first message would be expunged and the second message's timestamp would +become the new expire_stamp in database. After running expire-tool without +--test, the database is updated: + +---%<------------------------------------------------------------------------- +mysql> select mailbox, from_unixtime(expire_stamp), username from expires; ++---------+-----------------------------+----------+ +| mailbox | from_unixtime(expire_stamp) | username | ++---------+-----------------------------+----------+ +| Trash | 2009-07-18 16:03:11 | tss | ++---------+-----------------------------+----------+ +---%<------------------------------------------------------------------------- + +Also you can see the first message has been expunged from Trash: + +---%<------------------------------------------------------------------------- +2 fetch 1:* (internaldate x-savedate) +* 1 FETCH (INTERNALDATE "29-Jun-2003 23:20:09 -0400" X-SAVEDATE "11-Jul-2009 +16:03:11 -0400") +2 OK Fetch completed. +---%<------------------------------------------------------------------------- + +Example #2 timeline +------------------- + +Again you have Trash configured for 7 days, but this time you have an existing +message there before expire plugin has been enabled. Initially the expire +database is empty. Today is 2009-07-20. + +---%<------------------------------------------------------------------------- +1 fetch 1:* (internaldate x-savedate) +* 1 FETCH (INTERNALDATE "29-Jun-2003 23:20:09 -0400" X-SAVEDATE "11-Jul-2009 +16:03:11 -0400") +1 OK Fetch completed. +---%<------------------------------------------------------------------------- + +If you run expire-tool, you'll notice that it does nothing for the mailbox. +There's nothing in expire database, so expire-tool doesn't even mention it when +running with --test. + +After user moves the first message to Trash, the database gets updated: + +---%<------------------------------------------------------------------------- +mysql> select mailbox, from_unixtime(expire_stamp), username from expires; ++---------+-----------------------------+----------+ +| mailbox | from_unixtime(expire_stamp) | username | ++---------+-----------------------------+----------+ +| Trash | 2009-07-27 16:32:11 | tss | ++---------+-----------------------------+----------+ +---%<------------------------------------------------------------------------- + +The messages in Trash are: + +---%<------------------------------------------------------------------------- +2 fetch 1:* (internaldate x-savedate) +* 1 FETCH (INTERNALDATE "29-Jun-2003 23:20:09 -0400" X-SAVEDATE "11-Jul-2009 +16:03:11 -0400") +* 2 FETCH (INTERNALDATE "16-Dec-2002 11:02:39 -0500" X-SAVEDATE "20-Jul-2009 +16:32:11 -0400") +2 OK Fetch completed. +---%<------------------------------------------------------------------------- + +So the first message should be expiring already, right? No. It doesn't because +the timestamp in database is still in future. expire-tool --test says: + +---%<------------------------------------------------------------------------- +Info: tss/Trash: stop, expire time in future: Mon Jul 27 16:32:11 2009 +---%<------------------------------------------------------------------------- + +OK, let's see what happens when we finally reach July 27th: + +---%<------------------------------------------------------------------------- +Info: tss/Trash: seq=1 uid=3: Expunge +Info: tss/Trash: seq=2 uid=4: Expunge +Info: tss/Trash: no messages left +---%<------------------------------------------------------------------------- + +They both got expunged! The expire database's timestamp simply tells +expire-tool when to start looking into messages in that mailbox. After that +expire-tool looks at the actual save dates and figures out which messages +exactly need to be expunged. + +After running expire-tool without --test you'll see that the Trash mailbox is +empty and the database row is deleted. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.FTS.Lucene.txt b/doc/wiki/Plugins.FTS.Lucene.txt new file mode 100644 index 0000000..0ddc392 --- /dev/null +++ b/doc/wiki/Plugins.FTS.Lucene.txt @@ -0,0 +1,74 @@ +Lucene Full Text Search Indexing +================================ + +*NOTE*: Although the fts-lucene plugin works, it's using CLucene library, which +is very old and has some bugs. It's a much better idea to use <fts-solr> +[Plugins.FTS.Solr.txt] instead, which has much more features and is more +stable. + +Requires Dovecot v2.1+ to work properly. The CLucene version must be v2.3 (not +v0.9).Dovecot builds only a single Lucene index for all mailboxes. The Lucene +indexes are stored in 'lucene-indexes/' directory under the mail root index +directory (e.g.'~/Maildir/lucene-indexes/'). + +Compilation +----------- + +If you compile Dovecot yourself, you must add the following switches to your +configure command for the plugin to be built: + +---%<------------------------------------------------------------------------- +--with-lucene --with-stemmer +---%<------------------------------------------------------------------------- + +The second switch is only required if you have compiled libstemmer yourself or +if it's included in the CLucene you are using. + +Configuration +------------- + +Into 10-mail.conf (note add existing plugins to string) + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins fts fts_lucene +---%<------------------------------------------------------------------------- + +Into 90-plugins.conf + +---%<------------------------------------------------------------------------- +plugin { + fts = lucene + # Lucene-specific settings, good ones are: + fts_lucene = whitespace_chars=@. +} +---%<------------------------------------------------------------------------- + +The fts-lucene settings include: + + * whitespace_chars=<chars>: List of characters that are translated to + whitespace. You may want to use "@." so that e.g. in + "'first.last@example.org'" it won't be treated as a single word, but rather + you can search separately for "first", "last" and "example". + * default_language=<lang>: Default stemming language to use for mails. The + default is english. Requires that Dovecot is built with libstemmer, which + also limits the languages that are supported. + * textcat_conf=<path> textcat_dir=<path>: If specified, enable guessing the + stemming language for emails and search keywords. This is a little bit + problematic in practice, since indexing and searching languages may differ + and may not find even exact words because they stem differently. + * no_snowball: Support normalization of indexed words even without stemming + and libstemmer (Snowball). (v2.2.3+) + * mime_parts: Index each MIME part separately and include the MIME part number + in the "part" field. In future versions this will allowing showing which + attachment matched the search result. (v2.2.13+) + +Libraries +--------- + + * CLucene [http://sourceforge.net/projects/clucene/files/]: Get v2.3.3.4 (not + v0.9) + * libstemmer [http://snowball.tartarus.org/download.php]: Builds libstemmer.o, + which you can rename to libstemmer.a + * textcat [http://textcat.sourceforge.net/] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.FTS.Solr.txt b/doc/wiki/Plugins.FTS.Solr.txt new file mode 100644 index 0000000..e888a71 --- /dev/null +++ b/doc/wiki/Plugins.FTS.Solr.txt @@ -0,0 +1,289 @@ +Solr Full Text Search Indexing +============================== + +Solr [https://lucene.apache.org/solr/] is a Lucene indexing server. Dovecot +communicates to it using HTTP/XML queries. + +The steps described in this wiki page are tested for Solr 7.7.0. For other +versions, this these steps may need to be adjusted. + +Compiling +--------- + +Dovecot is not compiled with Solr FTS support by default. To enable it, you +need to add the '--with-solr' parameter to your invocation of the 'configure' +script. You will also need to have libexpat installed, including development +headers (typically from a separate development package). Configuration will +fail if '--with-solr' is enabled while libexpat headers cannot be found. Older +versions of Dovecot also required libcurl for Solr support, but recent versions +of Dovecot include a custom HTTP client. + +Configuration +------------- + +Solr Installation +----------------- + +First, the Solr server needs to be installed. Most operating systems will have +packages for this. The latest version can be downloaded and installed from +official website, and here are instructions to install 7.7.0 based on the howto +How to Install Apache Solr 7.5 on Debian 9/8 +[https://tecadmin.net/install-apache-solr-on-debian/]: + +---%<------------------------------------------------------------------------- +wget https://www-eu.apache.org/dist/lucene/solr/7.7.0/solr-7.7.0.tgz +tar xzf solr-7.7.0.tgz solr-7.7.0/bin/install_solr_service.sh +--strip-components=2 +sudo bash ./install_solr_service.sh solr-7.7.0.tgz +---%<------------------------------------------------------------------------- + +To use Solr with Dovecot, it needs to configured specifically for use with +Dovecot. + +---%<------------------------------------------------------------------------- +sudo -u solr /opt/solr/bin/solr create -c dovecot +---%<------------------------------------------------------------------------- + +The location of the files for the newly created instance on the filesystem +varies between operating systems and installation methods. For example, in +Archlinux, the config files are located in '/opt/solr/server/solr/dovecot/conf' +and data files can be found in '/opt/solr/server/solr/dovecot/data'. When +installed from tarball, these directories can be found in +'/var/solr/data/dovecot/'. + +Once the instance is created, you can start Solr. The means of starting, +stopping and querying the status of the 'solr' service varies between systems. +For systemd, these commands are as follows: + +---%<------------------------------------------------------------------------- +sudo systemctl stop solr +sudo systemctl start solr +sudo systemctl status solr +---%<------------------------------------------------------------------------- + +By default, the Solr administation page for the newly created instance is +located at https://localhost:8983/solr/#/~cores/dovecot. It can be used to +check the status of the Solr instance. Configuration errors are often most +conveniently viewed here. Solr also writes log files. For a tarball +installation, these can be found at '/var/solr/logs/'. + +Solr Configuration +------------------ + +There are three primary configuration files that need to be changed to +accommodate the Dovecot FTS needs: the instance configuration file +'solrconfig.xml' and the schema files 'schema.xml' and 'managed-schema' used by +the instance. These files are both located in the 'conf' directory of the Solr +instance (e.g.,'/var/solr/data/dovecot/conf/'). + +Remove default core configuration files +--------------------------------------- + +---%<------------------------------------------------------------------------- +rm -f /var/solr/data/dovecot/conf/schema.xml +rm -f /var/solr/data/dovecot/conf/managed-schema +rm -f /var/solr/data/dovecot/conf/solrconfig.xml +---%<------------------------------------------------------------------------- + +Install schema.xml and solrconfig.xml +------------------------------------- + +Copy doc/solr-config-7.7.0.xml +[https://raw.githubusercontent.com/dovecot/core/master/doc/solr-config-7.7.0.xml] +and doc/solr-schema-7.7.0.xml +[https://raw.githubusercontent.com/dovecot/core/master/doc/solr-schema-7.7.0.xml] +(Since Dovecot 2.3.6+) to '/var/solr/data/dovecot/conf/' as 'solrconfig.xml' +and 'schema.xml'. The 'managed-schema' file is generated based on 'schema.xml'. + +Dovecot Plugin +-------------- + +On Dovecot's side add: + +Into 10-mail.conf (note add existing plugins to string) + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins fts fts_solr +---%<------------------------------------------------------------------------- + +Into 90-plugins.conf + +---%<------------------------------------------------------------------------- +plugin { + fts = solr + fts_solr = url=https://solr.example.org:8983/solr/dovecot/ +} +---%<------------------------------------------------------------------------- + +Fields listed in 'fts_solr' plugin setting are space separated. They can +contain: + + * url=<solr url> : Required base URL for Solr. (remember to add your core name + if using solr 7+ : "/solr/dovecot/"). The default URL for Solr 7+ is + https://localhost:8983/solr/dovecot + * debug : Enable HTTP debugging. Writes to debug log. + * break-imap-search : Use Solr also for indexing TEXT and BODY searches. This + makes your server non-IMAP-compliant. (This is always enabled in v2.1+, and + removed since v2.3+ as it's default behaviour) + * rawlog_dir=<directory> : For debugging, store HTTP exchanges between Dovecot + and Solr in this directory. (2.3.6+) + * batch_size : Configure the number of mails sent in single requests to Solr, + default is 1000. (2.3.6+) + * with fts_autoindex=yes, each new mail gets separately indexed on arrival, + so batch_size only matters when doing the initial indexing of a mailbox. + * with fts_autoindex=no, new mails don't get indexed on arrival, so + batch_size is used when indexing gets triggered. + * soft_commit=yes|no : Control whether new mails are immediately searchable + via Solr, default to yes. When using no, it's important to set autoCommit or + autoSoftCommit time in solrconfig.xml so mails eventually become searchable. + (2.3.6+) + +Important notes: + + * Some mail clients will not submit any search requests for certain fields if + they index things locally eg. Thunderbird will not send any requests for + fields such as sender/recipients/subject when Body is not included as this + data is contained within the local index. + +Solr commits & optimization +--------------------------- + +Solr indexes should be optimized once in a while to make searches faster and to +remove space used by deleted mails. Dovecot never asks Solr to optimize, so you +should do this yourself. Perhaps a cronjob that sends the optimize-command to +Solr every n hours. + +With v2.2.3+ Dovecot only does soft commits to the Solr index to improve +performance. You must run a hard commit once in a while or Solr will keep +increasing its transaction log sizes. For example send the commit command to +Solr every few minutes. + +---%<------------------------------------------------------------------------- +# Optimize should be run somewhat rarely, e.g. once a day +curl https://<hostname/ip>:<port|default +8983>/solr/dovecot/update?optimize=true +# Commit should be run pretty often, e.g. every minute +curl https://<hostname/ip>:<port|default 8983>/solr/dovecot/update?commit=true +---%<------------------------------------------------------------------------- + +You may not need those if you are using a recent Solr (7+) or <SolrCloud.txt>. +The default configuration of Solr is to auto-commit every once in a while +(~15sec) so commit is not necessary. Also, the default / +<TieredMergePolicy.txt>/ in Solr will automatically purge removed documents +later, so optimize is not necessary. + +Re-index mailbox +---------------- + +If you require to force dovecot to reindex a whole mailbox you can run the +command shown, this will only take action when a search is done and will apply +to the whole mailbox. + +---%<------------------------------------------------------------------------- +doveadm fts rescan -u <username> +---%<------------------------------------------------------------------------- + +If you want to index a single mailbox/all mailboxes you can run the command +shown, this will happen immediately and will block until the action is +completed. + +---%<------------------------------------------------------------------------- +doveadm index [-u <user>|-A] [-S <socket_path>] [-q] [-n <max recent>] <mailbox +mask> +---%<------------------------------------------------------------------------- + +Sorting by relevancy +-------------------- + +Solr/Lucene supports returning a relevancy score for search results. If you +want to sort the search results by the score, use Dovecot's non-standard +X-SCORE sort key: + +---%<------------------------------------------------------------------------- +1 SORT (X-SCORE) UTF-8 <search parameters> +---%<------------------------------------------------------------------------- + +Indexes +------- + +Dovecot creates the following fields: + + * id: Unique ID consisting of uid/uidv/user/box. + * Note that your user names really shouldn't contain '/' character. + * uid: Message's IMAP UID. + * uidv: Mailbox's UIDVALIDITY. This changes if mailbox gets recreated. + * box: Mailbox name + * user: User name who owns the mailbox, or empty for public namespaces + * hdr: Indexed message headers + * body: Indexed message body + * any: "Copy field" from hdr and body, i.e. searching based on this will + search from both headers and bodies. + +Lucene does duplicate suppression based on the "id" field, so even if Dovecot +sends the same message multiple times to Solr it gets indexed only once. This +might happen currently if multiple searches are started at the same time. + +You might want to build a cronjob to go through the Lucene indexes once in a +while to delete indexed messages (or entire mailboxes) that no longer exist on +the filesystem. It shouldn't normally find any such messages though. + +Testing +------- + +---%<------------------------------------------------------------------------- +# telnet localhost imap +* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT +SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN +NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 ESEARCH ESORT SEARCHRES WITHIN +CONTEXT=SEARCH LIST-STATUS STARTTLS AUTH=PLAIN AUTH=LOGIN] I am ready. +1 login username password +2 select Inbox +3 SEARCH text "test" +---%<------------------------------------------------------------------------- + +Sharding +-------- + +If you have more users than fit into a single Solr box, you can split users off +to different servers. A couple of different ways you could do it are: + + * Have some HTTP proxy redirecting the connections based on the URL + * Configure Dovecot's userdb lookup to return a different host for 'fts_solr' + setting using <extra fields> [UserDatabase.ExtraFields.txt]. + * LDAP: 'user_attrs = ..., + solrHost=fts_solr=url=https://%$:8983/solr/dovecot/' + * MySQL: 'user_query = SELECT concat('url=https://', solr_host, + ':8983/solr/dovecot/') AS fts_solr, ...' + +You can also use SolrCloud +[https://lucene.apache.org/solr/guide/7_6/solrcloud.html], the clustered +version of Solr, that allows you to scale up, and adds failover / high +availability to your FTS system. Dovecot-solr works fine with a <SolrCloud.txt> +cluster as long as the solr schema is the right one. + +External Tutorials +------------------ + +External sites with tutorials on using Solr under Dovecot + + * Installing Apache Solr with Dovecot for fulltext search results (ATmail + support guide) + [https://help.atmail.com/hc/en-us/articles/201566404-Installing-Apache-Solr-with-Dovecot-for-fulltext-search-results] + * FreeBSD: https://mor-pah.net/2016/08/15/dovecot-2-2-with-solr-6-or-5/ + * Substring searches with ngrams: + https://dovecot.org/list/dovecot/2011-May/059338.html + +Tips +---- + +Some additional things which might help you configuring Solr search: + + * If you are using Tomcat: Set 'maxHttpHeaderSize="65536"' (connector + definition for port 8080 in '/etc/tomcat7/server.xml') to accept long search + query strings (iPhones tend to send multi-kilobyte-sized queries) + * Set 'df' to 'hdr' in '/etc/solr/conf/solrconfig.xml' ('/select' request + handler) to avoid strange 'undefined field text' errors. + * Please keep in mind that you will have to change the Solr URL to include the + core name (ie:'dovecot': 'https://localhost:8939/solr/dovecot'). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.FTS.Squat.txt b/doc/wiki/Plugins.FTS.Squat.txt new file mode 100644 index 0000000..07dc867 --- /dev/null +++ b/doc/wiki/Plugins.FTS.Squat.txt @@ -0,0 +1,128 @@ +Squat Full Text Search Indexing +=============================== + +NOTE: The Squat code is quite slow for large mailboxes. There are also a few +bugs that are unlikely to be fixed. In v2.1+ it's recommended to use +<fts-lucene> [Plugins.FTS.Lucene.txt] instead. There's also a "New Squat" +redesign/reimplementation going on, which will likely end up having a new name. + +The main difference between Squat indexes and the others is that Squat provides +support for substring searches, while pretty much all other FTS indexes support +only matching from the beginning of words. By strictly reading the IMAP RFC it +requires substring matching, so to optimize regular TEXT and BODY searches you +must use Squat with Dovecot v2.0. The other indexes are used only for Dovecot's +non-standard X-TEXT-FAST and X-BODY-FAST searches. However, almost all other +commonly used IMAP servers no longer care about this requirement, so Dovecot +v2.1 also no longer makes this distinction. In Dovecot v2.1 TEXT and BODY +searches are done using any indexes available. + + * The Squat indexes are currently updated only when SEARCH TEXT or SEARCH BODY + command is used. It's planned that in future they could be updated + immediately when messages are being saved. + * The Squat indexes take about 30% of the mailbox size (with partial=4 + full=4). + * The initial Squat index building for large mailboxes can be very CPU and + memory hungry. + * The Squat indexes are stored among Dovecot's other index files. They're + called 'dovecot.index.search' and 'dovecot.index.search.uids'. It's safe to + delete both of these files to trigger a rebuild. + +Some statistics with Core2 duo 6600, 2 GB memory (partial=4 full=4): + + * 1,4 GB mbox with 368000 messages: SEARCH BODY asdfgh + * Without Squat: 2 min 35 sec CPU, process RSS size 24 MB + * Initial Squat build: 6 min 36 sec CPU, process RSS size peaks at 800 MB, + drops to 96 MB at end. + * Subsequent searches: 0.10 sec CPU, 1.18 sec real with cold cache, process + RSS size 2 MB. + * Most of the time was spent verifying Squat results. Searching for a + 1..4 letter word gives results in 0.00 CPU secs and 0.80 real secs + with cold cache. + + * 32 MB mbox with 7500 messages: SEARCH BODY asdfgh + * Without Squat: 2.3 sec CPU, 3.6 sec real with cold cache, process RSS + size 5 MB + * Initial Squat build: 8.9 sec CPU, 10.0 sec real with cold cache, process + RSS size peaks at 61 MB, drops to 20 MB at end. + * 48 MB maildir with 10000 messages: SEARCH BODY asdfgh + * Without Squat: 2.6 sec CPU, 9.7 sec real with cold cache + * Initial Squat build: 9.7 sec CPU, 15.3 sec real with cold cache + +Internal workings +----------------- + +Squat works by building a trie of all 1..4 character combinations of all words +in messages. For example given a word "world" it indexes "worl", "orld", "rld", +"ld" and "d". Matching message UIDs are stored to each trie node, so Squat +supports giving definitive answers to any searches with a length of 1..4 +characters. For longer search words the word is looked up in 4 letter pieces +and the results are merged. The resulting list is a list of messages where the +word *may* exist. This means that those messages are still opened and the word +is searched from them the slow way. + +Squat also supports indexing more characters from the beginning of words. For +example if 5 first characters are indexed, the word "character" would be cut to +"chara". If a user then searches for "chara", Dovecot does: + + 1. Search for messages having "char" (reply example: 1,5,10) + 2. Search for messages having "hara" (reply example: 3,5,10) + 3. Store the intersection of the above searches to "maybe UIDs" (example: + 5,10) + 4. Search for full word "chara" and store it as "definite UIDs" (reply + example: 5) + 5. Remove definite UIDs (5) from maybe UIDs (5,10 -> 10) + +In the above example Dovecot would know that message UID 5 has the word +"chara", but it still has to check if UID 10 has it as a substring (e.g. in +word "achara") by reading the message contents. If the user's search words +match mostly non-substrings (which is common), using long enough full word +indexing can improve the search performance a lot, especially when the word +matches a lot of messages. + +The Squat name comes from Cyrus IMAP [http://cyrusimap.web.cmu.edu/] which +implements slightly similar Squat indexes ("Search QUery Answer Tool"). +Dovecot's implementation and file format however is completely different. The +main visible difference is that Dovecot allows updating the index incrementally +instead of requiring to re-read the entire mailbox to build it. Cyrus Squat +also doesn't support 1..3 characters long searches. + +Configuration +------------- + +'fts_squat' setting can be used to change Squat options: + + * partial=n: Length of the substring blocks to index. Default is 4 characters + and it's probably not a good idea to change it. + * full=n: Index n first characters from the beginning of words. Default is 4, + but it could be useful to increase this to e.g. 10 or so. However larger + values take more disk space. + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins fts fts_squat + +plugin { + fts = squat + fts_squat = partial=4 full=10 +} +---%<------------------------------------------------------------------------- + +Using both Squat and non-Squat (v2.0-only) +------------------------------------------ + +It's possible to use both Squat and non-Squat indices at the same time, so that +TEXT/BODY are looked up from Squat indexes and X-TEXT-FAST/X-BODY-FAST are +looked up from the non-Squat index. This of course means that indices will have +to be built and updated for both, so it might not be that good idea. + +---%<------------------------------------------------------------------------- +protocol imap { +.. + mail_plugins = fts fts_squat fts_solr +} +... +plugin { + fts = squat solr +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.FTS.txt b/doc/wiki/Plugins.FTS.txt new file mode 100644 index 0000000..e960b4c --- /dev/null +++ b/doc/wiki/Plugins.FTS.txt @@ -0,0 +1,102 @@ +Full text search indexing +========================= + +The following FTS indexers (in preferred order) are supported: + + * <Solr> [Plugins.FTS.Solr.txt] communicates with Lucene's Solr server + [http://lucene.apache.org/solr/]. + * <Lucene> [Plugins.FTS.Lucene.txt] uses Lucene's C++ library. (Requires + v2.1+) + * <fts-dovecot> [Plugins.FTS.Dovecot.txt] is Dovecot Pro's new search index, + and is not available without commercial agreement. (Requires v2.2+) + * <Squat> [Plugins.FTS.Squat.txt] is Dovecot's own search index. (Obsolete in + v2.1+) + * fts-xapian [https://github.com/grosjo/fts-xapian] is Xapian + [https://xapian.org] based plugin maintained by '<jom AT NOSPAM grosjo DOT + net>'. (Requires v2.3+) + +Indexing +-------- + +By default the FTS indexes are updated *only* while searching, so neither the +<LDA.txt> nor an IMAP APPEND command updates the indexes immediately. This +means that if user has received a lot of mail since the last indexing (== +search operation), it may take a while to index all the mails before replying +to the search command. Dovecot sends periodic "* OK Indexed n% of the mailbox" +updates which can be caught by webmail implementations to implement a progress +bar. + +In v2.2.9+ the indexing can be done automatically with 'fts_autoindex=yes' +setting (see below). + +The indexing can be done manually (e.g. cronjob) or by a LDA script by running: + + * v2.1: 'doveadm index -u user@domain -q INBOX' + * v2.0: 'printf "a select INBOX\nb search text xyzzy\nc logout\n" | + /usr/local/libexec/dovecot/imap -u user@domain' + +Of course the INBOX needs to be replaced with whatever mailbox needs to be +indexed. + +Indexing Attachments (v2.1+) +---------------------------- + +Attachments can be indexed either via a script that translates the attachment +to UTF-8 plaintext or Apache Tika server. + + * 'fts_decoder = <service>': Decode attachments to plaintext using this + service and index the resulting plaintext. See the 'decode2text.sh' script + included in Dovecot for how to use this. (v2.1+) + * 'fts_tika = http://tikahost:9998/tika/': This URL needs to be running Apache + Tika server (e.g. started with 'java -jar + tika-server/target/tika-server-1.5.jar') (v2.2.13+) + +Rescan (v2.1+) +-------------- + +Since v2.1 Dovecot keeps track of indexed messages in the dovecot.index files. +If this becomes out of sync with the actual FTS indexes (either too many or too +few mails), you'll need to do a rescan: + +---%<------------------------------------------------------------------------- +doveadm fts rescan -u user@domain +---%<------------------------------------------------------------------------- + +Other Settings +-------------- + +All the FTS settings go inside 'plugin {} ' section of 90-plugin.conf. + + * 'fts_autoindex=yes': Index new messages immediately after they've been + saved/copied. (v2.2.9+) + * 'fts_autoindex_exclude=pattern1', 'fts_autoindex_exclude2=pattern2', ...: + Exclude given mailboxes, one pattern per setting. Supports "*" and "?" + wildcards. If a name starts with '\', it's treated as a case-insensitive + special-use flag. (v2.2.25+) + * Example: + + ---%<------------------------------------------------------------------- + plugin { + fts_autoindex_exclude = \Junk + fts_autoindex_exclude2 = \Trash + fts_autoindex_exclude3 = DUMPSTER + } + ---%<------------------------------------------------------------------- + + * 'fts_autoindex_max_recent_msgs=n': Skip autoindexing the mailbox if it has + more than n \Recent messages (implying that the mailbox is never actually + being accessed). (v2.2.9+) + * 'fts_enforced': + * no (default): All body searches will index all missing mails in FTS. + Header searches will use FTS if the mails are indexed, otherwise fallback + to parsing the headers (usually from dovecot.index.cache). If FTS search + fails, fallback to reading and parsing all mails. + * yes: All header and body searches will index all missing mails in FTS. If + FTS search fails, error is returned to client. + * 'fts_index_timeout': When SEARCH notices that index isn't up to date, it + tells indexer to index the mails and waits until it is finished. This + setting adds a maximum timeout to this wait. If the timeout is reached, the + SEARCH fails with:'NO [INUSE] Timeout while waiting for indexing to finish' + (v2.1+) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.LastLogin.txt b/doc/wiki/Plugins.LastLogin.txt new file mode 100644 index 0000000..65ae6a8 --- /dev/null +++ b/doc/wiki/Plugins.LastLogin.txt @@ -0,0 +1,54 @@ +Last Login Plugin +================= + +Requires v2.2.14+. This plugin can be used to easily update user's last-login +timestamp in the configured <dictionary> [Dictionary.txt]. Configuration: + +---%<------------------------------------------------------------------------- +protocol imap { + mail_plugins = $mail_plugins last_login +} +protocol pop3 { + mail_plugins = $mail_plugins last_login +} + +plugin { + last_login_dict = redis:host=127.0.0.1:port=6379 + #last_login_key = last-login/%u # default +} +---%<------------------------------------------------------------------------- + +Note that we enable last_login plugin explicitly only for imap & pop3 +protocols. If enabled globally, it'll also update the timestamp whenever new +mails are delivered via lda/lmtp or when doveadm is run for the user. This can +also be thought of as a feature, so if you want to update a different timestamp +for user when new mails are delivered, you can do that by enabling the +last_login plugin also for lda/lmtp and changing the last_login_key setting. + +Example dict config with schema + +---%<------------------------------------------------------------------------- +CREATE TABLE `users` ( + `userid` varchar(255) NOT NULL, + +... + + `last_login` int(11) DEFAULT NULL, + PRIMARY KEY (`userid`) +) +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +map { + pattern = shared/last-login/$user + table = users + value_field = last_login + value_type = uint + + fields { + userid = $user + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Lazyexpunge.txt b/doc/wiki/Plugins.Lazyexpunge.txt new file mode 100644 index 0000000..a85e24a --- /dev/null +++ b/doc/wiki/Plugins.Lazyexpunge.txt @@ -0,0 +1,202 @@ +Lazy expunge +============ + +The idea behind this plugin is that expunged mails and deleted mailboxes stay +around for a while, so that user can undelete them without assistance from +sysadmin. The expunged mails won't be counted in user's quota. The plugin +itself doesn't clean up the expunged messages, you'll have to do it some other +way (see below). + +The plugin is configured by defining namespaces where the mails are moved. You +can decide if you want the namespaces to be visible to clients, or if you want +to show them only via some special webmail interface. + +1 mailbox (v2.2.24+) +-------------------- + +You create a single mailbox. All messages that are expunged from all the +mailboxes are moved there. This is the simplest configuration. The mailbox is +created automatically. You probably also want to hide it with an ACL. + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins lazy_expunge acl +plugin { + lazy_expunge = .EXPUNGED + acl = vfile:/etc/dovecot/dovecot.acl + + # Expunged messages most likely don't want to be included in quota: + quota_rule2 = .EXPUNGED:ignore +} +---%<------------------------------------------------------------------------- + +Where '/etc/dovecot/dovecot.acl' contains: + +---%<------------------------------------------------------------------------- +.EXPUNGED owner rwstipekxa +---%<------------------------------------------------------------------------- + +You could also leave the permissions empty if you don't want to allow clients +to access it at all. + +1 namespace +----------- + +You create only a single namespace. When a message is expunged from mailbox +/<name>/, it's moved to a mailbox /<name>/ in the expunge namespace. When an +entire mailbox /<name>/ is deleted, it's also moved to this namespace as +/<name>/. If it already exists, their contents are merged. + +Example configuration: + +---%<------------------------------------------------------------------------- +# the default namespace +namespace { + prefix = + separator = / + inbox = yes +} + +# namespace for lazy_expunge plugin: +namespace { + prefix = .EXPUNGED/ + hidden = yes + list = no + separator = / + location = maildir:~/Maildir/expunged +} + +mail_plugins = $mail_plugins lazy_expunge +plugin { + lazy_expunge = .EXPUNGED/ +} +---%<------------------------------------------------------------------------- + +3 namespaces (obsolete, v2.0 only) +---------------------------------- + +The namespaces are: + + 1. Expunged messages namespace. Whenever a message is expunged in mailbox + /<name>/, it's moved to a mailbox /<name>/ in this namespace. The mailboxes + are created automatically as needed. + 2. Deleted mailboxes namespace. Whenever a mailbox /<name>/ is deleted, it's + moved here with name /<name>-YYYMMDD-hhmmss/. The timestamp is there so + that the mailbox can be deleted multiple times. If the mailbox is deleted + multiple times within a second, random 16bit hex value is appended to it. + 3. Expunged messages in a deleted mailbox namespace. When a mailbox is deleted + and it has messages in its expunged namespace, the mailbox is moved from + the expunged namespace to this namespace. The destination mailbox name is + the same as in the 2nd namespace (ie. contains the same timestamp). + +Example configuration: + +---%<------------------------------------------------------------------------- +# the default namespace +namespace { + prefix = + separator = / + inbox = yes +} + +# namespaces for lazy_expunge plugin: +namespace { + prefix = .EXPUNGED/ + separator = / + location = maildir:~/Maildir/expunged +} +namespace { + prefix = .DELETED/ + separator = / + location = maildir:~/Maildir/deleted +} +namespace { + prefix = .DELETED/.EXPUNGED/ + separator = / + location = maildir:~/Maildir/deleted/expunged +} + +mail_plugins = $mail_plugins lazy_expunge +plugin { + lazy_expunge = .EXPUNGED/ .DELETED/ .DELETED/.EXPUNGED/ +} +---%<------------------------------------------------------------------------- + +Multi-dbox +---------- + +With multi-dbox use different MAILBOXDIRs (so copying between namespaces works +quickly within the same storage), but otherwise exactly the same paths (index, +control): + +---%<------------------------------------------------------------------------- +# the default namespace +namespace { + prefix = + inbox = yes + location = mdbox:~/mdbox:INDEX=/var/index/%d/%n +} + +# lazy_expunge namespace(s): +namespace { + prefix = .EXPUNGED/ + hidden = yes + list = no + subscriptions = no + + location = mdbox:~/mdbox:INDEX=/var/index/%d/%n:MAILBOXDIR=expunged + # If mailbox_list_index=yes is enabled, it needs a separate index file +(v2.2.28+): + #location = +mdbox:~/mdbox:INDEX=/var/index/%d/%n:MAILBOXDIR=expunged:LISTINDEX=expunged.list.index +} +---%<------------------------------------------------------------------------- + +Copy only the last instance (v2.2+) +----------------------------------- + +If mail has multiple copies (via IMAP COPY), each copy is normally moved to +lazy expunge namespace when it's expunged. With v2.2+ you can set 'plugin { +lazy_expunge_only_last_instance = yes }' to copy only the last instance and +immediately expunge the others. This may be useful if you want to provide a +flat list of all expunged mails without duplicates in your webmail. With many +clients this means that the last instance is always in the Trash mailbox. + +Cleaning up +----------- + +doveadm +------- + +---%<------------------------------------------------------------------------- +doveadm expunge mailbox 'deleted/*' savedsince 1d +---%<------------------------------------------------------------------------- + +cronjob +------- + +Run something like this for each user every night (not actually tested if it +works, and vulnerable to TOCTTOU if the user can place symlinks in any of the +directories find is traversing): + +---%<------------------------------------------------------------------------- +# delete a day old mails +find Maildir/expunged Maildir/deleted Maildir/deleted/expunged \ + -type f ! -cmin 1440 -print0 | xargs -0 rm +---%<------------------------------------------------------------------------- + +Trash plugin +------------ + +<Trash plugin> [Plugins.Trash.txt] with some help from <Quota plugin> +[Quota.txt] could probably be used to keep the expunged and deleted mailboxes +under a specified size (not tested). + +Expire plugin +------------- + +<Expire plugin> [Plugins.Expire.txt] was created to keep track of mails in +specific mailboxes, and expunge them when they've been there for a specified +amount of time. It keeps an internal database (e.g. SQL) of all such mailboxes, +so it doesn't have to go through all the mailboxes for all the users. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Listescape.txt b/doc/wiki/Plugins.Listescape.txt new file mode 100644 index 0000000..514978f --- /dev/null +++ b/doc/wiki/Plugins.Listescape.txt @@ -0,0 +1,64 @@ +Listescape plugin +================= + +The Listescape plugin allows users to use characters in mailboxes names that +would otherwise be illegal (due to the underlying mailbox storage), for +example: + + * Maildir++ layout disallows using the '.' character (unless LAYOUT=fs is + used), since it's used internally as the folder hierarchy separator. + * The '~' character at the beginning of the mailbox name is disallowed, + because of the possibility that it gets expanded to user's home directory. + * The '/' character is disallowed on POSIX systems. + +The Listescape plugin allows you to use all of these characters, as long as the +virtual separator (i.e. what is set by the separator= setting and used as such +by the IMAP protocol) is changed to something else, which means that the plugin +does *not* make it possible to use the virtual separator in folder names. + +The characters are escaped to the mailbox name as \NN hex codes. + +So what would be a good hierarchy separator to use? + + * '.' and '/' are very commonly used and should work everywhere + * '\' is used by Exchange, and should also work everywhere (when specifying + this in the separator= setting it must be quoted, so one sets separator = + "\\") + * '^' is used internally by Thunderbird and causes some trouble with it + * others? + +Examples +-------- + +Allow '.' characters with Maildir++ layout when virtual hierarchy separator is +changed to '/' (it could be anything else except '.' itself): + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins listescape + +namespace private { + separator = / + inbox = yes +} + +plugin { + # The default escape character is '\', but you can change it. + # Note that even here the expansion of % takes place, thus you need to + # use "%%" if you want to have the % sign as the escape character. + #listescape_char = "\\" +} +---%<------------------------------------------------------------------------- + +Allow both '.' and '/' characters when virtual hierarchy separator is changed +to '$'. The '$' has to be quoted to avoid variable expansion.: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins listescape + +namespace private { + separator = "$" + inbox = yes +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.MailCrypt.txt b/doc/wiki/Plugins.MailCrypt.txt new file mode 100644 index 0000000..1cab338 --- /dev/null +++ b/doc/wiki/Plugins.MailCrypt.txt @@ -0,0 +1,522 @@ +mail-crypt-plugin +================= + +Contents + + + 1. mail-crypt-plugin + + 1. Introduction + + 1. Functional Overview + + 2. Encryption Technologies + + 2. Technical Requirements + + 3. Settings for mail crypt plugin + + 4. Modes of operation + + 5. Folder keys + + 1. Unencrypted user keys + + 2. Encrypted user keys + + 6. Global keys + + 1. RSA key + + 2. EC key + + 3. Converting EC key to PKEY + + 4. Base64 encoded keys + + 7. New dcrypt format (mail_crypt_save_version = 2) + + 8. Old dcrypt format (mail_crypt_save_version = 1) + + 9. Read-only mode (mail_crypt_save_version = 0) + + 10. mail-crypt-plugin and ACLs + + 11. decrypting files encrypted with mail-crypt plugin + + 12. fs-crypt and fs-mail-crypt + + 2. doveadm plugin + + 1. doveadm mailbox cryptokey generate + + 2. doveadm mailbox cryptokey list + + 3. doveadm mailbox cryptokey export + + 4. doveadm mailbox cryptokey password + +Introduction +------------ + +The Mail crypt plugin is used to secure email messages stored in a Dovecot +system. Messages are encrypted before written to storage and decrypted after +reading. Both operations are transparent to the user. + +In case of unauthorized access to the storage backend, the messages will, +without access to the decryption keys, be unreadable to the offending party. + +There can be a single encryption key for the whole system or each user can have +a key of their own. The used cryptographical methods are widely usedstandards +and keys are stored in portable formats, when possible. + +Functional Overview +------------------- + +The use of Mail crypt plugin depends on a user having a keypair, a private and +a public key, for asymmetric cryptography. These keys are provisioned in a +variable via the user database or directly from Dovecot configuration files. + +The public half of the provisioned keypairs are used to generate and encrypt +keys for symmetric encryption. The symmetric keys are used to encrypt and +decrypt individual files. Symmetric encryption is faster and more suitable for +block mode storage encryption. The symmetric key used to encrypt a file is +stored, after being encrypted with the public asymmetric key, together with the +file. + +Encryption Technologies +----------------------- + +The Mail crypt plugin provides encryption at rest for emails. Encryption of the +messages is performed using the symmetric Advanced Encryption Standard (AES) +algorithm in Galois/Counter Mode (GCM) with 256 bit keys. Integrity of the data +is ensured using Authenticated Encryption with Associated Data (AEAD) with +SHA256 hashing. The encryption keys for the symmetric encryption are randomly +generated. These keys in turn are encrypted using a key derived with from the +provisioned private key. Provisioned private keys can be Elliptic Curve (EC) +keys or RSA Encryption is done using the Integrated Encryption Scheme (IES). +This algorithm is usable both with EC and RSA keys. + +Technical Requirements +---------------------- + +This feature is available in v2.2.27+. Using per-folder keys is not considered +production quality, but global keys are fine. + +*NB! Improper configuration or use can make your emails unrecoverable. Treat +encryption with care and backups.* + +mail-crypt-plugin encrypts and decrypts mail. The plugin has an older version, +and the extent of this version's backward compatibility is controlled by the +setting *mail_crypt_save_version*. The setting has three valid values, of which +one must be set for the plugin to do anything. The values are 0 and 2. With +*mail_crypt_save_version = 2*, mails are saved in dcrypt version 2 format, and +this is the value that should be used. With *mail_crypt_save_version = 0*, the +plugin does not write encrypted mails, but can still read them. To provide +*mail_crypt_global_private_key* and *mail_crypt_global_public_key* as userdb +attributes, you can base64 encode the original contents, such as PEM file. For +example, + +---%<------------------------------------------------------------------------- +cat ecprivkey.pem | base64 -w0 +---%<------------------------------------------------------------------------- + +Settings for mail crypt plugin +------------------------------ + +These all go into userdb environment or under plugin { } + + * *mail_crypt_save_version* - Save format, 0 = read only, 2 = current version + * *mail_crypt_curve* - EC curve to use for key generation + * *mail_crypt_global_private_key(_n)* - Private key to decrypt files, you can + specify many + * *mail_crypt_global_public_key* - Public key to use to encrypt files, you can + specify one + * *mail_crypt_private_key* - Private key to decrypt user's master key, can be + base64 encoded + * *mail_crypt_private_password* - Password to decrypt user's master key or + environment private key + * *mail_crypt_acl_require_secure_key_sharing* - Require secure key sharing + * *mail_crypt_require_encrypted_user_key* - Require user key encryption with + password + +All external keys must be in PEM format, using pkey format. + +Modes of operation +------------------ + +Mail crypt plugin can operate using *either* global keys *or* folder keys. +Using both is not supported. To perform any +encryption,*mail_crypt_save_version* must be specified and non-zero. + +Folder keys +----------- + +In this mode, the user is generated a key pair, and each folder is generated a +key pair, which is encrypted using the user's key pair. A user can have more +than one key pair but only one can be active. You must use save version 2. You +must also specify *mail_crypt_curve*. Any valid curve supported by underlying +cryptographic library is supported.*mail_attribute_dict* has to be set since it +is used to store the keys. + +Unencrypted user keys +--------------------- + +In this version of the folder keys mode, the users private key is stored +unencrypted on the server. + +Example config for folder keys with Maildir: + +---%<------------------------------------------------------------------------- +mail_attribute_dict = file:%h/Maildir/dovecot-attributes + +mail_plugins = $mail_plugins mail_crypt + +plugin { + mail_crypt_curve = secp521r1 + mail_crypt_save_version = 2 +} +---%<------------------------------------------------------------------------- + +Encrypted user keys +------------------- + +In this version of the folder keys mode, the users private key is stored +encrypted on the server. + +Example config for mandatory encrypted folder keys with Maildir: + +---%<------------------------------------------------------------------------- +mail_attribute_dict = file:%h/Maildir/dovecot-attributes + +mail_plugins = $mail_plugins mail_crypt + +plugin { + mail_crypt_curve = secp521r1 + mail_crypt_save_version = 2 + mail_crypt_require_encrypted_user_key = yes +} +---%<------------------------------------------------------------------------- + +The password that is used to decrypt the users master/private key, must be +provided via password query: + +---%<------------------------------------------------------------------------- +# File: /etc/dovecot/dovecot-sql.conf.ext + +password_query = SELECT \ +email as user, password, \ +'%w' AS userdb_mail_crypt_private_password \ +FROM virtual_users WHERE email='%u'; +---%<------------------------------------------------------------------------- + +Global keys +----------- + +In this mode, all keying material is taken from plugin environment. You can use +either EC keys (recommended) or RSA keys. No key generation is performed. + +RSA key +------- + +Use of RSA keys is discouraged, please use Elliptic Curve keys instead. + +You can generate an unencrypted RSA private key in the pkey format with the +command: + +---%<------------------------------------------------------------------------- +openssl genpkey -algorithm RSA -out rsaprivkey.pem +---%<------------------------------------------------------------------------- + +Alterantively, you can generate a password encrypted private key with: + +---%<------------------------------------------------------------------------- +openssl genpkey -algorithm RSA -out rsaprivkey.pem -aes-128-cbc -pass +pass:qwerty +---%<------------------------------------------------------------------------- + +This does make the password show up in the process listing, so it can be +visible for everyone on the system. + +Regardless of whether you generated an unencrypted or password encrypted +private key, you can generate a public key out of it with: + +---%<------------------------------------------------------------------------- +openssl pkey -in rsaprivkey.pem -pubout -out rsapubkey.pem +---%<------------------------------------------------------------------------- + +These keys can then be used by mail-crypt-plugin with the configuration: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mail_crypt + +plugin { + mail_crypt_global_private_key = <rsaprivkey.pem + mail_crypt_global_private_password = qwerty + mail_crypt_global_public_key = <rsapubkey.pem + mail_crypt_save_version = 2 +} +---%<------------------------------------------------------------------------- + +EC key +------ + +In order to generate an EC key, you must first choose a curve from the outputof +this command: + +---%<------------------------------------------------------------------------- +openssl ecparam -list_curves +---%<------------------------------------------------------------------------- + +If you choose the curve prime256v1, generate and EC key with the command: + +---%<------------------------------------------------------------------------- +openssl ecparam -name prime256v1 -genkey | openssl pkey -out ecprivkey.pem +---%<------------------------------------------------------------------------- + +Then generate a public key out of your private EC key + +---%<------------------------------------------------------------------------- +openssl pkey -in ecprivkey.pem -pubout -out ecpubkey.pem +---%<------------------------------------------------------------------------- + +These keys can now be used with mail-crypt-plugin with the configuration: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mail_crypt + +plugin { + mail_crypt_global_private_key = <ecprivkey.pem + mail_crypt_global_public_key = <ecpubkey.pem + mail_crypt_save_version = 2 +} +---%<------------------------------------------------------------------------- + +Converting EC key to PKEY +------------------------- + +If you have an EC private key which begins with something like: + +---%<------------------------------------------------------------------------- +-----BEGIN EC PRIVATE KEY----- +---%<------------------------------------------------------------------------- + +With possibly parameters like this before that: + +---%<------------------------------------------------------------------------- +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +---%<------------------------------------------------------------------------- + +You must convert it to pkey format with: + +---%<------------------------------------------------------------------------- +openssl pkey -in oldkey.pem -out newkey.pem +---%<------------------------------------------------------------------------- + +Then newkey.pem can be used with mail-crypt-plugin. + +Base64 encoded keys +------------------- + +Mail-crypt plugin can read keys that are base64 encoded. This is intended +mostly for providing PEM keys via userdb. + +Hence, this is possible: + +---%<------------------------------------------------------------------------- +openssl ecparam -name secp256k1 -genkey | openssl pkey | base64 -w0 > +ecprivkey.pem +base64 -d ecprivkey.pem | openssl ec -pubout | base64 -w0 > ecpubkey.pem +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +passdb { + driver = static + args = password=pass mail_crypt_global_public_key=<content of ecpubkey.pem> +mail_crypt_global_private_key=<content of ecprivkey.pem> +} + +mail_plugins = $mail_plugins mail_crypt + +plugin { + mail_crypt_save_version = 2 +} +---%<------------------------------------------------------------------------- + +New dcrypt format (mail_crypt_save_version = 2) +----------------------------------------------- + +The recommended setting of *mail_crypt_save_version* for new installations of +mail-crypt-plugin is 2. + +Old dcrypt format (mail_crypt_save_version = 1) +----------------------------------------------- + +Do not use this. It is supported for legacy reasons only and should not be used +to create new files. It will not work without a global key. + +Read-only mode (mail_crypt_save_version = 0) +-------------------------------------------- + +If you have encrypted mailboxes that you need to read, but no longer want to +encrypt new mail, use *mail_crypt_save_version = 0*: + +---%<------------------------------------------------------------------------- +plugin { + mail_crypt_save_version = 0 + mail_crypt_global_private_key = <server.key +} +---%<------------------------------------------------------------------------- + +mail-crypt-plugin and ACLs +-------------------------- + +If you are using global keys, mails can be shared within the key scope. The +global key can be provided with several different scopes: + + * Global scope (key is configured in dovecot.conf file) + * Per-user(group) scope(key is configured in userdb file) + +With folder keys, key sharing can be done to single user, or multiple users. +When key is shared to single user, and the user has public key available, the +folder key is encrypted to recipient's public key. If you have +*mail_crypt_acl_require_secure_key_sharing* plugin setting, you can't share the +key to groups or someone with no public key. + +decrypting files encrypted with mail-crypt plugin +------------------------------------------------- + +You can use decrypt.rb +[https://gist.github.com/cmouse/882f2e2a60c1e49b7d343f5a6a2721de] to decrypt +encrypted files. + +fs-crypt and fs-mail-crypt +-------------------------- + +The fs-crypt is a lib-fs wrapper that can encrypt and decrypt files. It works +similarly to the fs-compress wrapper. It can be used to encrypt e.g.: + + * FTS index objects (fts_dovecot_fs) + * External mail attachments (mail_attachment_fs) + +fs-crypt comes in two flavors, mail-crypt and crypt. mail-crypt is intended to +be used with user context, while crypt can be used elsewhere. + +Currently the fs-crypt plugin requires that all the files it reads are +encrypted. If it sees an unencrypted file it'll fail to read it. The plan is to +fix this later. + +FS driver syntax: +*crypt:[algo=<s>:][set_prefix=<n>:][private_key_path=/path:][public_key_path=/path:][password=password:]<parent +fs>* where: + + * *algo*: Encryption algorithm. Default is aes-256-gcm-sha256. + * *set_prefix*: Read _public_key and _private_key under this prefix. Default + is "mail_crypt_global". + * *private_key_path*: Path to private key + * *public_key_path*: Path to public key + * *password*: Password for decrypting public key + +Example: + +---%<------------------------------------------------------------------------- +plugin { + fts_index_fs = crypt:set_prefix=fscrypt_index:posix:prefix=/tmp/fts + fscrypt_index_public_key = <server.pub + fscrypt_index_private_key = <server.key +} +---%<------------------------------------------------------------------------- + +To encrypt/decrypt files manually, you can use + +---%<------------------------------------------------------------------------- +doveadm fs get/put crypt +private_key_path=foo:public_key_path=foo2:posix:prefix=/path/to/files/root +path/to/file +---%<------------------------------------------------------------------------- + +doveadm plugin +============== + +Following commands are made available via doveadm. + +doveadm mailbox cryptokey generate +---------------------------------- + +---%<------------------------------------------------------------------------- +doveadm [-o plugin/mail_crypt_private_password=some_password] mailbox cryptokey +generate [-u username | -A] [-Rf] [-U] mailbox-mask [mailbox-mask ...] +---%<------------------------------------------------------------------------- + +Generate new keypair for user or folder. + + * -o - Dovecot option, needed if you use password protected keys + * -u - Username or mask to operate on + * -A - All users + * -R - Re-encrypt all folder keys with current active user key + * -f - Force keypair creation, normally keypair is only created if none found + * -U - Operate on user keypair only + +To generate new active user key and re-encrypt all your keys with it can be +done with + +---%<------------------------------------------------------------------------- +doveadm mailbox cryptokey generate -u username -UR + +This can be used to generate new user keypair and re-encrypt and create folder +keys. +---%<------------------------------------------------------------------------- + +Note that you must provide password if you want to generate password-protected +keypair right away. You can also use doveadm mailbox cryptokey password to +secure it. + +doveadm mailbox cryptokey list +------------------------------ + +---%<------------------------------------------------------------------------- +doveadm mailbox cryptokey list [-u username | -A] [-U] mailbox-mask +[mailbox-mask ...] +---%<------------------------------------------------------------------------- + + * -u - Username or mask to operate on + * -A - All users + * -U - Operate on user keypair only + +Will list all keys for user or mailbox. + +doveadm mailbox cryptokey export +-------------------------------- + +---%<------------------------------------------------------------------------- +doveadm [-o plugin/mail_crypt_private_password=some_password] mailbox cryptokey +export [-u username | -A] [-U] mailbox-mask [mailbox-mask ...] +---%<------------------------------------------------------------------------- + + * -u - Username or mask to operate on + * -A - All users + * -U - Operate on user keypair only + +Exports user or folder private keys. + +doveadm mailbox cryptokey password +---------------------------------- + +---%<------------------------------------------------------------------------- +doveadm mailbox cryptokey password [-u username | -A] [-N | -n password] [-O | +-o password] [-C] +---%<------------------------------------------------------------------------- + + * -u - Username or mask to operate on + * -A - All users + * -N - Ask new password + * -n - New password + * -O - Ask old password + * -o - Old password + * -C - Clear password + +Sets, changes or clears password for user's private key. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.MailFilter.txt b/doc/wiki/Plugins.MailFilter.txt new file mode 100644 index 0000000..5526239 --- /dev/null +++ b/doc/wiki/Plugins.MailFilter.txt @@ -0,0 +1,80 @@ +Mail filter plugin +================== + +Mail filter plugin can be used to filter written and/or read mails via a +script, for example to encrypt/decrypt mails. Currently the filtering must not +modify the message in any way: mail -> write filter -> read filter -> must +produce exactly the original mail back. (TODO: Modifying the mail during +writing would be possible with some code changes.) + +Note that IMAP protocol requires that emails never change, so the read filter +must always produce the same output for the message. If the output changes +you'll probably see some errors about Dovecot's cache file being corrupted and +the IMAP client may also become confused if it has already cached some of the +mail data. + +Configuration +------------- + +Add to 'dovecot.conf': + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mail_filter + +plugin { + # Read filter: + mail_filter = mail-filter %u # %u = username given to the script as first +parameter + # Write filter: + mail_filter_out = mail-filter-out %u +} + +service mail-filter { + executable = script /usr/local/bin/mail-filter.sh + user = dovecot # run unprivileged + unix_listener mail-filter { + # enough permissions to give imap/pop3/etc processes access to this socket + mode = 0600 + user = vmail + } +} +service mail-filter-out { + executable = script /usr/local/bin/mail-filter-out.sh + user = dovecot # run unprivileged + unix_listener mail-filter { + # enough permissions to give imap/pop3/etc processes access to this socket + mode = 0600 + user = vmail + } +} +---%<------------------------------------------------------------------------- + +Example scripts +--------------- + +Here's a minimal example of how gpg could be used to encrypt and decrypt mails. +All the key handling details are left out. + +The mail is read from stdin and written to stdout. Note that the plugin +currently can't handle asynchronously reading+writing data, so the script +cannot write any data to stdout before it has read everything from stdin. This +is most easily done by first saving the stdin to a temporary file. + +'mail-filter.sh': + +---%<------------------------------------------------------------------------- +cat > tempfile +gpg -d tempfile +rm -f tempfile +---%<------------------------------------------------------------------------- + +'mail-filter-out.sh': + +---%<------------------------------------------------------------------------- +USER=$1 +cat > tempfile +gpg -e -r $USER tempfile +rm -f tempfile +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.MailLog.txt b/doc/wiki/Plugins.MailLog.txt new file mode 100644 index 0000000..4ee9eea --- /dev/null +++ b/doc/wiki/Plugins.MailLog.txt @@ -0,0 +1,54 @@ +Mail logger plugin +================== + +This plugin can be used to log several actions done in a mail session: + + * Setting and removing \Deleted flag + * Expunging (includes autoexpunge) + * Copying mails to another mailbox + * Mailbox creations + * Mailbox deletions + * Mailbox renames + * Any flag changes + * Saves + +Messages' UID and Message-ID header is logged for each action. Here's an +example: + +---%<------------------------------------------------------------------------- +imap(user): copy -> Trash: uid=908, msgid=<123.foo@bar> +imap(user): delete: uid=908, msgid=<123.foo@bar> +imap(user): expunged: uid=908, msgid=<123.foo@bar> +---%<------------------------------------------------------------------------- + +You can enable the plugin globally for all services by setting: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mail_log notify +---%<------------------------------------------------------------------------- + +The notify plugin is required for the mail_log plugin's operation, so be +certain it's also enabled. + +Configuration +------------- + +You can configure what and how mail_log plugin logs: + +---%<------------------------------------------------------------------------- +plugin { + # Events to log. Defined in src/plugins/mail-log/mail-log-plugin.c - also +available: flag_change save mailbox_create + # autoexpunge is included in expunge + mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename + + # Also available: Defined in src/plugins/mail-log/mail-log-plugin.c - flags +vsize from subject + mail_log_fields = uid box msgid size + + # Don't log fields that require opening the email (v2.2.28+). + #mail_log_cached_only = yes +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.MailboxAlias.txt b/doc/wiki/Plugins.MailboxAlias.txt new file mode 100644 index 0000000..465c170 --- /dev/null +++ b/doc/wiki/Plugins.MailboxAlias.txt @@ -0,0 +1,46 @@ +Mailbox alias plugin +==================== + +Requires v2.1.10+ (and currently mailbox_list_index=no). This plugin can be +used to configure mailbox aliases, which on the filesystem level are symlinks +to other mailboxes. This doesn't magically solve the problem of showing clients +e.g. multiple Sent mailboxes, but it can be used to make sure that all of the +different variants will have the same mails in them. Unfortunately it also +means that some clients will download the same mails to local cache multiple +times. + +The way it works is that: + + * The aliases won't be visible until the mailbox is CREATEd + * When alias is CREATEd, a symlink is created to the original mailbox. If the + original mailbox didn't exist yet, it's also created. + * If a mailbox with the same name as alias was already created before this + plugin was enabled, its behavior won't change unless it's deleted. + * When alias is DELETEd, the symlink is removed without deleting any of the + mails. + * The original mailbox can't be DELETEd while it still has aliases. + * Mailbox can't be RENAMEd if it's an alias or if it has aliases. + +Example configuration where "Sent" is the real mailbox and it has aliases "Sent +Messages" and "Sent Items": + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mailbox_alias +plugin { + mailbox_alias_old = Sent + mailbox_alias_new = Sent Messages + mailbox_alias_old2 = Sent + mailbox_alias_new2 = Sent Items +} + +# Usually you want the Sent mailbox to be autocreated and advertised as +SPECIAL-USE \Sent: +namespace inbox { + mailbox Sent { + auto = create # or subscribe + special_use = \Sent + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Notify.txt b/doc/wiki/Plugins.Notify.txt new file mode 100644 index 0000000..a0a7ac6 --- /dev/null +++ b/doc/wiki/Plugins.Notify.txt @@ -0,0 +1,9 @@ +Notify plugin +============= + +The notify plugin can be used to easily develop other plugins that need to do +some work when something in user's mailboxes change. See <mail_log> +[Plugins.MailLog.txt] plugin as an example how to develop a plugin based on the +notify plugin. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.NotifyStatus.txt b/doc/wiki/Plugins.NotifyStatus.txt new file mode 100644 index 0000000..2fbce16 --- /dev/null +++ b/doc/wiki/Plugins.NotifyStatus.txt @@ -0,0 +1,69 @@ +notify_status plugin (v2.2.33+) +=============================== + +This plugin updates a dict every time a mailbox changes. The status can contain +total message count and unseen count. It will update key priv/status/<mailbox +name>. See <Dictionary.txt> for how to configure dict. + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins notify notify_status + +plugin { + notify_status_dict = <dict uri> # For example proxy:dict-async:notify_status + + # Value written to dict: + #notify_status_value = {"messages":%%{messages},"unseen":%%{unseen}} + + # By default all mailboxes are added to dict. This can be limited with: + #notify_status_mailbox = INBOX + #notify_status_mailbox2 = pattern2/* + #... +} +---%<------------------------------------------------------------------------- + +If SQL dict is used, you can use this map: + +---%<------------------------------------------------------------------------- +map { + pattern = priv/status/$box + table = mailbox_status + value_field = status + username_field = username + + fields { + mailbox = $box + } +} +---%<------------------------------------------------------------------------- + +The matching SQL schema is: + +---%<------------------------------------------------------------------------- +CREATE TABLE mailbox_status ( + username VARCHAR(255) NOT NULL, + mailbox VARCHAR(255) NOT NULL, + status VARCHAR(255), + PRIMARY KEY (username, mailbox) +); +---%<------------------------------------------------------------------------- + +Supported fields +---------------- + +These fields can be used as %%{variables} in notify_status_value setting: + + * username - Username (user@domain) + * mailbox - name of mailbox + * messages - n. of messages + * unseen - n. unseen message + * recent - n. recent messages (not accurate) + * uidvalidity - current UID validity + * uidnext - predicted next UID value + * first_recent_uid - first recent UID + * highest_modseq - higest modification sequence number + * highest_pvt_modseq - highest private modification sequence number + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.PushNotification.txt b/doc/wiki/Plugins.PushNotification.txt new file mode 100644 index 0000000..ba1e240 --- /dev/null +++ b/doc/wiki/Plugins.PushNotification.txt @@ -0,0 +1,505 @@ +Push Notification Framework +=========================== + +Contents + + + 1. Push Notification Framework + + 1. Introduction + + 2. Usage + + 3. Drivers + + 1. DLOG (Debug log) + + 2. OX (Open-Xchange) driver + + 1. Metadata + + 2. Example Payload + + 3. Lua + + 1. Configuration + + 2. Example script + + 1. Simple example + + 2. Example with event code (v2.3.4+) + + 3. Overview + + 4. Transactions + + 5. Mailbox events + + 6. Message events + +Introduction +------------ + +Dovecot's Push Notification framework exposes RFC 5423 (Internet Message Store +Events) [https://tools.ietf.org/html/rfc5423] events that occur in Dovecot to a +system that can be used to report these events to external services. + +These events are available within the notification framework, although a driver +may not implement all: + + * FlagsClear + * FlagsSet + * MailboxCreate + * MailboxDelete + * MailboxRename + * MailboxSubscribe + * MailboxUnsubscribe + * MessageAppend + * MessageExpunge + * MessageNew + * MessageRead + * MessageTrash + +These events are not supported by the notification framework: + + * Login (handled by <Authentication.txt>) + * Logout (handled by <Authentication.txt>) + * QuotaExceed (handled by <Quota.txt>) + * QuotaWithin (handled by <Quota.txt>) + +Usage +----- + +To use push notifications, both the "notify" and the "push_notification" +plugins need to be activated. For LMTP delivery, this is required: + +---%<------------------------------------------------------------------------- +protocol lmtp { + mail_plugins = $mail_plugins notify push_notification +} +---%<------------------------------------------------------------------------- + +If you also want push notifications to work for LDA-based delivery, you would +need additional configuration: + +---%<------------------------------------------------------------------------- +protocol lda { + mail_plugins = $mail_plugins notify push_notification +} +---%<------------------------------------------------------------------------- + +Drivers +------- + +DLOG (Debug log) +---------------- + +---%<------------------------------------------------------------------------- +plugin { + push_notification_driver = dlog +} +---%<------------------------------------------------------------------------- + +This will cause notifications to end up in your debug log. + +OX (Open-Xchange) driver +------------------------ + + The OX backend supports sending notifications on MessageNew events (i.e. mail +deliveries, not IMAP APPENDs). + +The HTTP end-point (URL + authentication information) to use is configured in +the Dovecot configuration file. The appropriate configuration options will +contain the HTTP URL denoting the end-point to connect to as well as the +authentication information for Basic Authentication as configured by properties +"com.openexchange.rest.services.basic-auth.login" and +"com.openexchange.rest.services.basic-auth.password". The URL to configure in +Dovecot configuration follows this pattern. + +---%<------------------------------------------------------------------------- +<http|https> + "://" + <login> + ":" + <password> + "@" + <host> + ":" + <port> ++ "/preliminary/http-notify/v1/notify" +---%<------------------------------------------------------------------------- + +E.g. + +---%<------------------------------------------------------------------------- +plugin { + push_notification_driver = +ox:url=http://login:pass@node1.domain.tld:8009/preliminary/http-notify/v1/notify +} +---%<------------------------------------------------------------------------- + +For HTTPS endpoints, system CAs are trusted by default, but internal CAs might +need further configuration. + +Furthermore, it is also possible to specify more than one HTTP end-point to +connect to if a new message delivery occurs. Thus the configuration section +mentioned above may be extended by additional "push_notification_driver" +entries; e.g. push_notification_driver2, push_notification_driver3, etc. + +Please note that the path "/preliminary/http-notify/v1/notify" denotes the +internal REST API of the Open-Xchange Middleware, which is not publicly +accessible. The administrator can decide whether to add that path to the Apache +configuration (see alsoAppSuite:Apache_Configuration and AppSuite:Grizzly) +through a Location/ProxyPass directive: + +---%<------------------------------------------------------------------------- +<Location /preliminary> + Order Deny,Allow + Deny from all + # Only allow access from servers within the network. Do not expose this + # location outside of your network. In case you use a load balancing service +in front + # of your Apache infrastructure you should make sure that access to +/preliminary will + # be blocked from the internet / outside clients. Examples: + # Allow from 192.168.0.1 + # Allow from 192.168.1.1 192.168.1.2 + # Allow from 192.168.0. + ProxyPass /preliminary balancer://oxcluster/preliminary +</Location> +---%<------------------------------------------------------------------------- + +In case the "user=" sent by OX in the push_notification_driver url data does +not match the IMAP login of a user, Dovecot ignores it. This can be overridden +by defining "user_from_metadata" in the push_notification_driver url, e.g. + +---%<------------------------------------------------------------------------- +push_notification_driver = ox:url=http://example.com/ user_from_metadata +---%<------------------------------------------------------------------------- + +Metadata +-------- + +The push notifications are enabled separately for each user using METADATA. +Normally <AppSuite.txt> does this internally, but for e.g. testing purposes you +can do this yourself: + +---%<------------------------------------------------------------------------- +doveadm mailbox metadata set -u user@example.com -s "" +/private/vendor/vendor.dovecot/http-notify user=11@3 +---%<------------------------------------------------------------------------- + +Example Payload +--------------- + +See +https://github.com/dovecot/core/blob/master/src/plugins/push-notification/push-notification-driver-ox.c. + +Push notification sent in JSON format with the following fields: + + * *user*: User identifier (string) + * *event*: RFC 5423 event type (string; currently only "'MessageNew'") + * *folder*: Mailbox name (string) + * *imap-uidvalidity*: RFC 3501 UIDVALIDITY value of the mailbox (integer) + * *imap-uid*: UID of the message, if applicable (integer) + * *from*: RFC 2822 address of the message sender, if applicable (string) + * *subject*: Subject of the message, if applicable (string) + * *snippet*: Snippet of the message body, if applicable (string) + * *unseen*: RFC 3501 UNSEEN value of the mailbox (integer) + +---%<------------------------------------------------------------------------- +Content-Type: application/json; charset=utf-8 + +{ + "user": "4@464646669", + "imap-uidvalidity": 123412341, + "imap-uid": 2345, + "folder": "INBOX", + "event": "MessageNew", + "from": "alice@barfoo.org", + "subject": "Test", + "snippet": "Hey guys\nThis is only a test...", + "unseen": 2 +} +---%<------------------------------------------------------------------------- + +Lua +--- + +Since v2.3.4+ you can use Lua to write custom push notification handlers. See +<Design.Lua.txt> for general information about Lua in Dovecot. If you have +mail_lua_script (a global script for storage) it will be used if no script is +specified. + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins mail_lua notify push_notification +push_notification_lua + +plugin { + push_notification_driver = lua:file=/path/to/lua/script + # you can omit the script name if you want to use mail_lua_script script +instead + #mail_lua_script=/path/to/common/script.lua +} +---%<------------------------------------------------------------------------- + +Example script +-------------- + +Simple example +-------------- + +---CodeArea------------------------------------------------------------------- +-- To use 1 +-- 2 +-- plugin { 3 +-- push_notification_driver = lua:file=/home/cmouse/empty.lua 4 +-- push_lua_url = http://push.notification.server/handler 5 +-- } 6 +-- 7 +-- server is sent a POST message to given url with parameters 8 +-- 9 + 10 +local http = require("socket.http") 11 +local url = require("socket.url") 12 + 13 +function table_get(t, k, d) 14 + return t[k] or d 15 +end 16 + 17 +function dovecot_lua_notify_begin_txn(user) 18 + return {messages={}, ep=user:plugin_getenv("push_lua_url"), +username=user.username} 19 +end 20 + 21 +function dovecot_lua_notify_end_txn(ctx, success) 22 + local i, msg = next(ctx["messages"], nil) 23 + while i do 24 + local r, c = http.request(ctx["ep"], "from=" .. url.escape(table_get(msg, +"from", "")) .. "&to=" .. url.escape(table_get(msg, "to", "")) .. "&subject=" +..url.escape(table_get(msg, "subject", "")) .. "&snippet=" .. +url.escape(table_get(msg, "snippet", "")) .. "&user=" .. +url.escape(ctx["username"])) 25 + if r and c/100 ~= 2 then 26 + dovecot.i_error("lua-push: Remote error " .. tostring(c) .. " handling +push notication") 27 + end 28 + if r == nil then 29 + dovecot.i_error("lua-push: " .. c) 30 + end 31 + i, msg = next(ctx["messages"], i) 32 + end 33 +end 34 + 35 +function dovecot_lua_notify_event_message_append(ctx, event) 36 + table.insert(ctx["messages"], event) 37 +end 38 + 39 +function dovecot_lua_notify_event_message_new(ctx, event) 40 + table.insert(ctx["messages"], event) 41 +end 42 +---CodeArea------------------------------------------------------------------- + +Example with event code (v2.3.4+) +--------------------------------- + +---CodeArea------------------------------------------------------------------- +-- To use 1 +-- 2 +-- plugin { 3 +-- push_notification_driver = lua:file=/home/cmouse/empty.lua 4 +-- push_lua_url = http://push.notification.server/handler 5 +-- } 6 +-- 7 +-- server is sent a POST message to given url with parameters 8 +-- 9 + 10 +local http = require "socket.http" 11 +local ltn12 = require "ltn12" 12 +local url = require "socket.url" 13 + 14 +function table_get(t, k, d) 15 + return t[k] or d 16 +end 17 + 18 +function script_init() 19 + return 0 20 +end 21 + 22 +function dovecot_lua_notify_begin_txn(user) 23 + return {user=user, event=dovecot.event(), +ep=user:plugin_getenv("push_lua_url"), states={}, messages={}} 24 +end 25 + 26 +function dovecot_lua_notify_event_message_new(ctx, event) 27 + -- get mailbox status 28 + local mbox = ctx.user:mailbox(event.mailbox) 29 + mbox:sync() 30 + local status = mbox:status(dovecot.storage.STATUS_RECENT, +dovecot.storage.STATUS_UNSEEN, dovecot.storage.STATUS_MESSAGES) 31 + mbox:free() 32 + ctx.states[event.mailbox] = status 33 + table.insert(ctx.messages, +{from=event.from,subject=event.subject,mailbox=event.mailbox}) 34 +end 35 + 36 +function dovecot_lua_notify_event_message_append(ctx, event, user) 37 + dovecot_lua_notify_event_message_new(ctx, event, user) 38 +end 39 + 40 +function dovecot_lua_notify_end_txn(ctx) 41 + -- report all states 42 + for i,msg in ipairs(ctx.messages) do 43 + local e = dovecot.event(ctx.event) 44 + e:set_name("lua_notify_mail_finished") 45 + reqbody = "mailbox=" .. url.escape(msg.mailbox) .. "&from=" .. +url.escape(table_get(msg, "from", "")) .. "&subject=" .. +url.escape(table_get(msg, "subject", "")) 46 + e:log_debug(ctx.ep .. " - sending " .. reqbody) 47 + res, code = http.request({method="POST", 48 + url=ctx.ep, 49 + source=ltn12.source.string(reqbody), 50 + headers={ 51 + ["content-type"] = "application/x-www-form-url.escaped", +52 + ["content-length"] = tostring(#reqbody) 53 + } 54 + }) 55 + e:add_int("result_code", code) 56 + e:log_info("Mail notify status " .. tostring(code)) 57 + end 58 + for box,state in pairs(ctx.states) do 59 + local e = dovecot.event() 60 + e:set_name("lua_notify_mailbox_finished") 61 + reqbody = "mailbox=" .. url.escape(state.mailbox) .. "&recent=" .. +tostring(state.recent) .. "&unseen=" .. tostring(state.unseen) .. "&messages=" +.. tostring(state.messages) 62 + e:log_debug(ctx.ep .. " - sending " .. reqbody) 63 + res, code = http.request({method="POST", 64 + url=ctx.ep, 65 + source=ltn12.source.string(reqbody), 66 + headers={ 67 + ["content-type"] = "application/x-www-form-url.escaped", +68 + ["content-length"] = tostring(#reqbody) 69 + } 70 + }) 71 + e:add_int("result_code", code) 72 + e:log_info("Mailbox notify status " .. tostring(code)) 73 + end 74 +end 75 +---CodeArea------------------------------------------------------------------- + +Overview +-------- + +The Lua driver hooks into all events, and calls matching functions when found +in Lua script. + +Currently it supports + + * mailbox create, delete, rename, subscribe and unsubscribe + * message new, append, expunge, read and trash, flags set, flags clear + +All events are called within a transaction. The event is called with context +and an event table, which contains the event parameters.All events contain at +least + + * name - name of the event + * user - current mail user + +Events are always called after the fact. + +There has to be at least one event handler, or the transaction begin and end +functions are never called.This is optimization to avoid roundtrip to Lua when +it's not needed. + +Transactions +------------ + + * dovecot_lua_notify_begin_txn(user) + +Start transaction. Return value is used as transaction context and is treated +as opaque value by Lua driver. The user parameter is mail_user object. + + * dovecot_lua_notify_end_txn(context, success) + +End transaction, context is unreferenced. + +Mailbox events +-------------- + +All mailbox events contain 'mailbox' parameter, which is the name of the +affected mailbox. + + * dovecot_lua_notify_event_mailbox_create(context, {name, mailbox}) + +Called when mailbox has been created. + + * dovecot_lua_notify_event_mailbox_delete(context, {name, mailbox}) + +Called when mailbox has been deleted. + + * dovecot_lua_notify_event_mailbox_rename(context, {name, mailbox, + mailbox_old}) + +Called when mailbox has been renamed, old name is retained in mailbox_old +attribute. + + * dovecot_lua_notify_event_mailbox_subscribe(context, {name, mailbox}) + +Called when mailbox has been subscribed to. The mailbox does not necessarily +exist. + + * dovecot_lua_notify_event_mailbox_unsubscribe(context, {name, mailbox}) + +Called when mailbox has been unsubscribed from. The mailbox does not +necessarily exist. + +Message events +-------------- + +All message events contain following parameters ++--------------+----------------------+ +| mailbox | Mailbox name | ++--------------+----------------------+ +| uid | Message UID | ++--------------+----------------------+ +| uid_validity | Mailbox UID validity | ++--------------+----------------------+ + + * dovecot_lua_notify_event_message_new(context, {name, mailbox, uid, + uid_validity, date, tz, from, to, subject, snippet}) + +Called when message is delivered. + + * dovecot_lua_notify_event_message_append(context, {name, mailbox, uid, + uid_validity, from, to, subject, snippet}) + +Called when message is APPENDed to a mailbox. + + * dovecot_lua_notify_event_message_read(context, {name, mailbox, uid, + uid_validity}) + +Called when message is marked as Seen. + + * dovecot_lua_notify_event_message_trash(context, {name, mailbox, uid, + uid_validity}) + +Called when message is marked Deleted. + + * dovecot_lua_notify_event_message_expunge(context, {name, mailbox, uid, + uid_validity}) + +Called when message is EXPUNGEd. + + * dovecot_lua_notify_event_flags_set(context, {name, mailbox, uid, + uid_validity, flags, keywords_set}) + +Called when message flags or keywords are set. flags is a bitmask. keywords_set +is a table of strings of the keywords set by the event. + + * dovecot_lua_notify_event_flags_clear(context, {name, mailbox, uid, + uid_validity, flags, keywords_clear, keywords_old}) + +Called when message flags or keywords are removed. flags is a bitmask. +keywords_clear contains the keywords cleared, keywords_old is the table of +keywords that were set before the event. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.QuotaClone.txt b/doc/wiki/Plugins.QuotaClone.txt new file mode 100644 index 0000000..56325f7 --- /dev/null +++ b/doc/wiki/Plugins.QuotaClone.txt @@ -0,0 +1,37 @@ +Quota Clone Plugin +================== + +(Requires v2.2.17+) + +Quota clone plugin is useful when you want to store everybody's current quota +usage to a database, but you don't want to use the database as the +authoritative quota database. For example you might want to access everybody's +quota via Redis (or with SQL database, Redis is example here), but you don't +store the Redis database permanently so it could become empty once in a while. +In this case you can use e.g. <dict-file> [Quota.Dict.txt] or <count> +[Quota.Count.txt] as the authoritative quota database and make a copy of the +quota usage to Redis. From Redis you could then once in a while gather +everybody's current quota usage and send it to yet another place (e.g. for +statistics handling). + +Every time quota is updated, the value is updated to the cloned dict. There are +race conditions with it so the quota may not always be 100% correct. The old +value is always replaced with the new one though (not just +incremented/decremented) so the cloned quota is never too much wrong. + +The keys that are written to: + + * priv/quota/storage - storage usage in bytes + * priv/quota/messages - count of messages + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins quota quota_clone +plugin { + quota_clone_dict = redis:host=127.0.0.1:port=6379 +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Snarf.txt b/doc/wiki/Plugins.Snarf.txt new file mode 100644 index 0000000..a53e9ba --- /dev/null +++ b/doc/wiki/Plugins.Snarf.txt @@ -0,0 +1,63 @@ +Snarf Plugin +============ + +Requires v2.0.8+. + +This plugin can be used to move mails from a "snarf mailbox" to user's real +INBOX. For example from '/var/mail/user' mbox file to user's final INBOX (e.g. +'~/mbox' or '~/Maildir'). Dovecot moves as many messages as it can until it +runs out of messages or out of quota. + +Configuration +------------- + +You need a default and a snarf namespace, for example: + +---%<------------------------------------------------------------------------- +#mail_location = mbox:~/mail/:INBOX=~/mbox +#mail_location = maildir:~/Maildir + +namespace default { + prefix = + separator = / + inbox = yes +} +namespace snarf { + prefix = /snarf + separator = / + location = mbox:/var/run/dovecot/empty:INBOX=/var/mail/%u:INDEX=MEMORY + list = no + hidden = yes +} +---%<------------------------------------------------------------------------- + +Then tell snarf to get the mails from '/snarf/INBOX': + +---%<------------------------------------------------------------------------- +plugin { + snarf = /snarf/INBOX +} +---%<------------------------------------------------------------------------- + +Use hierarchy separator as the first character in snarf namespace prefix to +make sure that there won't be any conflicts with user's mailbox names. + +UW-IMAP style optional snarfing +------------------------------- + +UW-IMAP does snarfing from '/var/mail/user' to '~/mbox' file, but only if +'~/mbox' exists. Normally Dovecot does the snarfing always if it's enabled. To +enable it only optionally, set also: + +---%<------------------------------------------------------------------------- +# keep mail_location etc. settings as above + +plugin { + mbox_snarf = ~/mbox +} +---%<------------------------------------------------------------------------- + +Now the snarfing is done only if '~/mbox' file exists. If it's not, the +'/var/mail/user' is used directly as the INBOX. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Stats.txt b/doc/wiki/Plugins.Stats.txt new file mode 100644 index 0000000..b9f67ad --- /dev/null +++ b/doc/wiki/Plugins.Stats.txt @@ -0,0 +1,2 @@ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Trash.txt b/doc/wiki/Plugins.Trash.txt new file mode 100644 index 0000000..a37905d --- /dev/null +++ b/doc/wiki/Plugins.Trash.txt @@ -0,0 +1,41 @@ +Trash Plugin +============ + +This requires <quota plugin> [Quota.txt] to be loaded and configured to use +non- <FS quota> [Quota.FS.txt]. + +Normally if a message can't be saved/copied because it would bring user over +quota, the save/copy fails with "Quota exceeded" error. The trash plugin can be +used to avoid such situations by making Dovecot automatically expunge oldest +messages from configured mailboxes until the message can be saved. If the new +message is large enough that it wouldn't fit even if all messages from +configured mailboxes were expunged, then none are and user gets the "Quota +exceeded" error. + +The configuration file is a text file where each line is in format: '<priority> +<mailbox name>'. Mails are deleted in lowest -> highest priority number order. + +dovecot.conf: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins quota trash + +plugin { + trash = /etc/dovecot/dovecot-trash.conf.ext +} +---%<------------------------------------------------------------------------- + +dovecot-trash.conf.ext: + +---%<------------------------------------------------------------------------- +# Spam mailbox is emptied before Trash +1 Spam +# Trash mailbox is emptied before Sent +2 Trash +# If both Sent and "Sent Messages" mailboxes exist, the next oldest message +# to be deleted is looked up from both of the mailboxes. +3 Sent +3 Sent Messages +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.VarExpandCrypt.txt b/doc/wiki/Plugins.VarExpandCrypt.txt new file mode 100644 index 0000000..4bf43d9 --- /dev/null +++ b/doc/wiki/Plugins.VarExpandCrypt.txt @@ -0,0 +1,45 @@ +var_expand_crypt plugin +======================= + +This plugins provides generic encrypt/decrypt facility for var_expand. It +requires functional lib-dcrypt backend. For dovecot-auth process this plugin is +automatically usable. + +Syntax +------ + +---%<------------------------------------------------------------------------- +args=encrypted_value=%{encrypt;key=value,iv=value,noiv=yes,algo=algorithm,format=base64|hex:field} +args=decrypted_value=%{decrypt;key=value,iv=value,noiv=yes,algo=algorithm,format=base64|hex:field} +---%<------------------------------------------------------------------------- + + * key - hex-encoded value + * iv - hex-encoded value + * noiv - whether iv is included in return value + * algo - algorithm name (defaults to aes-256-cbc) + * format - return format + +decrypt expects input in base64 or hex format. + +NOTE: It is usually best to leave iv management to dovecot, and not use iv and +noiv options at all. + +Return formats +-------------- + +Without noiv encrypt returns iv$encrypted$. With noiv, just encrypted data is +returned. Field(s) are encoded using format. + +key and iv must be the length required by the given algorithm. + +Example +------- + +---%<------------------------------------------------------------------------- +%{encrypt;key=f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8:password} += 93736a0f910df27f89210e096e1d639a$966c2b4f3e7487f6acdb836f8d1dc3e0$ +%{decrypt;key=f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8f1f2f3f4f5f6f7f8:encrypted} += pass +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Virtual.txt b/doc/wiki/Plugins.Virtual.txt new file mode 100644 index 0000000..67f5e06 --- /dev/null +++ b/doc/wiki/Plugins.Virtual.txt @@ -0,0 +1,284 @@ +Virtual mailboxes +================= + +First, you'll have to load the plugin: + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins virtual +---%<------------------------------------------------------------------------- + +Namespace configuration +----------------------- + +Then, you'll have to create a <namespace> [Namespaces.txt] for the virtual +mailboxes, for example: + +---%<------------------------------------------------------------------------- +namespace { + prefix = virtual/ + separator = / + location = virtual:~/Maildir/virtual +} +---%<------------------------------------------------------------------------- + +After this you can create virtual mailboxes under '~/Maildir/virtual'. By +default it uses the "fs" layout, so you can create directories such as: + + * INBOX: '~/Maildir/virtual/INBOX/' + * Sub/mailbox: '~/Maildir/virtual/Sub/mailbox/' + +If you prefer to use Maildir++ layout instead, you can simply append +':LAYOUT=maildir++' to the location. + +Virtual mailbox configuration +----------------------------- + +For each virtual directory you need to create a 'dovecot-virtual' file. Its +syntax is like: + +---%<------------------------------------------------------------------------- +<1+ mailbox patterns> + <search program> +[<more mailbox patterns> + <search program for these mailboxes> +[etc..]] +---%<------------------------------------------------------------------------- + +Mailbox patterns can contain IMAP LIST-compatible +[http://tools.ietf.org/html/rfc3501#section-6.3.8] "*" and "%" wildcards. They +are currently evaluated only when the virtual mailbox is being selected, so if +more mailboxes are created during that they aren't noticed. + +"*" wildcard matches only one namespace at a time based on the namespace +prefix. For example if you have namespaces with an empty prefix and a prefix +"mail/": + + * '*' matches only mailboxes from the namespace with empty prefix + * 'mail*' matches mailboxes beginning with name "mail" from the namespace with + empty prefix + * 'mail/*' matches only mailboxes from the mail/ namespace + +Beware that "*" will not match any mailbox which already has a more specialised +match! + +The mailbox names have special prefixes: + + * '-': Don't include this mailbox. + * '+': Drop \Recent flags from the backend mailbox when opening it. + * '!': Save new mails to this mailbox (see below). + +If you need to actually include a mailbox name that contains such prefix, you +can currently just kludge it by using '+' prefix (if you don't care about the +\Recent flags) and adding the mailbox name after that (e.g. "+-box"). + +Search program is compatible with IMAP SEARCH command +[http://tools.ietf.org/html/rfc3501#section-6.4.4]. Besides the standard SEARCH +key you may want to use X-MAILBOX key which matches the message's original +mailbox. Note the leading whitespace in front of search specifications. + +Saving mails to virtual mailboxes +--------------------------------- + +It's possible to configure virtual mailbox so that it's possible to save/copy +messages there. This is done by specifying a single physical mailbox where the +message is really saved by prefixing it with '!', e.g.: + +---%<------------------------------------------------------------------------- +!INBOX +work/* + unseen +---%<------------------------------------------------------------------------- + +Note however that nothing guarantees that the saved mail will actually show up +in the virtual mailbox. If a message was saved with \Seen flag to the above +virtual mailbox, it wouldn't show up there. This also means it's problematic to +support IMAP UIDPLUS extension for virtual mailboxes, and currently Dovecot +doesn't even try (no [APPENDUID] or [COPYUID] is sent to client). + +The !-prefixed virtual mailbox is also selected from; you don't need to list it +again without an ! or you'll get two copies of your messages in the virtual +mailbox. + +Sieve filters with virtual mailboxes +------------------------------------ + +Using the sieve plugin with virtual mailboxes will cause dovecot to output a +fatal exception error in it's logs and crash. This is because sieve can't tell +the difference between a virtual location and a maildir/mbox location due to +the way it detects actions in the mailboxes. + +If you use virtual mailboxes that are configured in sieve, make sure that they +point to the namespace which has a maildir/mbox location and a unique prefix. +If you don't, sieve will crash trying to copy a message to a virtual mailbox. + +Mailbox selection base on metadata (v2.2.22+) +--------------------------------------------- + +Instead of a mailbox name, you can specify a metadata filter: + +---%<------------------------------------------------------------------------- +[-]/<metadata-entry-name>:<value-wildcard> +---%<------------------------------------------------------------------------- + +There can be multiple metadata entries. All the entries must match. + +For example: + +---%<------------------------------------------------------------------------- +* +/private/vendor/vendor.dovecot/virtual:* +-/private/vendor/vendor.dovecot/virtual:ignore + all +---%<------------------------------------------------------------------------- + +This matches all mailboxes, which contain a virtual METADATA entry that has any +value except "ignore". + +Examples +-------- + + * List all messages with \Deleted flag in all mailboxes: + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/Trash/dovecot-virtual +* + deleted +---%<------------------------------------------------------------------------- + + * List all unseen INBOX and work/* messages: + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/unseen/dovecot-virtual +INBOX +work/* + unseen +---%<------------------------------------------------------------------------- + + * Create a GMail-style "conversation view" for INBOX which shows all threads + that have messages in INBOX, but shows all messages in the thread regardless + of in what mailbox they physically exist in: + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/all/dovecot-virtual +* + all +---%<------------------------------------------------------------------------- + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/INBOX/dovecot-virtual +virtual/all + inthread refs x-mailbox INBOX +---%<------------------------------------------------------------------------- + + * Create a mailbox containing messages from all mailboxes except Trash and its + children: + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/all/dovecot-virtual +* +-Trash +-Trash/* + all +---%<------------------------------------------------------------------------- + + * Create a virtual Sentmail folder that includes Sent*: + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/Sentmail/dovecot-virtual +Sent* + all +---%<------------------------------------------------------------------------- + + * List messages from past 48 hours (syntax is in seconds): + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/recent/dovecot-virtual +INBOX +work/* + all younger 172800 +---%<------------------------------------------------------------------------- + + * List unseen messages from foo and flagged messages from all mailboxes + (including foo): + +---%<------------------------------------------------------------------------- +# ~/Maildir/virtual/example/dovecot-virtual +foo + or unseen flagged +* + flagged +---%<------------------------------------------------------------------------- + +Virtual POP3 INBOX +------------------ + +If you want POP3 INBOX to contain some or all mailboxes, you can do this in the +following way: + +Namespace configuration: + +---%<------------------------------------------------------------------------- +# The default namespace that is visible to IMAP clients +namespace inbox { + prefix = + separator = / + list = yes +} + +# Virtual namespace for the virtual INBOX. Use a global directory for +dovecot-virtual files. +namespace virtual { + prefix = virtual/ + separator = / + location = virtual:/etc/dovecot/virtual:INDEX=~/Maildir/virtual + list = no + hidden = yes +} + +# Copy of the inbox namespace. We'll use this in dovecot-virtual file. +namespace real { + prefix = RealMails/ + separator = / + list = no + hidden = yes +} +---%<------------------------------------------------------------------------- + +Note that none of the namespaces have inbox=yes. This is because for IMAP users +you want the inbox namespace to have inbox=yes, but for POP3 users you want the +virtual namespace to have inbox=yes. This requires setting the inbox=yes in +<userdb extra fields> [UserDatabase.ExtraFields.txt]. For example with MySQL +you can can do this like: + +---%<------------------------------------------------------------------------- +user_query = SELECT ..., \ + CASE '%s' WHEN 'pop3' THEN NULL ELSE 'yes' END AS 'namespace/inbox/inbox', \ + CASE '%s' WHEN 'pop3' THEN 'yes' ELSE NULL END AS 'namespace/virtual/inbox' \ + WHERE ... +---%<------------------------------------------------------------------------- + +Finally specify what the virtual INBOX looks like for POP3 users: + +'/etc/dovecot/virtual/INBOX/dovecot-virtual' : + +---%<------------------------------------------------------------------------- +RealMails +RealMails/* +-RealMails/Trash +-RealMails/Trash/* +-RealMails/Spam + all +---%<------------------------------------------------------------------------- + +You'll have to use the RealMails/ prefix if you want to use "*" wildcard, +otherwise it would match INBOX, which in turn would again lead to the virtual +INBOX and that would create a loop. + +Also to avoid accidental POP3 UIDL changes, you shouldn't base the UIDLs on +IMAP UIDs. Instead use for GUIDs (with maildir the same as base filename): + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %g +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Welcome.txt b/doc/wiki/Plugins.Welcome.txt new file mode 100644 index 0000000..e5da2f6 --- /dev/null +++ b/doc/wiki/Plugins.Welcome.txt @@ -0,0 +1,27 @@ +Welcome plugin +============== + +Requires v2.2.25+. Call a script when the user logs in for the first time. This +is specifically done when the INBOX is (auto)created. The scripts are called +similarly to <quota warning scripts> [Quota.Configuration.txt]. + +---%<------------------------------------------------------------------------- +plugin { + welcome_script = welcome %u + # By default we run the script asynchronously, but with this option we + # wait for the script to finish. + #welcome_wait = yes +} + +service welcome { + executable = script /usr/local/bin/welcome.sh + user = dovecot + unix_listener welcome { + user = vmail + } +} + +mail_plugins = $mail_plugins welcome +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.Zlib.txt b/doc/wiki/Plugins.Zlib.txt new file mode 100644 index 0000000..9b38af2 --- /dev/null +++ b/doc/wiki/Plugins.Zlib.txt @@ -0,0 +1,100 @@ +Zlib plugin +=========== + +Zlib plugin can be used to read compressed mbox, maildir or dbox files. It can +be also used to write(via IMAP, <LDA.txt> and/or <LMTP.txt>) compressed +messages to <dbox> [MailboxFormat.dbox.txt] or Maildir mailboxes. Zlib plugin +supports compression using zlib/gzip, bzlib/bzip2, liblzma/xz (v2.2.9+) and +liblz4/lz4 (v2.2.11+). + +Configuration: + +---%<------------------------------------------------------------------------- +# Enable zlib plugin globally for reading/writing: +mail_plugins = $mail_plugins zlib + +# Enable these only if you want compression while saving: +plugin { + zlib_save_level = 6 # 1..9; default is 6 + zlib_save = gz # or bz2, xz or lz4 +} +---%<------------------------------------------------------------------------- + +mbox +---- + +Compressed mbox files can be accessed only as read-only. The compression is +detected based on the file name, so your compressed mboxes should end with .gz +or .bz2 extension. There is no support for compression during saving. + +dbox +---- + +Mails can be stored as compressed. Existing uncompressed mails can't currently +be directly compressed (or vice versa). You could, however, use <dsync> +[Tools.Dsync.txt] to copy all mails to another location (which saves them +compressed) and then replace the original location with the new compressed +location. You can do this by treating the operation the same as if you were +migrating from one mailbox format to another (see the dsync page examples). + +Maildir +------- + +When this plugin is loaded Dovecot can read both compressed and uncompressed +files from Maildir. If you've enabled both gzip and bzip2 support you can have +files compressed with either one of them in the Maildir. The compression is +detected by reading the first few bytes from the file and figuring out if it's +a valid gzip or bzip2 header. The file name doesn't matter. This means that an +IMAP client could also try to exploit security holes in zlib/bzlib by writing +specially crafted mails using IMAP's APPEND command. This is prevented by +Dovecot not allowing clients to save mails that are detected as compressed. + +All mails must have ',S=<size>' in their filename where <size> contains the +original uncompressed mail size, otherwise there will be problems with quota +calculation as well as other potential random failures. Note that if the +filename doesn't contain the ',S=<size>' before compression, adding it +afterwards changes the base filename and thus the message UID. The safest thing +to do is simply to not compress such files. + +You should also preserve the file's mtime so INTERNALDATE doesn't change. + +If you want to use dsync to convert to a compressed Maildir you may need -o +maildir_copy_with_hardlinks=no (this is set to yes by default and will prevent +compression). + +Compression +----------- + +You'll probably want to use some cronjob to compress old mails. However note +that to avoid seeing duplicate mails in rare race conditions you'll have to use +the included maildirlock utility. The idea is to: + + 1. Find the mails you want to compress in a single maildir. + * Skip files that don't have ',S=<size>' in the filename. + 2. Compress the mails to 'tmp/' + * Update the compressed files' mtimes to be the same as they were in the + original files (e.g. touch command) + 3. Run 'maildirlock <path> <timeout>'. It writes PID to stdout, save it. + * <path> is path to the directory containing Maildir's dovecot-uidlist + (the control directory, if it's separate) + * <timeout> specifies how long to wait for the lock before failing. + 4. If maildirlock grabbed the lock successfully (exit code 0) you can + continue. + 5. For each mail you compressed: + 1. Verify that it still exists where you last saw it. + 2. If it doesn't exist, delete the compressed file. Its flags may have + been changed or it may have been expunged. This happens rarely, so just + let the next run handle it. + 3. If the file does exist, 'rename()' (mv) the compressed file over the + original file. + * Dovecot can now read the file, but to avoid compressing it again on + the next run, you'll probably want to rename it again to include + e.g. a "Z" flag in the file name to mark that it was compressed + (e.g.'1223212411.M907959P17184.host,S=3271:2,SZ'). Remember that the + Maildir specifications [http://cr.yp.to/proto/maildir.html] require + that the flags are sorted by their ASCII value, although Dovecot + itself doesn't care about that. + 6. Unlock the maildir by sending a TERM signal to the maildirlock process + (killing the PID it wrote to stdout). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Plugins.txt b/doc/wiki/Plugins.txt new file mode 100644 index 0000000..efdac36 --- /dev/null +++ b/doc/wiki/Plugins.txt @@ -0,0 +1,102 @@ +Plugins +======= + +Distributed with Dovecot: + + * <acl> [ACL.txt]: Access Control Lists for mailboxes + * <apparmor> [Plugins.Apparmor.txt]: Apparmor support plugin + * <autocreate> [Plugins.Autocreate.txt]: Automatically create/subscribe + mailboxes when user logs in + * <expire> [Plugins.Expire.txt]: Delete mails from specified mailboxes after a + designated number of days + * <fts> [Plugins.FTS.txt]: Full text search indexing + * <last_login> [Plugins.LastLogin.txt]: Last-login timestamp updating + * <lazy_expunge> [Plugins.Lazyexpunge.txt]: Make EXPUNGE and DELETE commands + just rename the mails elsewhere + * <listescape> [Plugins.Listescape.txt]: Allow using characters in mailbox + names that would otherwise be illegal + * <mailbox_alias> [Plugins.MailboxAlias.txt]: Map multiple names to the same + mailbox. + * <mail_filter> [Plugins.MailFilter.txt]: Filter mails while reading/writing + through a script + * <mail_log> [Plugins.MailLog.txt]: Log several mail actions + * <notify> [Plugins.Notify.txt]: Wrapper plugin for easily developing other + plugins that act on mailbox changes. + * <notify_status> [Plugins.NotifyStatus.txt]: Plugin for notify that pushes + mailbox status to dict on change + * <push_notification> [Plugins.PushNotification.txt]: Push notification + framework + * <push_notification_driver_ox> [Plugins.PushNotification.txt]: + Open-Xchange driver for push notification + * <push_notification_driver_dlog> [Plugins.PushNotification.txt]: dlog + driver for push notification + * <snarf> [Plugins.Snarf.txt]: UW-IMAP style (mbox) snarfing, i.e. keeps + moving all mails from one mailbox to INBOX + * <quota> [Quota.txt]: Quota tracking and enforcing + * imap_quota: IMAP commands for requesting current quota + * <quota_clone> [Plugins.QuotaClone.txt]: Copy the current quota usage to a + dict. + * <stats> [Plugins.Stats.txt]: Send statistics from mail processes to the + stats process + * <trash> [Plugins.Trash.txt]: Delete mails from Trash when user would go over + quota + * <virtual> [Plugins.Virtual.txt]: Virtual mailboxes + * <welcome> [Plugins.Welcome.txt]: Call a script on user's first login. + * <zlib> [Plugins.Zlib.txt]: Access compressed mails + * <imap_zlib> [Plugins.Compress.txt]: Enable IMAP COMPRESS + [http://www.ietf.org/rfc/rfc4978.txt] extension + * <mail_crypt> [Plugins.MailCrypt.txt]: In-rest mail encryption + * <var_expand_crypt> [Plugins.VarExpandCrypt.txt]: Variable + encryption/decryption + +External: + + * <antispam> [Plugins.Antispam.txt]: Integrates spam learning into Dovecot + * drac [http://sourceforge.jp/projects/dovecot2-drac/]: Pop-before-SMTP plugin + using DRAC + * whoson [http://ftp.ufanet.ru/pub/boco/dovecot/whoson-plugin-2/]: + Pop-before-SMTP plugin using WHOSON protocol [http://whoson.sourceforge.net] + + * alert [http://dovecot.org/patches/1.0/imap-alert-plugin.c]: Send IMAP ALERT + message from '/etc/dovecot.alert'. + * <Pigeonhole Sieve> [Pigeonhole.Sieve.txt]: Use the Sieve + [http://sieve.info/] language to perform actions upon message delivery, such + as filtering, forwarding, vacation replies, notifications and many other + actions. See the <documentation> [Pigeonhole.Sieve.txt] for a full list. + * Fetchmail wakeup [http://github.com/marschap/fetchmail_wakeup]: Wakes + fetchmail when Dovecot looks for new mail. This is a heavily extended and + updated version that is tested to work with Dovecot 1.1.x and 1.2.x. + Versions 2.x including the freshly released version 2.0.3 work with Dovecot + 2.0.x. + * Fetchmail wake [http://guichaz.free.fr/misc/]: Wakes fetchmail when Dovecot + looks for new mail. This is the original version that only works with + dovecot 1.0.x + * <deleted-to-trash> [Plugins.deleted-to-trash.txt]: Automatically move + deleted item to trash folder, if client side doesn't do it, such as outlook + and evolution. + * extra-copies [https://github.com/vandry/dovecot-plugin-extra-copies]: allows + extra copies of messages to be made in other folders whenever a message is + added to a particular folder. + * fts-elasticsearch [https://github.com/ascendantcom/fts-elasticsearch]: + Allows for the use of <ElasticSearch.txt> as a full-text search backend. + * openchange + [https://github.com/openchange/openchange/tree/master/mapiproxy/services/plugins/dovecot]: + Allows <OpenChange.txt> to update Microsoft Outook mailboxes automatically + when new emails are received by Dovecot 2.x. + * TREES [https://0xacab.org/riseuplabs/trees]: A NaCL-based Dovecot encryption + plugin + * dovecot-xaps-plugin [https://github.com/st3fan/dovecot-xaps-plugin]: iOS + Push Email for Dovecot + * dovecot-libsodium-plugin + [https://github.com/LuckyFellow/dovecot-libsodium-plugin]: Libsodium + password hashing schemes plugin + +Experimental Plugins: + + * <xexec> [Plugins.xexec.txt]: Execute any server side application and + communicate with it through plugins over IMAP + +To enable / disable plugins per user you can make your userdb return +'mail_plugins' extra field. See <UserDatabase.ExtraFields.txt> for examples. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PostLoginScripting.txt b/doc/wiki/PostLoginScripting.txt new file mode 100644 index 0000000..390ae00 --- /dev/null +++ b/doc/wiki/PostLoginScripting.txt @@ -0,0 +1,247 @@ +Post-login scripting +==================== + +If you want to do something special after authentication, but before beginning +the IMAP or POP3 session, you can do this by telling imap/pop3 executable to +use post-login service by editing conf.d/10-master.conf: + +---%<------------------------------------------------------------------------- +service imap { + # tell imap to do post-login lookup using a socket called "imap-postlogin" + executable = imap imap-postlogin +} + +# The service name below doesn't actually matter. +service imap-postlogin { + # all post-login scripts are executed via script-login binary + executable = script-login /usr/local/bin/postlogin.sh + + # the script process runs as the user specified here (v2.0.14+): + user = $default_internal_user + # this UNIX socket listener must use the same name as given to imap +executable + unix_listener imap-postlogin { + } +} +---%<------------------------------------------------------------------------- + +You can run multiple post-login scripts by just giving multiple scripts as +parameters to 'script-login', for example: + +---%<------------------------------------------------------------------------- + executable = script-login rawlog /usr/local/bin/postlogin.sh +/usr/local/bin/postlogin2.sh +---%<------------------------------------------------------------------------- + +The scripts are run in the specified order. Remember that the post-login script +runs with the privileges of the "user" setting given to the service (root by +default). If you need the script to access user's mail files, change it to +whatever user owns the mails (e.g. vmail). If you're using multiple UNIX UIDs +(e.g. system users), use 'script-login -d' to drop to the UID/GID specified by +the userdb lookup (ignoring user/group/chroot service settings). + +It's not currently possible to run post-login scripts in <proxies> +[PasswordDatabase.ExtraFields.Proxy.txt], because they're not actually logging +in to the local Dovecot. An alternative method could be implemented some day, +maybe as a plugin. + +Running environment +------------------- + +Standard input and output file descriptors are redirected to the client's +network socket, so you can send data to client by simply writing to stdout. +Standard error fd is redirected to Dovecot's error log, you can write errors +there as well. + +The script can use environment variables: + + * USER: Username + * IP: Remote IP address + * LOCAL_IP: Local IP address + * Fields returned by userdb lookup with their keys uppercased (e.g. if userdb + returned home, it's stored in HOME). + +It's possible to add/modify userdb fields by adding them to environment and +adding the field to USERDB_KEYS. For example to change user's mail location: + +---%<------------------------------------------------------------------------- +#!/bin/sh + +export MAIL=maildir:/tmp/test +export USERDB_KEYS="$USERDB_KEYS mail" +exec "$@" +---%<------------------------------------------------------------------------- + +You can change any Dovecot settings using the above method. + +Changing user's password after login +------------------------------------ + +See <HowTo.ConvertPasswordSchemes.txt> + +Last-login tracking +------------------- + +If you want to know when the user last logged in, you can do it like this: + +---%<------------------------------------------------------------------------- +#!/bin/sh +# a) Filesystem based timestamp in user's home directory +touch ~/.last_login +# b) SQL based tracking. Beware of potential SQL injection holes if you allow +# users to have ' characters in usernames. Following is just an example: +#echo "UPDATE mailbox SET modified = now() WHERE username = '$USER'" | mysql +postfixadmin +exec "$@" +---%<------------------------------------------------------------------------- + +/Note: if creating a timestamp inside the Maildir itself, it's better to avoid +filenames which begin with a dot. The IMAP "list" command will show such files +as IMAP folders, unless you also set 'maildir_stat_dirs = yes' which generates +more I/O ops./ + +Custom mailbox location autodetection +------------------------------------- + +See <MailLocation.txt> for an example. + +Alerts +------ + +If you want to give the user's client some warning notification, you can do it +just by writing it to stdout. But note: + + * Not all clients show the alerts, even though IMAP RFC requires it. + * IMAP protocol requires CRLF (\r\n) line feeds. Some clients will break if + you only send LF. + +---%<------------------------------------------------------------------------- +#!/bin/sh +if [ -f ~/.out-of-office ]; then + printf "* OK [ALERT] You're still marked as being out of office.\r\n" +fi +exec "$@" +---%<------------------------------------------------------------------------- + +Use UNIX groups for ACL authorization +------------------------------------- + +---%<------------------------------------------------------------------------- +#!/bin/sh +ACL_GROUPS=`groups $USER | tr ' ' ','` +export ACL_GROUPS +export USERDB_KEYS="$USERDB_KEYS acl_groups" +exec "$@" +---%<------------------------------------------------------------------------- + +Denying connection from some IP/User +------------------------------------ + +You can use the IP and USER shell variables that are setup by dovecot in a bash +script in order to deny connection (after a successful login), like this: + +---%<------------------------------------------------------------------------- +if [ "$USER" = "myuser" ] ; then + printf "* NO [ALERT] The user '$USER' can not login\r\n" + exit 0 +fi + +if [ ! "$IP" = "192.168.1.1" ] ; then + printf "* NO [ALERT] Access not allowed from the Internet\r\n" + exit 0 +fi +exec "$@" +---%<------------------------------------------------------------------------- + +You can also use + + * http://www.linux.org.py/wiki/howto/dovecot_connect_acl + * TCP wrappers can be used with 'login_access_sockets = tcpwrap' + +Dynamically adding shared mailboxes according to filesystem permissions +----------------------------------------------------------------------- + +Additional namespaces can be dynamically added via environment variables: + +---%<------------------------------------------------------------------------- +use strict; + +my $SHAREDDIR= '/var/spool/mail/Shared'; + +if (! @ARGV) { + exit 1; +} + +# for testing... +#if ($ENV{USER} eq 'lemur') { +# # print "* OK [ALERT] Hello $ENV{'USER'}!\n"; +# &set_namespaces(); +# system("env >> /tmp/dovecot-env-$$"); +#} + +&set_namespaces(); + +exec(@ARGV) or die "Unable to exec @ARGV: $!"; + +sub set_namespaces { + my $mailbox; + local *D; + if (opendir(D, $SHAREDDIR)) { + my $dir; + my @namespaces = (); + while ($mailbox= readdir(D)) { + next if ($mailbox =~ /^\./); + if (-r "${SHAREDDIR}/${mailbox}") { + my $nsname = 'S-'.uc($mailbox); + push(@namespaces, lc($nsname)); + &log("adding NAMESPACE/${nsname}/PREFIX ${SHAREDDIR}/${mailbox}"); + $ENV{"NAMESPACE/${nsname}/LOCATION"} = + "maildir:$SHAREDDIR/$mailbox:INDEX=~/Maildir/index/Shared/$mailbox"; + $ENV{"NAMESPACE/${nsname}/PREFIX"} = "Shared/$mailbox/"; + $ENV{"NAMESPACE/${nsname}/TYPE"}= "public"; + $ENV{"NAMESPACE/${nsname}/SEPARATOR"}= "/"; + $ENV{"NAMESPACE/${nsname}/LIST"}= "yes"; + # $ENV{"NAMESPACE/${nsname}/SUBSCRIPTIONS"} = "no" + } + } + closedir D; + if (@namespaces) { + $ENV{"NAMESPACE"} = join(' ', @namespaces); + my @userdb_keys; + if ($ENV{'USERDB_KEYS'}) { + push(@userdb_keys, $ENV{'USERDB_KEYS'}); + } + push(@userdb_keys, grep(/^NAMESPACE/, keys(%ENV))); + $ENV{'USERDB_KEYS'} = join(' ', @userdb_keys); + } + } +} + +sub log { + print STDERR "@_\n"; +} +---%<------------------------------------------------------------------------- + +This adds environment variables like that: + +---%<------------------------------------------------------------------------- +NAMESPACE/S-SPAMREP/LIST=yes +NAMESPACE/S-SPAMREP/LOCATION=maildir:/var/spool/mail/Shared/spamrep:INDEX=~/Maildir/index/Shared/spamrep +NAMESPACE/S-SPAMREP/PREFIX=Shared/spamrep/ +NAMESPACE/S-SPAMREP/SEPARATOR=/ +NAMESPACE/S-SPAMREP/TYPE=public +NAMESPACE/S-TESTSHARED/LIST=yes +NAMESPACE/S-TESTSHARED/LOCATION=maildir:/var/spool/mail/Shared/testshared:INDEX=~/Maildir/index/Shared/testshared +NAMESPACE/S-TESTSHARED/PREFIX=Shared/testshared/ +NAMESPACE/S-TESTSHARED/SEPARATOR=/ +NAMESPACE/S-TESTSHARED/TYPE=public +NAMESPACE=s-testshared s-spamrep +USERDB_KEYS=SYSTEM_GROUPS_USER UID GID HOME NAMESPACE/S-SPAMREP/LIST NAMESPACE +NAMESPACE/S-TESTSHARED/SEPARATOR NAMESPACE/S-TESTSHARED/TYPE +NAMESPACE/S-TESTSHARED/PREFIX NAMESPACE/S-TESTSHARED/LIST +NAMESPACE/S-TESTSHARED/LOCATION NAMESPACE/S-SPAMREP/SEPARATOR +NAMESPACE/S-SPAMREP/TYPE NAMESPACE/S-SPAMREP/PREFIX +NAMESPACE/S-SPAMREP/LOCATION +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/PreAuth.txt b/doc/wiki/PreAuth.txt new file mode 100644 index 0000000..97ec73c --- /dev/null +++ b/doc/wiki/PreAuth.txt @@ -0,0 +1,22 @@ +Pre-Authenticated Sessions +========================== + +For debugging purpose or to perform IMAP actions on-behalf of an user, you can +use pre-authenticated sessions. You can do this by simply running: + +---%<------------------------------------------------------------------------- +/usr/local/libexec/dovecot/imap +---%<------------------------------------------------------------------------- + +And you can start talking IMAP via stdin/stdout. This doesn't change process's +UID, GID, or get any userdb settings. If you want to emulate a full regular +login, you can execute + +---%<------------------------------------------------------------------------- +/usr/local/libexec/dovecot/imap -u username +---%<------------------------------------------------------------------------- + +Of course, you may need to run the above command as root if it needs to change +process's uid/gid. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/QuickConfiguration.txt b/doc/wiki/QuickConfiguration.txt new file mode 100644 index 0000000..9e1be7a --- /dev/null +++ b/doc/wiki/QuickConfiguration.txt @@ -0,0 +1,209 @@ +Quick Configuration +=================== + +If you just want to get Dovecot running with typical configuration in a typical +environment, here's what you'll have to do: + +Contents + + + 1. Quick Configuration + + 1. TLDR; Just want it running + + 2. Configuration file + + 1. Installing from sources + + 2. Split configuration files + + 3. Hints about writing configuration files + + 3. Authentication + + 4. Mail Location + + 5. Mbox + + 6. Maildir + + 7. Client Workarounds + + 8. SSL and Plaintext Authentication + + 9. NFS + + 10. Running + +TLDR; Just want it running +-------------------------- + +Here is a very simple basic configuration with single vmail user to be placed +as dovecot.conf. Please note that some distros split configuration under +/etc/dovecot/conf.d, which, while it can be useful, is not required. + +You need to create group vmail and user vmail. + +---%<------------------------------------------------------------------------- +mail_home=/srv/mail/%Lu +mail_location=sdbox:~/Mail + +## this is sometimes needed +#first_valid_uid = uid-of-vmail-user + +# if you want to use system users +passdb { + driver = pam +} + +userdb { + driver = passwd + args = blocking=no + override_fields = uid=vmail gid=vmail +} + +ssl=yes +ssl_cert=</path/to/cert.pem +ssl_key=</path/to/key.pem +# if you are using v2.3.0-v2.3.2.1 (or want to support non-ECC DH algorithms) +# since v2.3.3 this setting has been made optional. +#ssl_dh=</path/to/dh.pem + +namespace { + inbox = yes + separator = / +} +---%<------------------------------------------------------------------------- + +Configuration file +------------------ + +Prebuilt packages usually install the configuration files into '/etc/dovecot/'. +You'll find the correct path by running: + +---%<------------------------------------------------------------------------- +doveconf -n | head -n 1 +---%<------------------------------------------------------------------------- + +It's a good idea to read through all the config files and see what settings you +might want to change. + +Installing from sources +----------------------- + +If you compiled and installed Dovecot from sources, Dovecot has installed only +a '/usr/local/etc/dovecot/README' file, which contains the path to the +installed example configuration files, usually +'/usr/local/share/doc/dovecot/example-config'. Copy them to etc/: + +---%<------------------------------------------------------------------------- +cp -r /usr/local/share/doc/dovecot/example-config/* /usr/local/etc/dovecot/ +---%<------------------------------------------------------------------------- + +Split configuration files +------------------------- + +The default configuration starts from 'dovecot.conf', which contains an +'!include conf.d/*.conf' statement to read the rest of the configuration. The +idea is that the settings are nicely grouped into different files to make it +easier for new admins to scan through related settings. It doesn't matter which +config file you add which setting. In the production system it's often easier +to just have a single 'dovecot.conf' file, which you can create easily using + +---%<------------------------------------------------------------------------- +doveconf -nP > dovecot.conf +---%<------------------------------------------------------------------------- + +Hints about writing configuration files +--------------------------------------- + + * Usually it does not matter in which file you write the setting, however, + later settings replace earlier ones. If you use the same section multiple + times, the settings are merged together. + * Before v2.3, boolean settings in the 'plugin' section interpret /any/ value + as *true*, even '0', 'no' and 'false'. + * To read the content of a file, for instance for the SSL certificate option, + prefix the filename with a '<', e.g.: + +---%<------------------------------------------------------------------------- +ssl_cert = </etc/ssl/certs/imap.pem +---%<------------------------------------------------------------------------- + +Authentication +-------------- + +You'll probably be using <PAM> [PasswordDatabase.PAM.txt] authentication. See +the <PAM> [PasswordDatabase.PAM.txt] page for how to configure it. A typical +configuration with Linux would be to create '/etc/pam.d/dovecot' which +contains: + +---%<------------------------------------------------------------------------- +auth required pam_unix.so +account required pam_unix.so +---%<------------------------------------------------------------------------- + +If you're using something else, see <password databases> [PasswordDatabase.txt] +and <user databases> [UserDatabase.txt]. + +Mail Location +------------- + +You can let Dovecot do its automatic mail location detection, but if that +doesn't work, you can set the location manually in 'mail_location' setting. See +<MailLocation.txt> for more information. + +Mbox +---- + +Make sure that all software accessing the mboxes are using the same locking +methods in the same order. The order is important to prevent deadlocking. From +Dovecot's side you can change these from 'mbox_read_locks' and +'mbox_write_locks' settings. See <MboxLocking.txt> for more information. + +If you're using '/var/mail/' directory for INBOXes, you may need to set +'mail_privileged_group = mail' so Dovecot can create dotlocks there. + +For better performance you may want to set 'mbox_very_dirty_syncs = yes' +option. + +Maildir +------- + +For better performance you may want to set 'maildir_very_dirty_syncs = yes' +option. + +Client Workarounds +------------------ + +Check 'imap_client_workarounds' and 'pop3_client_workarounds' and see if you +want to enable more of them than the defaults. + +SSL and Plaintext Authentication +-------------------------------- + +If you intend to use SSL, set 'ssl_cert' and 'ssl_key' settings. Otherwise set +'ssl = no'. Easiest way to get SSL certificates built is to use Dovecot's +'doc/mkcert.sh' script. See <SSL.txt>. + +By default 'disable_plaintext_auth = yes', which means that Dovecot will fail +the authentication if the client doesn't use SSL (or use <non-plaintext +authentication> [Authentication.Mechanisms.txt]). This is recommended in most +situations, since it prevents leaking passwords. However, if you don't offer +SSL for some reason, you'll probably want to set 'disable_plaintext_auth = no'. + +Since v2.3.3 you only need ssl_key and ssl_cert, leaving ssl_dh unset (and +removing ssl-parameters.dat if left over from 2.2) will prevent using non-EC DH +algorithms. + +NFS +--- + +If you're using NFS or some other remote filesystem that's shared between +multiple computers, you should read <NFS.txt>. + +Running +------- + +See <RunningDovecot.txt> and <Logging.txt>. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.Configuration.txt b/doc/wiki/Quota.Configuration.txt new file mode 100644 index 0000000..75e78b2 --- /dev/null +++ b/doc/wiki/Quota.Configuration.txt @@ -0,0 +1,513 @@ +Quota Configuration +=================== + +Contents + + + 1. Quota Configuration + + 1. Quota rules + + 1. Limit configuration + + 2. Per-user quota + + 1. LDAP + + 2. MySQL + + 3. PostgreSQL, SQLite + + 4. passwd-file + + 5. passwd + + 3. Quota for public namespaces + + 4. Quota for private namespaces + + 5. Custom Quota Exceeded Message + + 6. Quota warnings + + 7. Overquota-flag (v2.2.16+) + + 8. Quota grace + + 9. Maximum saved mail size + + 10. Quota admin commands + +The configuration is split into multiple settings: + +First you have the quota root backend configuration. Quota root is a concept +from IMAP Quota specifications [http://www.rfc-editor.org/rfc/rfc2087.txt]. +Normally you'll have only one quota root, but in theory there could be e.g. +"user quota" and "domain quota" roots. It's unspecified how the quota roots +interact with each others (if at all). In some systems for example INBOX could +have a completely different quota root from the rest of the mailboxes (e.g. +INBOX in '/var/mail/' partition and others in '/home/' partition). + +Quota root configuration includes the backend name, quota root name and its +parameters, if there are any: + +---%<------------------------------------------------------------------------- +quota = <backend>[:<quota root name>[:<backend args>]] +---%<------------------------------------------------------------------------- + +The quota root name is just an arbitrary string that is sent to IMAP clients, +which in turn may show it to the user. The name has no meaning. By default an +empty string is used, but you may want to change that since some clients (Apple +Mail) break and don't show quota at all then. + +You can define multiple quota roots by appending an increasing number, for +example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota2 = fs:Disk quota + #quota3 = ... +} +---%<------------------------------------------------------------------------- + +Quota rules +----------- + +Quota rules configure the actual quota limits. The syntax is: + +---%<------------------------------------------------------------------------- +quota_rule = <mailbox name>:<limit configuration> +#quota_rule2 = ... +#quota_rule3 = ..etc.. +---%<------------------------------------------------------------------------- + +"*" as the mailbox name configures the default limit, which is applied on top +of a mailbox-specific limit if found. So for example: + +---%<------------------------------------------------------------------------- +quota_rule = *:storage=1G +quota_rule2 = Trash:storage=+100M +quota_rule3 = SPAM:ignore +---%<------------------------------------------------------------------------- + +This means that the user has 1GB quota, but when saving messages to Trash +mailbox it's possible to use up to 1.1GB of quota. The quota isn't specifically +assigned to Trash, so if you had 1GB of mails in Trash you could still save +100MB of mails to Trash, but nothing to other mailboxes. The idea of this is +mostly to allow the clients' move-to-Trash feature work while user is deleting +messages to get under quota. Additionally, any messages in the SPAM folder are +ignored per the 'ignore' directive and would not count against the quota. + +"?" as the mailbox name works almost like "*". The difference is that "?" is +used only if quota backend doesn't override the limit. For example with +Maildir++ [http://www.inter7.com/courierimap/README.maildirquota.html] quota if +'maildirsize' file exists the limits are taken from it, but if it doesn't exist +the "?" limits are used. + +"*" can't be used as a generic wildcard in mailbox names, so for example "box*" +wouldn't match "boxes". As shown in the above example, the first quota rule is +named 'quota_rule' while the following rules have an increasing digit in them. +You can have as many quota rules as you want. + +Limit configuration +------------------- + +The following limit names are supported: + + * *storage*: Quota limit in kilobytes, 0 means unlimited. + * *bytes*: Quota limit in bytes, 0 means unlimited. + * *messages*: Quota limit in number of messages, 0 means unlimited. This + probably isn't very useful. + * *backend*: Quota backend-specific limit configuration. + * *ignore*: Don't include the specified mailbox in quota at all. + +All of these support also b/k/M/G/T/% suffixes. So storage=100M and bytes=100M +both mean the exact same thing. messages=1k also means 1024 messages (not +1000). + +Percents are relative to the default rule. For example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota_rule = *:storage=1GB + # 10% of 1GB = 100MB + quota_rule2 = Trash:storage=+10%% + # 20% of 1GB = 200MB + quota_rule3 = Spam:storage=+20%% +} +---%<------------------------------------------------------------------------- + +Note that % is written twice to escape it, because <%variables> [Variables.txt] +are expanded in plugin section. <userdb> [UserDatabase.txt] configuration may +or may not require this escaping. + +Backend-specific configuration currently is used only with Maildir++ quota +backend. It means you can have the quota in Maildir++ format (e.g. +"10000000S"). + +Per-user quota +-------------- + +You can override quota rules in your <userdb> [UserDatabase.txt]'s <extra +fields> [UserDatabase.ExtraFields.txt]. Keep all the global settings in plugin +section and override only those settings you need to in your userdb. + +If you're wondering why per-user quota isn't working: + + * Check that 'dovecot-lda' is called with *-d* parameter. + * Check that you're not using <userdb static> [UserDatabase.Static.txt]. + * Check that 'quota_rule' setting is properly returned by userdb. Enable + 'auth_debug=yes' and 'mail_debug=yes' to see this. + +For example: + +---%<------------------------------------------------------------------------- +plugin { + quota = maildir:User quota + quota_rule = *:storage=1G + quota_rule2 = Trash:storage=+100M +} +---%<------------------------------------------------------------------------- + +Next override the default 1GB quota for users: + +LDAP +---- + +Quota limit is in quotaBytes field: + +---%<------------------------------------------------------------------------- +user_attrs = homeDirectory=home, quotaBytes=quota_rule=*:bytes=%$ +---%<------------------------------------------------------------------------- + +Remember that 'user_attrs' is used only if you use <userdb ldap> +[AuthDatabase.LDAP.txt]. + +MySQL +----- + +---%<------------------------------------------------------------------------- +user_query = SELECT uid, gid, home, \ + concat('*:bytes=', quota_limit_bytes) AS quota_rule \ + FROM users WHERE userid = '%u' + +# MySQL with userdb prefetch: Remember to prefix quota_rule with userdb_ +# (just like all other userdb extra fields): +password_query = SELECT userid AS user, password, \ + uid AS userdb_uid, gid AS userdb_gid, \ + concat('*:bytes=', quota_limit_bytes) AS userdb_quota_rule \ + FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +Remember that 'user_query' is used only if you use <userdb sql> +[AuthDatabase.SQL.txt]. + +PostgreSQL, SQLite +------------------ + +---%<------------------------------------------------------------------------- +user_query = SELECT uid, gid, home, \ + '*:bytes=' || quota_limit_bytes AS quota_rule \ + FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +Remember that 'user_query' is used only if you use <userdb sql> +[AuthDatabase.SQL.txt]. + +passwd-file +----------- + +Example passwd-file entries: + +---%<------------------------------------------------------------------------- +user:{plain}pass:1000:1000::/home/user::userdb_quota_rule=*:bytes=100M +user2:{plain}pass2:1001:1001::/home/user2::userdb_quota_rule=*:bytes=200M +user3:{plain}pass3:1002:1002::/home/user3::userdb_mail=maildir:~/Maildir +userdb_quota_rule=*:bytes=300M +---%<------------------------------------------------------------------------- + +passwd +------ + +The <passwd> [AuthDatabase.Passwd.txt] userdb doesn't support extra fields. +That's why you can't directly set users' quota limits to passwd file. One +possibility would be to write a script that reads quota limits from another +file, merges them with passwd file and produces another passwd-file, which you +could then use with Dovecot's <userdb passwd-file> +[AuthDatabase.PasswdFile.txt]. + +Quota for public namespaces +--------------------------- + +You can create a separate namespace-specific quota that's shared between all +users. This is done simply by adding ':ns=<namespace prefix>' parameter to +quota setting. For example you could have something like: + +---%<------------------------------------------------------------------------- +namespace { + type = public + prefix = Public/ + #location = .. +} + +plugin { + quota = maildir:User quota + quota2 = maildir:Shared quota:ns=Public/ + #quota_rules and quota2_rules.. +} +---%<------------------------------------------------------------------------- + +Quota for private namespaces +---------------------------- + +You can create a separate namespace-specific quota for a folder hierarchy. This +is done by adding another namespace and the ':ns=<namespace prefix>' parameter +to quota setting. For example you could have something like: + +---%<------------------------------------------------------------------------- +namespace { + type = private + prefix = Archive/ + #location = .. +} + +plugin { + # Maildir quota + quota = maildir:User quota:ns= + quota2 = maildir:Archive quota:ns=Archive/ + + # Dict quota + #quota = dict:User quota:%u.default:ns=:proxy::quota + #quota2 = dict:Archive quota:%u.archive:ns=Archive/:proxy::quota + + #quota_rules and quota2_rules.. +} +---%<------------------------------------------------------------------------- + +Note: If you're using dict quota, you need to make sure that the quota of the +'Archive' namespace is calculated for another "user" than the default +namespace. Either track different namespaces in different backends or make sure +the users differs.'%u.archive' defines '<username>.archive' as key to track +quota for the 'Archive' namespace, the '%u.default' tracks the quota of other +folders. See <Variables.txt> for further help on variables. + +Custom Quota Exceeded Message +----------------------------- + +You can configure Dovecot to send a custom string instead of the default quota +exceeded message. You could have something like: + +---%<------------------------------------------------------------------------- +plugin { + quota_exceeded_message = Quota exceeded, please go to +http://www.example.com/over_quota_help for instructions on how to fix this. +} +---%<------------------------------------------------------------------------- + +Dovecot can also read the quota exceeded message from a file: + +---%<------------------------------------------------------------------------- +plugin { + quota_exceeded_message = </path/to/quota_exceeded_message.txt +} +---%<------------------------------------------------------------------------- + +Quota warnings +-------------- + +You can configure Dovecot to run an external command when user's quota exceeds +a specified limit. Note that the warning is ONLY executed at the exact time +when the limit is being crossed, so when you're testing it you have to do it by +crossing the limit by saving a new mail. If something else besides Dovecot +updates quota so that the limit is crossed, the warning is never executed. The +syntax is: + +---%<------------------------------------------------------------------------- +quota_warning = <limit configuration> <quota-warning socket name> <parameters> +#quota_warning2 = ... +#quota_warning3 = ..etc.. +---%<------------------------------------------------------------------------- + +Limit configuration is almost exactly same as for rules, with the exception of +adding "-" before the value for "reverse" warnings where the script is called +when quota drops below the value. Usually you want to use percents instead of +absolute limits. Only the command for the first exceeded limit is executed, so +configure the highest limit first. The actual commands that are run need to be +created as services. + +An example configuration: + +---%<------------------------------------------------------------------------- +plugin { + quota_warning = storage=95%% quota-warning 95 %u + quota_warning2 = storage=80%% quota-warning 80 %u + quota_warning3 = -storage=100%% quota-warning below %u # user is no longer +over quota +} + +service quota-warning { + executable = script /usr/local/bin/quota-warning.sh + # use some unprivileged user for executing the quota warnings + user = vmail + unix_listener quota-warning { + } +} +---%<------------------------------------------------------------------------- + +With the above example when user's quota exceeds 80%, 'quota-warning.sh' is +executed with parameter 80. The same goes for when quota exceeds 95%. If user +suddenly receives a huge mail and the quota jumps from 70% to 99%, only the 95 +script is executed. + +You have to create the 'quota-warning.sh' script yourself. Here is an example +that sends a mail to the user: + +---%<------------------------------------------------------------------------- +#!/bin/sh +PERCENT=$1 +USER=$2 +cat << EOF | /usr/local/libexec/dovecot/dovecot-lda -d $USER -o +"plugin/quota=maildir:User quota:noenforcing" +From: postmaster@domain.com +Subject: quota warning + +Your mailbox is now $PERCENT% full. +EOF +---%<------------------------------------------------------------------------- + +The quota enforcing is disabled to avoid looping. You'll of course need to +change the 'plugin/quota' value to match the quota backend and other +configuration you use. Basically preserve your original "quota" setting and +just insert ":noenforcing" to proper location in it. For example with dict +quota, you can use something like:'-o "plugin/quota=dict:User +quota::noenforcing:proxy::quota"' + +Overquota-flag (v2.2.16+) +------------------------- + +Quota warnings scripts can be used to set an overquota-flag to userdb (e.g. +LDAP) when user goes over/under quota. This flag can be used by MTA to reject +mails to an user who is over quota already at SMTP RCPT TO stage. The only +problem with this has been that there are race conditions that in some rare +situations cause the overquota-flag to be set even when user is already under +quota. This situation doesn't get solved itself without manual admin +intervention or the new overquota-flag feature: This feature checks the flag's +value every time user logs in (or mail gets delivered or any other email access +to user) and compares it to the current actual quota usage. If the flag is +wrong, a script is executed that should fix up the situation. + +The overquota-flag name in userdb must be "quota_over_flag". There are two +settings to configure what to do: + +---%<------------------------------------------------------------------------- +plugin { + # If quota_over_flag=TRUE, the overquota-flag is enabled. Otherwise not. + quota_over_flag_value = TRUE + + # Any non-empty value for quota_over_flag means user is over quota. + # Wildcards can be used in a generic way, e.g. "*yes" or "*TRUE*" + #quota_over_flag_value = * + + # If set, overquota-flag is checked only when current quota usage is going to +be checked anyway. + # This can be used to optimize this check in case it's running too slowly. +(v2.2.25+) + #quota_over_flag_lazy_check = yes + + # Service script to execute if overquota-flag is wrong. Configured the + # same as quota_warning scripts. The current quota_over_flag's value is + # appended as the last parameter. + quota_over_script = quota-warning mismatch %u +} +---%<------------------------------------------------------------------------- + +Quota grace +----------- + +With v2.2+ by default the last mail can bring user over quota. This is useful +to allow user to actually unambiguously become over quota instead of fail some +of the last larger mails and pass through some smaller mails. Of course the +last mail shouldn't be allowed to bring the user hugely over quota, so by +default in v2.2+ this limit is 10% of the user's quota limit. (In v2.1 this is +disabled by default.) + +To change the quota grace, use: + +---%<------------------------------------------------------------------------- +plugin { + # allow user to become max 10% over quota + quota_grace = 10%% + # allow user to become max 50 MB over quota + quota_grace = 50 M +} +---%<------------------------------------------------------------------------- + +Maximum saved mail size +----------------------- + +(v2.2.29+) Dovecot allows specifying the maximum message size that is allowed +to be saved (e.g. by LMTP, IMAP APPEND or doveadm save). The default is 0, +which is unlimited. Since outgoing mail sizes are also typically limited on the +MTA size, it can be beneficial to prevent user from saving too large mails, +which would later on fail on the MTA side anyway. + +---%<------------------------------------------------------------------------- +plugin { + quota_max_mail_size = 100M +} +---%<------------------------------------------------------------------------- + +Quota admin commands +-------------------- + +The imap_quota plugin implements the SETQUOTA command, which allows changing +the logged in user's quota limit if the user is admin. Normally this means that +a master user must log in with 'userdb_admin=y' set in the master passdb. The +changing is done via dic_set() command, so you must configure the 'quota_set' +setting to point to some dictionary where your quota limit exists. Usually this +is in SQL, e.g.: + +dovecot.conf: + +---%<------------------------------------------------------------------------- +plugin { + quota_set = dict:proxy::sqlquota +} +dict { + sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +dovecot-dict-sql.conf.ext: + +---%<------------------------------------------------------------------------- +# Use "host= ... pass=foo#bar" with double-quotes if your password has '#' +character. +connect = host=/var/run/mysqld/mysqld.sock dbname=mails user=admin +password=pass +# Alternatively you can connect to localhost as well: +#connect = host=localhost dbname=mails user=admin password=pass # port=3306 + +map { + pattern = priv/quota/limit/storage + table = quota + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/limit/messages + table = quota + username_field = username + value_field = messages +} +---%<------------------------------------------------------------------------- + +Afterwards the quota can be changed with: + +---%<------------------------------------------------------------------------- +a SETQUOTA "User quota" (STORAGE 12345 MESSAGES 123) +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.Count.txt b/doc/wiki/Quota.Count.txt new file mode 100644 index 0000000..4e461ec --- /dev/null +++ b/doc/wiki/Quota.Count.txt @@ -0,0 +1,44 @@ +Count quota +=========== + +(Requires Dovecot v2.2.19+) + +The quota is tracked internally within Dovecot's index files. Each mailbox's +quota is tracked separately and when the current quota usage is wanted to be +known, the mailboxes' quotas are summed up together. To get the best +performance mailbox list indexes should be enabled. + +*WARNING*: If you're switching from some other quota backend to count, make +sure that all the mails have their virtual sizes already indexed. Otherwise +there may be a significant performance hit when Dovecot starts opening all the +mails to get their sizes. You can help to avoid this by accessing the mailbox +vsizes for all the users before doing the configuration change:'doveadm mailbox +status -u user@domain vsize '*'' + +Configuration +------------- + +---%<------------------------------------------------------------------------- +mailbox_list_index = yes +# Avoid spending excessive time waiting for the quota calculation to finish +when +# mails' vsizes aren't already cached. If this many mails are opened, finish +the +# quota calculation on background in indexer-worker process. Mail deliveries +will +# be assumed to succeed, and explicit quota lookups will return internal error. +# (v2.2.28+) +mail_vsize_bg_after_count = 100 + +plugin { + # 10MB quota limit + quota = count:User quota + quota_rule = *:storage=10M + + # This is required - it uses "virtual sizes" rather than "physical sizes" for +quota counting: + quota_vsizes = yes +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.Dict.txt b/doc/wiki/Quota.Dict.txt new file mode 100644 index 0000000..e346653 --- /dev/null +++ b/doc/wiki/Quota.Dict.txt @@ -0,0 +1,201 @@ +Dictionary quota +================ + +*NOTE:* Using the <count> [Quota.Count.txt] backend (possibly together with +<quota_clone> [Plugins.QuotaClone.txt] plugin) is now preferred to using this +backend. It has less of a chance of quota usage becoming wrong. + +The /dictionary/ quota backend supports both *storage* and *messages* quota +limits. The current quota is kept in the specified <dictionary> +[Dictionary.txt]. The available dictionaries include: + + * SQL + * Redis + * Flat files + +See <Dictionary.txt> for full description of the available backends. + +The quota root format is: + +---%<------------------------------------------------------------------------- +quota = dict:<quota root name>:<username>[:<option>[...]]:<dictionary URI> +---%<------------------------------------------------------------------------- + +If /username/ is left empty, the logged in username is used (this is typically +what you want). Another useful username is '%d' for supporting domain-wide +quotas. + +The supported options are: + + * noenforcing: Don't enforce quota limits, only track them. + * ignoreunlimited: If user has unlimited quota, don't track it. + * ns=<prefix>: This quota root is tracked only for the given namespace. + * hidden: Hide the quota root from IMAP GETQUOTA* commands. + * no-unset: When recalculating quota, don't unset the quota first. This is + needed if you wish to store the quota usage among other data in the same SQL + row - otherwise the entire row could get deleted. Note that the unset is + required with PostgreSQL or the merge_quota() trigger doesn't work + correctly. (v2.2.20+) + +NOTE: The dictionary stores only the current quota usage. The quota limits are +still configured in userdb the same way as with other quota backends. + +NOTE2: By default the quota dict may delete rows from the database when it +wants to rebuild the quota. You must use a separate table that contains only +the quota information, or you'll lose the other data. This can be avoided with +the "no-unset" parameter. + +Examples +-------- + +Simple per-user flat file +------------------------- + +This will create one quota-accounting file for each user. + +The Dovecot user process (imap, pop3 or lda) needs write access to this file, +so %h or mail_location are good candidates to store it. + +*Warning*: if a user has shell or file access to this location, he can mangle +his quota file, thus overcoming his quota limit by lying about his used +capacity. + +---%<------------------------------------------------------------------------- +plugin { + quota = dict:User quota::file:%h/mdbox/dovecot-quota + quota_rule = *:storage=10M:messages=1000 +} +---%<------------------------------------------------------------------------- + +Server-based dictionaries +------------------------- + +---%<------------------------------------------------------------------------- +plugin { + # SQL backend: + quota = dict:User quota::proxy::sqlquota + # Redis backend (v2.1.9+): + quota = dict:User quota::redis:host=127.0.0.1:prefix=user/ + + quota_rule = *:storage=10M:messages=1000 +} +dict { + sqlquota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +The above SQL example uses dictionary proxy process (see below), because SQL +libraries aren't linked to all Dovecot binaries. The file and Redis examples +use direct access. + +Example 'dovecot-dict-sql.conf.ext': + +---%<------------------------------------------------------------------------- +connect = host=localhost dbname=mails user=sqluser password=sqlpass +map { + pattern = priv/quota/storage + table = quota + username_field = username + value_field = bytes +} +map { + pattern = priv/quota/messages + table = quota + username_field = username + value_field = messages +} +---%<------------------------------------------------------------------------- + +Create the table like this: + +---%<------------------------------------------------------------------------- +CREATE TABLE quota ( + username varchar(100) not null, + bytes bigint not null default 0, + messages integer not null default 0, + primary key (username) +); +---%<------------------------------------------------------------------------- + +MySQL uses the following queries to update the quota. You need suitable +privileges. + +---%<------------------------------------------------------------------------- +INSERT INTO table (bytes,username) VALUES ('112497180','foo@example.com') ON +DUPLICATE KEY UPDATE bytes='112497180'; +INSERT INTO table (messages,username) VALUES ('1743','foo@example.com') ON +DUPLICATE KEY UPDATE messages='1743'; +UPDATE table SET bytes=bytes-14433,messages=messages-2 WHERE username = +'foo@example.com'; +DELETE FROM table WHERE username = 'foo@example.com'; +---%<------------------------------------------------------------------------- + +If you're using SQLite, then take a look at the trigger in this post: +http://dovecot.org/pipermail/dovecot/2013-July/091421.html + +If you're using PostgreSQL, you'll need a trigger: + +---%<------------------------------------------------------------------------- +CREATE OR REPLACE FUNCTION merge_quota() RETURNS TRIGGER AS $$ +BEGIN + IF NEW.messages < 0 OR NEW.messages IS NULL THEN + -- ugly kludge: we came here from this function, really do try to insert + IF NEW.messages IS NULL THEN + NEW.messages = 0; + ELSE + NEW.messages = -NEW.messages; + END IF; + return NEW; + END IF; + + LOOP + UPDATE quota SET bytes = bytes + NEW.bytes, + messages = messages + NEW.messages + WHERE username = NEW.username; + IF found THEN + RETURN NULL; + END IF; + + BEGIN + IF NEW.messages = 0 THEN + INSERT INTO quota (bytes, messages, username) + VALUES (NEW.bytes, NULL, NEW.username); + ELSE + INSERT INTO quota (bytes, messages, username) + VALUES (NEW.bytes, -NEW.messages, NEW.username); + END IF; + return NULL; + EXCEPTION WHEN unique_violation THEN + -- someone just inserted the record, update it + END; + END LOOP; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER mergequota BEFORE INSERT ON quota + FOR EACH ROW EXECUTE PROCEDURE merge_quota(); +---%<------------------------------------------------------------------------- + +Dictionary proxy server +----------------------- + +To avoid each process making a new SQL connection, you can make all dictionary +communications go through a dictionary server process which keeps the +connections permanently open. + +The dictionary server is referenced with URI 'proxy:<dictionary server socket +path>:<dictionary name>'. The socket path may be left empty if you haven't +changed 'base_dir' setting in 'dovecot.conf'. Otherwise set it to +'<base_dir>/dict-server'. The dictionary names are configured in +'dovecot.conf'. For example: + +---%<------------------------------------------------------------------------- +dict { + quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext + expire = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +See <Dict.txt> for more information, especially about permission issues. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.Dirsize.txt b/doc/wiki/Quota.Dirsize.txt new file mode 100644 index 0000000..ec28989 --- /dev/null +++ b/doc/wiki/Quota.Dirsize.txt @@ -0,0 +1,21 @@ +Dirsize quota +============= + +The /dirsize/ quota backend supports *storage* quota limits, but not *messages* +quota limits. The current quota is calculated by finding all files in +configured mail directories and summing up their sizes. This works pretty fast +with mboxes, but *dirsize is a really bad idea with maildirs*. It will end up +eating all your CPU and disk I/O. + +Example +------- + +---%<------------------------------------------------------------------------- +plugin { + # 10MB quota limit + quota = dirsize:User quota + quota_rule = *:storage=10M +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.FS.txt b/doc/wiki/Quota.FS.txt new file mode 100644 index 0000000..7b59802 --- /dev/null +++ b/doc/wiki/Quota.FS.txt @@ -0,0 +1,122 @@ +Filesystem quota +================ + +Filesystem quota supports both local filesystems and rquota (NFS). + +If you are using systemd, please make sure you /turn off/ 'PrivateDevices=yes', +otherwise it won't work properly. Best way to do this is to use 'systemctl edit +dovecot' command or add file +'/etc/systemd/system/dovecot.service.d/override.conf' with + +---%<------------------------------------------------------------------------- +[Service] +PrivateDevices=off +---%<------------------------------------------------------------------------- + +Index files +----------- + +It's a good idea to keep index files in a partition where there are no +filesystem quota limits. The index files exist to speed up mailbox operations, +so Dovecot runs more slowly if it can't keep them updated. You can specify the +index file location by appending ':INDEX=/somewhere' to <mail_location> +[MailLocation.txt]. + +Dovecot can handle "out of disk space" errors in index file handling and +transparently move to in-memory indexes. It'll use the in-memory indexes until +the mailbox is re-opened. + +mbox +---- + +It's a good idea to have 'mbox_lazy_writes=yes' (default), otherwise Dovecot +might give "Not enough disk space" errors when opening the mailbox, making it +impossible to expunge any mails. + +If user has run out of quota and index files are also in memory (because +they're also over quota), it's possible that message flag changes are lost. +This should be pretty rare though because Dovecot keeps some extra space +allocated inside the mbox file for flag changes. + +Example preferred configuration: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u:INDEX=/var/no-quotas/index/%u +---%<------------------------------------------------------------------------- + +Maildir +------- + +Maildir needs to be able to add UIDs of new messages to 'dovecot-uidlist' file. +If it can't do this, it can give an error when opening the mailbox, making it +impossible to expunge any mails. + +Currently the only way to avoid this is to use a separate partition for the +uidlist files where there are no filesystem quota limits. You can do this by +appending ':CONTROL=/somewhere' to <mail_location> [MailLocation.txt]. + +Example preferred configuration: + +---%<------------------------------------------------------------------------- +mail_location = +maildir:~/Maildir:INDEX=/var/no-quotas/index/%u:CONTROL=/var/no-quotas/control/%u +---%<------------------------------------------------------------------------- + +Note that if you change the location of the control files, Dovecot will look in +the new CONTROL directory ('/var/no-quotas/control/%u') for the subscriptions +file. + +Parameters +---------- + +By default only user quota is shown, or if it doesn't exist, group quota is +used as fallback. + + * user: Report only user quotas, don't fallback to showing group quotas. + * group: Report only group quotas + * inode_per_mail: Report inode quota as "number of message" quota. This can be + useful with Maildir or single-dbox. + * noenforcing: Don't try to enforce quotas by calculating if saving would get + user over quota. Only handle write failures. + * mount=<path>: Report quota from given path. Default is to use the path for + the mail root directory. + +If you want to give multiple parameters, separate them with ':' (e.g. +"inode_per_mail:noenforcing"). + +Examples +-------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins quota +protocol imap { + mail_plugins = mail_plugins imap_quota +} + +plugin { + quota = fs:user +} +---%<------------------------------------------------------------------------- + +If you want to see both user and group quotas as separate quota roots, you can +use this: + +---%<------------------------------------------------------------------------- +plugin { + quota = fs:User quota:user + quota2 = fs:Group quota:group +} +---%<------------------------------------------------------------------------- + +If you have your mails in two filesystems, you can create two quota roots: + +---%<------------------------------------------------------------------------- +plugin { + # Assuming INBOX in /var/mail/ which is mounted to / + quota = fs:INBOX:mount=/ + # Assuming other mailboxes are in /home mount + quota2 = fs:Others:mount=/home +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.Maildir.txt b/doc/wiki/Quota.Maildir.txt new file mode 100644 index 0000000..d6ccc85 --- /dev/null +++ b/doc/wiki/Quota.Maildir.txt @@ -0,0 +1,51 @@ +Maildir++ quota +=============== + +Maildir++ is the most commonly used quota backend with Maildir format. Note +that *Maildir++ quota works only with Maildir format*. With other mailbox +formats you should use <count quota> [Quota.Count.txt]. Dovecot implements the +standard Maildir++ specification +[http://www.courier-mta.org/imap/README.maildirquota.html], so it's compatible +with Courier [http://www.courier-mta.org/], maildrop +[http://www.courier-mta.org/maildrop/], Exim [http://www.exim.org], etc. + +There are two ways to configure Maildir++ quota limits: + + 1. Configure the limits in Dovecot. You most likely want to do this. See + <quota main page> [Quota.txt] for how to do this configuration. + 2. Make Dovecot get the limits from existing 'maildirsize' files. + +Only Maildir++-specific settings are described below. See <Quota.txt> for more +generic configuration. + +Maildir++ quota relies on 'maildirsize' file having correct information, so if +your users can modify the file in some way (e.g. shell access), you're relying +on the goodwill of your users for the quota to work. + +You can't rely on Dovecot noticing external changes to Maildir and updating +maildirsize accordingly. This happens eventually when quota is being +recalculated, but it may take a while. Quota recalculation also currently +doesn't trigger quota warning executions. + +Maildirsize file +---------------- + +The 'maildirsize' file in the Maildir root directory contains both the quota +limit information and the current quota status. It contains a header in format: + +---%<------------------------------------------------------------------------- +<storage limit in bytes>S,<messages limit>C +---%<------------------------------------------------------------------------- + +If you don't configure any quota limits in Dovecot ('quota=maildir' with no +other settings), Dovecot takes the limits from the header. If the file does not +exist, quota isn't enforced. + +If you configure quota limits in Dovecot, Dovecot makes sure that this header +is kept up to date. If the file does not exist, it's simply rebuilt. + +Once the 'maildirsize' reaches 5120 bytes, the quota is recalculated and the +file is recreated. This makes sure that if quota happens to be broken (e.g. +externally deleted files) it won't stay that way forever. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Quota.txt b/doc/wiki/Quota.txt new file mode 100644 index 0000000..6d82d2a --- /dev/null +++ b/doc/wiki/Quota.txt @@ -0,0 +1,134 @@ +Quota +===== + +Quota backend specifies the method how Dovecot keeps track of the current quota +usage. They don't (usually) specify users' quota limits, that's done by +<returning extra fields from userdb> [Quota.Configuration.txt]. There are +different quota backends that Dovecot can use: + + * <fs> [Quota.FS.txt]: Filesystem quota. + * <dirsize> [Quota.Dirsize.txt]: The simplest and slowest quota backend, but + it works quite well with mboxes. + * <dict> [Quota.Dict.txt]: Store quota usage in a dictionary (e.g. SQL, or + flat files). + * <maildir> [Quota.Maildir.txt]: Store quota usage in Maildir++ maildirsize + files. This is the most commonly used quota for virtual users. + * <count> [Quota.Count.txt]: Store quota usage within Dovecot's index files. + * <imapc> [MailboxFormat.imapc.txt]: Use quota from remote IMAP server with + imapc. + +Since v2.2.19 we recommend using <count> [Quota.Count.txt] for any new +installations. If you need usage data to an external database, consider using +<Plugins.QuotaClone.txt> for exporting the information. + +Quota service +------------- + +The quota service allows postfix to check quota before delivery: + +---%<------------------------------------------------------------------------- +service quota-status { + executable = quota-status -p postfix + inet_listener { + port = 12340 + # You can choose any port you want + } + client_limit = 1 +} +---%<------------------------------------------------------------------------- + +And then have postfix check_policy_service check that: + +---%<------------------------------------------------------------------------- +smtpd_recipient_restrictions = + ... + check_policy_service inet:mailstore.example.com:12340 +---%<------------------------------------------------------------------------- + +For more about this service see +https://sys4.de/en/blog/2013/04/08/postfix-dovecot-mailbox-quota/ + +Enabling quota plugins +---------------------- + +There are three quota related plugins: + + * quota: Implements the actual quota handling and includes also all the quota + backends. + * imap_quota: For reporting quota information via IMAP. + * quota_grace: Determines if and how far user can go over quota + +Enable them in configuration files, e.g.: + +conf.d/10-mail.conf: + +---%<------------------------------------------------------------------------- +# Space separated list of plugins to load for all services. Plugins specific to +# IMAP, LDA, etc. are added to this list in their own .conf files. +mail_plugins = $mail_plugins quota +---%<------------------------------------------------------------------------- + +conf.d/20-imap.conf: + +---%<------------------------------------------------------------------------- +protocol imap { + # Space separated list of plugins to load (default is global mail_plugins). + mail_plugins = $mail_plugins imap_quota +} +---%<------------------------------------------------------------------------- + +conf.d/90-quota.conf: (for use with the quota-status service) + +---%<------------------------------------------------------------------------- +plugin { + quota_grace = 10%% + # 10% is the default + quota_status_success = DUNNO + quota_status_nouser = DUNNO + quota_status_overquota = "552 5.2.2 Mailbox is full" +} +---%<------------------------------------------------------------------------- + +Configuration +------------- + +See <Quota.Configuration.txt> for backend-independent quota configuration. + +Quota recalculation +------------------- + +If your quotas are out of sync, you can use 'doveadm quota recalc -u <uid>' +command to recalculate them. + +Quota and Trash mailbox +----------------------- + +Standard way to expunge messages with IMAP works by: + + 1. Marking message with \Deleted flag + 2. Actually expunging the message using EXPUNGE command + +Both of these commands can be successfully used while user's quota is full. +However many clients use a "move-to-Trash" feature, which works by: + + 1. COPY the message to Trash mailbox + 2. Mark the message with \Deleted + 3. Expunge the message from the original mailbox. + 4. (Maybe later expunge the message from Trash when "clean trash" feature is + used) + +If user is over quota (or just under it), the first COPY command will fail and +user may get an unintuitive message about not being able to delete messages +because user is over quota. The possible solutions for this are: + + * Disable move-to-trash feature from client + * You can create a separate quota rule ignoring Trash mailbox's quota. Note + that this would allow users to store messages infinitely to the mailbox. + * You can create a separate quota rule giving Trash mailbox somewhat higher + quota limit (but not unlimited). + +To make sure users don't start keeping messages permanently in Trash you can +use a nightly <cronjob> [Plugins.Expire.txt] to expunge old messages from Trash +mailbox. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Replication.txt b/doc/wiki/Replication.txt new file mode 100644 index 0000000..58d25a9 --- /dev/null +++ b/doc/wiki/Replication.txt @@ -0,0 +1,382 @@ +Replication with dsync +====================== + +Dovecot supports master/master replication using dsync. It's recommended that +the same user always gets redirected to the same replica, but no changes get +lost even if the same user modifies mails simultaneously on both replicas, some +mails just might have to be redownloaded. The replication is done +asynchronously, so high latency between the replicas isn't a problem. The +replication is done by looking at Dovecot index files (not what exists in +filesystem), so no mails get lost due to filesystem corruption or an accidental +rm -rf, they will simply be replicated back. + +NOTE: v2.2 is highly recommended for this. Earlier versions can't do +incremental metadata syncing. This means that the more mails a mailbox has, the +slower it is to sync it. + +Replication works only between server pairs. If you have a large cluster, you +need multiple independently functioning Dovecot backend pairs. This means that +<director> [Director.txt] isn't currently supported with replication. The +replication in general is a bit resource intensive, so it's not recommended to +be used in multi-million user installations. + +*WARNING*: Shared folder replication doesn't work correctly right now – mainly +it can generate a lot of duplicate emails. This is because there's currently a +per-user lock that prevents multiple dsyncs from working simultaneously on the +same user. But with shared folders multiple users can be syncing the same +folder. So this would need additional locks (e.g. shared folders would likely +need to lock the owner user, and public folders would likely need a per-folder +lock or a maybe a global public folder lock). Fixing this is currently low +priority for Dovecot developers. + +Configuration +------------- + +Since v2.3.1 you can disable replication for a user by providing 'noreplicate' +<user database field> [UserDatabase.ExtraFields.txt]. Another way to disable +replication for some users is to return mail_replica field from userdb for +users you want to replicate. + +Make sure that user listing is configured for your userdb, this is required by +replication to find the list of users that are periodically replicated: + +---%<------------------------------------------------------------------------- +doveadm user '*' +---%<------------------------------------------------------------------------- + +Enable the replication plugin globally (most likely you'll need to do this in +10-mail.conf): + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins notify replication +---%<------------------------------------------------------------------------- + +Replicator process should be started at startup, so it can start replicating +users immediately: + +---%<------------------------------------------------------------------------- +service replicator { + process_min_avail = 1 +} +---%<------------------------------------------------------------------------- + +You need to configure how and where to replicate. Using SSH for example: + +---%<------------------------------------------------------------------------- +dsync_remote_cmd = ssh -l%{login} %{host} doveadm dsync-server -u%u +plugin { + mail_replica = remote:vmail@anotherhost.example.com +} +---%<------------------------------------------------------------------------- + +The mail processes need to have access to the replication-notify fifo and +socket. If you have a single vmail UID, you can do: + +---%<------------------------------------------------------------------------- +service aggregator { + fifo_listener replication-notify-fifo { + user = vmail + } + unix_listener replication-notify { + user = vmail + } +} +---%<------------------------------------------------------------------------- + +The replication-notify only notifies the replicator processes that there is +work to be done, so it's not terribly insecure either to just set 'mode=0666'. + +Enable doveadm replicator commands by setting: + +---%<------------------------------------------------------------------------- +service replicator { + unix_listener replicator-doveadm { + mode = 0600 + user = vmail + } +} +---%<------------------------------------------------------------------------- + +You can configure how many dsyncs can be run in parallel (10 by default): + +---%<------------------------------------------------------------------------- +replication_max_conns = 10 +---%<------------------------------------------------------------------------- + +Normally all replication is asynchronous. You can also optionally configure new +mail saving to be synchronous, with a timeout to avoid waiting too long. This +can be configured with: + +---%<------------------------------------------------------------------------- +plugin { + # When saving a new mail via IMAP or delivering a mail via LDA/LMTP, + # wait for the mail to be synced to the remote site. If it doesn't finish + # in 2 seconds, return success anyway. + replication_sync_timeout = 2s +} +---%<------------------------------------------------------------------------- + +dsync over TCP connections (v2.2+) +---------------------------------- + +Create a listener for doveadm-server: + +---%<------------------------------------------------------------------------- +service doveadm { + inet_listener { + port = 12345 + } +} +---%<------------------------------------------------------------------------- + +And tell doveadm client to use this port by default: + +---%<------------------------------------------------------------------------- +doveadm_port = 12345 +---%<------------------------------------------------------------------------- + +Both the client and the server also need to have a shared secret: + +---%<------------------------------------------------------------------------- +doveadm_password = secret +---%<------------------------------------------------------------------------- + +Now you can use 'tcp:hostname' as the dsync target. You can also override the +port with 'tcp:hostname:port'. + +---%<------------------------------------------------------------------------- +plugin { + mail_replica = tcp:anotherhost.example.com # use doveadm_port + #mail_replica = tcp:anotherhost.example.com:12345 # use port 12345 explicitly +} +---%<------------------------------------------------------------------------- + +SSL +--- + +You can also use SSL for the connection: + +---%<------------------------------------------------------------------------- +service doveadm { + inet_listener { + port = 12345 + ssl = yes + } +} +---%<------------------------------------------------------------------------- + +The doveadm listener will use the SSL certificate that is configured globally +for all SSL listeners, i.e. via the following settings at the top level of the +configuration file: + +---%<------------------------------------------------------------------------- +ssl_cert = </etc/ssl/dovecot.pem +ssl_key = </etc/ssl/dovecot.pem +---%<------------------------------------------------------------------------- + +'ssl_cert' is not a valid setting inside 'service' or 'inet_listener' blocks, +so you can't use a separate SSL certificate for the doveadm listener.You can, +however, use separate SSL certificates for the /other/ protocols, like so: + +---%<------------------------------------------------------------------------- +protocol imap { + ssl_cert = </etc/ssl/certs/imap.pem + ssl_key = </etc/ssl/private/imap.pem +} +protocol pop3 { + ssl_cert = </etc/ssl/certs/pop3.pem + ssl_key = </etc/ssl/private/pop3.pem +} +---%<------------------------------------------------------------------------- + +When one Dovecot instance connects to the other one in the replication pair, it +has to verify that the partner's SSL certificate is valid, so you need to +specify a directory or file containing valid SSL CA roots: + +---%<------------------------------------------------------------------------- +ssl_client_ca_dir = /etc/ssl/certs # Debian/Ubuntu +ssl_client_ca_file = /etc/pki/tls/cert.pem # RedHat +---%<------------------------------------------------------------------------- + +Now you can use 'tcps:hostname' or 'tcps:hostname:port' as the dsync target. + +Note that the SSL certificate must be signed by one of the CAs in the +'ssl_client_ca_dir' or 'ssl_client_ca_file'. You can't use a self-signed +certificate or a private CA, unless you correctly set them up into the CA +file/directory (see openssl documentation for details). + +You could point 'ssl_client_ca_file' to your private CA, but keep in mind that +'ssl_client_ca_file' and 'ssl_client_ca_dir' also affect other services where +Dovecot acts as an SSL client (e.g. the imapc feature), so be careful not to +break SSL for those services. + +dsync wrapper script for root SSH login (v2.2+) +----------------------------------------------- + +If you're using multiple UIDs, dsync needs to be started as root, which means +you need to log in as root with ssh (or use sudo). Another possibility is to +allow root to run only a wrapper script. There is some built-in support for +this in v2.2+ to make it easier: + +dovecot.conf: + +---%<------------------------------------------------------------------------- +dsync_remote_cmd = /usr/bin/ssh -i /root/.ssh/id_dsa.dsync %{host} +/usr/local/bin/dsync-in-wrapper.sh +plugin { + mail_replica = remoteprefix:vmail@anotherhost.example.com +} +---%<------------------------------------------------------------------------- + +/root/.ssh/authorized_keys: + +---%<------------------------------------------------------------------------- +command="/usr/local/bin/dsync-in-wrapper.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty +<ssh key> +---%<------------------------------------------------------------------------- + +/usr/local/bin/dsync-in-wrapper.sh: + +---%<------------------------------------------------------------------------- +read username +ulimit -c unlimited # for debugging any crashes +/usr/local/bin/doveadm dsync-server -u $username +---%<------------------------------------------------------------------------- + +dsync parameters +---------------- + +With v2.2.9+ you can configure what parameters replicator uses for the 'doveadm +sync' command: + +---%<------------------------------------------------------------------------- +replication_dsync_parameters = -d -N -l 30 -U +---%<------------------------------------------------------------------------- + +The '-f' and '-s' parameters are added automatically when needed. + +Usually the only change you may want to do is replace '-N' (= sync all +namespaces) with '-n <namespace>' or maybe just add '-x <exclude>' +parameter(s). + +Administration +-------------- + +'doveadm replicator status' provides a summary. For example: + +---%<------------------------------------------------------------------------- +Queued 'sync' requests 0 +Queued 'high' requests 0 +Queued 'low' requests 0 +Queued 'failed' requests 0 +Queued 'full resync' requests 90 +Waiting 'failed' requests 10 +Total number of known users 100 +---%<------------------------------------------------------------------------- + +The first 3 fields describe users who have a replication pending with a +specific priority. The same user can only be in one (or none) of these queues: + + * Queued 'sync' requests: This priority is used only for mail saves if + 'replication_sync_timeout' setting is used. + * Queued 'high' requests: This priority is used only for mail saves if + 'replication_sync_timeout' setting is not used, or if the sync request timed + out. + * Queued 'low' requests: This priority is used for everything else except mail + saves. + +The following fields are: + + * Queued 'failed' requests: Number of users who have a replication pending and + where the last sync attempt failed. These users are retried as soon as + higher priority users' replication has finished. + * Queued 'full resync' requests: Number of users who don't specifically have + any replication pending, but who are currently waiting for a periodic "full + sync". This is controlled by the 'replication_full_sync_interval' setting. + * Waiting 'failed' requests: Number of users whose last replication attempt + failed, and we're now waiting for the retry interval (5 mins) to pass before + another attempt. + * Total number of known users: Number of users that replicator knows about. + The users can be listed with:'doveadm replicator status '*'' + +The per-user replication status can be shown with 'doveadm replicator status +<username pattern>'. The username pattern can contain '*' and '?' wildcards. +The response contains for example: + +---%<------------------------------------------------------------------------- +username priority fast sync full sync success sync failed +test100 none 02:03:52 02:08:52 02:03:52 - +test1 none 00:00:01 00:43:33 03:20:46 y +test2 none 02:03:51 02:03:51 02:03:51 - +---%<------------------------------------------------------------------------- + +These fields mean: + + * priority: none, low, high, sync + * fast sync: How long time ago the last "fast sync" (non-full sync) attempt + was performed. Ideally this is close to the time when the user was last + modified. This doesn't mean that the sync succeeded necessarily. + * full sync: How long time ago the last "full sync" attempt was performed. + This should happen once per 'replication_full_sync_interval'. This doesn't + mean that the sync succeeded necessarily. + * success sync: Time when the last successful sync was performed. If the last + sync succeeded, this is the same as the "fast sync" or the "full sync" + timestap. + * failed: "y" if the last sync failed, "-" if not. + +The current dsync replication status can be looked up with 'doveadm replicator +dsync-status'. This shows the dsync replicator status for each potential dsync +connection, as configured by 'replication_max_conns'. An example output is: + +---%<------------------------------------------------------------------------- +username type status +test100 full Waiting for dsync to finish +test1 normal Waiting for handshake + - Not connected + - Not connected +---%<------------------------------------------------------------------------- + +Here there are 4 lines, meaning 'replication_max_conns=4'. Only two of the +dsync-connections are being used currently. + +The fields mean: + + * username: User currently being replicated. + * type: incremental, normal or full. Most of the replications are + "incremental", while full syncs are "full". A "normal" sync is done when + incremental syncing state isn't available currently. The "incremental" + matches doveadm sync's -s parameter, "full" is -f parameter and "normal" is + the default. + * status: Human-readable status of the connection. These are the current + values: + * Not connected + * Failed to connect to '%s' - last attempt %ld secs ago + * Idle + * Waiting for handshake + * Waiting for dsync to finish + +Failed replication attempts are always automatically retried, so any temporary +problems should get fixed automatically. In case of bugs it may be necessary to +fix something manually. These should be visible in the error logs. So if a user +is marked as failed, try to find any errors logged for the user and see if the +same error keeps repeating in the logs. If you want to debug the dsync, you can +manually trigger it with:'doveadm -D sync -u user@domain -d -N -l 30 -U' (the +parameters after "sync" should be the same as in 'replication_dsync_parameters' +setting). + +Notes +----- + +Random things to remember: + + * The replicas can't share the same quota database, since both will always + update it + * With mdbox format "doveadm purge" won't be replicated + * "doveadm force-resync", "doveadm quota recalc" and other similar fixing + commands don't get replicated + * The servers must have different hostnames or the locking doesn't work and + can cause replication problems. + * v2.2.6+: If you're having trouble, verify that 'dovecot --hostdomain' + returns different values for the servers. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/RunningDovecot.txt b/doc/wiki/RunningDovecot.txt new file mode 100644 index 0000000..0520846 --- /dev/null +++ b/doc/wiki/RunningDovecot.txt @@ -0,0 +1,140 @@ +Running Dovecot +=============== + +Starting +-------- + +Dovecot can simply be started by running 'dovecot' as root. If there are any +problems, they're usually written to terminal, but they may also be written to +<error log> [Logging.txt] as well. + + * A sample universal <init.d script> [DovecotInit.txt]. + * A sample Mac OS X 10.4 <launchd plist file> [LaunchdInstall.txt] + +Stopping +-------- + +Killing the Dovecot master process with a normal TERM signal does a clean +shutdown. This can be done easily with: + +---%<------------------------------------------------------------------------- +doveadm stop +---%<------------------------------------------------------------------------- + +'shutdown_clients' setting controls whether existing IMAP and POP3 sessions are +killed. + +Processes +--------- + +When Dovecot is running, it uses several processes: + +---%<------------------------------------------------------------------------- +# ps auxw|grep "dovecot" +root 7245 0.1 0.1 2308 1096 pts/0 S+ 19:53 0:00 dovecot +dovecot 7246 0.0 0.0 2084 824 pts/0 S+ 19:53 0:00 dovecot/anvil +root 7247 0.0 0.0 2044 908 pts/0 S+ 19:53 0:00 dovecot/log +root 7250 0.0 0.3 4988 3740 pts/0 S+ 19:53 0:00 dovecot/config +root 7251 0.0 0.2 10024 2672 pts/0 S+ 19:53 0:00 dovecot/auth +root 7303 0.6 0.3 10180 3116 pts/0 S+ 19:57 0:00 dovecot/auth +-w +vmail 7252 0.0 0.1 3180 1264 pts/0 S+ 19:53 0:00 dovecot/imap +vmail 7255 0.0 0.1 3228 1596 pts/0 S+ 19:54 0:00 dovecot/pop3 +dovenull 7260 0.0 0.1 4028 1940 pts/0 S+ 19:54 0:00 +dovecot/imap-login +dovenull 7262 0.0 0.1 4016 1916 pts/0 S+ 19:54 0:00 +dovecot/pop3-login +---%<------------------------------------------------------------------------- + + * 'dovecot' process is the Dovecot master process which keeps everything + running. + * 'anvil' keeps track of user connections + * 'log' writes to log files. All logging, except from master process, goes + through it. + * 'config' parses the configuration file and sends the configuration to other + processes. + * 'auth' handles all authentication. + * 'auth -w' process is an "authentication worker" process. It's used only with + some "blocking" authentication databases, such as MySQL. + * 'imap-login' and 'pop3-login' processes handle new IMAP and POP3 connections + until user has logged in. They also handle proxying SSL connections even + after login. + * 'imap' and 'pop3' processes handle the IMAP and POP3 connections after user + has logged in. + +Reloading Configuration +----------------------- + +Sending HUP signal to Dovecot reloads configuration. This can be done easily +with: + +---%<------------------------------------------------------------------------- +doveadm reload +---%<------------------------------------------------------------------------- + +An acknowledgement is written to log file: + +---%<------------------------------------------------------------------------- +Jun 14 19:59:59 master: Warning: SIGHUP received - reloading configuration +---%<------------------------------------------------------------------------- + +Running Multiple Invocations of Dovecot +--------------------------------------- + +You may wish to invoke a second session (or even multiple sessions) of Dovecot +for testing different functionality, configurations, etc. In order to run +multiple instances of Dovecot, you must: + + 1. Create a differently named copy of the dovecot.conf configuration file with + these changes: + 1. Change 'base_dir' to the new run directory + 2. Change services' inet_listener port numbers to new, unused values (in + '10-master.conf'). + 3. Optionally change 'instance_name' to show a different "dovecot/" prefix + in ps output. (v2.0.18+) + 4. If you're using authentication sockets (for SMTP AUTH or deliver), + you'll need to change them as well.'auth_socket_path' specifies the + socket path for deliver. + * Alternatively if all the instances have identical authentication + configuration, you can have only a single Dovecot instance serve the + auth sockets and have the other instances use them. + 2. Invoke 'dovecot' (and 'dovecot-lda') with the '-c' parameter and the + modified configuration file, e.g.:'dovecot -c /usr/local/etc/dovecot2.conf' + + 3. In order to tell the logs apart, you can set different log facilities for + the instances, e.g.'syslog_facility=local6', then configure syslogd to + write local6 into "dovecot-otherinstance.log". Alternatively specify the + log paths directly in 'log_path' and related settings. + +Rotating Log Files +------------------ + +If you specified log file paths manually in 'dovecot.conf' instead of using +syslog, you can send USR1 signal to Dovecot to make it close and reopen the log +files. This can be done easily with: + +---%<------------------------------------------------------------------------- +doveadm log reopen +---%<------------------------------------------------------------------------- + +Troubleshooting +--------------- + +If you can't see the Dovecot processes running after starting 'dovecot', +something is most likely wrong in your 'dovecot.conf'. Look at the error from +Dovecot's log file. See <Logging.txt> for how to find the log. + +If you really can't find any error messages from any logs, try starting Dovecot +with 'dovecot -F'. If you see it crash like: + +---%<------------------------------------------------------------------------- +sh: segmentation fault (core dumped) dovecot -F +---%<------------------------------------------------------------------------- + +Then it's a bug in Dovecot. Please report it with your configuration file. + +If it simply quits without giving any error, then it wrote the error to a log +file and you just didn't find it. Try specifying the log file manually and make +sure you're really looking at the correct file. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SSL.CertificateClientImporting.txt b/doc/wiki/SSL.CertificateClientImporting.txt new file mode 100644 index 0000000..94be09e --- /dev/null +++ b/doc/wiki/SSL.CertificateClientImporting.txt @@ -0,0 +1,65 @@ +SSL certificate importing to clients +==================================== + +You may import either the server's self-signed certificate or the CA +certificate (see <SSL.CertificateCreation.txt>). + +Windows XP +---------- + +Import to Trusted Root Certification Authorities store: +http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sag_cmprocsimport.mspx?mfr=true + +Outlook and Outlook Express uses the Windows's certificate store. + +Mac OS X +-------- + + * Doubleclick the certificate + * Keychain should open + * Add the certificate to X509 Anchors keychain + +Apple Mail uses the OS X's certificate store. + +Thunderbird +----------- + +Preferences -> Privacy -> Security -> View Certificates -> Authorities -> +Import -> Trust this CA to identify email users. + +Opera Mail +---------- + +Preferences -> Advanced > Security > Certificates > Import certificate file. + +Evolution +--------- + +Preferences -> Certificates -> Authorities -> Import -> Trust this CA to +identify email users. + +Pine +---- + +http://www.madboa.com/geek/pine-ssl/ tells a story how to do this. Basically it +seems to be: + + 1. Find out your OPENSSLDIR: 'openssl version -d' + 2. Get a hash of your certificate: 'openssl x509 -in cert.pem -hash -noout' + 3. Copy the certificate to '$OPENSSLDIR/certs/$hash.0' + +This probably works only for self-signed certificates. + +KMail +----- + +Instructions needed. + +Claws Mail +---------- + +Configuration -> Edit accounts (Choose here your's one and press 'Edit'-button) + +Account -> SSL -> Certificate for receiving->Browse + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SSL.CertificateCreation.txt b/doc/wiki/SSL.CertificateCreation.txt new file mode 100644 index 0000000..59dcfe0 --- /dev/null +++ b/doc/wiki/SSL.CertificateCreation.txt @@ -0,0 +1,93 @@ +SSL certificate creation +======================== + +Self-signed SSL certificates +---------------------------- + +Self-signed SSL certificates are the easiest way to get your SSL server +working. However unless you take some action to prevent it,*this is at the cost +of security*: + + * The first time the client connects to the server, it sees the certificate + and asks the user whether to trust it. The user of course doesn't really + bother verifying the certificate's fingerprint, so a man-in-the-middle + attack can easily bypass all the SSL security, steal the user's password and + so on. + * If the client was lucky enough not to get attacked the first time it + connected, the following connections will be secure as long as the client + had permanently saved the certificate. Some clients do this, while others + have to be manually configured to accept the certificate. + +The only way to be fully secure is to import the SSL certificate to client's +(or operating system's) list of trusted CA certificates prior to first +connection. See <SSL.CertificateClientImporting.txt> how to do it for different +clients. + +Self-signed certificate creation +-------------------------------- + +Dovecot includes a script to build self-signed SSL certificates using OpenSSL. +In the source distribution this exists in doc/mkcert.sh +[http://dovecot.org/doc/mkcert.sh]. Binary installations usually create the +certificate automatically when installing Dovecot and don't include the script. + +The SSL certificate's configuration is taken from doc/dovecot-openssl.cnf +[http://dovecot.org/doc/dovecot-openssl.cnf] file. Modify the file before +running mkcert.sh. Especially important field is the CN (Common Name) field, +which should contain your server's host name. The clients will verify that the +CN matches the connected host name, otherwise they'll say the certificate is +invalid. It's also possible to use wildcards (eg. *.domain.com) in the host +name. They should work with most clients. + +By default the certificate is created to '/etc/ssl/certs/dovecot.pem' and the +private key file is created to '/etc/ssl/private/dovecot.pem'. Also by default +the certificate will expire in 365 days. If you wish to change any of these, +modify the mkcert.sh script. + +Certificate Authorities +----------------------- + +The correct way to use SSL is to have each SSL certificate signed by an +Certificate Authority (CA). The client has a list of trusted Certificate +Authorities, so whenever it sees a new SSL certificate signed by a trusted CA, +it will automatically trust the new certificate without asking the user any +questions. + +There are two ways to get a CA signed certificate: get it from an external CA, +or create your own CA. + +The clients have a built-in list of trusted CAs, so getting it from one of +those CAs will have the advantage of the certificate working without any client +configuration. There are already-trusted-CAs where you can buy the certificate, +and there are already-trusted-CAs where you can get your certificate for free. +On the oher hand, if you create your own CA, you'll have to install the CA +certificate to all the clients (see <SSL.CertificateClientImporting.txt>). + +So the two options end up being three: + + * a) Get it from an external CA (which already have the public keys installed + on the clients, so the clients trust the CA) + * a.1) Purchase the certificate. + * a.2) Get a free certificate. + * b) Create your own CA (in this case you'll have to add the CA public keys + into the clients, as you are bot trusted by default) + +If you choose "a.2)", there is letsencrypt.org [https://letsencrypt.org/] where +you need to do some technical effort to demonstrate to a robot that you own the +domains for which the certificate is issued. Let's encrypt is an initiative of +the Internet Security Research Group (ISRG), with board members from Cisco, +Mozilla and the University of Michingan among others and technical advisors +from Akamai, Google, Electronic Frontier Foundation, Internet Sociaty and +independents among others. Let's encrypt CA is trusted by default by many +clients. If you can control the entries in your DNS, you'll be able to +demonstrate to the robot that "you are you" for domain-based identities. There +is this specific conversation about letsencrypt + dovecot here +[https://community.letsencrypt.org/t/simple-guide-using-lets-encrypt-ssl-certs-with-dovecot/2921]. + +If you choose "b)", there are multiple different tools for managing your own +CA. The simplest way is to use a CA managing tool as gnoMint +[http://gnomint.sourceforge.net/] or TinyCA [http://tinyca.sm-zone.net/]. +However, if you need to tailor the properties of the CA, you always can use +OpenSSL, very much customizable, but however a bit cumbersome. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SSL.DovecotConfiguration.txt b/doc/wiki/SSL.DovecotConfiguration.txt new file mode 100644 index 0000000..fb70671 --- /dev/null +++ b/doc/wiki/SSL.DovecotConfiguration.txt @@ -0,0 +1,522 @@ +Dovecot SSL configuration +========================= + +Contents + + + 1. Dovecot SSL configuration + + 1. Multiple SSL certificates + + 1. Different certificates per algorithm + + 2. Different certificates per IP and protocol + + 3. With client TLS SNI (Server Name Indication) support + + 2. Password protected key files + + 3. Chained SSL certificates + + 4. SSL security settings + + 5. SSL verbosity + + 6. Client certificate verification/authentication + + 7. Testing + + 8. Testing CA + + 1. Testing CA On Debian + + 2. Testing CA On RHEL + + 3. Testing CA Success + + 9. Client connections + +The most important SSL settings are (in 'conf.d/10-ssl.conf'): + +---%<------------------------------------------------------------------------- +ssl = yes +# Preferred permissions: root:root 0444 +ssl_cert = </etc/ssl/certs/dovecot.pem +# Preferred permissions: root:root 0400 +ssl_key = </etc/ssl/private/dovecot.pem +---%<------------------------------------------------------------------------- + +The '<' is mandatory. It indicates that the variable should contain *contents* +of the file, instead of the file name. Not using it will cause an error. + +The certificate file can be world-readable, since it doesn't contain anything +sensitive (in fact it's sent to each connecting SSL client). The key file's +permissions should be restricted to only root (and possibly ssl-certs group or +similar if your OS uses such). Dovecot opens both of these files while still +running as root, so you don't need to give Dovecot any special permissions to +read them (in fact:*do not give dovecot user any permissions to the key file*). + +It's possible to keep the certificate and the key both in the same file: + +---%<------------------------------------------------------------------------- +# Preferred permissions: root:root 0400 +ssl_cert = </etc/ssl/dovecot.pem +ssl_key = </etc/ssl/dovecot.pem +---%<------------------------------------------------------------------------- + +It's also possible to use different certificates for IMAP and POP3. However its +important to note that "ssl = yes" must be set globally if you require SSL for +any protocol (or dovecot will not listen on the SSL ports), which in turn +requires that a certificate and key are specified globally even if you intend +to specify certificates per protocol. The per protocol certificate settings +override the global setting.: + +---%<------------------------------------------------------------------------- +protocol imap { + ssl_cert = </etc/ssl/certs/imap.pem + ssl_key = </etc/ssl/private/imap.pem +} +protocol pop3 { + ssl_cert = </etc/ssl/certs/pop3.pem + ssl_key = </etc/ssl/private/pop3.pem +} +---%<------------------------------------------------------------------------- + +There are a couple of different ways to specify when SSL/TLS is required: + + * 'ssl=no': SSL/TLS is completely disabled. + * 'ssl=yes' and 'disable_plaintext_auth=no': SSL/TLS is offered to the client, + but the client isn't required to use it. The client is allowed to login with + plaintext authentication even when SSL/TLS isn't enabled on the connection. + This is insecure, because the plaintext password is exposed to the internet. + * 'ssl=yes' and 'disable_plaintext_auth=yes': SSL/TLS is offered to the + client, but the client isn't required to use it. The client isn't allowed to + use plaintext authentication, unless SSL/TLS is enabled first. However, if + <non-plaintext authentication mechanisms> [Authentication.Mechanisms.txt] + are enabled they are still allowed even without SSL/TLS. Depending on how + secure they are, the authentication is either fully secure or it could have + some ways for it to be attacked. + * 'ssl=required': SSL/TLS is always required, even if non-plaintext + authentication mechanisms are used. Any attempt to authenticate before + SSL/TLS is enabled will cause an authentication failure. + * NOTE: If you have only plaintext mechanisms enabled (e.g. 'auth { mechanisms + = plain login }'), 'ssl=yes' and 'ssl=required' are completely equivalent + because in either case the authentication will fail unless SSL/TLS is + enabled first. + * NOTE2: With both 'ssl=yes' and 'ssl=required' it's still possible that the + client attempts to do a plaintext authentication before enabling SSL/TLS, + which exposes the plaintext password to the internet. Dovecot attempts to + indicate this to the IMAP clients via the LOGINDISABLED capability, but many + clients still ignore it and send the password anyway. There is unfortunately + no way for Dovecot to prevent this behavior. The POP3 standard doesn't have + an equivalent capability at all, so the POP3 clients can't even know if the + server would accept a plaintext authentication. + * The main difference between 'ssl=required' and 'disable_plaintext_auth=yes' + is that if 'ssl=required', it guarantees that the entire connection is + protected against eavesdropping (SSL/TLS encrypts the rest of the + connection), while 'disable_plaintext_auth=yes' only guarantees that the + password is protected against eavesdropping (SASL mechanism is encrypted, + but no SSL/TLS is necessarily used). Nowadays you most likely should be + using SSL/TLS anyway for the entire connection, since the cost of SSL/TLS is + cheap enough. Using both SSL/TLS and non-plaintext authentication would be + the ideal situation since it protects the plaintext password even against + man-in-the-middle attacks. + +Note that plaintext authentication is always allowed (and SSL not required) for +connections from localhost, as they're assumed to be secure anyway. This +applies to all connections where the local and the remote IP addresses are +equal. Also IP ranges specified by 'login_trusted_networks' setting are assumed +to be secure. + +Multiple SSL certificates +------------------------- + +Different certificates per algorithm +------------------------------------ + +Since v2.2.31+ you can specify alternative ssl certificate that will be used if +the algorithm differs from the primary certificate. This is useful when +migrating to e.g. ECDSA certificate. + +---%<------------------------------------------------------------------------- +ssl_alt_cert=</path/to/alternative/cert.pem +ssl_alt_key=</path/to/alternative/key.pem +---%<------------------------------------------------------------------------- + +Different certificates per IP and protocol +------------------------------------------ + +If you have multiple IPs available, this method is guaranteed to work with all +clients. + +---%<------------------------------------------------------------------------- +local 192.0.2.10 { # instead of IP you can also use hostname, which will be +resolved + protocol imap { + ssl_cert = </etc/ssl/dovecot/imap-01.example.com.cert.pem + ssl_key = </etc/ssl/dovecot/imap-01.example.com.key.pem + } + + protocol pop3 { + ssl_cert = </etc/ssl/dovecot/pop-01.example.com.cert.pem + ssl_key = </etc/ssl/dovecot/pop-01.example.com.key.pem + } +} + +local 192.0.2.20 { + protocol imap { + ssl_cert = </etc/ssl/dovecot/imap-02.example.com.cert.pem + ssl_key = </etc/ssl/dovecot/imap-02.example.com.key.pem + } + + protocol pop3 { + ssl_cert = </etc/ssl/dovecot/pop-02.example.com.cert.pem + ssl_key = </etc/ssl/dovecot/pop-02.example.com.key.pem + } +} +---%<------------------------------------------------------------------------- + +Note that you will still need a top-level "default" 'ssl_key' and 'ssl_cert' as +well, or you will receive errors. + +---%<------------------------------------------------------------------------- +# doveconf -n +doveconf: Error: ssl enabled, but ssl_cert not set +---%<------------------------------------------------------------------------- + +With client TLS SNI (Server Name Indication) support +---------------------------------------------------- + +/It is important to note that having multiple SSL certificates per IP will not +be compatible with all clients, especially mobile ones. It is a TLS SNI +limitation./ See <SSL.SNIClientSupport.txt> for list of clients known to (not) +support SNI. + +---%<------------------------------------------------------------------------- +local_name imap.example.org { + ssl_cert = </etc/ssl/certs/imap.example.org.crt + ssl_key = </etc/ssl/private/imap.example.org.key +} +local_name imap.example2.org { + ssl_cert = </etc/ssl/certs/imap.example2.org.crt + ssl_key = </etc/ssl/private/imap.example2.org.key +} +# ..etc.. +---%<------------------------------------------------------------------------- + +Password protected key files +---------------------------- + +SSL key files may be password protected. There are two ways to provide Dovecot +with the password: + + 1. Starting Dovecot with 'dovecot -p' asks the password. It's not stored + anywhere, so this method prevents Dovecot from starting automatically at + startup. + 2. 'ssl_key_password' setting. Note that 'dovecot.conf' is by default + world-readable, so you probably shouldn't place it there directly. Instead + you could store it in a different file, such as '/etc/dovecot-private.conf' + containing: + + ---%<--------------------------------------------------------------------- + ssl_key_password = secret + ---%<--------------------------------------------------------------------- + + and then use '!include_try /etc/dovecot-private.conf' in the main + 'dovecot.conf'. + +Chained SSL certificates +------------------------ + +Put all the certificates in the 'ssl_cert' file. For example when using a +certificate signed by TDC the correct order is: + + 1. Dovecot's public certificate + 2. TDC SSL Server CA + 3. TDC Internet Root CA + 4. Globalsign Partners CA + +SSL security settings +--------------------- + +When Dovecot starts up for the first time, it generates new 512bit and 1024bit +Diffie Hellman parameters and saves them into +'<prefix>/var/lib/dovecot/ssl-parameters.dat'. Dovecot v2.1.x and older +regenerated them every week by default, but because the extra security gained +by the regeneration is quite small, Dovecot v2.2 disabled the regeneration +feature completely. + + * Since v2.3.3+ Diffie-Hellman parameters have been made optional, and you are + encouraged to disable non-ECC DH algorithms completely. + +From and up to version 2.2, you can specify the wanted DH parameters length +using: + +---%<------------------------------------------------------------------------- +ssl_dh_parameters_length = 2048 +---%<------------------------------------------------------------------------- + +From version 2.3, you must specify path to DH parameters file using: + +---%<------------------------------------------------------------------------- +ssl_dh=</path/to/dh.pem +---%<------------------------------------------------------------------------- + +To generate new parameters file, you can use: + +---%<------------------------------------------------------------------------- +# This might take a very long time. Run it on a machine with sufficient +entropy. +openssl dhparam 4096 > dh.pem +---%<------------------------------------------------------------------------- + +You can also convert an old v2.2 parameters file with command: + +---%<------------------------------------------------------------------------- +dd if=/path/to/ssl-parameters.dat bs=1 skip=88 | openssl dhparam -inform DER +---%<------------------------------------------------------------------------- + +This should work most of the times. If not, generate new file. + +By default Dovecot's allowed ciphers list contains: + +---%<------------------------------------------------------------------------- +ssl_cipher_list = +ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH +---%<------------------------------------------------------------------------- + +Disallowing more won't really gain any security for those using better ciphers, +but it does prevent people from accidentally using insecure ciphers. See +http://www.openssl.org/docs/apps/ciphers.html for a list of the ciphers. + +You should usually prefer server ciphers and their order, so setting + +---%<------------------------------------------------------------------------- +ssl_prefer_server_ciphers=yes +---%<------------------------------------------------------------------------- + +is recommended. + +SSL verbosity +------------- + +---%<------------------------------------------------------------------------- +verbose_ssl = yes +---%<------------------------------------------------------------------------- + +This will make Dovecot log all the problems it sees with SSL connections. Some +errors might be caused by dropped connections, so it could be quite noisy. + +Client certificate verification/authentication +---------------------------------------------- + +If you want to require clients to present a valid SSL certificate, you'll need +these settings: + +---%<------------------------------------------------------------------------- +ssl_ca = </etc/ssl/ca.pem +ssl_verify_client_cert = yes + +auth_ssl_require_client_cert = yes +#auth_ssl_username_from_cert = yes +---%<------------------------------------------------------------------------- + +The CA file should contain the certificate(s) followed by the matching CRL(s). +Note that the CRLs are required to exist. For a multi-level CA place the +certificates in this order: + + 1. Issuing CA cert + 2. Issuing CA CRL + 3. Intermediate CA cert + 4. Intermediate CA CRL + 5. Root CA cert + 6. Root CA CRL + +The certificates and the CRLs have to be in PEM format. To convert a DER format +CRL (e.g.http://crl.cacert.org/class3-revoke.crl) into PEM format, use: + +---%<------------------------------------------------------------------------- +openssl crl -in class3-revoke.crl -inform DER -outform PEM > class3-revoke.pem +---%<------------------------------------------------------------------------- + +With the above settings if a client connects which doesn't present a +certificate signed by one of the CAs in the 'ssl_ca' file, Dovecot won't let +the user log in. This could present a problem if you're using Dovecot to +provide SASL authentication for an MTA (such as Postfix) which is not capable +of supplying client certificates for SASL authentication. If you need Dovecot +to provide SASL authentication to an MTA without requiring client certificates +and simultaneously provide IMAP service to clients while requiring client +certificates, you can put 'auth_ssl_require_client_cert = yes' inside of a +protocol block as shown below to make an exemption for SMTP SASL clients (such +as Postfix). + +---%<------------------------------------------------------------------------- +protocol !smtp { + auth_ssl_require_client_cert = yes +} +---%<------------------------------------------------------------------------- + +You may also force the username to be taken from the certificate by setting +'auth_ssl_username_from_cert = yes'. + + * The text is looked up from subject DN's specified field using OpenSSL's + 'X509_NAME_get_text_by_NID()' function. + * By default the 'CommonName' field is used. + * You can change the field with 'ssl_cert_username_field = name' setting + (parsed using OpenSSL's 'OBJ_txt2nid()' function). 'x500UniqueIdentifier' is + a common choice. + +You may also want to disable the password checking completely. Doing this +currently circumvents Dovecot's security model so it's not recommended to use +it, but it is possible by making the <passdb> [PasswordDatabase.txt] allow +logins using any password (typically requiring <"nopassword" extra field> +[PasswordDatabase.ExtraFields.txt] to be returned). + +Testing +------- + +Try out your new setup: + +---%<------------------------------------------------------------------------- +openssl s_client -servername mail.sample.com -connect mail.sample.com:pop3s +---%<------------------------------------------------------------------------- + +You should see something like this: + +---%<------------------------------------------------------------------------- +CONNECTED(00000003) +depth=2 /O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing +Authority/emailAddress=support@cacert.org +verify error:num=19:self signed certificate in certificate chain +verify return:0 +--- +Certificate chain + 0 s:/CN=mail.example.com + i:/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root + 1 s:/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root + i:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing +Authority/emailAddress=support@cacert.org + 2 s:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing +Authority/emailAddress=support@cacert.org + i:/O=Root CA/OU=http://www.cacert.org/CN=CA Cert Signing +Authority/emailAddress=support@cacert.org +--- +Server certificate +-----BEGIN CERTIFICATE----- +MIIE1DCCArygAwIBAgIDAMBPMA0GCSqGSIb3DQEBBAUAMFQxFDASBgNVBAoTC0NB +Y2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5vcmcxHDAaBgNV +BAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwHhcNMTAxMjIwMTM1NDQ1WhcNMTIxMjE5 +MTM1NDQ1WjAmMSQwIgYDjksadnjkasndjksandjksandjksandj5YXJlYS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3jOX3FC8wVqnb2r65Sfvk +cYUpJhlbhCfqPdN41c3WS0y1Jwwum1q4oMAJvdRnD5TMff1+fqTFy3lS1sYxIXiD +kBRo478eNqzXHMpBOqbvKjYp/UZgWUNA9ebI1nQtwd7rnjmm/GrtyItjahCsgzDS +qPAie+mXYzuT49ZoG+Glg7/R/jDcLMcJY0d5eJ7kufB1RLhvRitZD4FEbJVehqhY +aevf5bLk1BNFhzRBfLXmv6u/kfvWf2HjGAf0aFhaQyiAldDgnZrvaZOFjkToJk27 +p9MguvwGmbciao0DmMjcJhQ0smclFwy8Kj98Tz+nTkfAlU8jJdb1J/tIatJdpSRh +AgMBAAGjgdwwgdkwDAYDVR0TAQH/BAIwADA0BgNVHSUELTArBggrBgEFBQcDAgYI +KwYBBQUHAwEGCWCGSAGG+EIEAQYKKwYBBAGCNwoDAzALBgNVHQ8EBAMCBaAwMwYI +KwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhadodHRwOi8vb2NzcC5jYWNlcnQub3Jn +LzBRBgNVknsadkjasnjdksandjksandjsnNlY3VyaXR5YXJlYS5vcmegKQYIKwYB +BQUHCAWgHQwbbWFpbC5qb2ludC5zZWN1cml0eWFyZWEub3JnMA0GCSqGSIb3DQEB +BQUAA4ICAQAX8ceObvUZNKYTlNQ/cv0BiA1XweRsVNca1ILACNLdVPR9mvf+aXCh +ODkHaZAmGngj1DfD4fJsTbaydGWSPeVH91Qi9F+Pi6szhsxylI83NKbuXihcenuG +twnte8aIb5FelVHttLQPSKRR62E8YmDWk3KYivuFAuZqDaGnWc5yeneTBpsGter/ +4awqsgymBK2YEg1HIWMPaRBvwzCVN/yUyWhFH9Nj11f/xgZE87VXrjLHWT/73i2Z +S4uIZ2KHQUYuxMGldgpXm+QxFM8DGA6z1T1oPCVfW85cezlfr8QVvX6SXZrAUNL0 +3D5YPzQuevW+5CrqnGA+F5ff4mBMl8R8Sg0+0LoLqt5PbpGyTt9vS1INZCdfvtIA +/d7Ae7Xp9W8FVRqd7tvNMIy3ZA0/wNMDUczkhC/YtvHfMELpjtMJAGF15OtO7Vik +V+FZnBP1Yd7760dtEmd6bF8vjcXCvDdxwGtcAehAUpIgAWvkHHOt8+H56tkFENAP +/ZpJ+Wr+K3lxkkG+BN1bucxMuAdVyTpFyZfKDHRXIO/5e0hpPOaTO+obD3kifzdh +yy7KmdKvDclHTiPuonJBzEXeM3JQBjcDHbMSyA6+38yBcso27h9VqCQJB2cZmSlW +ArS/9wt2X21KgeuGHlTZ/8z9gXAjQKXhDYECWWd6LkWl98ZDBihslQ== +-----END CERTIFICATE----- +subject=/CN=mail.example.com +issuer=/O=CAcert Inc./OU=http://www.CAcert.org/CN=CAcert Class 3 Root +--- +No client certificate CA names sent +--- +SSL handshake has read 5497 bytes and written 293 bytes +--- +New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA +Server public key is 2048 bit +Secure Renegotiation IS supported +Compression: zlib compression +Expansion: zlib compression +SSL-Session: + Protocol : TLSv1 + Cipher : DHE-RSA-AES256-SHA + Session-ID: +114A22BE4625B33F6893124ACF640AE0628B48B5039E90B3B9A20ADF7FA691F3 + Session-ID-ctx: + Master-Key: +B8A55EC91A060575CFB29503FBF7160C2DC8BCBFE02D20A7F704882F72D8D00272D8D002CE5CCC4B94A492F43ED8F + Key-Arg : None + TLS session ticket: + 0000 - 86 c7 46 63 a5 b6 48 74-16 d8 e0 a7 e2 64 e8 89 ..Fc..Ht.....d.. + 0010 - 97 90 59 4b 57 f3 e2 b3-e2 d2 88 90 a8 aa b4 44 ..YKW..........D + 0020 - ea 24 08 5e b4 14 7f e1-2a 1a 1c 40 ca 85 e7 41 .$.^....*..@...A + 0030 - 9d 0d a8 4c f7 e3 db 1e-ef da 53 9c fe 43 cc 62 ...L......S..C.b + 0040 - 79 b6 ad ea 9d cf ca b2-37 41 b7 0f ea 7d 59 e8 y.......7A...}Y. + 0050 - 10 01 a0 eb dc c2 63 66-56 54 6a e8 3a 4b 93 49 ......cfVTj.:K.I + 0060 - 77 da e4 4b 21 e8 30 7e-bf 10 91 3a 2c f9 59 80 w..K!.0~...:,.Y. + 0070 - 01 1f 36 0b 92 85 67 55-c8 86 1d 44 b1 6f 0d ae ..6...gU...D.o.. + 0080 - 15 36 b6 49 3a ef 94 9a-ef 6d 27 f0 80 20 43 09 .6.I:....m'.. C. + 0090 - be 70 c5 30 15 3b 93 c6-c1 4c e9 7f 5c 34 98 dd .p.0.;...L..\4.. + + Compression: 1 (zlib compression) + Start Time: 1292857721 + Timeout : 300 (sec) + Verify return code: 19 (self signed certificate in certificate chain) +--- ++OK Dovecot ready. +---%<------------------------------------------------------------------------- + +Testing CA +---------- + +The above test procedure returns: + +---%<------------------------------------------------------------------------- + Verify return code: 19 (self signed certificate in certificate chain) +---%<------------------------------------------------------------------------- + +which is expected result since test command omits option to verify CA root +certificate. The following commands will enable CA root certificate +validation. + +Testing CA On Debian +-------------------- + +On Debian derived distributions try: + +---%<------------------------------------------------------------------------- +openssl s_client -CApath /etc/ssl/certs -connect mail.sample.com:pop3s +---%<------------------------------------------------------------------------- + +Testing CA On RHEL +------------------ + +On Red Hat Enterprise Linux derived distributions try: + +---%<------------------------------------------------------------------------- +openssl s_client -CAfile /etc/pki/tls/cert.pem -connect mail.sample.com:pop3s +---%<------------------------------------------------------------------------- + +Testing CA Success +------------------ + +---%<------------------------------------------------------------------------- + Verify return code: 0 (ok) +---%<------------------------------------------------------------------------- + +Client connections +------------------ + +Since v2.3.4 dovecot accepts default system CAs for outgoing connections. + +---%<------------------------------------------------------------------------- +ssl_client_ca_dir = /path/to/pem/certificates +ssl_client_ca_file = /path/to/pem/bundle +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SSL.SNIClientSupport.txt b/doc/wiki/SSL.SNIClientSupport.txt new file mode 100644 index 0000000..ba65cc7 --- /dev/null +++ b/doc/wiki/SSL.SNIClientSupport.txt @@ -0,0 +1,21 @@ +TLS SNI Client Support +====================== + +Works: + + * Thunderbird (Linux) + * K-9 on Android (merged Sept 2015 - https://github.com/k9mail/k-9/pull/718) + * Apple Mail (according to + https://forums.cpanel.net/threads/mail-ssl-sni.454592/ ) + * Mutt (ticket https://dev.mutt.org/trac/ticket/3923) + * <NeoMutt.txt> (since 2016-03-07 according to + https://www.neomutt.org/feature/tls-sni) + +Doesn't work: + + * K-9 on Droid X2 (maybe fixed in newer versions - see above) + * Apple Mail (Mac OS X 10.10 and lower AND iOS 9.3 and lower) + * Outlook for Mac version 15 (according to + https://forums.cpanel.net/threads/mail-ssl-sni.454592/ ) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SSL.txt b/doc/wiki/SSL.txt new file mode 100644 index 0000000..7e32883 --- /dev/null +++ b/doc/wiki/SSL.txt @@ -0,0 +1,65 @@ +SSL +=== + + * <Creating SSL certificates> [SSL.CertificateCreation.txt] + * <Configuring Dovecot to use SSL certificates> [SSL.DovecotConfiguration.txt] + + * <Importing CAs and self-signed SSL certificates to clients> + [SSL.CertificateClientImporting.txt] + * SSL works pretty much the same universally, so for more information about + SSL you can see for example Apache's documentation + [http://httpd.apache.org/docs/2.2/ssl/]. + * Dovecot uses OpenSSL, so whatever information you find about it applies also + to Dovecot. + +SSL, TLS and STARTTLS confusion +------------------------------- + +SSL and TLS terms are often used in confusing ways: + + * SSL (Secure Sockets Layer) is the original protocol implementation. SSLv3 is + still allowed by Dovecot, but it's rarely used. Some clients use SSL to mean + that they're going to connect to the imaps (993), pop3s (995) or smtps (465) + port, although they're still going to use TLSv1 protocol. + * TLS (Transport Layer Security) replaced the SSL protocol. TLSv1 protocol is + used practically always nowadays. Some clients use TLS to mean that they're + going to use STARTTLS command after connecting to the standard imap (143), + pop3 (110) or smtp port (25/587). Nothing would prevent using SSLv3 protocol + after STARTTLS command. + +Unfortunately there doesn't seem to be any clear and simple way to refer to +these different meanings. SSL term is much more widely understood than TLS, so +Dovecot configuration and this documentation only talks about SSL when in fact +it means both SSL/TLS. + +Originally SSL support was added to protocols by giving them a separate "SSL +port" (imaps, pop3s, etc.), where the SSL handshake starts immediately when +client connects, and only after the session is encrypted the regular protocol +handling begins. Using two separate ports for plaintext and SSL connections was +thought to be wasteful and adds complexity for clients which may wish to make +use of SSL when it is advertised, so STARTTLS command was added and intended to +deprecate the SSL ports. Clients using STARTTLS work by connecting to the +regular unencrypted port and immediately issue a STARTTLS command, after which +the session is encrypted. After SSL handshake there is no difference between +SSL port initiated connections and STARTTLS initiated connections. + +SSL port deprecation never really happened, probably because of a few reasons: + + * Some admins don't even know about STARTTLS. + * Some admins want to require SSL/TLS, but don't realize that this is also + possible with STARTTLS (Dovecot has 'disable_plaintext_auth=yes' and + 'ssl=required' settings). + * Some admins understand everything, but still prefer to allow only SSL ports + (maybe with a firewall). This could be because it makes it easier to ensure + that no information is leaked, because SSL/TLS handshake happens + immediately. Some clients unfortunately try to do plaintext authentication + without STARTTLS, even when IMAP server has told the client that it won't + work. Besides, it requires fewer round-trips if you begin SSL upon + connection when you know you want it, instead of connect, negotiate + capabilities, insist on TLS, then start all over again inside the encrypted + session. + * According to some reports (like this + [https://it.slashdot.org/story/14/11/11/2349244/isps-removing-their-customers-email-encryption]) + STARTTLS can not guarantee encrypted delivery of mail. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Sasl.txt b/doc/wiki/Sasl.txt new file mode 100644 index 0000000..940f187 --- /dev/null +++ b/doc/wiki/Sasl.txt @@ -0,0 +1,27 @@ +SASL +==== + +SASL stands for "Simple Authentication and Security Layer". SASL itself is +nothing more than a list of requirements for <authentication mechanisms> +[Authentication.Mechanisms.txt] and protocols to be SASL-compatible as +described in RFC 4422 [http://www.ietf.org/rfc/rfc4422.txt]. IMAP, POP3 and +SMTP protocols all have support for SASL. + +Many people confuse SASL with one specific SASL implementation: the Cyrus SASL +library. Dovecot has its own SASL implementation which may at some point be +separated from Dovecot itself to "compete" against Cyrus SASL library in server +side. + +Dovecot SASL can already be used with: + + * Postfix *v2.3* and later. See <HowTo.PostfixAndDovecotSASL.txt> for details. + + * Exim *v4.64* and later. See <HowTo.EximAndDovecotSASL.txt> for details. + * chasquid [https://blitiri.com.ar/p/chasquid] *v0.04* and later. See + <HowTo.ChasquidAndDovecotSASL.txt> for details. + * Prosody (with mod_auth_dovecot) + * ejabberd (with check_dovecot.pl) + +Hopefully more software will follow. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SecurityTuning.txt b/doc/wiki/SecurityTuning.txt new file mode 100644 index 0000000..90a2dfa --- /dev/null +++ b/doc/wiki/SecurityTuning.txt @@ -0,0 +1,22 @@ +Security tuning +=============== + +Dovecot is pretty secure out-of-the box. It uses multiple processes and +privilege separation to isolate different parts from each others in case a +security hole is found from one part. + +Some things you can do more: + + * Allocate each user their own UID and GID (see <UserIds.txt>) + * Use a separate /dovecot-auth/ user for authentication process (see + <UserIds.txt>) + * You can chroot authentication and mail processes (see <Chrooting.txt>) + * Compiling Dovecot with garbage collection ('--with-gc' configure option) + fixes at least in theory any security holes caused by double free()s. + However this hasn't been tested much and there may be problems. + * There are some security related SSL settings (see + <SSL.DovecotConfiguration.txt>) + * Set 'first/last_valid_uid/gid' settings to contain only the range actually + used by mail processes + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Services.txt b/doc/wiki/Services.txt new file mode 100644 index 0000000..67904ec --- /dev/null +++ b/doc/wiki/Services.txt @@ -0,0 +1,502 @@ +Service configuration +===================== + +Contents + + + 1. Service configuration + + 1. Service basics + + 2. Service privileges + + 3. Service limits + + 4. Service listeners + + 1. unix_listeners and fifo_listeners + + 2. inet_listeners + + 2. Default services + + 1. anvil + + 2. auth + + 3. auth-worker + + 4. config + + 5. dict + + 6. director + + 7. dns_client + + 8. doveadm + + 9. imap, pop3, submission, managesieve + + 10. imap-login, pop3-login, submission-login, managesieve-login + + 11. indexer + + 12. indexer-worker + + 13. ipc + + 14. lmtp + + 15. log + + 16. ssl-params + + 17. stats + +This page describes Dovecot's services comprehensively. Most admins don't need +to know these details. The important service settings are described in the +'example-config/conf.d/10-master.conf' file. + +Service basics +-------------- + +executable: + The binary path to execute and its parameters. If the path doesn't begin with + '/', it's relative to *base_dir*. + +type: + Type of this service: + * "" is the default. + * "startup" creates one process at startup. For example SSL parameters are + generated at startup because of this, instead of only after the first SSL + connection arrives. + * "login" is used by login processes. The login processes have "all + processes full" notification fd. It's used by the processes to figure out + when no more client connections can be accepted because client and process + limits have been reached. The login processes can then kill some of their + oldest connections that haven't logged in yet. + * "log", "config" and "anvil" are treated specially by these specific + processes. + +protocol: + If non-empty, this service is enabled only when the protocol name is listed + in *protocols* setting. + +idle_kill: + If a process doesn't appear to be doing anything after this much time, notify + it that it should kill itself if it's not doing anything.*process_min_avail* + setting overrides this. If set to 0,*default_idle_kill* is used. + +Service privileges +------------------ + +user: + UNIX user (UID) which runs this process. *default_login_user* setting's value + should be used for type=login processes and *default_internal_user* should be + used for other processes that don't require root privileges. + +group: + The primary UNIX group (GID) which runs this process. + +extra_groups: + Secondary UNIX groups that this process belongs to. + +privileged_group: + Secondary UNIX group, which is disabled by default, but can be enabled by the + process. This setting is probably never needed + directly.*mail_privileged_group* setting is a more user friendly way to use + this setting for mail processes. + +chroot: + The processes are chrooted to this directory at startup. Relative to + *base_dir*. + +drop_priv_before_exec: + Drop all privileges after forking, but before executing the binary. This is + mainly useful for dumping core files on non-Linux OSes, since the processes + are no longer in "setuid" mode. This setting can't be used with non-empty + chroot. + +Service limits +-------------- + +client_limit: + Maximum number of simultaneous client connections per process. Once this + number of connections is received, the next incoming connection will prompt + Dovecot to spawn another process. If set to 0,*default_client_limit* is used + instead. + +service_count: + Number of client connections to handle until the process kills itself. 0 + means unlimited. 1 means only a single connection is handled until the + process is stopped - this is the most secure choice since there's no way for + one connection's state to leak to the next one. For better performance this + can be set higher, but ideally not unlimited since more complex services can + have small memory leaks and/or memory fragmentation and the process should + get restarted eventually. For example 100..1000 can be good values. + +process_limit: + Maximum number of processes that can exist for this service. If set to 0, + *default_process_limit* is used instead. + +process_min_avail: + Minimum number of processes that always should be available to accept more + client connections. For service_count=1 processes this decreases the latency + for handling new connections. For service_count!=1 processes it could be set + to the number of CPU cores on the system to balance the load among them. + +vsz_limit: + Limit the process's address space (both RLIMIT_DATA and RLIMIT_AS if + available). When the space is reached, some memory allocations may start + failing with "Out of memory", or the kernel may kill the process with signal + 9. This setting is mainly intended to prevent memory leaks from eating up all + of the memory, but there can be also legitimate reasons why the process + reaches this limit. For example a huge mailbox may not be accessed if this + limit is too low. The default value (18446744073709551615 = 2^64-1) sets the + limit to *default_vsz_limit*, while 0 disables the limit entirely. + +There are 3 types of services that need to be optimized in different ways: + + 1. Master services (e.g. auth, anvil, indexer, director, log): + * Currently there isn't any easy way to optimize these. If these become a + bottleneck, typically you need to run another Dovecot server. In some + cases it may be possible to create multiple master processes and have + each one be responsible for only specific users/processes, although this + may also require some extra development. + 2. Services that do disk I/O or other blocking operations (e.g. imap, pop3, + lmtp): + * These should have *client_limit=1*, because any blocking operation will + block all the other clients and cause unnecessary delays and even + timeouts. + * This means that *process_limit* specifies the maximum number of + available parallel connections. + 3. Services that have no blocking operations (e.g. imap-login, pop3-login): + * For best performance (but a bit less safety), these should have + *process_limit* and *process_min_avail* set to the number of CPU cores, + so each CPU will be busy serving the process but without unnecessary + context switches. + * Then *client_limit* needs to be set high enough to be able to serve all + the needed connections (max connections =*process_limit* * + *client_limit*). + * *service_count* is commonly set to unlimited (0) for these services. + Otherwise when the *service_count* is beginning to be reached, the total + number of available connections will shrink. With very bad luck that + could mean that all the processes are simply waiting for the existing + connections to die away before the process can die and a new one can be + created. Although this could be made less likely by setting + *process_limit* higher than *process_min_avail*, but that's still not a + guarantee since each process could get a very long running connection + and the *process_limit* would be eventually reached. + +Service listeners +----------------- + +unix_listeners and fifo_listeners +--------------------------------- + +path: + Path to the file, relative to *base_dir* setting. This is also used as the + section name. + +user: + Owner of the file. Defaults to 0 (root). + +group: + Group of the file. Defaults to 0 (root/wheel). + +mode: + Mode of the file. Defaults to 0700. Note that 0700 is an octal value, while + 700 is a different decimal value. Setting mode to 0 disables the listener. + +inet_listeners +-------------- + +name: + Section name of this listener. It is meant to be descriptive for humans (e.g. + "imap", "imaps"). + +address: + Space separated list of IP addresses / host names to listen on. "*" means all + IPv4 addresses, "::" means all IPv6 addresses. Defaults to *listen* setting. + +port: + Port number where to listen. 0 disables the listener. + +ssl: + If yes, the listener does an immediate SSL/TLS handshake after accepting a + connection. This is needed for the legacy imaps and pop3s ports. + + All listeners with ssl=yes will be removed if global ssl is turned off + +haproxy (v2.2.19+): + If yes, this listener is configured for use with <HAProxy.txt>. It expects a + Proxy Protocol [http://blog.haproxy.com/haproxy/proxy-protocol/] header right + after accepting the connection. Connections are aborted immediately when this + protocol is violated. + +Default services +================ + +anvil +----- + +The anvil process tracks state of users and their connections. + + * *chroot=empty* and *user=$default_internal_user*, because anvil doesn't need + access to anything. + * *process_limit=1*, because there can be only one. + * *idle_kill=4294967295s*, because it should never die or all of its tracked + state would be lost. + * "doveadm who" and some other doveadm commands connect to anvil's UNIX + listener and request its state. + +auth +---- + +The master auth process. There are 4 types of auth client connections: + + 1. client: Only SASL authentication is allowed. This can be safely exposed to + entire world. + 2. userdb: userdb lookups and passdb lookups (without the password itself) can + be done for any user, and a list of users can be requested. This may or may + not be a security issue. Access to userdb lookup is commonly needed by + dovecot-lda, doveadm and other tools. + 3. login: Starts a two phase user login by performing authenticating (same as + "client" type). Used by login processes. + 4. master: Finishes the two phase user login by performing a userdb lookup + (similar to "userdb" type). Used by post-login processes (e.g. imap, pop3). + +With UNIX listeners the client type is selected based on the filename after the +last "-" in the filename. For example "anything-userdb" is of "userdb" type. +The default type is "client" for inet insteners and unrecognized UNIX +listeners. You can add as many client and userdb listeners as you want (and you +probably shouldn't touch the login/master listeners). + + * *client_limit* should be large enough to handle all the simultaneous + connections. Typically only login processes use long lasting auth + connections, while other processes do only quick lookups and disconnect + afterwards. + * *process_limit=1*, because there can be only one auth master process. + * *user=$default_internal_user*, because it typically doesn't need permissions + to do anything (PAM lookups are done by auth-workers). + * *chroot* could be set (to e.g. "empty") if passdb/userdb doesn't need to + read any files (e.g. SQL, LDAP config is read before chroot) + +auth-worker +----------- + +Auth master process connects to auth worker processes. It is mainly used by +passdbs and userdbs that do potentially long running lookups. For example MySQL +supports only synchronous lookups, so each query is run in a separate auth +worker process that does nothing else during the query. PostgreSQL and LDAP +supports asynchronous lookups, so those don't use worker processes at all. With +some passdbs and userdbs you can select if worker processes should be used. + + * *client_limit=1*, because only the master auth process connects to auth + worker. + * *service_count=1*, because auth master stops extra idling workers by + disconnecting from them. + * *process_limit* should be a bit higher than *auth_worker_max_count* setting. + + * *user=root* by default, because by default PAM authentication is used, which + usually requires reading '/etc/shadow'. If this isn't needed, it's a good + idea to change this to something else, such as *$default_internal_user*. + * *chroot* could also be set if possible. + +config +------ + +Config process reads and parses the 'dovecot.conf' file, and exports the parsed +data in simpler format to config clients. + + * *user=root*, because the process needs to be able to reopen the config files + during a config reload, and often some parts of the config having secrets + are readable only by root. + * Only root should be able to connect to its UNIX listener, unless there are + no secrets in the configuration. Passwords are obviously secrets, but less + obviously *ssl_key* is also a secret, since it contains the actual SSL key + data instead of only a filename. + +dict +---- + +Dovecot has a "lib-dict" API for doing simple key-value lookups/updates in +various backends (SQL, file, others in future). This is optionally used by +things like quota, expire plugin and other things in future. It would be +wasteful for each mail process to separately create a connection to SQL, so +usually they go through the "proxy" dict backend. These proxy connections are +the client connections of dict processes. + + * dict / Synchronous lookups (e.g. mysql): + * *client_limit=1*, because dict lookups are synchronous and the client is + supposed to disconnect immediately after the lookup. + * dict-async / Asynchronous lookups (e.g. pgsql, cassandra, ldap): + * *process_limit* should commonly be the same as number of CPU cores. + Although with Cassandra this may not be true, because Cassandra library + can use multiple threads. + * *user=$default_internal_user*, because the proxy dict lookups are typically + SQL lookups, which require no filesystem access. (The SQL config files are + read while still running as root.) + * The dict clients can do any kind of dict lookups and updates for all users, + so they can be rather harmful if exposed to an attacker. That's why by + default only root can connect to dict socket. Unfortunately that is too + restrictive for all setups, so the permissions need to be changed so that + Dovecot's mail processes (and only them) can connect to it. + +director +-------- + +<Director.txt> tracker process, which hooks into all auth-client and +auth-userdb connections. + + * *process_limit=1*, because only one process can keep track of everyone's + state. + * *user=$default_internal_user*, because director doesn't access any files. + * *chroot* can't be set, because it still needs to be connect to auth process. + + * Connections are basically proxying auth connections, so they have similar + security considerations. + +dns_client +---------- + +Used by "lib-dns" library to perform asynchronous DNS lookups. The dns-client +processes internally use the synchronous 'gethostbyname()' function. + + * *client_limit=1*, because the DNS lookup is synchronous. + * *user=$default_internal_user*, because typically no special privileged files + need to be read. + * *chroot* can be used only if it contains 'etc/resolv.conf' and other files + necessary for DNS lookups. + +doveadm +------- + +It's possible to run doveadm mail commands via doveadm server processes. This +is useful for running doveadm commands for multiple users simultaneously, and +it's also useful in a multiserver system where doveadm can automatically +connect to the correct backend to run the command. + + * *client_limit=1*, because doveadm command execution is synchronous. + * *service_count=1* just in case there were any memory leaks. This could be + set to some larger value (or 0) for higher performance. + * *user=root*, but the privileges are (temporarily) dropped to the mail user's + privileges after userdb lookup. If only a single UID is used, user can be + set to the mail UID for higher security, because the process can't gain root + privileges anymore. + +imap, pop3, submission, managesieve +----------------------------------- + +Post-login process for handling IMAP/POP3/ <Submission.txt>/ <ManageSieve> +[Pigeonhole.ManageSieve.txt] client connections. + + * *client_limit* may be increased from the default 1 to save some CPU and + memory, but it also increases the latency when one process serving multiple + clients it waiting for a long time for a lock or disk I/O. In future these + waits may be reduced or avoided completely, but for now it's not safe to set + this value higher than 1 in enterprise mail systems. For small mostly-idling + hobbyist servers a larger number may work without problems. + * *service_count* can be changed from 1 if only a single UID is used for mail + users. This is improves performance, but it's less secure, because bugs in + code may leak email data from another user's earlier connection. + * *process_limit* defaults to 1024, which means that the number of + simultaneous connections for the protocol that this service handles (IMAP, + POP3, <Submission.txt>, or <ManageSieve> [Pigeonhole.ManageSieve.txt]) is + limited by this setting. If you expect more connections, increase this + value. + +imap-login, pop3-login, submission-login, managesieve-login +----------------------------------------------------------- + +See <LoginProcess.txt>. + +indexer +------- + +Indexer master process, which tracks and prioritizes indexing requests from +mail processes. The actual indexing is done by indexer-worker processes. The +indexing means both updating Dovecot's internal index and cache files with new +messages and more importantly updating full text search indexes (if enabled). +The indexer master process guarantees that the FTS index is never modified by +more than one process. + + * *process_limit=1*, because only one process can keep the FTS guarantee. + * *user=$default_internal_user*, because the process doesn't need any + permissions. + * *chroot* could be set to *$base_dir* for extra security. It still needs to + be able to connect to indexer-worker socket. + +indexer-worker +-------------- + +Indexer worker process. + + * *client_limit=1*, because indexing is a synchronous operation. + * *process_limit* defaults to 10, because the FTS index updating can eat a lot + of CPU and disk I/O. You may need to adjust this value depending on your + system. + * *user=root*, but the privileges are (temporarily) dropped to the mail user's + privileges after userdb lookup. If only a single UID is used, user can be + set to the mail UID for higher security, because the process can't gain root + privileges anymore. + +ipc +--- + +IPC hub process. + + * *process_limit=1*, because there can be only one hub. + * *chroot=empty* and *user=$default_internal_user*, because it doesn't need + any files and there are no outbound connections. + * The "ipc" UNIX socket can be used to send any commands to other processes, + such as killing a specific user's connection. It is somewhat security + sensitive. + +lmtp +---- + +LMTP process for delivering new mails. + + * *client_limit=1*, because most of the time spent on an LMTP client is spent + waiting for disk I/O and other blocking operations. There's no point in + having more clients waiting around during that doing nothing. + * However, LMTP proxying is only writing to temporary files that normally + stay only in memory. So for LMTP proxying a client_limit above 1 could be + useful. + * *user=root*, but the privileges are (temporarily) dropped to the mail user's + privileges after userdb lookup. If only a single UID is used, user can be + set to the mail UID for higher security, because the process can't gain root + privileges anymore. + +log +--- + +All processes started via Dovecot master process log their messages via the +"log" process. This allows some nice features compared to directly logging via +syslog. + + * *process_limit=1*, because the log process keeps track of all the other + logging processes. + * *user=root*, because it guarantees being able to write to syslog socket and + to the log files directly. + +ssl-params +---------- + +Build SSL parameters every n days, based on *ssl_parameters_regenerate* +setting. Obsoleted in v2.3.0. + + * *type=startup* so that the (re)generation can be started immediately at + startup when needed, instead of waiting until the first SSL handshake + starts. + +stats +----- + +Mail process statistics tracking. Its behavior is very similar to the anvil +process, but anvil's data is of higher importance and lower traffic than stats, +so stats are tracked in a separate process. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.ClusterSetup.txt b/doc/wiki/SharedMailboxes.ClusterSetup.txt new file mode 100644 index 0000000..ae581d1 --- /dev/null +++ b/doc/wiki/SharedMailboxes.ClusterSetup.txt @@ -0,0 +1,51 @@ +Shared Mailboxes in Dovecot Cluster +=================================== + +As mentioned in <Director.txt>, you can't have multiple servers accessing the +same user at the same time or it will lead into trouble. This becomes +problematic with shared mailboxes, because two users who are sharing a folder +may run in different servers. The solution here is to access the shared folders +via IMAP protocol, which passes through the Dovecot proxies/directors so the +actual filesystem access is done only by one server. + +There are a couple of things still missing for this kind of use case: + + * imapc_* settings are global. You can't have two different namespaces with + different imapc settings yet. + * The imapc code doesn't support many IMAP features. Most importantly SEARCH + isn't supported, which may result in lower performance. + +Setting up user-shared folders +------------------------------ + +You'll need to setup master user logins to work for all the users. The logged +in user becomes the master user. This way the ACLs are applied correctly. + +---%<------------------------------------------------------------------------- +namespace { + type = shared + prefix = shared/%%u/ + location = imapc:~/shared/%%u/ # cache for shared indexes +} +imapc_host = director-ip +imapc_master_user = %u +#imapc_user = # leave this empty. It'll be automatically filled with the +destination username. +imapc_password = master-secret + +plugin { + acl_shared_dict = fs:posix:prefix=/nfs/shared-acls/ +} +---%<------------------------------------------------------------------------- + +The shared dictionary needs to be accessible from all the backends. The +possibilities for it are: + + * file: A single shared file in filesystem. This becomes a performance + bottleneck easily if there are many users sharing folders. + * fs posix: Shared directory in filesystem. This will create many small files + to the filesystem. + * sql: Shared SQL server + * Any other <shared dictionary> [Dictionary.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.Permissions.txt b/doc/wiki/SharedMailboxes.Permissions.txt new file mode 100644 index 0000000..d3772f6 --- /dev/null +++ b/doc/wiki/SharedMailboxes.Permissions.txt @@ -0,0 +1,168 @@ +Filesystem permissions in shared mailboxes +========================================== + +IMAP processes need filesystem level permissions to access shared/public +mailboxes. This means that: + + * If you use more than one <UNIX UID> [UserIds.txt] for your mail users (e.g. + you use system users), you'll need to make sure that all users can access + the mailboxes on filesystem level. ( <ACL plugin> [ACL.txt] won't help you + with this.) + * You can remove write permissions on purpose from public namespace root + directory to prevent users from creating new mailboxes under it. + +Dovecot never modifies permissions for existing mail files or directories. When +users share mailboxes between each others, the system must have been set up in +a way that filesystem permissions don't get in the way. The easiest way to do +that is to use only a single UID. Another possibility would be to use one or +more groups for all the mail files that may be shared to other users belonging +to the same group. For example if you host multiple domains, you might create a +group for each domain and allow mailbox sharing (only) between users in the +same domain. + +System user UNIX groups +----------------------- + +There's no requirement to use UNIX groups (i.e. typically defined in +'/etc/group') for anything. If you don't care about them, you can safely ignore +this section. + +If you use <passwd> [AuthDatabase.Passwd.txt] userdb, the IMAP process has +access to all the UNIX groups defined for that user. You may use these groups +when granting filesystem permissions. If you wish to use UNIX groups defined in +'/etc/group' but don't use passwd userdb, you can still do this by returning +'system_groups_user' <userdb extra field> [UserDatabase.ExtraFields.txt], which +contains the UNIX user name whose groups are read from the group file. + +You can also set up extra UNIX groups by listing them in 'mail_access_groups' +setting. To have per-user UNIX groups, return 'mail_access_groups' as userdb +extra field. The advantage of using this method is that only Dovecot mail +processes have access to the group, but nothing else, such as user's SSH +session. For example a simple way to set up shared mailbox access for all +system users is to make all mail dirs/files 0770/0660 mode and owned by group +"sharedmail" and then set 'mail_access_groups=sharedmail'. Using more fine +grained groups of course leaks less mail data in case there's a security hole +in Dovecot. + +Permissions for new mailboxes +----------------------------- + +When creating a new mailbox, Dovecot copies the permissions from the mailbox +root directory. For example with mboxes if you have directories: + +---%<------------------------------------------------------------------------- +drwx--xr-x 8 user group 4096 2009-02-21 18:31 /home/user/mail/ +drwxrwxrwx 2 user group 4096 2009-02-21 18:32 /home/user/mail/foo/ +---%<------------------------------------------------------------------------- + +When creating a new foo/bar/ directory, Dovecot gives it permissions: + +---%<------------------------------------------------------------------------- +drwx--xr-x 2 user group 4096 2009-02-21 18:33 /home/user/mail/foo/bar/ +---%<------------------------------------------------------------------------- + +As you can see, the file mode was copied from mail/ directory, not mail/foo/. +The group is also preserved. If this causes problems (e.g. different users +having different groups create mailboxes, causing permission denied errors when +trying to preserve the group) you can set the setgid bit for the root +directory: + +---%<------------------------------------------------------------------------- +chmod g+s /home/user/mail +---%<------------------------------------------------------------------------- + +This will cause the group to be automatically copied by the OS for all created +files/directories under it, even if the user doesn't belong to the group. + +Permissions for new files in mailboxes +-------------------------------------- + +When creating new files inside a mailbox, Dovecot copies the read/write +permissions from the mailbox's directory. For example if you have: + +---%<------------------------------------------------------------------------- +drwx--xr-x 5 user group 4096 2009-02-21 18:53 /home/user/Maildir/.foo/ +---%<------------------------------------------------------------------------- + +Dovecot creates files under it with modes: + +---%<------------------------------------------------------------------------- +drwx--xr-x 2 user group 4096 2009-02-21 18:54 cur/ +drwx--xr-x 2 user group 4096 2009-02-21 18:54 new/ +drwx--xr-x 2 user group 4096 2009-02-21 18:54 tmp/ +-rw----r-- 1 user group 156 2009-02-21 18:54 dovecot.index.log +-rw----r-- 1 user group 17 2009-02-21 18:54 dovecot-uidlist +---%<------------------------------------------------------------------------- + +Note how the g+x gets copied to directories, but for files it's simply ignored. +The group is copied the same way as explained in the previous section. + +When mails are copied between Maildirs, it's usually done by hard linking. If +the source and destination directory permissions are different, Dovecot create +a new file and copies data the slow way so that it can assign the wanted +destination permissions. The source and destination permission lookups are done +only by looking at the mailbox root directories' permissions, not individual +mail files. This may become a problem if the mail files' permissions aren't as +Dovecot expects. + +Permissions to new /domain/user directories +------------------------------------------- + +If each user has different UIDs and you have '/var/mail/domain/user/' style +directories, you run into a bit of trouble. The problem is that the first user +who creates '/var/mail/domain/' will create it as 0700 mode, and other users +can't create their own user/ directories under it anymore. The solution is to +use a common group for the users and set '/var/mail/' directory's permissions +properly (group-suid is required): + +---%<------------------------------------------------------------------------- +chgrp dovemail /var/mail +chmod 02770 /var/mail # or perhaps 03770 for extra security +---%<------------------------------------------------------------------------- + +and in dovecot.conf: + +---%<------------------------------------------------------------------------- +mail_location = maildir:/var/vmail/%d/%n/Maildir +mail_access_groups = dovemail +---%<------------------------------------------------------------------------- + +The end result should look like this: + +---%<------------------------------------------------------------------------- +drwxrwsr-x 3 user dovemail 60 Oct 24 12:04 domain.example.com/ +drwx--S--- 3 user user 60 Oct 24 12:04 domain.example.com/user/ +---%<------------------------------------------------------------------------- + +Note that this requires that the mail_location setting is in its explicit +format with %variables. Using 'maildir:~/Maildir' won't work, because Dovecot +can't really know how far down it should copy the permissions from. + +Permissions to new user home directories (v2.2+) +------------------------------------------------ + +When mail_location begins with '%h' or '~/', its permissions are copied from +the first existing parent directory if it has setgid-bit set. This isn't done +when the path contains any other %variables. + +Mail Delivery Agent permissions +------------------------------- + +When using Dovecot <LDA.txt>, it uses all the same configuration files as +IMAP/POP3, so you don't need to worry about it. + +When using an external MDA to deliver to a shared mailbox, you need to make +sure that the resulting files have proper permissions. For example with +Procmail + Maildir, set 'UMASK=007' in '.procmailrc' to make the delivered mail +files group-readable. To get the file to use the proper group, set the group to +the Maildir's 'tmp/' directory and also set its setgid bit ('chmod g+s'). + +Dictionary files +---------------- + +Created dictionary files (e.g. 'acl_shared_dict = file:...') also base their +initial permissions on parent directory's permissions. After the initial +creation, the permissions are permanently preserved. So if you want to use +different permissions, just chown/chmod the file. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.Public.txt b/doc/wiki/SharedMailboxes.Public.txt new file mode 100644 index 0000000..e958f19 --- /dev/null +++ b/doc/wiki/SharedMailboxes.Public.txt @@ -0,0 +1,241 @@ +Contents + + + 1. Public Mailboxes + + 1. Per-user \Seen flag (v2.2+) + + 2. Maildir: Per-user \Seen flag + + 1. Maildir: Keyword sharing + + 3. Subscriptions + + 4. Read-only mailboxes + + 1. Read-only mboxes + + 2. Read-only Maildirs + + 5. Example: Public mailboxes with ACLs + +Public Mailboxes +================ + +Public mailboxes are typically mailboxes that are visible to all users or to +large user groups. They are created by defining a public namespace, under which +all the shared mailboxes are. See <SharedMailboxes.Permissions.txt> for issues +related to filesystem permissions. See <Namespaces.txt> for details of how +namespaces are configured. + +For example to create a public Maildir mailboxes, use: + +---%<------------------------------------------------------------------------- +# User's private mail location +mail_location = maildir:~/Maildir + +# When creating any namespaces, you must also have a private namespace: +namespace { + type = private + separator = / + prefix = + #location defaults to mail_location. + inbox = yes +} + +namespace { + type = public + separator = / + prefix = Public/ + location = maildir:/var/mail/public + subscriptions = no +} +---%<------------------------------------------------------------------------- + +In the above example, you would then create Maildir mailboxes under the +'/var/mail/public/' directory. For example: + +---%<------------------------------------------------------------------------- +# ls -la /var/mail/public/ +drwxr-s--- 1 root mail 0 2007-03-19 03:12 . +drwxrws--- 1 root mail 0 2007-03-19 03:12 .lkml +drwxrws--- 1 root mail 0 2007-03-19 03:12 .bugtraq +-rw-rw---- 1 root mail 0 2007-03-19 03:12 dovecot-shared +---%<------------------------------------------------------------------------- + +Note that there are no 'cur/', 'new/' or 'tmp/' directories directly under the +'/var/mail/public/', because the Public/ namespace isn't a mailbox itself. (If +you create them manually, it does become a selectable mailbox. ) + +The 'dovecot-shared' file isn't directly used for either lkml or bugtraq +mailboxes, but if you create a new public mailbox via Dovecot it's +automatically copied there. + +Note that Dovecot uses Maildir++ layout by default for folders, where the +folder names must begin with a "." or Dovecot will ignore them. You can also +optionally use the <"fs" layout> [MailboxFormat.Maildir.txt] if you want the +directory structure to look like: + + * '/var/mail/public/' (root dir) + * '/var/mail/public/info/' (maildir folder) + * '/var/mail/public/company/' (maildir folder) + +Per-user \Seen flag (v2.2+) +--------------------------- + +Since v2.2 the recommended way to enable private flags for shared mailboxes is +to create private indexes with :INDEXPVT=<path>. This creates +dovecot.index.pvt[.log] files, which contain only the message UIDs and the +private flags. Currently the list of private flags is hardcoded only to the +\Seen flag. + +Example: + +---%<------------------------------------------------------------------------- +namespace { + type = public + separator = / + prefix = Public/ + location = maildir:/var/mail/public:INDEXPVT=~/Maildir/public + subscriptions = no +} +---%<------------------------------------------------------------------------- + +Maildir: Per-user \Seen flag +---------------------------- + +(With v2.2+ you should instead use the INDEXPVT as described above.) + +With Maildir a 'dovecot-shared' file controls if the \Seen flags are shared or +private. The file must be created separately inside each Maildir, although if +the file already exists in the Maildir root it's automatically copied for newly +created mailboxes. If 'dovecot-shared' file doesn't exist in Maildir, the \Seen +flags are shared. If it exists, the \Seen flag state is stored only in the +user's index files. By making each user have their own private index files, you +can make the \Seen flag private for the users. For example: + +---%<------------------------------------------------------------------------- +namespace { + type = public + separator = / + prefix = Public/ + location = maildir:/var/mail/public:INDEX=~/Maildir/public + subscriptions = no +} +---%<------------------------------------------------------------------------- + +Now when accessing e.g. "Public/lkml" mailbox, Dovecot keeps its index files in +'~/Maildir/public/.lkml/' directory. If it ever gets deleted, the \Seen flags +are lost. + +If you want to change what flags are shared when 'dovecot-shared' file exists, +currently you'll have to modify the source +code:'src/lib-storage/index/maildir/maildir-storage.c' maildir_open() has +'mbox->ibox.box.private_flags_mask = MAIL_SEEN;' Change the 'MAIL_SEEN' to any +flag combination you want. See 'src/lib-mail/mail-types.h' for list of valid +flags. + +Maildir: Keyword sharing +------------------------ + +Make sure you don't try to use per-user CONTROL directory. Otherwise +'dovecot-keywords' file doesn't get shared and keyword mapping breaks. + +Subscriptions +------------- + +Typically you want each user to have control over their own subscriptions for +mailboxes in public namespaces. This is why you should set 'subscriptions=no' +to the namespace. Dovecot will then use the parent namespace's subscriptions +file. Note that this practically means you must have a namespace with empty +prefix, otherwise there is no "parent namespace". + +Read-only mailboxes +------------------- + +Read-only mboxes +---------------- + +If you have a read-only directory structure containing mbox files, you'll need +to store index files elsewhere: + +---%<------------------------------------------------------------------------- +namespace { + type = public + prefix = Public/ + location = mbox:/var/mail/public/:INDEX=/var/indexes/public + subscriptions = no +} +---%<------------------------------------------------------------------------- + +In the above example all the users would still be sharing the index files, so +you might have problems with filesystem permissions. Alternatively you could +place the index files under user's home directory. + +Read-only Maildirs +------------------ + +If your Maildir is read-only, the control and index files still need to be +created somewhere. You can specify the path for these by appending +':CONTROL=<path>:INDEX=<path>' to mail location. The path may point to a +directory that is shared among all users, or to a per-user path. Note that if +the Maildir has any keywords, the per-user control directory breaks the +keywords since there is no 'dovecot-keywords' file. + +When configuring multiple namespaces, the CONTROL/INDEX path must be different +for each namespace. Otherwise if namespaces have identically named mailboxes +their control/index directories will conflict and cause all kinds of problems. + +If you put the control files to a per-user directory, you must also put the +index files to a per-user directory, otherwise you'll get errors. It is however +possible to use shared control files but per-user index files, assuming you've +set up permissions properly. + +---%<------------------------------------------------------------------------- +namespace { + type = public + separator = / + prefix = Public/ + location = +maildir:/var/mail/public:CONTROL=~/Maildir/public:INDEX=~/Maildir/public + subscriptions = no +} +namespace { + type = public + separator = / + prefix = Team/ + location = maildir:/var/mail/team:CONTROL=~/Maildir/team:INDEX=~/Maildir/team + subscriptions = no +} +---%<------------------------------------------------------------------------- + +Example: Public mailboxes with ACLs +----------------------------------- + +See <ACL.txt> for more information about ACLs. + +---%<------------------------------------------------------------------------- +namespace { + type = public + separator = . + prefix = public. + location = maildir:/var/mail/public + subscriptions = no + list = children +} + +plugin { + acl = vfile +} +---%<------------------------------------------------------------------------- + +It's important that the namespace type is "public" regardless of whether you +set the namespace prefix to "shared." or something else. + +After this you have to place 'dovecot-acl' files in every mailbox/folder below +'/var/mail/public' with rights for that folder (e.g. 'user=someone lr'). + +'acl_shared_dict' setting is not relevant for public mailboxes (only for +shared). + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.Shared.txt b/doc/wiki/SharedMailboxes.Shared.txt new file mode 100644 index 0000000..879b4f4 --- /dev/null +++ b/doc/wiki/SharedMailboxes.Shared.txt @@ -0,0 +1,306 @@ +Mailbox sharing between users +============================= + +To enable mailbox sharing, you'll need to create a shared namespace. See +<ACL.txt> for more information about ACL-specific settings. + +---%<------------------------------------------------------------------------- +# User's private mail location. +mail_location = maildir:~/Maildir + +# When creating any namespaces, you must also have a private namespace: +namespace { + type = private + separator = / + prefix = + #location defaults to mail_location. + inbox = yes +} + +namespace { + type = shared + separator = / + prefix = shared/%%u/ + # a) Per-user seen flags. Maildir indexes are shared. (INDEXPVT requires +v2.2+) + location = maildir:%%h/Maildir:INDEXPVT=~/Maildir/shared/%%u + # b) Per-user seen flags. Maildir indexes are not shared. If users have +direct filesystem level access to their mails, this is a safer option: + #location = +maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u:INDEXPVT=~/Maildir/shared/%%u + subscriptions = no + list = children +} + +mail_plugins = acl +protocol imap { + mail_plugins = $mail_plugins imap_acl +} +plugin { + acl = vfile +} +---%<------------------------------------------------------------------------- + +This creates a shared/ namespace under which each user's mailboxes are. If you +have multiple domains and allow sharing between them, you might want to set +'prefix=shared/%%d/%%n/' instead (although %%u works just fine too). If you +don't, you might want to drop the domain part and instead use +'prefix=shared/%%n/'. + +'list=children' specifies that if no one has shared mailboxes to the user, the +"shared" directory isn't listed by the LIST command. If you wish it to be +visible always, you can set 'list=yes'. + +The 'location' setting specifies how to access other users' mailboxes. If you +use %%h, the user's home directory is asked from auth process via auth-userdb +socket. See <LDA.txt> for how to configure the socket. If the users' mailboxes +can be found using a template, it's faster not to use the %%h. For example: + +---%<------------------------------------------------------------------------- + location = maildir:/var/mail/%%d/%%n/Maildir:INDEXPVT=~/Maildir/shared/%%u +---%<------------------------------------------------------------------------- + +% vs %% +------- + +%var expands to the logged in user's variable, while %%var expands to the other +users' variables. For example if your name is "myself" and "someone1" and +"someone2" have shared mailboxes to you, the variables could be expanded like: + + * %u expands to "myself" + * %%u expands to "someone1" or "someone2" + * %h might expand to "/home/myself" + * %%h might expand to "/home/someone1" or "/home/someone2" + * ~/ equals %h/ + +Note that in e.g. mail_location setting you might need both. For example in: + +---%<------------------------------------------------------------------------- +mail_location = maildir:%%h/Maildir:INDEXPVT=%h/Maildir/shared/%%u +---%<------------------------------------------------------------------------- + +What it means is: + + * %%h/Maildir points to the other user's Maildir, e.g. "/home/someone1". + * :INDEXPVT=%h/Maildir/shared/%%u points to a per-user directory under your + own Maildir, e.g. "/home/myself/Maildir/someone1" or + "/home/myself/Maildir/someone2". This is necessary for storing per-user seen + flags. + +dbox +---- + +With dbox the index files are a very important part of the mailboxes. You must +not try to :INDEX= to have copies of index files. This will only result in +mailbox corruption. (INDEXPVT can be used though.) + +Filesystem permissions +---------------------- + +Dovecot assumes that it can access the other users' mailboxes. If you use +multiple UNIX UIDs, you may have problems setting up the permissions so that +the mailbox sharing works. Dovecot never modifies existing files' permissions. +See <SharedMailboxes.Permissions.txt> for more information. + +Shared mailbox listing +---------------------- + +With the above configuration it's possible to open shared mailboxes if you know +their name, but they won't be visible in the mailbox list. This is because +Dovecot has no way of knowing what users have shared mailboxes to whom. +Iterating through all users and looking inside their mail directories would be +horribly inefficient for more than a couple users. + +To overcome this problem Dovecot needs a dictionary, which contains the list of +users who have shared mailboxes and to whom they have shared. If the users +aren't properly listed in this dictionary, their shared mailboxes won't be +visible. Currently there's no way to automatically rebuild this dictionary, so +make sure it doesn't get lost. If it does, each user having shared mailboxes +must use the IMAP SETACL command (see below) to get the dictionary updated for +themselves. + +You could use any dictionary backend, including SQL, but a simple flat file +should work pretty well too: + +---%<------------------------------------------------------------------------- +plugin { + acl_shared_dict = file:/var/lib/dovecot/db/shared-mailboxes.db +} +---%<------------------------------------------------------------------------- + +The IMAP processes must be able to write to the 'db/' directory. If you're +using system users, you probably want to make it mode 0770 and group +'sharedusers' and set 'mail_access_groups=sharedusers' (or something similar). + +If you use multiple domains and don't wish users to share their mailboxes to +users in other domains, you can use separate dict files for each domain: + +---%<------------------------------------------------------------------------- +plugin { + # assumes mailboxes are in /var/mail/%d/%n: + acl_shared_dict = file:/var/mail/%d/shared-mailboxes.db +} +---%<------------------------------------------------------------------------- + +Using SQL dictionary +-------------------- + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +plugin { + acl_shared_dict = proxy::acl +} + +dict { + acl = pgsql:/etc/dovecot/dovecot-dict-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +See <Dict.txt> for more information, especially about permission issues. + +Database tables: + +---%<------------------------------------------------------------------------- +CREATE TABLE user_shares ( + from_user varchar(100) not null, + to_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user, to_user) +); +COMMENT ON TABLE user_shares IS 'User from_user shares folders to user +to_user.'; + +CREATE INDEX to_user +ON user_shares (to_user); -- because we always search for to_user + +CREATE TABLE anyone_shares ( + from_user varchar(100) not null, + dummy char(1) DEFAULT '1', -- always '1' currently + primary key (from_user) +); +COMMENT ON TABLE anyone_shares IS 'User from_user shares folders to anyone.'; +---%<------------------------------------------------------------------------- + +'/etc/dovecot/dovecot-dict-sql.conf.ext': + +---%<------------------------------------------------------------------------- +connect = host=localhost dbname=mails user=sqluser password=sqlpass +map { + pattern = shared/shared-boxes/user/$to/$from + table = user_shares + value_field = dummy + + fields { + from_user = $from + to_user = $to + } +} + +map { + pattern = shared/shared-boxes/anyone/$from + table = anyone_shares + value_field = dummy + + fields { + from_user = $from + } +} +---%<------------------------------------------------------------------------- + +Mailbox sharing +--------------- + +You can use <doveadm acl> [Tools.Doveadm.ACL.txt] to share mailboxes or it can +be done using IMAP SETACL command. It is the only way to update the shared +mailbox list dictionary. + +Below is a quick introduction to IMAP ACL commands. See RFC 4314 +[http://www.ietf.org/rfc/rfc4314.txt] for more details. + + * MYRIGHTS <mailbox>: Returns the user's current rights to the mailbox. + * GETACL <mailbox>: Returns the mailbox's all ACLs. + * SETACL <mailbox> <id> [+|-]<rights>: Give <id> the specified rights to the + mailbox. + * DELETEACL <mailbox> [-]<id>: Delete <id>'s ACL from the mailbox. + +<id> is one of: + + * anyone: Matches all users, including anonymous users. + * authenticated: Like "anyone", but doesn't match anonymous users. + * $group: Matches all users belonging to the group ($ is not part of the group + name). + * $!group: See group-override in <ACL.txt> (Dovecot-specific feature). + * user: Matches the given user. + +The $group syntax is not a standard, but it is mentioned in RFC 4314 examples +and is also understood by at least Cyrus IMAP. Having '-' before the identifier +specifies negative rights. + +See <ACL.txt> for list of <rights>. + +Sharing mailboxes to everyone +----------------------------- + +By default Dovecot doesn't allow using the IMAP "anyone" or "authenticated" +identifier, because it would be an easy way to spam other users in the system. +If you wish to allow it, set: + +---%<------------------------------------------------------------------------- +plugin { + acl_anyone = allow +} +---%<------------------------------------------------------------------------- + +Note that you can also do this only for some users by using the second table +"anyone_shares". Every user listed in this table shares his folders with +everyone. See also <userdb extra field> [UserDatabase.ExtraFields.txt]. + +IMAP ACL examples +----------------- + +Let's begin with some simple example that first gives "read" and "lookup" +rights, and later adds "write-seen" right: + +---%<------------------------------------------------------------------------- +1 SETACL Work user@domain rl +1 OK Setacl complete. + +2 SETACL Work user@domain +s +2 OK Setacl complete. + +3 GETACL Work +* ACL "Work" "user@domain" lrs "myself" lrwstipekxacd +3 OK Getacl completed. +---%<------------------------------------------------------------------------- + +Let's see how negative rights work by testing it on ourself. See how we +initially have "lookup" right, but later we don't: + +---%<------------------------------------------------------------------------- +1 MYRIGHTS Work +* MYRIGHTS "Work" lrwstipekxacd +1 OK Myrights completed. + +2 SETACL Work -myself l +2 OK Setacl complete. + +3 GETACL Work +* ACL "Work" "-myself" l "user@domain" lr "myself" lrwstipekxacd +3 OK Getacl completed. + +4 myrights Work +* MYRIGHTS "Work" rwstipekxacd +4 OK Myrights completed. +---%<------------------------------------------------------------------------- + +Troubleshooting +--------------- + + * Make sure the % and %% variables are specified correctly in the namespace + location.'mail_debug=yes' will help you see if Dovecot is trying to access + correct paths. + * 'doveadm acl debug -u user@domain shared/user/box' can be helpful in + figuring out why a mailbox can't be accessed. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.Symlinks.txt b/doc/wiki/SharedMailboxes.Symlinks.txt new file mode 100644 index 0000000..08cd903 --- /dev/null +++ b/doc/wiki/SharedMailboxes.Symlinks.txt @@ -0,0 +1,42 @@ +Mailbox sharing with symlinks +============================= + +It's possible to share mailboxes simply by symlinking them among user's private +mailboxes. See <SharedMailboxes.Permissions.txt> for issues related to +filesystem permissions. + +Maildir +------- + +---%<------------------------------------------------------------------------- +ln -s /home/user2/Maildir/.Work /home/user1/Maildir/.shared.user2 +ln -s /home/user3/Maildir/.Work /home/user1/Maildir/.shared.user3 +---%<------------------------------------------------------------------------- + +Now user1 has a "shared" directory containing "user2" and "user3" child +mailboxes, which point to those users' "Work" mailbox. + +With Maildir++ layout it's not possible to automatically share "mailbox and its +children". You'll need to symlink each mailbox separately. With v1.1+ you could +do this by using "fs" layout for mailboxes (requires converting existing +maildirs from Maildir++). + +mbox +---- + +Doing the same as in the above Maildir example: + +---%<------------------------------------------------------------------------- +mkdir /home/user1/mail/shared +ln -s /home/user2/mail/Work /home/user1/mail/shared/user2 +ln -s /home/user3/mail/Work /home/user1/mail/shared/user3 +---%<------------------------------------------------------------------------- + +One additional problem with mbox format is the creation of dotlock files. The +dotlocks would be created under user1's directory, which makes them useless. +Make sure the locking works properly with only fcntl or flock locking (See +<MboxLocking.txt>) and just disable dotlocks. Alternatively instead of +symlinking an mbox file, put the shared mailboxes inside a directory and +symlink the entire directory. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SharedMailboxes.txt b/doc/wiki/SharedMailboxes.txt new file mode 100644 index 0000000..8009553 --- /dev/null +++ b/doc/wiki/SharedMailboxes.txt @@ -0,0 +1,17 @@ +Shared mailboxes +================ + +Dovecot can support mailbox sharing in several different ways: + + * <Public mailboxes> [SharedMailboxes.Public.txt]: Shared mailboxes created by + administrators (ACLs can still restrict who sees them) + * <Shared mailboxes> [SharedMailboxes.Shared.txt]: Users sharing their + mailboxes to other users (using IMAP ACL commands) (v1.2+) + * <Symlinking mailboxes> [SharedMailboxes.Symlinks.txt]: Quick and dirty way + of sharing a few mailboxes. + * <Shared Mailboxes in Dovecot Cluster> [SharedMailboxes.ClusterSetup.txt] + +See <SharedMailboxes.Permissions.txt> for common filesystem related permission +problems that are common with all the sharing methods. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SocketUnavailable.txt b/doc/wiki/SocketUnavailable.txt new file mode 100644 index 0000000..b4068bc --- /dev/null +++ b/doc/wiki/SocketUnavailable.txt @@ -0,0 +1,84 @@ +UNIX Socket Resource Temporarily Unavailable +============================================ + +Commonly visible as: + +---%<------------------------------------------------------------------------- +imap-login: Error: net_connect_unix(imap) failed: Resource temporarily +unavailable +---%<------------------------------------------------------------------------- + +This means that there are more imap-login processes trying to connect to the +"imap" UNIX socket than there are imap processes accepting the connections. The +kernel's connection listener queue got full and it started rejecting further +connections. So what can be done about it? + +Wrong service settings +---------------------- + +This can happen if 'service imap { client_limit } ' is set to anything else +than 1. IMAP (and POP3 and other mail) processes do disk IO, lock waiting and +such, so if all the available imap processes are stuck waiting on something, +they can't accept new connections and they queue up in the kernel. For mail +processes only 'client_limit=1' is recommended, except maybe for very tiny +systems with a few users. + +It can also happen if 'service imap { process_limit } ' is reached. Dovecot +logs a warning if process_limit or client_limit is reached. + +Out of file descriptors +----------------------- + +If the "ulimit -n" is too low, kernel stops notifying the process about +incoming connections. Make sure that the limit is at least as high as the +client_limit. Dovecot also internally checks this, and if it's too low it +writes a warning to stderr at startup (and to log in v2.2.33+). + +Note that Dovecot is not using "dovecot" user's or PAM's limits in general. +Make sure the limits are correct with:'cat /proc/`pidof dovecot`/limits' + +Master process busy +------------------- + +Dovecot master process forks all of the new processes. If it's using 100% CPU, +it doesn't have time to fork enough new processes. Even if it's not constantly +using 100% CPU there may be fork bursts where it temporarily gets too busy. The +solution is to make it do less work by forking less processes: + + * Most importantly switch to <high-performance login process mode> + [LoginProcess.txt]. This alone might be enough. + * You can also switch (most of the) other commonly forked processes to be + reused. For example 'service imap { service_count = 100 } ' reuses the imap + process for 100 different IMAP connections before it dies. This is useful + mainly for imap, pop3 and managesieve services. It's better to avoid using + 'service_count=0' (unlimited) in case there are memory leaks. + * You can pre-fork some idling processes to handle bursts with 'service { + process_min_avail }'. + +See <Services.txt> before changing any service settings. Some services require +specific values to work correctly. + +Listener queue size +------------------- + +Dovecot uses the ' service { client_limit } '*' service { process_limit } ' as +the listener queue size. Dovecot v2.2.25 and older also had a hardcoded maximum +of 511, while later versions have no upper limit. Most OSes use an even lower +limit, typically 128. In Linux you can increase this from +'/proc/sys/net/core/somaxconn'. + +Dovecot v2.2.[0-6] bug +---------------------- + +Dovecot v2.2.0 - v2.2.6 were attempting to optimize host.domain lookups by +doing them only once in the master process. Unfortunately they were actually +doing the lookup every time when creating a new process. In some configuration +this lookup could have done a somewhat slow DNS lookup, causing the process +creation to become very slow and triggering this message. + +The fix is in v2.2.7 and you can also workaround this: + + * Add to dovecot.conf: 'import_environment = TZ DEBUG_OUTOFMEM + DOVECOT_HOSTDOMAIN=mailserver.example.com' (of course changing the value) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Statistics.Old.txt b/doc/wiki/Statistics.Old.txt new file mode 100644 index 0000000..210103a --- /dev/null +++ b/doc/wiki/Statistics.Old.txt @@ -0,0 +1,227 @@ +Statistics +========== + +Dovecot v2.1+ supports gathering statistics (CPU, disk usage, etc.) from mail +processes (IMAP, POP3, LMTP, etc.) to the stats process. The stats process can +later be queried what's going on in the system. With imap_stats plugin you can +get per-command level statistics for IMAP commands. + +There are different "zoom levels" you can look at the statistics: + + * command: Per-IMAP command + * session: Per IMAP/POP3 connection + * user: Per user (all of user's sessions summed up) + * domain: Per domain (all of domain's users summed up) + * ip: Per IP address (all sessions from the IP summed up) + * global: Everything summed up (2.2.16+) + +Basic Configuration +------------------- + +---%<------------------------------------------------------------------------- +mail_plugins = $mail_plugins stats +protocol imap { + mail_plugins = $mail_plugins imap_stats +} +plugin { + # how often to session statistics (must be set) + stats_refresh = 30 secs + # track per-IMAP command statistics (optional) + stats_track_cmds = yes +} +---%<------------------------------------------------------------------------- + +You'll also need to give enough permissions for mail processes to be able to +write to stats-mail fifo. For example if you use a single "vmail" user for mail +access: + +---%<------------------------------------------------------------------------- +service stats { + fifo_listener stats-mail { + user = vmail + mode = 0600 + } +} +---%<------------------------------------------------------------------------- + +Memory usage configuration +-------------------------- + +The stats process attempts to keep memory usage below a specified amount. This +value is only approximate because of extra overhead caused by malloc() itself. + +---%<------------------------------------------------------------------------- +stats_memory_limit = 16 M +---%<------------------------------------------------------------------------- + +Once the memory limit is reached, oldest statistics are freed from memory. +Different statistics levels have different timeout limits, which are configured +in: + +---%<------------------------------------------------------------------------- +stats_command_min_time = 1 mins +stats_domain_min_time = 12 hours +stats_ip_min_time = 12 hours +stats_session_min_time = 15 mins +stats_user_min_time = 1 hours +---%<------------------------------------------------------------------------- + +So for example the above means: + + * An IMAP command is kept in memory for at least 1 minute after it has + finished + * A user is kept in memory for 1 hour after its last session has disconnected. + +The stats process attempts to honor these min_time-settings, but if memory is +tight it can go below these values to honor the 'stats_memory_limit' setting. + +Statistics gathered +------------------- + +Statistics gathered internally by the stats process: + + * num_logins: Number of logins (2.2.14+) + * num_cmds: Number of IMAP commands run (2.2.14+) + * num_connected_sessions: Number of current IMAP sessions (2.2.14+) + +Statistics gathered using the 'getrusage()' system call: + + * user_cpu: User CPU (seconds.microseconds) + * sys_cpu: System CPU (seconds.microseconds) + * clock_time: Wall-clock time (seconds.microseconds). Doesn't include time + spent waiting in ioloop, which means it doesn't include (most of) the time + spent waiting on client network traffic. (v2.2.11+) + * min_faults: Minor page faults (page reclaims) + * maj_faults: Major page faults + * vol_cs: Voluntary context switches + * invol_cs: Involuntary context switches + * disk_input: Number of bytes read from disk + * disk_output: Number of bytes written to disk + +The disk_input and disk_output attempt to count the actual read/write bytes to +physical disk, so e.g. reads from OS's cache aren't counted. Note that not all +operating systems and filesystem support this, instead they simply show these +values always as 0. + +Statistics gathered from '/proc/self/io' output (Linux-only): + + * read_count: Number of read() syscalls + * write_count: Number of write() syscalls + * read_bytes: Number of bytes read using read() syscalls + * write_bytes: Number of bytes written using write() syscalls + +Note that the above numbers are not only about disk I/O, but also about network +I/O, Dovecot's IPC and every other kind of reads/writes as well. + +Statistics gathered by Dovecot's lib-storage internally: + + * mail_lookup_path: Number of open() and stat() calls (i.e. "path lookups") + * mail_lookup_attr: Number of stat() and fstat() calls + * mail_read_count: Number of read() calls for message data (e.g. index files + not counted) + * mail_read_bytes: Number of message bytes read() + * mail_cache_hits: Number of cache hits from 'dovecot.index.cache' file + +Note that statistics are collected only on backends so stats service doesn't do +anything on directors and proxies. + +doveadm stats +------------- + +top +--- + +'doveadm stats top [<sort field>]' + +The top command gives a very simple "top"-like view of connected sessions. The +optional sort field is one of: + + * disk: disk_input and disk_output summed up (default) + * cpu: user_cpu and sys_cpu summed up + * any other statistics field + +This "top" isn't very good, but a much better one can be found as a Perl +script:stats-top.pl [https://dovecot.org/tools/stats-top.pl], which also +requires stats.pl [https://dovecot.org/tools/stats.pl] and tab-formatter.pl +[https://dovecot.org/tools/tab-formatter.pl]. + +dump +---- + +'doveadm stats dump <level> [<filter>]' + +The dump command shows a raw output of the statistics. The level parameter is +one of the levels listed at the top of this page (e.g. "session"). The filter +can contain zero of more filters: + + * connected: The session must be currently connected (or the user/domain/ip + must have at least one session that is currently connected) + * since=<timestamp>: Last update was since this UNIX timestamp + * user=<wildcard>: Username matches this wildard + * domain=<wildcard>: Domain name matches this wildard + * ip=<ip>[/bits]: IP address matches this IP/network (e.g. 192.168.1.0/24) + +If nothing matches the filter, the output is a single empty line. Otherwise it +begins with a header line followed by data lines. Each line has a list of +fields separated by TABs. The header describes what the data fields are. The +list of fields depends on what level you're listing. Some of the fields are: + + * session: 128 bit session GUID in hex format. This uniquely identifies a + single session. Used by commands and sessions. + * connected: Is the client currently connected? 0=no, 1=yes. + * pid: Process ID of the session. If the session is no longer connected, the + PID may not exist anymore. + * last_update: UNIX timestamp of the last time this data was updated + * reset_timestamp: UNIX timestamp of when this user/domain/ip structure was + created. This is useful when you want to track incrementally what changed: + * If timestamp is the same as in your previous lookup, you can simply count + different = new_value - previous_value. + * If timestamp has changed since your previous lookup, the statistics were + reset to zero since and the difference = new_value. + +Stats protocol +-------------- + +You can connect to stats process via '$base_dir/stats' UNIX socket, or you can +simply add more UNIX/TCP listeners to the stats service, e.g.: + +---%<------------------------------------------------------------------------- +service stats { + inet_listener { + address = 127.0.0.1 + port = 24242 + } +} +---%<------------------------------------------------------------------------- + +The protocol is almost entirely identical to 'doveadm stats dump' command's +parameters and output. The only difference is that you prefix your request with +"EXPORT<tab>". For example: + +---%<------------------------------------------------------------------------- +EXPORT<tab>session<tab>connected<lf> +---%<------------------------------------------------------------------------- + +The output will be identical to 'doveadm stats dump session connected' command. + +Carbon support +-------------- + +Since v2.2.27, you can configure dovecot to send statistics periodically in +carbon format. To do this, configure + +---%<------------------------------------------------------------------------- +stats_carbon_server=ip:port # default port 2003 +stats_carbon_name=hostname # do not use dots +stats_carbon_interval=30s # default is 30 seconds + +service stats { + # this is needed if you want stats to be sent when no one is connected + process_min_avail=1 +} +---%<------------------------------------------------------------------------- + +this will send all available global statistics in carbon format +[https://graphite.readthedocs.io/en/latest/feeding-carbon.html]. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Statistics.txt b/doc/wiki/Statistics.txt new file mode 100644 index 0000000..e299220 --- /dev/null +++ b/doc/wiki/Statistics.txt @@ -0,0 +1,109 @@ +Statistics +========== + +This page is about the statistics support for Dovecot v2.3. For v2.1 and v2.2 +see <Statistics.Old.txt>. + +See <Events.txt> for list of all events that can be used in statistics. + +Dovecot v2.3 supports gathering statistics from "events". Eventually all of the +log messages should be events, so it will be possible to configure Dovecot to +get statistics for anything that is logged. For debug messages it's possible to +get statistics even if the message itself isn't logged. + +Currently there are no statistics logged by default (but this might change). +You'll need to add some metrics: + +---%<------------------------------------------------------------------------- +metric name { + # Individual events can be identified either by their name or source +file:line location. + # The source location of course can change between Dovecot versions, so it +should be + # avoided. + event_name = example_event_name + #source_location = example.c:123 + + # Space-separated list of categories that must match the event (e.g. "mail" +or "storage") + #categories = + + # List of fields in event parameters that are included in the metrics. + # All events have a default "duration" field that doesn't need to be listed +here. + #fields = + + # List of key=value pairs that must match the event. The value can contain +'?' and '*' wildcards. + #filter { + # field_key = wildcard + #} +} +---%<------------------------------------------------------------------------- + +Listing Statistics +------------------ + +The gathered statistics are available by running: + +---%<------------------------------------------------------------------------- +doveadm stats dump +---%<------------------------------------------------------------------------- + +Each event has a "duration" field, which tracks in microseconds how long the +event existed. For example with imap_command_finished field it could be: + +---%<------------------------------------------------------------------------- +metric_name field count sum min max avg median %95 +imap_commands duration 35 1190122 162 340477 34003 244 188637 +---%<------------------------------------------------------------------------- + +The above means: + + * count: There have been 35 IMAP commands + * sum: The IMAP commands were running in total for 1190122 microseconds (= 1.1 + seconds) + * min: The fastest IMAP command took 162 microseconds + * max: The slowest IMAP command took 340477 microseconds + * avg: The average time spent on an IMAP commands was 34003 microseconds + * median: The median time spent on an IMAP command was 244 microseconds + * %95: 95% of the IMAP commands took 188637 microseconds or less + +The other fields (than duration) track whatever that field represents. For +example with imap_command_finished's bytes_in field could be tracking how many +bytes were being used by the IMAP commands. Non-numeric fields can also be +tracked, although only the "count" is relevant to those. + +The stats counters are reset whenever the stats process is started, which also +means a dovecot reload will reset statistics. Using 'doveadm stats -r' +parameter will also reset the statistics atomically after they're dumped. + +Examples +-------- + +---%<------------------------------------------------------------------------- +metric imap_select_no { + event_name = imap_command_finished + filter { + name = SELECT + tagged_reply_state = NO + } +} +metric imap_select_no_notfound { + event_name = imap_command_finished + filter { + name = SELECT + tagged_reply = NO*Mailbox doesn't exist:* + } +} + +metric storage_http_gets { + event_name = http_request_finished + categories = storage + filter { + method = get + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Submission.txt b/doc/wiki/Submission.txt new file mode 100644 index 0000000..46bafb3 --- /dev/null +++ b/doc/wiki/Submission.txt @@ -0,0 +1,191 @@ +Submission Server +================= + +As of version 2.3.0, Dovecot provides an SMTP submission service, also known as +a Mail Submission Agent (MSA) [https://tools.ietf.org/html/rfc6409]. It is +currently implemented as a proxy that acts as a front-end for any <MTA.txt>, +adding the necessary functionality required for a submission service: it adds +the required AUTH [https://tools.ietf.org/html/rfc4954] support, avoiding the +need to configure the MTA for SASL authentication. More SMTP capabilities like +CHUNKING [https://tools.ietf.org/html/rfc3030] and SIZE +[https://tools.ietf.org/html/rfc1870] are supported, without requiring the +backend MTA supporting these extensions. Other capabilities like 8BITMIME +[https://tools.ietf.org/html/rfc6152] and DSN +[https://tools.ietf.org/html/rfc3461] currently require support from the +backend/relay MTA. + +The most notable feature that the proxy adds is the BURL capability +[https://tools.ietf.org/html/rfc4468]. The main application of that +capabilitytogether with <IMAP> [IMAPServer.txt] URLAUTH +[https://tools.ietf.org/html/rfc4467]is avoiding a duplicate upload of +submitted e-mail messages; normally the message is both sent through SMTP and +uploaded to the "Sent" folder through IMAP. Using BURL, the client can first +upload the message to IMAP and then use BURL to make the SMTP server fetch the +message from IMAP for submission, thereby avoiding a second upload. Few clients +currently support the BURL capability, but once it becomes available on the +server side, client developers will at least have some incentive to provide +support for this feature. + +*NOTE:* Currently, the submission proxy is still pretty basic. However, it will +provide a basis for adding all kinds of functionality in the (not so distant) +future. For the first time, it will be possible to act upon message submission, +rather than only message retrieval; e.g. plugins can be devised that process +outgoing messages somehow. Examples of the things that could be implemented are +adding <Sieve> [Pigeonhole.txt] filtering support for outgoing messages, or +implicitly storing submitted messages to the Sent folder. Once a plugin API is +devised, you can create your own plugins. + +Features +-------- + +The following SMTP capabilities are supported by the Dovecot submission +service: + + * 8BITMIME [https://tools.ietf.org/html/rfc6152] - Only if relay MTA provides + support + * AUTH [https://tools.ietf.org/html/rfc4954] + * BURL [https://tools.ietf.org/html/rfc4468] + * CHUNKING [https://tools.ietf.org/html/rfc3030] + * DSN [https://tools.ietf.org/html/rfc3461] - Only if relay MTA provides + support + * ENHANCEDSTATUSCODES [https://tools.ietf.org/html/rfc2034] + * PIPELINING [https://tools.ietf.org/html/rfc2920] + * SIZE [https://tools.ietf.org/html/rfc1870] + * STARTTLS [https://tools.ietf.org/html/rfc3207] + * VRFY [https://tools.ietf.org/html/rfc5321] + * XCLIENT [http://www.postfix.org/XCLIENT_README.html] + +Configuration +------------- + +Submission Service +------------------ + +Just add 'submission' to the 'protocols=' setting and configure the relay MTA +server. The submission service is a login service, just like IMAP, POP3 and +<ManageSieve> [Pigeonhole.ManageSieve.txt], so clients are required to +authenticate. The same <authentication configuration> [Authentication.txt] will +also apply to submission, unless you're doing protocol-specific things, in +which case you may need to amend your configuration for the new protocol. BURL +support requires a working IMAP URLAUTH implementation. + +The following settings apply to the Submission service: + +submission_logout_format = in=%i out=%o: + The SMTP Submission logout format string. The following variable + substitutions are supported: + %i : + Total number of bytes read from client + + %o : + Total number of bytes sent to client + + %{command_count} : + Number of commands received from client + + %{reply_count} : + Number of replies sent to client + + %{session} : + Session ID of the login session + + %{transaction_id} : + ID of the current transaction, if any + +hostname : + The host name reported by the SMTP service (and other parts of Dovecot), for + example to the client in the initial greeting and to the relay server in the + HELO/EHLO command. Default is the system's real hostname@domain. + +submission_max_mail_size : + The maximum size of messages accepted for relay. This announced in the SMTP + SIZE capability. If not configured, this is either determined from the relay + server or left unlimited if no limit is known (the relay MTA will reply with + error if some unknown limit exists there, which is duly passed to Dovecot's + client). + +submission_max_recipients : + Maximum number of recipients accepted per connection (default: unlimited). + +Relay MTA +--------- + +The Dovecot SMTP submission service directly proxies the mail transaction to +the SMTP relay configured with the following settings: + +submission_relay_host : + Host name for the relay server (required). + +submission_relay_port = 25 : + Port for the relay server. + +submission_relay_trusted = no : + Is the relay server trusted? This determines whether we try to send + (Postfix-specific) XCLIENT data to the relay server. + +submission_relay_user = : + User name for authentication to the relay MTA if authentication is required + there (authorization ID). + +submission_relay_master_user = : + Master user name for authentication to the relay MTA if authentication is + required there (authentication ID). + +submission_relay_password = : + Password for authentication to the relay MTA if authentication is required + there. + +submission_relay_ssl = no : + Indicates whether TLS is used for the connection to the relay server. The + following values are defined for this setting: + no : + No SSL is used. + + smtps : + An SMTPS connection (immediate SSL) is used. + + starttls : + The STARTTLS command is used to establish the TLS layer. + +submission_relay_ssl_verify = yes : + Configures whether the TLS certificate of the relay server is to be verified. + +submission_relay_rawlog_dir : + Write protocol logs for relay connection to this directory for debugging. + +See <Debugging.Rawlog.txt> for more details on rawlogs. + +Login Proxy +----------- + +Like IMAP and POP3, the Submission login service supports proxying to multiple +backend Dovecot servers. The <proxy configuration wiki page> +[PasswordDatabase.ExtraFields.Proxy.txt] for POP3 and IMAP applies +automatically to Submission as well. + +*IMPORTANT*: Please note that the login proxy described here is configured +between two Dovecot servers (e.g. director frontend and mail storage backend). +This is not the way to configure the relay connection between the Dovecot +submission service and the MTA! That is configured using the relay settings +described in the <previous section> [Submission.txt]. If you get this wrong, +things will seem to work (at least to some extent), but the service provided by +Dovecot will be effectively bypassed. + +Client Support +-------------- + +As of April 2019 there aren't many clients that support the BURL extension. ++-------------+-----------+-------------------------------------------------------------------------------------------------------+ +| *Client* | *Supports | *Notes* | +| | BURL?* | | ++-------------+-----------+-------------------------------------------------------------------------------------------------------+ +| Trojita | Yes | Mentioned on the dovecot discussion list | +| | | [http://dovecot.2317879.n4.nabble.com/New-Dovecot-service-SMTP-Submission-RFC6409-tp62117p62122.html] | ++-------------+-----------+-------------------------------------------------------------------------------------------------------+ +| Thunderbird | No | Vote on bugzilla [https://bugzilla.mozilla.org/page.cgi?id=voting/user.html&bug_id=421779] | ++-------------+-----------+-------------------------------------------------------------------------------------------------------+ +| KDE Akonadi | No | KDE bugzilla [https://bugs.kde.org/show_bug.cgi?id=408732] | +| / KMail | | | ++-------------+-----------+-------------------------------------------------------------------------------------------------------+ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/SystemUsers.txt b/doc/wiki/SystemUsers.txt new file mode 100644 index 0000000..45b5fd9 --- /dev/null +++ b/doc/wiki/SystemUsers.txt @@ -0,0 +1,112 @@ +System Users +============ + +System users are typically defined in '/etc/passwd' file, but this isn't +necessary. Using NSS [http://en.wikipedia.org/wiki/Name_Service_Switch] you can +configure the lookups to be done from elsewhere (e.g. LDAP). See <passwd> +[AuthDatabase.Passwd.txt] userdb configuration for how to set this up. +Especially if you're using nss_ldap you must set 'blocking=yes'. + +System users usually have their own separate user IDs (UIDs). This is good from +security point of view, because it means that the kernel will also prevent +users from accessing each others' mails. + +If the users have direct write access to the mail files (eg. the users have +shell access), they can easily cause all sorts of mailbox corruptions. That may +generate all kinds of error messages to Dovecot's error logs, so it may be +sometimes difficult to tell if there really is a problem or if user is just +doing something stupid. + +If users are going to access the mailboxes with other software than Dovecot, +it's important to make sure that their mailbox accesses are compatible. This +mostly means that with mboxes you must make sure that everyone uses the <same +locking methods in the same order> [MailboxFormat.mbox.txt]. + +Authentication +-------------- + +Admins often wish to use different passwords for IMAP and POP3 than for other +services (eg. SSH), because IMAP and POP3 clients often send the password +unencrypted over the internet without even bothering to give users any +warnings. Dovecot can easily support non-system passwords for system users. + +If you wish to use system passwords, you'll want to use one of these passdbs: + + * <PAM> [PasswordDatabase.PAM.txt]: Most commonly used in Linux and BSDs + nowadays. + * <BSDAuth> [PasswordDatabase.BSDAuth.txt]: BSD authentication is used by + OpenBSD. + * <Passwd> [AuthDatabase.Passwd.txt]: System users (NSS, '/etc/passwd', or + similiar). This may work instead of PAM (mostly in some BSDs). + * <Shadow> [PasswordDatabase.Shadow.txt]: Shadow passwords for system users + (NSS,'/etc/shadow' or similiar). Deprecated by PAM nowadays, but it should + work with Linux and Solaris. + +If you wish to use non-system passwords, you can use pretty much any of the +Dovecot's <password databases> [PasswordDatabase.txt], but for simple +installations you'll probably want to use <passwd-file> +[AuthDatabase.PasswdFile.txt]. + +<User database> [UserDatabase.txt] for system users is always <passwd> +[AuthDatabase.Passwd.txt]. + +Mail Location +------------- + +Usually UNIX systems are configured by default to deliver mails to +'/var/mail/username' or '/var/spool/mail/username' mboxes. You may decide to +use these, or use <maildir> [MailboxFormat.Maildir.txt] format instead. + +Dovecot detects the mailbox format and location automatically if +'mail_location' setting isn't set, but it's still a good idea to explicitly +tell Dovecot where to find the mails. This makes it sure that Dovecot behaves +correctly also when the user's mailbox doesn't exist at the moment (eg. a new +user). If Dovecot can't figure out where the existing mails are, it simply +gives an error message and quits. It never tries to create a missing mailbox +when autodetection is used. + +See <MailLocation.txt> for more information how to configure the mailbox +location. Below are the highlights for mbox and maildir. + +mbox +---- + +The '/var/mail/username' mbox is called user's INBOX. IMAP protocol supports +multiple mailboxes however, so Dovecot needs some directory where to store the +other mailboxes. Typically they're stored in '~/mail/' or '~/Mail/' directory. +All of these locations are included in mailbox location autodetection. You can +specify them manually with: + +---%<------------------------------------------------------------------------- +mail_location = mbox:~/mail:INBOX=/var/mail/%u +---%<------------------------------------------------------------------------- + +Remember that the first path after 'mbox:' is the mailbox root directory, never +try to give 'mbox:/var/mail/%u' because that just isn't going to work (unless +you really want to store mails under '/var/mail/%u/' directory). + +If you're also using other software than Dovecot to access mboxes, you should +try to figure out what locking methods exactly they're using and update +'mbox_read_locks' and 'mbox_write_locks' settings accordingly. See locking +section in <mbox> [MailboxFormat.mbox.txt] for more information. + +Maildir +------- + +Maildir is typically stored in '~/Maildir' directory. You can specify this +manually with: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +---%<------------------------------------------------------------------------- + +Chrooting +--------- + +Dovecot, including several other software, allow using "/./" in home directory +path to specify the chroot path. For example '/home/./user' would chroot to +'/home'. If you want to enable this for Dovecot, add the chroot path to +'valid_chroot_dirs' setting ('/home' in the previous example). If this isn't +done, Dovecot just ignores the "/./". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/TestInstallation.txt b/doc/wiki/TestInstallation.txt new file mode 100644 index 0000000..71416dc --- /dev/null +++ b/doc/wiki/TestInstallation.txt @@ -0,0 +1,239 @@ +Contents + + + 1. Check that it's running + + 2. Check that it's listening + + 3. Check that it's allowing logins + + 4. Check that it's allowing remote logins + + 5. Check that it finds INBOX + + 6. Check that it finds other mailboxes + + 7. Check out some other IMAP commands + + 8. Check that real mail clients work + + 9. Make a graceful exit + +For testing POP3 installation, see <TestPop3Installation.txt>. + +Check that it's running +----------------------- + +First check with 'ps' that 'dovecot' process is actually running. If it's not, +you had an error in 'dovecot.conf' and the error message was written to log. Go +back to <RunningDovecot.txt> and <Logging.txt> if you can't find it. + +Check that it's listening +------------------------- + +Next check that Dovecot is listening for connections: + +---%<------------------------------------------------------------------------- +# telnet localhost 143 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. +* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE STARTTLS +AUTH=PLAIN] Dovecot ready. +---%<------------------------------------------------------------------------- + +If you got "connection refused", make sure that Dovecot is configured to serve +the imap protocol and listening on the expected interfaces/addresses.The +simplest way to do that would be using <doveconf(1)> [Tools.Doveconf.txt]: + +---%<------------------------------------------------------------------------- +# doveconf protocols listen +protocols = imap pop3 lmtp sieve +listen = *, :: +---%<------------------------------------------------------------------------- + +If the protocols setting don't contain 'imap' then add it. Also make sure, that +relevant '!include' or '!include_try' configuration lines are not commented. + +If the telnet fails and dovecot emits a log "/auth: Fatal: Support not compiled +in for passdb driver 'pam'/", then rebuild dovecot with package libpam0g-dev +installed. In that case you have to re-run the configure script, possibly +including option *--with-pam* to the configure command line. + +Next check that it also works from remote host: + +---%<------------------------------------------------------------------------- +# telnet imap.example.com 143 +Trying 1.2.3.4... +Connected to imap.example.com. +Escape character is '^]'. +* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE STARTTLS +AUTH=PLAIN] Dovecot ready. +---%<------------------------------------------------------------------------- + +If that didn't work, check all possible firewalls in between, and check that +'listen' setting is '*' in 'dovecot.conf'. + +If you have only imaps enabled, see "remote login" section below for how to +test using openssl s_client. + +Check that it's allowing logins +------------------------------- + +---%<------------------------------------------------------------------------- +# telnet localhost 143 +a login "username" "password" +---%<------------------------------------------------------------------------- + +Replace the username and password with the ones you added to 'passwd.dovecot' +in <BasicConfiguration.txt>. Note that all IMAP commands begin with a tag, +which is basically any string you want, but it must be there. So don't leave +out the "a" in the above example. If the password contains '"' character, +escape it with '\' (e.g.'"foo\"bar"'). + +You should get an "a OK Logged in." reply. If you get "Authentication failed" +error, set 'auth_verbose = yes' and 'auth_debug = yes' in 'dovecot.conf', +restart Dovecot and try again. The log file should now show enough information +to help you fix the problem. + +Check that it's allowing remote logins +-------------------------------------- + +You'll need to try this from another computer, since all local IPs are treated +as secure: + +---%<------------------------------------------------------------------------- +# telnet imap.example.com 143 +a login "username" "password" +---%<------------------------------------------------------------------------- + +If the connection is hanging instead of giving '* Dovecot ready', you have a +firewall that's preventing the connections. + +Otherwise, the only difference here compared to step above is that you might +get: + +---%<------------------------------------------------------------------------- +* BAD [ALERT] Plaintext authentication is disabled, but your client sent +password in plaintext anyway. If anyone was listening, the password was +exposed. +a NO Plaintext authentication disabled. +---%<------------------------------------------------------------------------- + +If this is the case, you didn't set 'disable_plaintext_auth = no'. You could +alternatively use OpenSSL to test that the server works with SSL: + + * Test using imaps port (assuming you haven't disabled imaps port): + ---%<---------------------------------------------------------------------- + # openssl s_client -connect imap.example.com:993 + * OK Dovecot ready. + ---%<---------------------------------------------------------------------- + + * Test using imap port and STARTTLS command (works also with imap port): + ---%<---------------------------------------------------------------------- + # openssl s_client -connect imap.example.com:143 -starttls imap + * OK Dovecot ready. + ---%<---------------------------------------------------------------------- + +Check that it finds INBOX +------------------------- + +After logging in, check that the INBOX is found: + +---%<------------------------------------------------------------------------- +b select inbox +* FLAGS (\Answered \Flagged \Deleted \Seen \Draft) +* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags +permitted. +* 1 EXISTS +* 1 RECENT +* OK [UIDVALIDITY 1106186941] UIDs valid +* OK [UIDNEXT 2] Predicted next UID +b OK [READ-WRITE] Select completed. +---%<------------------------------------------------------------------------- + +It should contain the mail that you sent to yourself in <FindMailLocation.txt> +step. + +If anything goes wrong, set 'mail_debug = yes' and try again. The log file +should now contain debugging information of where Dovecot is trying to find the +mails. Fix 'mail_location' setting and try again. + +Check that it finds other mailboxes +----------------------------------- + +If you already have other mailboxes created, you can check that Dovecot finds +them: + +---%<------------------------------------------------------------------------- +c list "" * +* LIST (\NoInferiors) "/" "test" +* LIST (\NoInferiors) "/" "INBOX" +c OK List completed. +---%<------------------------------------------------------------------------- + +If they weren't found, set 'mail_debug = yes' and look at the debugging +information. Fix 'mail_location' setting and try again. + +Check out some other IMAP commands +---------------------------------- + +If you already have some emails, you can try reading them: + +---%<------------------------------------------------------------------------- +1 SELECT INBOX +2 FETCH 1:* (FLAGS INTERNALDATE BODY.PEEK[HEADER.FIELDS (SUBJECT)]) +3 FETCH 1 BODY[TEXT] +---%<------------------------------------------------------------------------- + +'1:*' means all messages + +You can also try moving a mail to Trash: + +---%<------------------------------------------------------------------------- +4 CREATE Trash +5 COPY 1 Trash +6 STORE 1 +FLAGS \Deleted +7 EXPUNGE +---%<------------------------------------------------------------------------- + +Check that real mail clients work +--------------------------------- + +Since mail clients can be configured in various ways, please check first if the +problem is with Dovecot configuration or with the client's configuration. You +can rule out it being Dovecot's problem with the "telnet" methods described +above. + +If you can't log in, + + * Make sure SSL/TLS settings are correct. + * Make sure the client uses plaintext authentication method, unless you've + specifically configured Dovecot to accept others. + +If you can see only INBOX, + + * Clear out any "IMAP namespace prefix" or similar settings from clients. + * Check if client is configured to show only "subscribed mailboxes". If so, + you'll have to subscribe to the mailboxes you wish to see. You can see a + list of subscribed mailboxes with: + ---%<---------------------------------------------------------------------- + d lsub "" * + * LSUB () "/" "INBOX" + d OK Lsub completed. + ---%<---------------------------------------------------------------------- + +Most IMAP clients have been tested with Dovecot and they work. + +Make a graceful exit +-------------------- + +To close the connection to Dovecot issue a logout: + +---%<------------------------------------------------------------------------- +e logout +* BYE Logging out +e OK Logout completed. +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/TestPop3Installation.txt b/doc/wiki/TestPop3Installation.txt new file mode 100644 index 0000000..dc38b40 --- /dev/null +++ b/doc/wiki/TestPop3Installation.txt @@ -0,0 +1,149 @@ +Contents + + + 1. Check that it's running + + 2. Check that it's listening + + 3. Check that it's allowing logins + + 4. Check that it's allowing remote logins + + 5. Check that it finds the mails + + 6. Check that real mail clients work + + 7. Make a graceful exit + +Check that it's running +----------------------- + +First check with 'ps' that 'dovecot' process is actually running. If it's not, +you had an error in 'dovecot.conf' and the error message was written to log. Go +back to <RunningDovecot.txt> and <Logging.txt> if you can't find it. + +Check that it's listening +------------------------- + +Next check that Dovecot is listening for connections: + +---%<------------------------------------------------------------------------- +# telnet localhost 110 +Trying 127.0.0.1... +Connected to localhost. +Escape character is '^]'. ++OK Dovecot ready. +---%<------------------------------------------------------------------------- + +If you got "connection refused", check that 'pop3' is included in 'protocols' +setting in 'dovecot.conf'. Also check that 'listen' setting is '*'. + +Next check that it also works from remote host: + +---%<------------------------------------------------------------------------- +# telnet imap.example.com 110 +Trying 1.2.3.4... +Connected to imap.example.com. +Escape character is '^]'. ++OK Dovecot ready. +---%<------------------------------------------------------------------------- + +If that didn't work, check all possible firewalls in between, and check that +'listen' setting is '*' in 'dovecot.conf'. + +Check that it's allowing logins +------------------------------- + +---%<------------------------------------------------------------------------- +# telnet localhost 110 +user username +pass password +---%<------------------------------------------------------------------------- + +Replace the username and password with the ones you added to 'passwd.dovecot' +in <BasicConfiguration.txt>. + +You should get an "+OK Logged in." reply. If you get "Authentication failed" +error, set 'auth_verbose = yes' and 'auth_debug = yes' in 'dovecot.conf', +restart Dovecot and try again. The log file should now show enough information +to help you fix the problem. + +Check that it's allowing remote logins +-------------------------------------- + +You'll need to try this from another computer, since all local IPs are treated +as secure: + +---%<------------------------------------------------------------------------- +# telnet imap.example.com 110 +user username +pass password +---%<------------------------------------------------------------------------- + +If the connection is hanging instead of giving '+OK Dovecot ready', you have a +firewall that's preventing the connections. + +Otherwise, the only difference here compared to step above is that you might +get: + +---%<------------------------------------------------------------------------- +-ERR Plaintext authentication disabled. +---%<------------------------------------------------------------------------- + +If this is the case, you didn't set 'disable_plaintext_auth = no'. You could +alternatively use OpenSSL to test that the server works with SSL (assuming +you've already set it up): + +---%<------------------------------------------------------------------------- +# openssl s_client -connect imap.example.com:995 ++OK Dovecot ready. +---%<------------------------------------------------------------------------- + +Check that it finds the mails +----------------------------- + +After logging in, check that it sees mails: + +---%<------------------------------------------------------------------------- +stat ++OK 1 1532 +retr 1 ++OK 1532 octets +<the mail's contents> +. +---%<------------------------------------------------------------------------- + +It should contain the mail that you sent to yourself in <FindMailLocation.txt> +step. + +If anything goes wrong, set 'mail_debug = yes' and try again. The log file +should now contain debugging information of where Dovecot is trying to find the +mails. Fix 'mail_location' setting and try again. + +Check that real mail clients work +--------------------------------- + +Since mail clients can be configured in various ways, please check first if the +problem is with Dovecot configuration or with the client's configuration. You +can rule out it being Dovecot's problem with the "telnet" methods described +above. + +If you can't log in, + + * Make sure SSL/TLS settings are correct. + * Make sure the client uses plaintext authentication method, unless you've + specifically configured Dovecot to accept others. + +Many POP3 clients have been tested with Dovecot and they work. + +Make a graceful exit +-------------------- + +To close the connection to Dovecot issue a logout: + +---%<------------------------------------------------------------------------- +quit ++OK Logging out. +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/TimeMovedBackwards.txt b/doc/wiki/TimeMovedBackwards.txt new file mode 100644 index 0000000..cb64a99 --- /dev/null +++ b/doc/wiki/TimeMovedBackwards.txt @@ -0,0 +1,87 @@ +Time moved backwards error +========================== + +Dovecot isn't very forgiving if your system's time moves backwards. There are +usually two possibilities why it's moving backwards: + + 1. You're running 'ntpdate' periodically. This isn't a good idea. + 2. You're using some kind of a virtual server and you haven't configured it + right (or it's buggy). + +Moving time backwards might cause various problems (see below), so Dovecot +versions older than v2.0 don't even try to handle the situation. + +Time synchronization +-------------------- + +There are two choices for synchronizing your clock: + + 1. Use ntpd [http://www.ntp.org/]. It periodically checks the current time + from NTP server and slows down or speeds up the clock if necessary. Unlike + ntpdate, it doesn't just move the time forwards or backwards (unless the + difference is large). + * If the time difference is too large for ntpd and it "steps", then use + "-x" as a command line option for ntpd or use "tinker step 0" in + '/etc/ntp.conf'. + * This shows up in logs as: 'ntpd[17697]: time reset -2.075483 s' + 2. If ntpd doesn't work well (e.g. a bad network connection), you can use + clockspeed [http://cr.yp.to/clockspeed.html] or chrony + [http://chrony.sunsite.dk/] as well. + +In some systems ntpd/ntpdate is run at boot, but only after Dovecot has +started. That can cause Dovecot to die immediately. If you have this problem, +fix your init scripts to run ntpd/ntpdate first, before starting Dovecot. +Also, seriously consider running ntp-wait before starting Dovecot. + +Bugs/Issues +----------- + + * With Xen you should run ntpd only in dom0. Other domains should synchronize + time automatically (see this Xen FAQ [http://xen.epiuse.com/xen-faq.txt] and + this thread [http://dovecot.org/list/dovecot/2009-October/043301.html]). + * With Vmware you follow the guidlines at the Vmware knowledge base + [http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1006427]. + * Time moved backwards by 4398 seconds + [http://www.dovecot.org/list/dovecot/2008-June/031548.html]? Buggy + kernel/hardware. + +What about Daylight Saving/Summer time? +--------------------------------------- + +On Unix-like systems, time is stored internally as the number of seconds since +January 1, 1970, 00:00:00 UTC (see Unix_time [WikiPedia:Unix_time] on +Wikipedia); concepts such as time zones and daylight saving time are applied in +user space by the C library, and will normally not have an impact on Dovecot's +behavior. + +Dovecot shouldn't just die! +--------------------------- + +Dovecot v2.0 finally tries to handle this a bit more gracefully. Its behavior +when time moves backwards is: + + * Existing imap and pop3 processes either sleep or die, just like with older + versions + * Master process stops creating new processes until either the original time + is reached, or after a maximum wait of 3 minutes. + * Other processes log a warning, but do nothing else. + * Timeouts are updated so that the timeout is executed approximately at the + original intended time. + +Dovecot v2.0 also notices when time unexpectedly jumps forwards. In that +situation it logs a warning and also updates timeouts. + +The reason why imap/pop3 processes get killed and new ones can't be created for +a while is to avoid problems related to timestamps. Some issues are: + + * Uniqueness of Maildir filenames and dbox global unique identifiers relies on + a growing timestamp + * Dotlock files' staleness is detected by looking at its mtime. + * Timestamps are stored internally all around in memory (as well as in index + files) and compared to current time. Those checks may or may not be buggy if + current time shrinks. + +While killing mail processes doesn't fully solve any of those issues, they're +at least less likely to happen then. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Timeouts.txt b/doc/wiki/Timeouts.txt new file mode 100644 index 0000000..8eaceba --- /dev/null +++ b/doc/wiki/Timeouts.txt @@ -0,0 +1,61 @@ +Timeouts +======== + +Dovecot has a lot of timeouts in various components. Most of them have +hardcoded values, because there's normally no need to change them. Here are +some of them listed: + +IMAP +---- + + * Before login: CLIENT_LOGIN_TIMEOUT_MSECS = MASTER_LOGIN_TIMEOUT_SECS*1000 = + 3 minutes (login-common/client-common.h and lib-master/master-interface.h) + * This may be shorter if all the available connections are in use (service + imap-login { client_limit * process_limit }). In that case the oldest + non-logged in connection is disconnected. + * After login: CLIENT_IDLE_TIMEOUT_MSECS = 30 minutes (minimum required by + IMAP RFC) + * If IDLE command is started, Dovecot never disconnects. Only if the + connection is lost there will be a disconnection. A dead connection is + detected by Dovecot periodically sending "I'm still here" notifications + to client (imap_idle_notify_interval setting - default every 2 minutes). + * IMAP clients are supposed to send something before 30 minutes are up, + but several clients don't do this. Some Outlook versions even stop + receiving new mails entirely until manual intervention if IMAP server + disconnects the client. + * Dovecot also disconnects an IMAP client that sends too many invalid + commands: + * Before login: Disconnect on 3rd invalid command (CLIENT_MAX_BAD_COMMANDS + in imap-login/client.c) + * After login: Disconnect on 20th invalid command (CLIENT_MAX_BAD_COMMANDS + in imap/imap-common.h) + +POP3 +---- + + * Before login: CLIENT_LOGIN_TIMEOUT_MSECS = MASTER_LOGIN_TIMEOUT_SECS*1000 = + 3 minutes (common with IMAP code) + * This may be shorter if all the available connections are in use (service + imap-login { client_limit * process_limit }). In that case the oldest + non-logged in connection is disconnected. + * After login: CLIENT_IDLE_TIMEOUT_MSECS = 10 minutes + * Dovecot also disconnects an POP3 client that sends too many invalid + commands: + * Before login: Disconnect on 3rd invalid command in v2.2.16+, 11th on + earlier versions (CLIENT_MAX_BAD_COMMANDS in pop3-login/client.c) + * After login: Disconnect on 20th invalid command (CLIENT_MAX_BAD_COMMANDS + in pop3/pop3-client.c) + +IMAP & POP3 proxies +------------------- + + * Dovecot proxy handles IMAP and POP3 pre-login timeouts and invalid error + command handling the same as Dovecot backend. After login the proxy will + continue proxying until the client or the backend disconnects. + * Connect timeout to backend is PROXY_DEFAULT_TIMEOUT_MSECS = 30 secs by + default. Can be overridden by proxy_timeout passdb extra field. + * After connection has been established, there's still a login timeout + CLIENT_LOGIN_TIMEOUT_MSECS = MASTER_LOGIN_TIMEOUT_SECS*1000 = 3 minutes + (login-common/client-common.h and lib-master/master-interface.h) + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.1.0.txt b/doc/wiki/Upgrading.1.0.txt new file mode 100644 index 0000000..d61e159 --- /dev/null +++ b/doc/wiki/Upgrading.1.0.txt @@ -0,0 +1,137 @@ +Upgrading Dovecot v0.99.x to v1.0 +================================= + +Contents + + + 1. Upgrading Dovecot v0.99.x to v1.0 + + 1. Configuration file + + 2. PAM + + 3. SQL Configuration + + 4. Subscriptions + + 5. Keywords + + 6. POP3 UIDLs + + 7. mbox errors + + 8. Port Changes + + 9. Log Changes for POP before SMTP + +The upgrade from Dovecot v0.99.x to v1.0 isn't just a drop-in upgrade, but also +requires the administrator to adjust the configuration in several places, as +detailed in the chapters below. + +Configuration file +------------------ + +The configuration file has had a lot of changes, so it's better to just modify +the included 'dovecot-example.conf' file manually. The easiest way to remember +what you had changed in the old file is with grep: + +---%<------------------------------------------------------------------------- +egrep -v '^ *(#|$)'|less +---%<------------------------------------------------------------------------- + +PAM +--- + +Dovecot v0.99.x defaulted to using "imap" or "pop3" PAM service identifiers, +ie.'/etc/pam.d/imap' or '/etc/pam.d/pop3' files. With v1.0, the default is to +use "dovecot" service identifier, i.e.'/etc/pam.d/dovecot'. Either change the +passdb pam args to use the "*" parameter or set up the '/etc/pam.d/' files +properly. + +SQL Configuration +----------------- + +The SQL configuration has changed. 'password_query' in the new dovecot-sql.conf +must return a field named 'password'. + +Subscriptions +------------- + +*Maildir only*: The filename that stores user subscriptions has changed from +'.subscriptions' to 'subscriptions'. (It is still called '.subscriptions' for +mbox.). Since v1.0.rc2 the renaming is done automatically. + +Keywords +-------- + +*Maildir-only*: The former '.customflags' file has been renamed to +*dovecot-keywords*, which is incompatible with v0.99.x's format. Since v1.0.rc2 +Dovecot can convert the file automatically. (This conversion does not happen +when going directly from v0.99 to v1.1, though. The files must be renamed +manually.) + +POP3 UIDLs +---------- + +UIDLs are used by POP3 clients to keep track of what messages they've +downloaded, typically only if you've enabled "keep messages in server" option. +If the UIDL changes, the existing messages are re-downloaded as new messages, +which you should try to avoid. + +For compatibility with Dovecot v0.99.x, use: + +---%<------------------------------------------------------------------------- +pop3_uidl_format = %v.%u +---%<------------------------------------------------------------------------- + +However this doesn't work well for Outlook 2003 users (as it didn't with +v0.99.x either), which is the reason this isn't the default anymore. See +<POP3Server#uidl> [POP3Server.txt] for alternative (and better) UIDL formats. + +mbox errors +----------- + +The first time a user opens a mailbox after upgrading it may log some errors +such as: + +---%<------------------------------------------------------------------------- +mbox sync: UID inserted in the middle of mailbox /var/mail/**** (4409 > 4237) +---%<------------------------------------------------------------------------- + +The user may need to log out and log in again to see all of the messages in the +affected mailboxes. Note that this shouldn't happen unless the mbox already had +some errors. The new mbox parsing code just does better error checking. + +Port Changes +------------ + +The port settings are different. The new settings are: + +---%<------------------------------------------------------------------------- +# if you wish to just change IP address, change: +listen = 1.2.3.4 +ssl_listen = 1.2.3.4 + +# if you wish to change ports also, use instead: +protocol imap { + listen = *:143 + ssl_listen = *:993 +} +protocol pop3 { + listen = *:110 + ssl_listen = *:995 +} +---%<------------------------------------------------------------------------- + +Log Changes for POP before SMTP +------------------------------- + +If you used <POP-before-SMTP> [PopBSMTPAndDovecot.txt], the log strings are +different. This should work with new versions: + +---%<------------------------------------------------------------------------- + $s =~ s/^... .. ..:..:.. .* dovecot: (pop3|imap)-login: Login: .+ +rip=(\d+\.\d+\.\d+\.\d+),.*$/$2/i; +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.1.1.txt b/doc/wiki/Upgrading.1.1.txt new file mode 100644 index 0000000..892deb7 --- /dev/null +++ b/doc/wiki/Upgrading.1.1.txt @@ -0,0 +1,90 @@ +Upgrading Dovecot v1.0 to v1.1 +============================== + +You can use your old 'dovecot.conf' from v1.0. It should work without changes, +although a couple of deprecated settings have been removed. + +Upgrading from Dovecot versions older than v1.0.rc1 directly to v1.1 is not +recommended. v1.0 versions contain some backwards compatibility checks and file +format converters that have been removed from v1.1. + +If you want to downgrade back after running v1.1, don't downgrade to older +versions than v1.0.8 or you'll get crashes. Especially if you're using maildir, +the 'dovecot-uidlist' file format has changed and Dovecot versions older than +v1.0.2 can't read it. + +Connections +----------- + + * 'listen = [::]' listens only for IPv6 connections now in most operating + systems. If you want both IPv4 and IPv6 use 'listen = *, [::]' + * By default the number of connections per-user per-IP is limited to 10. You + can change this with the 'mail_max_userip_connections' setting. + +Authentication +-------------- + + * <passwd-file> [AuthDatabase.PasswdFile.txt]: If you use %d in args, it no + longer means that domain isn't looked up from the passwd-file. You'll need + to add 'username_format=%n' prefix to args (e.g. 'args = username_format=%n + /etc/virtual.%d'). + * Empty or NULL password no longer means "any password is valid". You'll also + have to return "nopassword" field. + * <PAM> [PasswordDatabase.PAM.txt]: There's no more 'blocking=yes' setting, + it's now always enabled. If you want to limit the number of lookups done by + a dovecot-auth worker, change 'auth_worker_max_request_count' setting. + Setting it to 1 makes it work basically the same as the old 'blocking=no'. + * <passwd> [AuthDatabase.Passwd.txt]: The problem with passwd lookups is that + temporary errors (e.g. LDAP server down) are returned as "user doesn't + exist" errors. You may want to try the new <NSS> [UserDatabase.NSS.txt] + userdb. + * <SQL> [AuthDatabase.SQL.txt] and <LDAP> [AuthDatabase.LDAP.txt]: + 'user_global_uid' and 'user_global_gid' fields have been removed from their + config files. Instead you can now use 'mail_uid' and 'mail_gid' settings in + 'dovecot.conf'. This also means that it's no longer a requirement to specify + a userdb at all (a dummy <static userdb> [UserDatabase.Static.txt] is used + internally). + +Mail handling +------------- + + * In v1.0 'mmap_disable=yes' might have worked faster. If you had changed this + only because of that, it's time to set it back to "no". + * <NFS.txt> users should now set 'mail_nfs_storage=yes' and + 'mail_nfs_index=yes'. Dovecot no longer requires attribute cache to be + disabled. + * <Quota.txt> plugin has completely new configuration. See <Quota.1.1.txt>. + * <Maildir> [MailboxFormat.Maildir.txt]: 'dovecot-uidlist' file is in a new + format. The old format is automatically converted to new one, but if you + plan to move back to v1.0 be sure to use at least v1.0.2 which will also + understand this new format. + * Index files have slightly changed as well. Upgrading to v1.1 should go + transparently, but moving back to v1.0 might again cause some errors. v1.0.8 + fixes some assert-crashes that were caused by reading v1.1-generated index + files. + * 'dotlock_use_excl=yes' is default nowadays. If you're still using an ancient + NFSv2 setup, you'll need to set this to "no". + * mbox: Delete existing dovecot.index.cache files from all mailboxes. + Otherwise you may see some errors in logs. + * 'default_mail_env' has been renamed to 'mail_location' (since v1.0.rc11 + already). + * Namespaces: + * deliver now supports namespaces. If you use namespace prefixes or a + non-default separator and you deliver to non-INBOXes, deliver will now + have to use the configured prefix and separators. + * This is especially important for Sieve scripts. For example if you + only have "INBOX." namespace prefix and you used to use 'fileinto + "box"', it now has to be instead: 'fileinto "INBOX.box"' + * 'hidden=yes' now hides the namespace only from IMAP NAMESPACE reply. + You'll also need to set 'list=no' to truly hide them from clients' + mailbox list. + +Removed settings +---------------- + + * mail_read_mmaped: Mails are never read mmaped anymore. There wasn't much + point. + * mmap_no_write: OpenBSD users will have to settle for mmap_disable=yes for + now. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.1.2.txt b/doc/wiki/Upgrading.1.2.txt new file mode 100644 index 0000000..f381e83 --- /dev/null +++ b/doc/wiki/Upgrading.1.2.txt @@ -0,0 +1,57 @@ +Upgrading Dovecot v1.1 to v1.2 +============================== + + * Relative home directory paths are giving errors now. They were never + supported, but earlier they just didn't usually cause problems. + * If you were using e.g. 'mail_location = maildir:/var/mail/%h', just + change it to 'mail_location = maildir:%h' and add '/var/mail/' prefix to + home dirs. + * To get absolute home dir from relative path in LDAP, use something like: + 'user_attrs = .., homeDirectory=home=/var/mail/%$' + * SQL dictionary (quota, expire plugin) configuration file is different than + in v1.1. See 'doc/dovecot-dict-sql-example.conf' or <Quota.Dict.txt> for the + new format. + * When creating files or directories to mailboxes, Dovecot now uses the + mailbox directory's permissions and GID for them. Previous versions simply + used 0600 mode always, so you should check the directories' permissions to + make sure they're strict enough. For backwards compatibility + 'dovecot-shared' file's permissions still override these with Maildir. + +Authentication: + + * system_user <userdb extra field> [UserDatabase.ExtraFields.txt] was renamed + to system_groups_user to better describe its functionality. + +Settings: + + * Renamed 'ssl_disable=yes' to 'ssl=no'. + * Renamed 'auth_ntlm_use_winbind' to 'auth_use_winbind', which also determines + if GSS-SPNEGO is handled by GSSAPI or winbind. + * Removed 'login_greeting_capability'. The capabilities are now always sent + (LEMONADE [http://www.lemonadeformobiles.com/] requires this and it's not + that much extra traffic). + * Removed 'auth_worker_max_request_count'. It was useful only with PAM, so it + can now be specified in 'passdb pam { args = max_requests=n } '. The default + is 100. + * Removed 'umask'. It wasn't really used anywhere anymore. + +ACL: + + * The global ACL file overrides per-mailbox ACL file. + +Sieve: + + * You should consider <migrating from CMU Sieve to Pigeonhole> + [Pigeonhole.Sieve.Configuration.txt] (see the link for instructions). + +<ManageSieve> [Pigeonhole.ManageSieve.txt]: + + * The 'sieve=' and 'sieve_storage=' settings need to be placed in the ' plugin + {}' section now and 'sieve_storage=' needs to be renamed to 'sieve_dir='. + This removes the duplication of these values with respect to the <Sieve + Plugin> [Pigeonhole.Sieve.txt] for <Deliver> [LDA.txt]. So, since you are + using the Sieve plugin, these settings should already be there and all that + needs to be done is remove the 'sieve=' and 'sieve_storage=' settings from + the ' protocol managesieve {} ' section. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.2.0.txt b/doc/wiki/Upgrading.2.0.txt new file mode 100644 index 0000000..1114ea1 --- /dev/null +++ b/doc/wiki/Upgrading.2.0.txt @@ -0,0 +1,92 @@ +Upgrading Dovecot v1.2 to v2.0 +============================== + +A lot of settings have changed. Dovecot v2.0 can still use most of the v1.x +configuration files, but it logs a lot of warnings at startup. A quick and easy +way to convert your old config file to v2.0 format is: + +---%<------------------------------------------------------------------------- +# convert old config to new temp config file +doveconf -n -c /etc/dovecot/dovecot.conf > dovecot-2.conf + +# replace the old config file with the new generated file +mv dovecot-2.conf /etc/dovecot/dovecot.conf +---%<------------------------------------------------------------------------- + +This command logs a warning about each obsolete setting it converts to the new +format.*You can simply ignore all the warnings* in most cases. If you really +want to, you can modify your old config file using the instructions from the +warnings, but even that can be done more easily by looking at the generated +config file. Some of the warning messages aren't obvious. + +Once running v2.0, it's safe to downgrade to v1.2.5 or newer. Older versions +don't understand some of the changes to index files and will log errors. + +Permission related changes +-------------------------- + + * Dovecot uses two system users for internal purposes now by default: + "dovenull" and "dovecot". You need to create the "dovenull" user or change + 'default_login_user' setting. "dovenull" user is used by completely + untrustworthy processes, while "dovecot" user is used for slightly more + trusted processes. + * If you want to be using something else than "dovecot" as the other user, + you need to change 'default_internal_user' setting. + * Just like with "dovecot" user, "dovenull" doesn't need a password, home + directory or anything else (but it's good to give it its own private + "dovenull" group). + * "auth-master" socket related configuration should be replaced with + "auth-userdb" socket everywhere (auth-master should still work, but it gives + more permissions than necessary) + * If you get any kind of "permission denied" errors related to UNIX sockets, + you can change their permissions from 'service { unix_listener { ... } } ' + blocks. See 'example-config/conf.d/10-master.conf' for examples or 'doveconf + -a' output for their current values. + +Other major changes +------------------- + + * No more convert plugin, use <dsync> [Tools.Dsync.txt] instead + * No more expire-tool, use <doveadm expunge> [Plugins.Expire.txt] instead. + Also expire configuration is different. + * <Post-login scripts are configured differently> [PostLoginScripting.txt] and + need to be modified + * <Quota warnings are configured differently> [Quota.Configuration.txt] and + the script may need to be modified (most environment settings like $USER are + gone) + * Global ACL filenames now require namespace prefix (e.g. if you use "INBOX." + prefix,'/etc/acls/foo' needs to be renamed to '/etc/acls/INBOX.foo' + * Maildir: Permissions for newly created mail files are no longer copied from + dovecot-shared file, but instead from the mail directory (e.g. for "foo" + mailbox, they're taken from '~/Maildir/.foo' directory) + * dbox: v2.0 format is slightly different, but backwards compatible. The main + problem is that v2.0 no longer supports maildir-dbox hybrid resulting from + "fast Maildir migration". If you have any Maildir files in your dbox, you + need to convert them somehow (some examples + [http://dovecot.org/list/dovecot/2010-September/053012.html]). You might + also consider using <dsync> [Tools.Dsync.txt] to get rid of the old unused + metadata in your dbox files. + * Pre-login and post-login CAPABILITY reply is now different. Dovecot expects + clients to recognize new automatically sent capabilities. + [http://dovecot.org/list/dovecot/2010-April/048147.html] This should work + with all commonly used clients, but some rarely used clients might have + problems. Either get the client fixed, or set 'imap_capability' manually. + * ManageSieve protocol [http://tools.ietf.org/html/rfc5804] was assigned an + official port by IANA: 4190. This is used by <Pigeonhole.txt> by default + now. If you want to listen also on the old 2000 port, see the + <Pigeonhole.ManageSieve.Configuration.txt> example. + * 'dovecot --exec-mail imap' has been replaced by simply running "imap" + binary. You can also use "imap -u<username>" to access other users' mails + more easily. + +LDA +--- + + * deliver binary was renamed to dovecot-lda (but a symlink still exists for + now) + * -n parameter was replaced by lda_mailbox_autocreate setting. The default + also changed to "no". + * -s parameter was replaced by lda_mailbox_autosubscribe setting. The default + is "no", as before. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.2.1.txt b/doc/wiki/Upgrading.2.1.txt new file mode 100644 index 0000000..0dec9ff --- /dev/null +++ b/doc/wiki/Upgrading.2.1.txt @@ -0,0 +1,35 @@ +Upgrading Dovecot v2.0 to v2.1 +============================== + +v2.1 is mostly compatible with v2.0 configuration, except: + + * 15-mailboxes.conf included in the default configuration now specifies a few + default SPECIAL-USE [http://tools.ietf.org/html/rfc6154] mailboxes. This + file assumes that you already have 'namespace inbox { .. } ' specified (in + 10-mail.conf). If you don't, you'll get errors about namespaces. Note that + the namespace's name must be "inbox" (as well as usually include inbox=yes + setting). The solution is to either make sure that you have such a namespace + defined, or you can simply delete the 15-mailboxes.conf if you don't care + about SPECIAL-USE. + * <Plugins.txt> now use UTF-8 mailbox names rather than mUTF-7: acl, + autocreate, expire, trash, virtual + * Usernames in authentication are now lowercased by default. + * Non-lowercase usernames in password/user database result in "unknown + user" errors + * To allow mixed case usernames again, set 'auth_username_format=' (i.e. to + empty) + * <Solr> [Plugins.FTS.Solr.txt] full text search backend changed to use + mailbox GUIDs instead of mailbox names, requiring reindexing everything. + solr_old backend can be used with old indexes to avoid reindexing, but it + doesn't support some newer features. + * <Expire plugin> [Plugins.Expire.txt]: Only go through users listed by userdb + iteration. Delete dict rows for nonexistent users, unless + expire_keep_nonexistent_users=yes. + * <dsync> [Tools.Dsync.txt] was merged into doveadm. There is still "dsync" + symlink pointing to "doveadm", which you can use the old way for now. The + preferred ways to run dsync are "doveadm sync" (for old "dsync mirror") and + "doveadm backup". + * dsync protocol isn't compatible with v2.0's dsync, so you can't dsync + between v2.0 and v2.1 servers. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.2.2.txt b/doc/wiki/Upgrading.2.2.txt new file mode 100644 index 0000000..b8d6865 --- /dev/null +++ b/doc/wiki/Upgrading.2.2.txt @@ -0,0 +1,45 @@ +Upgrading Dovecot v2.1 to v2.2 +============================== + +v2.2 has a couple of changes to settings since v2.1: + + * doveadm_proxy_port setting renamed to doveadm_port (but the old exists still + as an alias) + * imapc_ssl_ca_dir and pop3c_ssl_ca_dir settings replaced by a common + ssl_client_ca_dir + +There are also some changes you should be aware of: + + * fts-solr no longer does "hard commits" to the Solr index for performance + reasons. <You must do this manually once in a while> [Plugins.FTS.Solr.txt]. + + * When creating home directories, the permissions are copied from the parent + directory if it has setgid-bit set. For full details, see + <SharedMailboxes.Permissions.txt>. + * "doveadm auth" command was renamed to "doveadm auth test" + * IMAP: ID command now advertises server name as Dovecot by default. It was + already trivial to guess this from command replies. + * LDA/LMTP: If saving a mail brings user from under quota to over quota, allow + it based on quota_grace setting (default: 10% above quota limit). + * pop3_lock_session=yes now uses a POP3-only dovecot-pop3-session.lock file + instead of actually locking the mailbox (and causing IMAP/LDA/LMTP to wait + for the POP3 session to close). + * mail_shared_explicit_inbox setting's default switched to "no". + * dsync isn't compatible with v2.1 protocol. (The new protocol will be + compatible with future Dovecot versions.) + * autocreate plugin is being deprecated and it will log warnings. Convert the + configuration to <MailboxSettings.txt> instead. + +Downgrading can be done fully safely to v2.1.16. + + * v2.1.16 adds support for "attribute changes", which are used by URLAUTH + command and dsync with ACLs and/or Sieve scripts. If none of these features + are used, you can downgrade safely to v2.1.11. + * The error message for these attribute changes is: 'Log synchronization + error at seq=..,offset=.. for .../dbox-Mails/dovecot.index: Unknown + transaction record type 0x0' + * v2.1.11 adds support for cache file changes. Older versions may think that + the 'dovecot.index.cache' files are corrupted and complain about "Invalid + magic in hole header". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.2.3.txt b/doc/wiki/Upgrading.2.3.txt new file mode 100644 index 0000000..8cda65f --- /dev/null +++ b/doc/wiki/Upgrading.2.3.txt @@ -0,0 +1,212 @@ +Upgrading Dovecot v2.2 to v2.3 +============================== + +Downgrading is possible to v2.2.27 and later. (v2.2.27 accidentally broke +dovecot.index* backwards compatibility a bit.) + +Settings Changes +---------------- + + * 'director_consistent_hashing' setting removed. It's always assumed to be + "yes" now. + * *WARNING*: You can't run a director ring with mixed + 'director_consistent_hashing' settings. If you already didn't have it set + to "yes", upgrading to v2.3 will require you to shutdown the entire + director ring. It may be safer to first do this setting change in v2.2 + before the upgrade. + * If you really don't wish to shutdown the ring, an alternative would be + to set up a whole new director ring. Then start moving users to the + new ring in the Dovecot proxy. To avoid the same user having + connections to both rings at the same time (-> two backends at the + same time), this would need to be done so that passdb moves the user + to the new ring and old connections are kicked. See + <PasswordDatabase/ExtraFields/Proxy#moving> + [PasswordDatabase.ExtraFields.Proxy.txt] + * 'director_doveadm_port' setting removed. Name the 'inet_listener doveadm { + .. }' instead. + * 'mdbox_purge_preserve_alt' setting removed. It's always assumed to be "yes" + now. + * 'recipient_delimiter' setting used to be treated as a separator string. Now + it's instead treated as a list of alternative delimiter characters. + * Time interval based settings no longer default to "seconds". All numbers + must explicitly be followed by the time unit (except 0). This is important, + because some settings now support milliseconds as well. + * fs-posix: prefix=path parameter no longer automatically appends '/' to the + path if it's not there. This allows using it properly as a prefix, instead + of only a directory prefix. Make sure you have the '/' appended to the + prefix, or the "dir/filename" will be accessed just as "dirnamename". + * 'ssl_protocols' setting was replaced by 'ssl_min_protocol'. Now you only + specify the minimum ssl protocol version Dovecot accepts, defaulting to + TLSv1. + * 'ssl_parameters' was replaced with 'ssl_dh'. See <Diffie-Hellman Parameters + for SSL> [Upgrading.2.3.txt]. + * 'SSLv2' is no longer supported in 'ssl_protocols'. + +Statistics Redesign +------------------- + +The statistics code was redesigned. + + * Statistics is no longer optional - it is always there. + * The old "stats" plugin was renamed to "old_stats". + * The "doveadm stats" command was renamed to "doveadm oldstats". + * There's a new "doveadm stats" command that isn't compatible with the old + one. + * The new stats code doesn't require a plugin, so make sure you remove 'stats' + from 'mail_plugin' setting. For more details see <Statistics.txt>. + +Config changes required to 2.2.x config to keep using the "old" stats: + + * 'mail_plugins = stats' -> 'mail_plugins = old_stats' + * 'mail_plugins = imap_stats' -> 'mail_plugins = imap_old_stats' + * 'service stats' -> 'service old-stats' + * 'executable = stats' -> 'executable = old-stats' + * 'fifo_listener stats-mail' -> 'fifo_listener old-stats-mail' + * 'fifo_listener stats-user' -> 'fifo_listener old-stats-user' + * 'unix_listener stats' -> 'unix_listener old-stats' + * 'plugin { stats_refresh }' -> 'plugin { old_stats_refresh }' + * 'plugin { stats_notify_path }' -> 'plugin { old_stats_notify_path }' + * 'plugin { stats_track_cmds }' -> 'plugin { old_stats_track_cmds }' + * 'auth_stats' -> keep as 'auth_stats' + * 'stats_*' settings -> 'old_stats_*' + +Submission Service (new) +------------------------ + +Dovecot can now act as a submission service. See <Submission.txt> for more +information. + +Localhost Auth Penalty +---------------------- + +Dovecot no longer disables auth penalty waits for clients connecting from +localhost (or 'login_trusted_networks' in general). The previous idea was that +it would likely be a webmail that would have its own delays, but there are no +guarantees about this. + +If the old behavior is still wanted, it's possible to do nowadays even more +generically with e.g. setting following as the first passdb: + +---%<------------------------------------------------------------------------- +passdb { + driver = passwd-file + args = username_format=%{rip} /etc/dovecot/passdb + default_fields = noauthenticate=y +} +---%<------------------------------------------------------------------------- + +/etc/dovecot/passdb: + +---%<------------------------------------------------------------------------- +127.0.0.1:::::::nodelay=yes +192.168.10.124:::::::nodelay=yes +---%<------------------------------------------------------------------------- + +Changed Setting Defaults +------------------------ + ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| *Setting* | *Old Default Value* | *New Default Value* | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'mdbox_rotate_size' | 2M | 10M | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'mailbox_list_index' | no | yes | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'imap_logout_format' | n=%i out=%o | in=%i out=%o deleted=%{deleted} expunged=%{expunged} trashed=%{trashed} | +| | | hdr_count=%{fetch_hdr_count} hdr_bytes=%{fetch_hdr_bytes} body_count=%{fetch_body_count} | +| | | body_bytes=%{fetch_body_bytes} | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'ssl_cipher_list' | ALL:!LOW:!SSLv2:!EXP:!aNULL | ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'mail_log_prefix' | "%s(%u): " | "%s(%u)<%{pid}><%{session}>: " | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| mysql: | no | yes | +| 'ssl_verify_server_cert' | | | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ +| 'ssl_options' | | no_compression is now the default, and a new compression option is introduced for enabling | +| | | compression | ++--------------------------+-----------------------------+----------------------------------------------------------------------------------------------+ + +Diffie-Hellman Parameters for SSL +--------------------------------- + + * ssl-parameters.dat file is now obsolete. You should use ssl_dh setting + instead:'ssl_dh=</etc/dovecot/dh.pem' + * You can convert an existing ssl-parameters.dat to dh.pem: + + ---%<------------------------------------------------------------------- + dd if=/var/lib/dovecot/ssl-parameters.dat bs=1 skip=88 | openssl dhparam + -inform der > /etc/dovecot/dh.pem + ---%<------------------------------------------------------------------- + + * ssl-params process has also been removed, as it is no longer used to + generate these parameters. + * You are encouraged to create at least 2048 bit parameters. 4096 is industry + recommendation. + * Note that it will take LONG TIME to generate the parameters, and it should + be done with a machine that has GOOD SOURCE OF ENTROPY. Running it on a + virtual machine is not recommended, unless there is some entropy + helper/driver installed. Running this on your production proxy can starve + connections due to lack of entropy. + * Since v2.3.3+ DH parameter usage is *optional* and can be omitted. You are + invited to amend ciphers to disallow non-ECC based DH algorithms, but if you + don't and someone does try to use them, error will be emitted. + * Example: + 'ssl_cipher_list=ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW:!DH@STRENGTH' + +Other Changes +------------- + + * Invalid 'postmaster_address' now causes a failure early on with + sieve/imap_sieve plugin enabled. It still defaults to 'postmaster@%d', which + expands to invalid 'postmaster@' address if your usernames do not contain a + domain, or are converted into domainless usernames by passdb/userdb. See + <DomainLost.txt>. + * Linux: Dovecot no longer enables core dumping for "setuid processes", which + most of them are. + * To enable them with Linux kernel v3.6+: Make sure core dumps get written + to a globally shared directory and enable them with:'sysctl -w + fs.suid_dumpable=2' + * With older Linux kernel versions you can set it to 1, but that's not + good for security of your system. + * You can also revert to old behavior with: 'import_environment = + $import_environment PR_SET_DUMPABLE' + * However, this also may have some security implications depending on + the setup. Mainly if you have system users and you've enabled + chrooting or mail_access_groups, this could allow the system users to + gain unintentional access. + * userdb nss was removed. Use userdb passwd instead. + * doveadm: table formatter prints the header now to stdout, not stderr + * doveadm: Removed mount commands + * OpenSSL version is required to be at least 1.0.1 for Dovecot to build + * subscriptions file is written in a new version 2 format. Dovecot v2.2.17 and + newer can read this file. + * mail_log plugin: Headers are logged as UTF-8 (instead of MIME-encoded) + * auth: When iterating users in userdb passwd, skip users that aren't in the + first/last_valid_gid range + * auth protocol has changed some error fields: + * temp -> code=temp_fail + * authz -> code=authz_fail + * user_disabled -> code=user_disabled + * pass_expired -> code=pass_expired + * auth now supports bcrypt algorithm by default. + * Some API changes have been made, if you have your own plugins please be + aware that they might require change(s) to be compatible again. + * Due to the new stats environment, for now some environments may get harmless + errors about not being able to connect to stats-writer socket. To avoid + these errors, give enough permissions for the processes to connect to the + stats-writer, for example: + +---%<------------------------------------------------------------------------- +service stats { + client_limit = 10000 # make this large enough so all Dovecot processes +(especially imap, pop3, lmtp) can connect to it + unix_listener stats-writer { + user = vmail + #mode = 0666 # Use only if nothing else works. It's a bit insecure, since +it allows any user in the system to mess up with the statistics. + } +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Upgrading.txt b/doc/wiki/Upgrading.txt new file mode 100644 index 0000000..ae95ccb --- /dev/null +++ b/doc/wiki/Upgrading.txt @@ -0,0 +1,26 @@ +Upgrading between micro versions +================================ + +(For example v1.0.x -> v1.0.y or v1.1.x -> v1.1.y) + +The NEWS file [http://dovecot.org/doc/NEWS] contains all the important changes +marked with "*" character. Read them to see if there is anything that concerns +you. In general all the changes try to preserve backwards compatibility, but +some changes which are meant to improve the stability and correctness of the +configuration could mean breaking some existing installations. And that may be +a good thing, since it can expose problems which could otherwise show up as +random errors. + +Upgrading between other versions +================================ + + * <v0.99.x to v1.0> [Upgrading.1.0.txt] + * <v1.0 to v1.1> [Upgrading.1.1.txt] + * <v1.1 to v1.2> [Upgrading.1.2.txt] + * <v1.2 to v2.0> [Upgrading.2.0.txt] + * <v2.0 to v2.1> [Upgrading.2.1.txt] + * <v2.1 to v2.2> [Upgrading.2.2.txt] + * <v2.2 to v2.3> [Upgrading.2.3.txt] + * <v2.3 to v2.4> [Upgrading.2.4.txt] + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserDatabase.ExtraFields.txt b/doc/wiki/UserDatabase.ExtraFields.txt new file mode 100644 index 0000000..edf5c3f --- /dev/null +++ b/doc/wiki/UserDatabase.ExtraFields.txt @@ -0,0 +1,115 @@ +User database extra fields +========================== + +A user database lookup typically returns <uid, gid and home> [UserDatabase.txt] +fields, as per traditional /etc/passwd lookups. Other fields may also be stored +in the userdb, and these are called 'extra fields'. Possibilities are: + + * *mail*: <Mail location> [MailLocation.txt], overrides the global + 'mail_location' setting. + * *nice*: Set the mail process's priority to be the given value. + * *chroot*: Chroot to given directory. Overrides 'mail_chroot' setting in + 'dovecot.conf'. + * *system_groups_user*: Specifies the username whose groups are read from + '/etc/group' (or wherever NSS is configured to taken them from). The logged + in user has access to those groups. This may be useful for shared mailboxes. + * *userdb_import*: This allows returning multiple extra fields in one + TAB-separated field. It's useful for userdbs which are a bit less flexible + for returning a variable number of fields (e.g. SQL). + * *uidgid_file*: Get uid and gid for user based on the given filename. + * It's possible to override settings from 'dovecot.conf' (most commonly + quota_rule to set per-user quota limits or also plugin-settings). + * *user*: User can be overriden (normally set in <passdb> + [PasswordDatabase.txt]). + * *noreplicate*: User will not be replicated using replicator (see + <Replication.txt>) + * The extra fields are also passed to <post-login scripts> + [PostLoginScripting.txt]. + +The following suffixes added to a field name are handled specially: + + * *:protected*: Set this field only if it hasn't been set before. + * *:remove*: Remove this field entirely. + +These fields can be returned the exact same way as uid, gid, and home fields. +Below are examples for some user databases. + +Overriding settings +------------------- + +Most commonly settings are overridden from plugin section. For example if your +plugin section has 'quota_rule=*:storage=100M' value and the userdb lookup +returns 'quota_rule=*:storage=200M', the original quota setting gets +overridden. In fact if the lookup always returns a 'quota_rule' field, there's +no point in having the 'quota_rule' setting in the plugin section at all, +because it always gets overridden anyway. + +To understand how imap and pop3 processes see their settings, it may be helpful +to know how Dovecot internally passes them: + + 1. First all actual settings are first read into memory. + 2. Next all the extra fields returned by userdb lookup are used to override + the settings. Any unknown setting is placed into the plugin {} section + (e.g.'foo=bar' will be parsed as if it were 'plugin { foo=bar }'). + 3. Last, if <post-login scripting is used> [PostLoginScripting.txt], it may + modify the settings if wanted. + +If you want to override settings inside sections, you can separate the section +name and key with '/'. For example: + +---%<------------------------------------------------------------------------- +namespace default { + inbox = yes + separator = . + location = maildir:~/Maildir +} +---%<------------------------------------------------------------------------- + +The separator setting can be overridden by returning +'namespace/default/separator=.' extra field. + +Examples +-------- + +SQL +--- + +dovecot-sql.conf: + +---%<------------------------------------------------------------------------- +user_query = SELECT home, uid, gid, \ + CONCAT('*:bytes=', quota_bytes) AS quota_rule, \ + separator AS "namespace/default/separator" \ + FROM users WHERE username = '%n' and domain = '%d' +---%<------------------------------------------------------------------------- + +LDAP +---- + +dovecot-ldap.conf: + +---%<------------------------------------------------------------------------- +user_attrs = \ + =home=%{ldap:homeDirectory}, \ + =uid=%{ldap:uidNumber}, + =gid=%{ldap:gidNumber}, + =quota_rule=*:bytes=%{ldap:quotaBytes}, + =namespace/default/separator=%{ldap:mailSeparator} +---%<------------------------------------------------------------------------- + +passwd-file +----------- + +Below are examples that show how to give two userdb extra fields ("mail" and +"quota"). Note that all userdb extra fields must be prefixed with "userdb_", +otherwise they're treated as <passdb extra fields> +[PasswordDatabase.ExtraFields.txt]. + +---%<------------------------------------------------------------------------- +user:{plain}pass:1000:1000::/home/user::userdb_mail=mbox:~/mail +userdb_quota_rule=*:storage=100M userdb_namespace/default/separator=/ +user2:{plain}pass2:1001:1001::/home/user2::userdb_mail=maildir:~/Maildir +userdb_quota_rule=*:storage=200M +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserDatabase.NSS.txt b/doc/wiki/UserDatabase.NSS.txt new file mode 100644 index 0000000..fac2a04 --- /dev/null +++ b/doc/wiki/UserDatabase.NSS.txt @@ -0,0 +1,34 @@ +NSS +=== + +NOTE: This userdb is probably useless with Dovecot v2.0.12+, since it uses +getpwnam_r(), which supports error reporting. + +Usually NSS [http://en.wikipedia.org/wiki/Name_Service_Switch] is used with +<passwd> [AuthDatabase.Passwd.txt] userdb, but it has one problem: It can't +distinguish between temporary and permanent errors. So if you're using e.g. +nss_ldap and your LDAP database is down, all userdb lookups may return "user +doesn't exist" errors. This is especially bad if you're using <LDA.txt>, which +causes the mails to be bounced back to sender. + +The NSS userdb works around this problem by loading the NSS modules and calling +them itself. This is a bit kludgy, and it probably works only with Linux. + +This userdb has two parameters: + + * *service=<name>*: This parameter is required. The name specifies what NSS + module to use, for example "ldap". + * *blocking=no* causes the lookups to be done in auth master processes instead + of in worker processes. + +Example +------- + +---%<------------------------------------------------------------------------- +userdb { + driver = nss + args = service=ldap +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserDatabase.Prefetch.txt b/doc/wiki/UserDatabase.Prefetch.txt new file mode 100644 index 0000000..715b8bc --- /dev/null +++ b/doc/wiki/UserDatabase.Prefetch.txt @@ -0,0 +1,87 @@ +Prefetch User Database +====================== + +Prefetch userdb can be used to combine passdb and userdb lookups into a single +lookup. It's usually used with <SQL> [AuthDatabase.SQL.txt], <LDAP> +[AuthDatabase.LDAP.txt] and <checkpassword> +[PasswordDatabase.CheckPassword.txt] passdbs. + +Prefetch basically works by requiring that the passdb returns the userdb +information in <extra fields> [PasswordDatabase.ExtraFields.txt] with 'userdb_' +prefixes. For example if a userdb typically returns 'uid', 'gid' and 'home' +fields, the passdb would have to return 'userdb_uid', 'userdb_gid' and +'userdb_home' fields. + +If you're using <LDA.txt> or <LMTP.txt>, you still need a valid userdb which +can be used to locate the users. You can do this by adding a normal SQL/LDAP +userdb *after the userdb prefetch*. The order of definitions is significant. +See below for examples. + +LDAP: 'auth_bind=yes' with 'auth_bind_userdn'-template is incompatible with +prefetch, because no passdb lookup is done then. If you want zero LDAP lookups, +you might want to use <static userdb> [UserDatabase.Static.txt] instead of +prefetch. + +SQL example +----------- + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +userdb { + driver = prefetch +} +# The userdb below is used only by lda. +userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf.ext +} +---%<------------------------------------------------------------------------- + +'dovecot-sql.conf.ext': + +---%<------------------------------------------------------------------------- +password_query = SELECT userid AS user, password, \ + home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \ + FROM users \ + WHERE userid = '%u' + +# For LDA: +user_query = SELECT home, uid, gid FROM users WHERE userid = '%u' +---%<------------------------------------------------------------------------- + +LDAP example +------------ + +'dovecot.conf': + +---%<------------------------------------------------------------------------- +passdb { + driver = ldap + args = /etc/dovecot/dovecot-ldap.conf.ext +} +userdb { + driver = prefetch +} +# The userdb below is used only by LDA. +userdb { + driver = ldap + args = /etc/dovecot/dovecot-ldap.conf.ext +} +---%<------------------------------------------------------------------------- + +'dovecot-ldap.conf.ext': + +---%<------------------------------------------------------------------------- +pass_attrs = uid=user, userPassword=password, \ + homeDirectory=userdb_home, uidNumber=userdb_uid, gidNumber=userdb_gid + +# For LDA: +user_attrs = homeDirectory=home, uidNumber=uid, gidNumber=gid +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserDatabase.Static.txt b/doc/wiki/UserDatabase.Static.txt new file mode 100644 index 0000000..53d9e30 --- /dev/null +++ b/doc/wiki/UserDatabase.Static.txt @@ -0,0 +1,41 @@ +Static User Database +==================== + +Static user database can be used when you want to use only single UID and GID +values for all users, and their home directories can be specified with a simple +template. The syntax is: + +---%<------------------------------------------------------------------------- +userdb { + driver = static + args = uid=<uid> gid=<gid> home=<dir template> +} +---%<------------------------------------------------------------------------- + +The home is optional. You can also return other <extra fields> +[UserDatabase.ExtraFields.txt]. You can use the standard <variables> +[Variables.txt] everywhere. + +LDA and passdb lookup for user verification +------------------------------------------- + +Unless your MTA already verifies that the user exists before calling +dovecot-lda, you'll most likely want dovecot-lda itself to verify the user's +existence. Since dovecot-lda looks up the user only from the userdb, it of +course doesn't work with static userdb because there is no list of users. +Normally static userdb handles this by doing a passdb lookup instead. This +works with most passdbs, with <PAM> [PasswordDatabase.PAM.txt] being the most +notable exception. If you want to avoid this user verification, you can add +'allow_all_users=yes' to the args in which case the passdb lookup is skipped. + +Example +------- + +---%<------------------------------------------------------------------------- +userdb { + driver = static + args = uid=500 gid=500 home=/home/%u +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserDatabase.txt b/doc/wiki/UserDatabase.txt new file mode 100644 index 0000000..31a745c --- /dev/null +++ b/doc/wiki/UserDatabase.txt @@ -0,0 +1,126 @@ +User Databases +============== + +After a user has been successfully authenticated, Dovecot looks up the user's +userdb information. The userdb lookup is also done by <LDA.txt> to find out how +to deliver mails for the user. + +The user database lookup can return these fields: + + * *uid*: User's <UID> [UserIds.txt] (UNIX user ID), overrides the global + 'mail_uid' setting. + * *gid*: User's <GID> [UserIds.txt] (UNIX group ID), overrides the global + 'mail_gid' setting. + * *home*: User's <home directory> [VirtualUsers.Home.txt], overrides the + global 'mail_home' setting. Although not required, it's <highly recommended + even for virtual users> [VirtualUsers.Home.txt]. + * Optional <extra fields> [UserDatabase.ExtraFields.txt] + * *user*: Changes the username (can also be done by the passdb lookup) + * Overwriting all mail-related settings, for example: + * *mail*: <Mail location> [MailLocation.txt], overrides the global + 'mail_location' setting. + * *quota_rule* to specify per-user quota limit + * The extra fields are also passed to <post-login scripts> + [PostLoginScripting.txt] + +The user and <password databases> [PasswordDatabase.txt] may be the same or +they may be different depending on your needs. You can also have <multiple +databases> [Authentication.MultipleDatabases.txt]. + +Currently supported user databases are: + + * <Passwd> [AuthDatabase.Passwd.txt]: System users (NSS, '/etc/passwd', or + similiar) + * <Passwd-file> [AuthDatabase.PasswdFile.txt]: '/etc/passwd'-like file in + specified location + * <NSS> [UserDatabase.NSS.txt]: Name Service Switch + * <LDAP> [AuthDatabase.LDAP.txt]: Lightweight Directory Access Protocol + * <SQL> [AuthDatabase.SQL.txt]: SQL database (PostgreSQL, MySQL, SQLite) + * <Dict> [AuthDatabase.Dict.txt]: Dict key-value database (Redis, memcached, + etc.) + * <Static> [UserDatabase.Static.txt]: Userdb information generated from a + given template + * <VPopMail> [AuthDatabase.VPopMail.txt]: External software used to handle + virtual domains + * <Prefetch> [UserDatabase.Prefetch.txt]: This assumes that the passdb already + returned also all the required user database information + * <Lua> [AuthDatabase.Lua.txt]: Lua script for authentication (v2.3.0+) + +Userdb settings +--------------- + +An example userdb entry might look like this: + +---%<------------------------------------------------------------------------- +userdb { + driver = passwd-file + args = username_format=%n /etc/dovecot/users + + default_fields = uid=vmail gid=vmail + override_fields = + + # v2.2.10+: + skip = never + result_failure = continue + result_internalfail = continue + result_success = return-ok + + # v2.2.24+: + auth_verbose = default +} +---%<------------------------------------------------------------------------- + +First we have the settings that provide content for the userdb lookup: + + * driver: The userdb backend name + * args: Arguments for the userdb backend. The format of this value depends on + the userdb driver. Each one uses different args. + * default_fields: Userdb fields (and <extra fields> + [UserDatabase.ExtraFields.txt]) that are used, unless overwritten by the + userdb backend. They are in format 'key=value key2=value2 ...'. The values + can contain <%variables> [Variables.txt]. + * override_fields: Same as default_fields, but instead of providing the + default values, these values override what the userdb backend returned. For + example useful with <userdb passwd> [AuthDatabase.Passwd.txt] for overriding + e.g. home directory or the uid/gid. + * auth_verbose: If this is explicitly set to yes or no, it overrides the + global auth_verbose setting. (However, auth_debug=yes overrides the + auth_verbose setting.) (v2.2.24+) + +Then we have the setting which specify when the userdb is used (v2.2.10+): + + * skip: Do we sometimes want to skip over this userdb? + * never + * found: Skip if an earlier userdb already found the user + * notfound: Skip if previous userdbs haven't yet found the user + +And finally we can control what happens when we're finished with this userdb +(v2.2.10+): + + * result_success: What to do if the user was found from the userdb (default: + return-ok) + * result_failure: What to do if the user wasn't found from the userdb + (default: continue) + * result_internalfail: What to do if the userdb lookup had an internal failure + (default: continue). If any of the userdbs had an internal failure and the + final userdb also returns "continue", the lookup will fail with "internal + error".*WARNING*: If multiple userdbs are required (results are merged), + it's important to set result_internalfail=return-fail to them, otherwise the + userdb lookup could still succeed but not all the intended extra fields are + set. + +The result values that can be used: + + * return-ok: Return success, don't continue to the next userdb. + * return-fail: Return "user doesn't exist", don't continue to the next userdb. + + * return: Return earlier userdb's success or failure, don't continue to the + next userdb. If this was the first userdb, return "user doesn't exist". + * continue-ok: Set the current user existence state to "found", and continue + to the next userdb. + * continue-fail: Set the current user existence state to "not found", and + continue to the next userdb. + * continue: Continue to the next userdb without changing the user existence + state. The initial state is "not found". + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/UserIds.txt b/doc/wiki/UserIds.txt new file mode 100644 index 0000000..b71a7c7 --- /dev/null +++ b/doc/wiki/UserIds.txt @@ -0,0 +1,147 @@ +System users used by Dovecot +============================ + +Dovecot typically requires 3 or more system users: + + * /root/: Dovecot is started as root. + * /dovenull/: Dovecot uses an unprivileged /dovenull/ user for untrusted login + processes. + * /dovecot/: Dovecot uses an unprivileged /dovecot/ user for internal + processes. + * auth user: Password and user database lookups are done as auth user. + * mail user(s): Mails are accessed using yet another user. The mail user + should not be /dovecot/ user. + +Using multiple users allows privilege separation, which makes it harder for +attackers to compromise the whole system if a security hole is found from one +component. However, if you really want to run everything under a single user, +<it's possible> [HowTo.Rootless.txt]. + +Dovenull user +------------- + +/dovenull/ user is used internally for processing users' logins. It shouldn't +have access to any files, authentication databases or anything else either. It +should belong to its own private *dovenull* group where no one else belongs to, +and which doesn't have access to any files either (other than what Dovecot +internally creates). + +You can change the default /dovenull/ user to something else from +'default_login_user' setting. + +Dovecot user +------------ + +/dovecot/ user is used internally for unprivileged Dovecot processes. It should +belong to its own private /dovecot/ group. Mail files are not accessed as +/dovecot/ user, so you shouldn't give it access to mails. + +You can change the default /dovecot/ user to something else from +'default_internal_user' setting. + +Mail users +---------- + +You can use one or more system users for accessing users' mails. Most +configurations can be placed to two categories: + + 1. <System users> [SystemUsers.txt] where each Dovecot user has their own + system user in '/etc/passwd'. For system user setups you generally don't + have to worry about UIDs or GIDs, they are returned by the <userdb passwd> + [AuthDatabase.Passwd.txt] lookup. + 2. <Virtual users> [VirtualUsers.txt] where all Dovecot users run under a + single system user. Typically you'd set this with 'mail_uid' setting (e.g. + 'mail_uid=vmail'). Note that you most likely don't want the <userdb lookup> + [UserDatabase.txt] to return any UID/GID, as they override the 'mail_uid' + setting. + +However it's possible to use a setup that is anything between these two. For +example use a separate system user for each domain. See below for more +information about how UIDs can be used. + +UIDs +---- + +Dovecot's <user database> [UserDatabase.txt] configuration calls system users +UIDs. There are a few things you should know about them: + + * Although UID normally means a numeric ID (as specified by '/etc/passwd'), + it's anyway possible to use names as UID values and let Dovecot do the + lookup (eg. uid=vmail). However depending on where you used it, it may slow + down the authentication. + * The UIDs don't really have to exist in '/etc/passwd' (the kernel doesn't + care about that). For example you could decide to use UIDs 10000-59999 for + 50000 virtual Dovecot users. You'll then just have to be careful that the + UIDs aren't used unintentionally elsewhere. + * The important thing to consider with your UID allocation policy is that if + Dovecot has a security hole in its IMAP or POP3 implementation, the attacker + can read mails of other people who are using the same UID. So clearly the + most secure way is to allocate a different UID for each user. It can however + be a bit of a pain and OSes don't always support more than 65536 UIDs. + * By default Dovecot allows users to log in only with UID numbers 500 and + above. This check tries to make sure that no-one can ever log in as daemons + or other system users. If you're using an UID lower than 500, you'll need to + change the 'first_valid_uid' setting. + +GIDs +---- + +System groups (GIDs) work very much the same way as UIDs described above: You +can use names instead of numbers for GID values, and the used GIDs don't have +to exist in '/etc/group'. + +System groups are useful for sharing mailboxes between users that have +different UIDs but belong to a same group. Currently Dovecot doesn't try to do +anything special with the groups, so if you're not sure how you should create +them, you might as well place all the users into a single group or create a +separate group for each user. + +If you use multiple UIDs and you wish to create <shared mailboxes> +[SharedMailboxes.txt], setting up the groups properly may make your +configuration more secure. For example if you have two teams and their +mailboxes are shared only to their team members, you could create a group for +each team and set the shared mailbox's group to the team's group and +permissions to 0660, so neither team can even accidentally see each others' +shared mailboxes. + +Currently Dovecot supports specifying only the primary group, but if your +userdb returns 'system_user' <extra field> [UserDatabase.ExtraFields.txt], the +non-primary groups are taken from '/etc/group' for that user. In a future +version the whole GID list will be configurable without help from '/etc/group'. + +It's also possible to give all the users access to extra groups with +'mail_access_groups' setting. + +Authentication process user +--------------------------- + +Depending on passdb and userdb configuration, the lookups are done either by +auth process or auth worker process. They have different default users: + +---%<------------------------------------------------------------------------- +service auth { + user = $default_internal_user +} +service auth-worker { + user = root +} +---%<------------------------------------------------------------------------- + +The user must have access to your <password databases> [PasswordDatabase.txt] +and <user databases> [UserDatabase.txt]. It's not used for anything else. The +default is to use root, because it's guaranteed to have access to all the +password databases. If you don't need this, you should change it to +$default_internal_user. + +<PAM> [PasswordDatabase.PAM.txt] and <shadow> [PasswordDatabase.Shadow.txt] +passdbs are usually configured to read '/etc/shadow' file. Even this doesn't +need root access if the file is readable by shadow group: + +---%<------------------------------------------------------------------------- +service auth-worker { + user = $default_internal_user + group = shadow +} +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/Variables.txt b/doc/wiki/Variables.txt new file mode 100644 index 0000000..9051220 --- /dev/null +++ b/doc/wiki/Variables.txt @@ -0,0 +1,355 @@ +Variables +========= + +You can use special variables in several places: + + * <mail_location> [MailLocation.txt] setting and <namespace> [Namespaces.txt] + locations + * <static userdb> [UserDatabase.Static.txt] and <passwd-file userdb> + [AuthDatabase.PasswdFile.txt] template strings + * <LDAP> [AuthDatabase.LDAP.txt] and <SQL> [AuthDatabase.SQL.txt] userdb query + strings + * log prefix for imap/pop3 process + * <Plugin> [Plugins.txt] settings + +The variables that work (almost) everywhere are: + + * ++------------+------------------------------+---------------------------------+ +| *Variable* | *Long name* | *Description* | ++------------+------------------------------+---------------------------------+ +| %% | | '%' character. See | +| | | <SharedMailboxes.Shared.txt> for| +| | | further information about %% | +| | | variables | ++------------+------------------------------+---------------------------------+ +| %u | user | full username (e.g. user@domain)| ++------------+------------------------------+---------------------------------+ +| %n | username | user part in user@domain, same | +| | | as %u if there's no domain | ++------------+------------------------------+---------------------------------+ +| %d | domain | domain part in user@domain, | +| | | empty if user with no domain | ++------------+------------------------------+---------------------------------+ +| %s | service | imap, pop3, smtp, lda (and | +| | | doveadm, dsync, etc.) | ++------------+------------------------------+---------------------------------+ +| %p | pid | PID of the current process | +| | | (login or imap/pop3 process) | ++------------+------------------------------+---------------------------------+ +| %l | lip | local IP address | ++------------+------------------------------+---------------------------------+ +| %r | rip | remote IP address | ++------------+------------------------------+---------------------------------+ +| | session | session ID for this client | +| | | connection (unique for 9 years) | +| | | (v2.1.6+) | ++------------+------------------------------+---------------------------------+ +| | auth_user | SASL authentication ID (e.g. if | +| | | master user login is done, this | +| | | contains the master username). | +| | | If username changes during | +| | | authentication, this value | +| | | contains the original username. | +| | | Otherwise the same as %{user}. | +| | | (v2.2.11+) | ++------------+------------------------------+---------------------------------+ +| | auth_username | user part in %{auth_user} | +| | | (v2.2.11+) | ++------------+------------------------------+---------------------------------+ +| | auth_domain | domain part in %{auth_user} | +| | | (v2.2.11+) | ++------------+------------------------------+---------------------------------+ +| | userdb:<name> | Expands to extra field "name" | +| | | returned by userdb (v2.2.19+) | ++------------+------------------------------+---------------------------------+ +| | encrypt;<parameters>:<field> | Encrypt field (v2.2.29+) (see | +| | | <Plugins.VarExpandCrypt.txt>) | ++------------+------------------------------+---------------------------------+ +| | decrypt;<parameters<:<field> | Decrypt field (v2.2.29+) (see | +| | | <Plugins.VarExpandCrypt.txt>) | ++------------+------------------------------+---------------------------------+ + +These variables work almost everywhere else except in Dovecot-auth (userdb +queries/templates): + + * ++------------+----------+-----------------------------------------------------+ +| *Variable* | *Long | *Description* | +| | name* | | ++------------+----------+-----------------------------------------------------+ +| %h | home | home directory. Use of ~/ is better whenever | +| | | possible. | ++------------+----------+-----------------------------------------------------+ +| %i | uid | UNIX UID of the user | ++------------+----------+-----------------------------------------------------+ +| | gid | UNIX group identifier of the user (v2.0.17+) | ++------------+----------+-----------------------------------------------------+ + +These variables work only in Dovecot-auth and 'login_log_format_elements' +setting: + + * ++----+--------------------+---------------------------------------------------+ +| %m | mech | <authentication mechanism> | +| | | [Authentication.Mechanisms.txt], e.g. PLAIN | ++----+--------------------+---------------------------------------------------+ +| %a | lport | Local port | ++----+--------------------+---------------------------------------------------+ +| %b | rport | Remote port | ++----+--------------------+---------------------------------------------------+ +| %c | secured | "secured" string with SSL, TLS and localhost | +| | | connections. Otherwise empty. | ++----+--------------------+---------------------------------------------------+ +| | real_rip | Same as %{rip}, except in proxy setups contains | +| | | the remote proxy's IP instead of the client's IP | +| | | (v2.1.10+) | ++----+--------------------+---------------------------------------------------+ +| | real_lip | Same as %{lip}, except in proxy setups contains | +| | | the local proxy's IP instead of the remote proxy's| +| | | IP (v2.2+) | ++----+--------------------+---------------------------------------------------+ +| | real_rport | Similar to %{real_rip} except for port instead of | +| | | IP (v2.2+) | ++----+--------------------+---------------------------------------------------+ +| | real_lport | Similar to %{real_lip} except for port instead of | +| | | IP (v2.2+) | ++----+--------------------+---------------------------------------------------+ +| | orig_user | Same as %{user}, except using the original | +| | | username the client sent before any changes by | +| | | auth process (v2.2.6+, v2.2.13+ for auth) | ++----+--------------------+---------------------------------------------------+ +| | orig_username | Same as %{username}, except using the original | +| | | username (v2.2.6+, v2.2.13+ for auth) | ++----+--------------------+---------------------------------------------------+ +| | orig_domain | Same as %{domain}, except using the original | +| | | username (v2.2.6+, v2.2.13+ for auth) | ++----+--------------------+---------------------------------------------------+ +| | local_name | Expands to TLS SNI hostname, if given (v2.2.26+) | ++----+--------------------+---------------------------------------------------+ +| | client_id | Expands to client ID request as IMAP arglist | +| | | (v2.2.29+/v2.3+). Needs imap_id_retain=yes | ++----+--------------------+---------------------------------------------------+ +| | passdb:<name> | Expands to extra field "name" returned by passdb | +| | | (v2.2.19+) | ++----+--------------------+---------------------------------------------------+ +| | forward_<variable> | Used by proxies to pass on values to next hop, see| +| | | <PasswordDatabase.ExtraFields.Proxy.txt> | +| | | (v2.2.29+/v2.3+) | ++----+--------------------+---------------------------------------------------+ + +These variables work only in Dovecot-auth: + + * ++------------+----------------+-----------------------------------------------+ +| *Variable* | *Long name* | *Description* | ++------------+----------------+-----------------------------------------------+ +| %w | password | plaintext password from plaintext | +| | | authentication mechanism | ++------------+----------------+-----------------------------------------------+ +| %k | cert | "valid" if client had sent a valid client | +| | | certificate, otherwise empty. | ++------------+----------------+-----------------------------------------------+ +| | login_user | For master user logins: Logged in user@domain | ++------------+----------------+-----------------------------------------------+ +| | login_username | For master user logins: Logged in user | ++------------+----------------+-----------------------------------------------+ +| | login_domain | For master user logins: Logged in domain | ++------------+----------------+-----------------------------------------------+ +| | domain_first | For "username@domain_first@domain_last" style | +| | | usernames (v2.2.6+) | ++------------+----------------+-----------------------------------------------+ +| | domain_last | For "username@domain_first@domain_last" style | +| | | usernames (v2.2.6+) | ++------------+----------------+-----------------------------------------------+ +| | master_user | For master user logins: The master username | +| | | (v2.2.7+) | ++------------+----------------+-----------------------------------------------+ +| | session_pid | For user logins: The PID of the IMAP/POP3 | +| | | process handling the session. (v2.2.7+) | ++------------+----------------+-----------------------------------------------+ +| | passdb:<name> | Return passdb extra field "name". | +| | | %{passdb:name:default} returns "default" if | +| | | "name" doesn't exist (not returned if name | +| | | exists but is empty) (v2.2.19+) | ++------------+----------------+-----------------------------------------------+ +| | userdb:<name> | Return userdb extra field "name". | +| | | %{userdb:name:default} returns "default" if | +| | | "name" doesn't exist (not returned if name | +| | | exists but is empty) (v2.2.19+) | ++------------+----------------+-----------------------------------------------+ + +These variables work only in 'login_log_format_elements' setting: + + * ++------------+--------------+-------------------------------------------------+ +| *Variable* | *Long name* | *Description* | ++------------+--------------+-------------------------------------------------+ +| %k | ssl_security | SSL protocol and cipher information, e.g. "TLSv1| +| | | with cipher DHE-RSA-AES256-SHA (256/256 bits)" | ++------------+--------------+-------------------------------------------------+ +| %e | mail_pid | Mail process (imap/pop3) PID that handles the | +| | | post-login connection | ++------------+--------------+-------------------------------------------------+ +| | listener | Expands to the socket listener name as specified| +| | | in config file (v2.2.19+) | ++------------+--------------+-------------------------------------------------+ + +These variables work only in 'deliver_log_format' setting: + + * ++------------+---------------+------------------------------------------------+ +| *Variable* | *Long name* | *Description* | ++------------+---------------+------------------------------------------------+ +| %$ | | Log entry | ++------------+---------------+------------------------------------------------+ +| %m | msgid | Message-ID | ++------------+---------------+------------------------------------------------+ +| %s | subject | Subject | ++------------+---------------+------------------------------------------------+ +| %f | from | From address | ++------------+---------------+------------------------------------------------+ +| %e | from_envelope | Envelope sender | ++------------+---------------+------------------------------------------------+ +| | to_envelope | Envelope recipient (v2.2.19+) | ++------------+---------------+------------------------------------------------+ +| %p | size | Message size | ++------------+---------------+------------------------------------------------+ +| %w | vsize | Virtual message size | ++------------+---------------+------------------------------------------------+ +| | delivery_time | How many milliseconds was spent actually | +| | | delivering the mail (v2.2.18+) | ++------------+---------------+------------------------------------------------+ +| | session_time | How many milliseconds the LMTP session took in | +| | | total, including network waits (v2.2.18+) | ++------------+---------------+------------------------------------------------+ + +These variables work only in 'auth_policy_request_attributes' setting: + + * ++------------+--------------------+-------------------------------------------+ +| *Variable* | *Long name* | *Description* | ++------------+--------------------+-------------------------------------------+ +| | hashed_password | Truncated auth policy hash of username and| +| | | password | ++------------+--------------------+-------------------------------------------+ +| | requested_username | Since v2.2.34, contains correct username | ++------------+--------------------+-------------------------------------------+ + + * Long variable names can be used like '%{long_name} ' or with L modifier: + '%L{long_name}'. + * Environment variables can be accessed with '%{env:ENVIRONMENT_VARIABLE} '. + * Additionally, the (self-explanatory) variables '%{pid} ' and '%{hostname} ' + are available. + +Modifiers +--------- + +You can apply a modifiers for each variable (e.g. %Us = POP3): + + * %L - lowercase + * %U - uppercase + * %E - escape '"', "'" and '\' characters by inserting '\' before them. Note + that variables in SQL queries are automatically escaped, you don't need to + use this modifier for them. + * %X - parse the variable as a base-10 number, and convert it to base-16 + (hexadecimal) + * %R - reverse the string + * %N - take a 32bit hash of the variable and return it as hex. You can also + limit the hash value. For example %256Nu gives values 0..ff. You might want + padding also, so %2.256Nu gives 00..ff. This can be useful for example in + dividing users automatically to multiple partitions. + * This is "New Hash", based on MD5 to give better distribution of values + (no need for any string reversing kludges either). (v2.2.3+) + * %H - Same as %N, but use "old hash" (not recommended anymore) + * %H hash function is a bit bad if all the strings end with the same + text, so if you're hashing usernames being in user@domain form, you + probably want to reverse the username to get better hash value + variety, e.g. %3RHu. + * %{<hash + algorithm>;rounds=<n>,truncate=<bits>,salt=s,format=<hex|hexuc|base64>:field} + - Generic hash function that outputs a hex (by default) or base64 value. + Hash algorithm is any of the supported ones, e.g. md5, sha1, sha256. Also + "pkcs5" is supported using SHA256. For example: %{sha256:user} or + %{md5;truncate=32:user}. (v2.2.27+) + * %M - return the string's MD5 sum as hex. + * %D - return "sub.domain.org" as "sub,dc=domain,dc=org" (for LDAP queries) + * %T - Trim trailing whitespace + +You can take a substring of the variable by giving optional offset followed by +'.' and width after the '%' character. For example %2u gives first two +characters of the username. %2.1u gives third character of the username. + +If the offset is negative, it counts from the end, for example %-2.2i gives the +UID mod 100 (last two characters of the UID printed in a string). If a positive +offset points outside the value, empty string is returned, if a negative offset +does then the string is taken from the start. + +If the width is prefixed with zero, the string isn't truncated, but only padded +with '0' character if the string is shorter. For example %04i may return +"0001", "1000" and "12345". %1.04i for the same string would return "001", +"000" and "2345". + +If the width is negative, it counts from the end, for example %0.-2u gives all +but the last two characters from the username. (v2.2.13+) + +The modifiers are applied from left-to-right order, except the substring is +always taken from the final string. + +Conditionals +------------ + +Since v2.2.33 it's possible to use conditionals in variable expansion. The +generic syntax is + +---%<------------------------------------------------------------------------- + %{if;value1;operator;value2;value-if-true;value-if-false} +---%<------------------------------------------------------------------------- + +Each field can contain another variable expansion, facilitating for nested ifs. +If some field refers to another field, it must use either %v or %{value} +syntax. + +Escaping is supported, so one can have values like \%{value} that will not get +expanded, or literal : and ; in the expression. + +Spaces and quotes are fully supported. + +Following operators are supported ++------------+--------------------------------------------------------------+ +| *operator* | *explanation* | ++------------+--------------------------------------------------------------+ +| == | NUMERIC equality | ++------------+--------------------------------------------------------------+ +| != | NUMERIC inequality | ++------------+--------------------------------------------------------------+ +| < | NUMERIC less than | ++------------+--------------------------------------------------------------+ +| <= | NUMERIC less or equal | ++------------+--------------------------------------------------------------+ +| > | NUMERIC greater than | ++------------+--------------------------------------------------------------+ +| >= | NUMERIC greater or equal | ++------------+--------------------------------------------------------------+ +| eq | String equality | ++------------+--------------------------------------------------------------+ +| ne | String inequality | ++------------+--------------------------------------------------------------+ +| lt | String inequality | ++------------+--------------------------------------------------------------+ +| le | String inequality | ++------------+--------------------------------------------------------------+ +| gt | String inequality | ++------------+--------------------------------------------------------------+ +| ge | String inequality | ++------------+--------------------------------------------------------------+ +| * | Wildcard match (mask on value2) | ++------------+--------------------------------------------------------------+ +| !* | Wildcard non-match (mask on value2) | ++------------+--------------------------------------------------------------+ +| ~ | Regular expression match (pattern on value2, extended POSIX) | ++------------+--------------------------------------------------------------+ +| !~ | String inequality (pattern on value2, extended POSIX) | ++------------+--------------------------------------------------------------+ + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/VirtualUsers.Home.txt b/doc/wiki/VirtualUsers.Home.txt new file mode 100644 index 0000000..02b4f57 --- /dev/null +++ b/doc/wiki/VirtualUsers.Home.txt @@ -0,0 +1,89 @@ +Home Directories for Virtual Users +================================== + +Home directory is a per-user directory where *Dovecot can save user-specific +files*. + + * Dovecot's home directories have nothing to do with system users' home + directories. + * It's irrelevant if it's under '/home/' or '/var/mail/' or wherever. + * If you have trouble understanding this, mentally replace all occurrences of + "home directory" with "mail user's private state directory". + +And in particular: + + * Never configure your userdb to return the same home directory for multiple + users! + * Home directory must be an absolute path, don't even try to use relative + paths! + +Some uses for home directory are: + + * By default <Sieve> [Pigeonhole.Sieve.txt] scripts are in user's home + directory. + * Duplicate mail check database is in user's home directory. Suppression of + duplicate rejects/vacations won't work if home directory isn't specified. + * Debugging: If an imap or pop3 process crashes, the core file is written to + the user's home directory. + +Home vs. mail directory +----------------------- + +Home directory shouldn't be the same as mail directory with mbox or Maildir +formats (but with dbox/obox it's fine). It's possible to do that, but you might +run into trouble with it sooner or later. Some problems with this are: + + * Non-mailbox files may show up as mailboxes. + * If you see this with Maildir, 'maildir_stat_dirs=yes' hides them. + * Or user just might not be able to create mailbox with wanted name, because + there already exists a conflicting file + * e.g. with Maildir if you have '.dovecot.sieve' file, user can't create a + mailbox called "dovecot.sieve" (i.e. "dovecot" mailbox that has a "sieve" + child) + * And vice versa: If user creates "dovecot.sieve" mailbox, Dovecot will + probably start logging all kinds of errors because the mailbox directory + isn't a valid <Sieve> [Pigeonhole.Sieve.txt] script. + * If you ever intend to migrate to another mailbox format, it's much easier to + do if you can have both old and new mail directories under the user's home + directory. + +Ways to set up home directory +----------------------------- + +The directory layouts for home and mail directories could look like one of +these (in the preferred order): + + 1. Mail directory under home, for example: home='/var/vmail/domain/user/' + mail='/var/vmail/domain/user/mail/' + 2. Completely distinct home and mail directories: + home='/home/virtual/domain/user/' mail='/var/vmail/domain/user/' + 3. Home directory under mail, for example: + * Maildir: home='/var/vmail/domain/user/home/' + mail='/var/vmail/domain/user/' + * mbox: There's really no good and safe way to do it. + 4. The home directory is the same as the mail directory. + +If for example home='/var/vmail/domain/user/' +mail='/var/vmail/domain/user/mail/', set: + +---%<------------------------------------------------------------------------- +mail_home = /var/vmail/%d/%n +mail_location = maildir:~/mail +---%<------------------------------------------------------------------------- + +Examples +-------- + +LDAP with relative directory paths +---------------------------------- + +If your LDAP database uses e.g. 'mailDirectory = domain/user/', you can use it +as a base for home directory: + +---%<------------------------------------------------------------------------- +user_attrs = .., mailDirectory=home=/var/vmail/%$ +---%<------------------------------------------------------------------------- + +Then just use 'mail_location = maildir:~/Maildir'. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/VirtualUsers.txt b/doc/wiki/VirtualUsers.txt new file mode 100644 index 0000000..24a963d --- /dev/null +++ b/doc/wiki/VirtualUsers.txt @@ -0,0 +1,149 @@ +Virtual Users +============= + +There are many ways to configure Dovecot to use virtual users. If you have no +idea how you want your users to be configured, select some <HOWTO> [HowTo.txt] +and follow its instructions. + +Users are often categorized as being either system users (in '/etc/passwd') or +virtual users (not in '/etc/passwd'). However from Dovecot's point of view +there isn't much of a difference between them. If a <passwd> +[AuthDatabase.Passwd.txt] lookup and a <SQL> [AuthDatabase.SQL.txt] lookup +return the same <userdb> [UserDatabase.txt] information, Dovecot's behavior is +identical. + +Password and user databases +--------------------------- + +Dovecot supports many different <password databases> [PasswordDatabase.txt] and +<user databases> [UserDatabase.txt]. With virtual users the most commonly used +ones are <LDAP> [AuthDatabase.LDAP.txt], <SQL> [AuthDatabase.SQL.txt] and +<passwd-file> [AuthDatabase.PasswdFile.txt]. The databases usually contain the +following information: + + * Username + * Password + * UNIX User ID (UID) and primary UNIX Group ID (GID) + * Home directory and/or mail location + +Usernames and domains +--------------------- + +Dovecot doesn't care much about domains in usernames. IMAP and POP3 protocols +currently have no concept of "domain", so the username is just something that +shows up in your logs and maybe in some configuration, but they have no direct +functionality. + +So although Dovecot makes it easier to handle "user@domain" style usernames +(eg. %n and %d <variables> [Variables.txt]), nothing breaks if you use for +example "domain%user" style usernames instead. However some <authentication +mechanisms> [Authentication.Mechanisms.txt] do have an explicit support for +realms (pretty much the same as domains). If those mechanisms are used, the +username is changed to be "user@realm". + +And of course there's no need to have domains at all in the usernames. + +Passwords +--------- + +The password can be in <any format that Dovecot supports> +[Authentication.PasswordSchemes.txt], but you need to tell the format to +Dovecot because it won't try to guess it. The SQL and LDAP configuration files +have the 'default_pass_scheme' setting for this. If you have passwords in +multiple formats, or the passdb doesn't have such a setting, you'll need to +prefix each password with "{<scheme>}", for example "{PLAIN}plaintext-password" +or "{PLAIN-MD5}1a1dc91c907325c69271ddf0c944bc72". + +UNIX UIDs +--------- + +The most important thing you need to understand is that *Dovecot doesn't access +the users' mails as the /dovecot/ user*! So *don't* put /dovecot/ into the +/mail/ group, and don't make mails owned by the /dovecot/ user. That will only +make your Dovecot installation less secure. + +So, if not the /dovecot/ user, what then? You can decide that yourself. You can +create, for example, one /vmail/ user which owns all the mails, or you can +assign a separate UID for each user. See <UserIds#mailusers> [UserIds.txt] for +more information about different ways to allocate UIDs for users. + +UNIX GIDs +--------- + +Unless you're using <shared mailboxes> [SharedMailboxes.txt] and multiple UIDs, +it doesn't really matter what GIDs you use. You can, for example, use a single +GID for all users, or create a separate GID for each user. See <UserIds#gids> +[UserIds.txt] for more information. + +Home directories +---------------- + +Some people are opposed to the idea of virtual users having home directories, +but no matter what you call it, it's a good idea to have a directory where +user-specific configuration and other state is stored. See +<VirtualUsers.Home.txt> more information. + +Mail location +------------- + +The userdb can return the 'mail' <field> [UserDatabase.txt] to override the +default 'mail_location' setting. Usually you shouldn't need this. + +Examples +-------- + +Dynamic passwd-file locations +----------------------------- + +---%<------------------------------------------------------------------------- +mail_location = maildir:/home/%d/%n/Maildir +passdb { + driver = passwd-file + args = username_format=%n /home/%d/etc/shadow +} +userdb { + driver = passwd-file + args = username_format=%n /home/%d/etc/passwd +} +---%<------------------------------------------------------------------------- + +In the above examples users are expected to log in as "user@domain". Their mail +is kept in their home directory at '/home/<domain>/<username>/Maildir'. + +The usernames in the passwd and shadow files are expected to contain only the +user part, no domain. This is because the path itself already contained %d to +specify the domain. If you want the files to contain full user@domain names, +you can use 'username_format=%u'. + +static userdb +------------- + +Many people store only usernames and passwords in their database and don't want +to deal with UIDs or GIDs. In that case the easiest way to get Dovecot running +is to use the <static userdb> [UserDatabase.Static.txt]: + +---%<------------------------------------------------------------------------- +mail_location = maildir:~/Maildir +passdb { + driver = pam +} +userdb { + driver = static + args = uid=vmail gid=vmail home=/var/mail/virtual/%d/%n +} +---%<------------------------------------------------------------------------- + +This makes Dovecot look up the mails from +'/var/mail/virtual/<domain>/<user>/Maildir/' directory, which should be owned +by vmail user and vmail group. + +Existing virtual user management software +----------------------------------------- + + * VPopMail [http://www.inter7.com/vpopmail/]: Dovecot <supports VPopMail + directly> [AuthDatabase.VPopMail.txt]. + * Linuxconf [http://www.solucorp.qc.ca/linuxconf/]: See + <Migration.Linuxconf.txt> + * Also see the <HowTo.txt> page + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/WhyDoesItNotWork.txt b/doc/wiki/WhyDoesItNotWork.txt new file mode 100644 index 0000000..54dd8e1 --- /dev/null +++ b/doc/wiki/WhyDoesItNotWork.txt @@ -0,0 +1,116 @@ +Why is Dovecot not working for me? +================================== + + * *Dovecot always logs an error message* if anything goes wrong, so make sure + you're looking at the correct log files. Debug messages may be written to a + different log file than error messages. See <Logging.txt>. + * Are you upgrading? Make sure you read the <upgrading documents> + [Upgrading.txt]. + * Make sure you're modifying the correct config file! Ubuntu creates two of + them. Other distributions may also have older config files lying around. For + example add "garbage=blah" to the config file and verify that Dovecot now + fails to start up. + * Try logging in manually by sending IMAP commands. If you're trying with an + IMAP client you can't be sure if the problem is with the client's + configuration or Dovecot's configuration. Many IMAP clients handle all + errors simply by showing you the login password dialog, even if the problem + has nothing to do with authentication. See <TestInstallation.txt> (or + <TestPop3Installation.txt>). + * Are you using an old version? If you have a problem, see if NEWS + [http://dovecot.org/doc/NEWS] file mentions anything related to it. There + are also <binary packages> [PrebuiltBinaries.txt] available for newer + versions. + +If you have upgraded OpenVZ to LXC (ProxMox 4) and you are getting permisssion +issues +------------------------------------------------------------------------------------- + +This is due to ACL option being added to mount options. Simple fix is to run + +---%<------------------------------------------------------------------------- +setfacl -k /var/run/dovecot +setfacl -b /var/run/dovecot/* +---%<------------------------------------------------------------------------- + +and the issue should go away. For more information about this, see +https://forum.proxmox.com/threads/permission-error-w-sockets-inside-ct-since-migration-to-pve-4-1.25244/ + +It says "Authentication failed" +------------------------------- + +First of all enable 'auth_debug_passwords=yes' and see if the logs show what +the problem is. For non-PAM setups it should contain all the information needed +to solve the problem. If it's trying to use a wrong password scheme, you can +change that. See <Authentication.PasswordSchemes.txt>. + +'Aborted login (no auth attempts)' means that the client isn't even attempting +to log in. Most likely you have 'disable_plaintext_auth=yes' (default) and the +client isn't configured to use SSL/TLS (or you've also set 'ssl=no'). + +If you're using <PAM> [PasswordDatabase.PAM.txt]: + + * Make sure that Dovecot's auth process is running as root (assuming it's + using '/etc/shadow'). + * PAM errors aren't written to Dovecot's own logs. Usually they go to + '/var/log/auth.log' or something similar. + * Unfortunately PAM's error messages aren't always all that helpful in + figuring out what exactly the problem is. + * You could (temporarily) try to use <passdb shadow> + [PasswordDatabase.Shadow.txt] instead to see if it logs something more + understandable. + * Usually the problem is that you don't have a correctly named file in + '/etc/pam.d/'. See <PasswordDatabase.PAM.txt>. + +Authenticated SMTP is hanging when authenticating, when configured with dovecot +authenticator +--------------------------------------------------------------------------------------------- + +It is possible that you SMTP daemon is configured with the wrong socket. Please +note that '/run/dovecot/auth-client' and '/run/dovecot/auth-userdb' do respond +do different protocols. They are however very similar and it is possible that +the difference may not be reported as an error and the SMTP server is waiting +for a response that will never come. + +It's not finding my emails +-------------------------- + +'mail_debug=yes' makes Dovecot log where it's really looking for mails. Also +'auth_debug=yes' may be helpful in debugging. See <MailLocation.txt> for how to +configure where the mails are looked up from. + +Permission errors accessing the mail storage +-------------------------------------------- + +---%<------------------------------------------------------------------------- +lda(user1): Error: chdir(/home/user1/) failed: Permission denied +(euid=1025(user1) egid=1026(user1) stat() failed: No such file or directory, +euid is not dir owner) +---%<------------------------------------------------------------------------- + +Check out the access permissions of the mentioned directory, check: + + 1. Unix permissions with the command 'ls -aln /home/user1', see Unix + permissions + [https://en.wikipedia.org/wiki/File_system_permissions#Traditional_Unix_permissions], + as well as make sure the user has "x" permission for "'/'" and all + directories, just "'/home'" in this case, test with: "'su - user1 ls + -aln /home/user1'" + 2. security tools, like SELinux: run "'sestatus'" and "'grep -i AVC + /var/log/audit/audit.log'" to identify SELinux caused denials, + 3. what file system the storage is located on, for instance AFS implements + different access permissions or POSIX eXtended attributes may change the + traditional permissions. + +---%<------------------------------------------------------------------------- +Couldn't create mailbox list lock +/data/mail/domain.com/username/mailboxes.lock: +file_create_locked(/data/mail/domain.com/username/mailboxes.lock) failed: +link(/data/mail/domain.com/username/mailboxes.lock6628a230290f9029, +/data/mail/domain.com/username/mailboxes.lock) failed: Operation not permitted +---%<------------------------------------------------------------------------- + + 1. Your filesystem is not supported + 2. You have SELinux/AppArmor/RBAC or some other security framework that + prevents this + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/maildrop.txt b/doc/wiki/maildrop.txt new file mode 100644 index 0000000..99d4883 --- /dev/null +++ b/doc/wiki/maildrop.txt @@ -0,0 +1,71 @@ +Maildrop +======== + +Maildrop is available at https://www.courier-mta.org/maildrop + +Although it is the default LDA for the courier mail server, it also works as a +standalone LDA. The install script can even build an rpm package if you prefer +to manage software that way. Maildrop can be used with sendmail as a drop-in +replacement for procmail. It has better maildir support than procmail and it +has filtering capability using syntax that looks a lot like shell script +language with a little bit of perl thrown in. + +To use maildrop with sendmail, make the following change in your sendmail.mc +file, then make etc. + +---%<------------------------------------------------------------------------- +dnl FEATURE(`local_procmail,', `procmail -t -Y -a $h -d $u')dnl +dnl # replace above line with below line to use maildrop instead of procmail +FEATURE(`local_procmail', `/usr/bin/maildrop', `maildrop -d $u')dnl +---%<------------------------------------------------------------------------- + +A default system wide configuration file for maildir style mailboxes might look +like the following: + +---%<------------------------------------------------------------------------- +# file: /etc/maildroprc +# system-wide settings for maildrop + +SHELL="/bin/bash" +SENDMAIL="/usr/sbin/sendmail -oi -t" +logfile "/var/log/maildrop.log" + +DEFAULT="$HOME/Maildir/" +---%<------------------------------------------------------------------------- + +In the above configuration, the users should be a member of the same group and +the group should have write privileges to the logfile. + +To use maildrop with Postfix, take a look at +https://www.postfix.org/MAILDROP_README.html + +Dovecot Authentication extension for maildrop +--------------------------------------------- + +Announced on the Dovecot's mailing list: +https://dovecot.org/list/dovecot/2009-April/039121.html + +A patch for maildrop that would allow it to perform user lookups directly +against Dovecot in a similar way how they are done by Dovecot's LDA deliver +depending on used version of maildrop is available at the following locations: ++--------------+---------------------------------------------------------------+ +| *maildrop* | *patch* | ++--------------+---------------------------------------------------------------+ +| 2.0.4 | https://www.max.rs/ozone/maildrop-2.0.4-dovecotauth.patch.txt | ++--------------+---------------------------------------------------------------+ +| 2.1.0 | https://www.max.rs/ozone/maildrop-2.1.0-dovecotauth.patch.txt | ++--------------+---------------------------------------------------------------+ +| 2.2.0 | https://www.max.rs/ozone/maildrop-2.2.0-dovecotauth.patch.txt | ++--------------+---------------------------------------------------------------+ +| 2.3.0, | https://www.max.rs/ozone/maildrop-2.3.0-dovecotauth.patch.txt | +| 2.4.0-2.4.3, | | +| 2.5.0-2.5.4 | | ++--------------+---------------------------------------------------------------+ + +When this patch is applied, maildrop will be extended with another command line +option "-t", which can be used to specify the location of Dovecot's master auth +socket that will be used when performing user lookups. There's a readme file +(README.dovecotauth) together with patch with a little bit more information +regarding the use of this extension. + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/mutt.txt b/doc/wiki/mutt.txt new file mode 100644 index 0000000..6cebfc2 --- /dev/null +++ b/doc/wiki/mutt.txt @@ -0,0 +1,104 @@ +Contents + + + 1. Using mutt with IMAP + + 1. configuration + + 2. problems + + 1. Move read messages to mbox + + 2. New mail in a folder just left + + 3. Authentication realm + + 2. References + +Using mutt with IMAP +==================== + +configuration +------------- + +First, mutt needs to be told to use IMAP. To achieve this, edit '~/.muttrc' (or +a file it 'source's) to contain: + +---%<------------------------------------------------------------------------- +set spoolfile=imap://user@hostname/INBOX +set folder=imap://user@hostname/ +---%<------------------------------------------------------------------------- + +problems +-------- + +Move read messages to mbox +-------------------------- + +If mutt asks 'Move read messages to /home/$user/mbox? ([no]/yes):' + +Your alternatives (to set in '~/.muttrc') are (pick one and ignore the others): + + 1. don't ask about moving messages, just do it: + + ---%<--------------------------------------------------------------------- + set move=yes + ---%<--------------------------------------------------------------------- + + 2. don't ask about moving messages and _don't_ do it: + + ---%<--------------------------------------------------------------------- + set move=no + ---%<--------------------------------------------------------------------- + + 3. ask about moving message, default answer 'yes': + + ---%<--------------------------------------------------------------------- + set move=ask-yes + ---%<--------------------------------------------------------------------- + + 4. ask about moving message, default answer 'no': + + ---%<--------------------------------------------------------------------- + set move=ask-no + ---%<--------------------------------------------------------------------- + +New mail in a folder just left +------------------------------ + +There is a bug with dovecot in <=0.99. It can sometimes make mutt think there +is new email in a mailbox you just +'left'...https://dovecot.org/list/dovecot/2004-February/002950.html + +Authentication realm +-------------------- + +If you are using IMAP with SASL and get error messages like 'Invalid realm' in +your dovecot log files, try putting this in your '.muttrc' or '/etc/Muttrc]': + +---%<------------------------------------------------------------------------- +set imap_authenticators="plain" +---%<------------------------------------------------------------------------- + +It might be easier however to just put the following in your 'dovecot.conf': + +For Dovecot 1.0: + ---%<----------------------------------------------------------------------- + auth default { + mechanisms = plain + } + ---%<----------------------------------------------------------------------- + +For Dovecot 0.99: + ---%<----------------------------------------------------------------------- + auth_mechanisms = plain + ---%<----------------------------------------------------------------------- + +References +========== + + * Official mutt homepage [http://www.mutt.org/] + * mutt with IMAP documentation [http://mutt.sourceforge.net/imap/] + * http://jamespo.org.uk/blog/archives/000271.html + +(This file was created from the wiki on 2019-06-19 12:42) diff --git a/doc/wiki/uw2dovecot.sh.txt b/doc/wiki/uw2dovecot.sh.txt new file mode 100644 index 0000000..7c63596 --- /dev/null +++ b/doc/wiki/uw2dovecot.sh.txt @@ -0,0 +1,13 @@ +---%<------------------------------------------------------------------------- +#!/bin/sh +# Written by Michal Grzedzicki - public domain +# handy script to rename uw-imapd style subscriptions to dovecot + +for hdir in `cat /etc/passwd|cut -d: -f6` ; do + if [ -f "$hdir/.mailboxlist" ]; then + cp -a "$hdir/.mailboxlist" "$hdir/.subscriptions" + fi +done +---%<------------------------------------------------------------------------- + +(This file was created from the wiki on 2019-06-19 12:42) |