diff --git a/dovecot/defaults/main.yml b/dovecot/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2e094cc55266fee2bf1a0ab72fe2a7245e54ef98
--- /dev/null
+++ b/dovecot/defaults/main.yml
@@ -0,0 +1,31 @@
+---
+
+dovecot_admin_mail: "postmaster@{{ domain }}"
+dovecot_protocols: imap lmtp sieve
+dovecot_mail_location: "maildir:~/mail:LAYOUT=fs"
+dovecot_maildir_separator: /
+dovecot_deny_users: []
+dovecot_users_group: users
+dovecot_auth_virtual: no
+dovecot_auth_system: yes
+dovecot_min_uid: 500
+dovecot_max_uid: 0
+
+dovecot_tls_cert: /etc/ssl/private/fullchain.pem
+dovecot_tls_key: /etc/ssl/private/privkey.pem
+dovecot_tls_ca_dir: /etc/ssl/certs
+dovecot_tls_ciphers: "{{ tls_ciphers }}"
+dovecot_tls_dh_length: 4096
+dovecot_tls_protocols: TLSv1.1 TLSv1.2 !SSLv3
+
+dovecot_dsync: yes
+dovecot_dsync_tls: no
+dovecot_dsync_group: dovecot
+dovecot_dsync_address: '0.0.0.0'
+dovecot_dsync_password: "{{ lookup('passwordstore', dovecot_dsync_passwordstore ~ ' create=true length=20') }}"
+dovecot_dsync_passwordstore: selfhosted/dsync
+dovecot_dsync_host_attribute: ansible_host
+
+dovecot_content_filter: yes
+dovecot_spam_folder: Spam
+
diff --git a/dovecot/files/filter_junk.sieve b/dovecot/files/filter_junk.sieve
deleted file mode 100644
index bf4276e09a7df0013a744017c276b390f33fd04e..0000000000000000000000000000000000000000
--- a/dovecot/files/filter_junk.sieve
+++ /dev/null
@@ -1,10 +0,0 @@
-require ["fileinto", "mailbox"];
-
-if header :contains "X-Spam-Flag" "YES" {
- fileinto :create "Junk";
-}
-
-if header :contains "Subject" "*SPAM*" {
-  fileinto :create "Junk";
-}
-
diff --git a/dovecot/files/sa-learn-ham.sh b/dovecot/files/sa-learn-ham.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d18e5539c0b6638538012f3641e90594b3471ef6
--- /dev/null
+++ b/dovecot/files/sa-learn-ham.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# you can also use tcp/ip here, consult spamc(1)
+exec /usr/bin/spamc -u ${1} -L ham -C report
diff --git a/dovecot/files/sa-learn-spam.sh b/dovecot/files/sa-learn-spam.sh
new file mode 100644
index 0000000000000000000000000000000000000000..69b3608336d6641b9459f25b8c5bdee09c4cc42a
--- /dev/null
+++ b/dovecot/files/sa-learn-spam.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# you can also use tcp/ip here, consult spamc(1)
+exec /usr/bin/spamc -u ${1} -L spam -C report
diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml
index 8e7127557c9004a43bba941e85ce8379357381fa..ed49f2168adcc3abcd42df1d90c89c6c579ed7cc 100644
--- a/dovecot/tasks/main.yml
+++ b/dovecot/tasks/main.yml
@@ -1,7 +1,9 @@
 ---
 
 - name: ensure all required dovecot packages are installed
-  apt: name={{ item }} state=present 
+  apt:
+    name: "{{ item }}"
+    state: present
   with_items:
     - dovecot-core
     - dovecot-imapd
@@ -13,18 +15,22 @@
     - mail
 
 - name: ensure all configs are present
-  template: src={{item.src}} dest={{item.dest}}
+  template:
+    src: "{{ item }}.j2"
+    dest: "/etc/dovecot/{{ item }}"
   with_items:
-    - { src: 'templates/dovecot.conf.j2', dest: '/etc/dovecot/dovecot.conf' }
-    - { src: 'templates/conf.d/10-auth.conf.j2', dest: '/etc/dovecot/conf.d/10-auth.conf' }
-    - { src: 'templates/conf.d/10-mail.conf.j2', dest: '/etc/dovecot/conf.d/10-mail.conf' }
-    - { src: 'templates/conf.d/10-master.conf.j2', dest: '/etc/dovecot/conf.d/10-master.conf' }
-    - { src: 'templates/conf.d/10-ssl.conf.j2', dest: '/etc/dovecot/conf.d/10-ssl.conf' }
-    - { src: 'templates/conf.d/20-managesieve.conf.j2', dest: '/etc/dovecot/conf.d/20-managesieve.conf' }
-    - { src: 'templates/conf.d/20-imap.conf.j2', dest: '/etc/dovecot/conf.d/20-imap.conf' }
-    - { src: 'templates/conf.d/20-lmtp.conf.j2', dest: '/etc/dovecot/conf.d/20-lmtp.conf' }
-    - { src: 'templates/conf.d/90-sieve.conf.j2', dest: '/etc/dovecot/conf.d/90-sieve.conf' }
-    - { src: 'templates/conf.d/auth-passwdfile.conf.ext.j2', dest: '/etc/dovecot/conf.d/auth-passwdfile.conf.ext' }
+    - dovecot.conf
+    - deny-users
+    - conf.d/10-auth.conf
+    - conf.d/10-mail.conf
+    - conf.d/10-master.conf
+    - conf.d/10-ssl.conf
+    - conf.d/15-lda.conf
+    - conf.d/20-managesieve.conf
+    - conf.d/20-imap.conf
+    - conf.d/20-lmtp.conf
+    - conf.d/90-sieve.conf
+    - conf.d/auth-passwdfile.conf.ext
   notify:
     - restart dovecot
   tags:
@@ -32,31 +38,68 @@
     - mail
 
 - name: ensure there is a folder for global sieve scripts
-  file: dest=/var/lib/dovecot/sieve.d state=directory owner=dovecot group=vmail mode=0770
+  file:
+    dest: /var/lib/dovecot/sieve.d
+    state: directory
+    owner: dovecot
+    group: "{{ dovecot_users_group }}"
+    mode: 0770
   tags:
     - dovecot
     - mail
-  when: content_filter is defined
 
 - name: ensure the global spam filter and learning sieve script is present
-  copy: src="files/{{ item }}" dest="/var/lib/dovecot/sieve.d/{{ item }}" mode=0550 owner=dovecot group=vmail
-  with_items: 
-    - filter_junk.sieve
+  template:
+    src: "sieve/{{ item }}.j2"
+    dest: "/var/lib/dovecot/sieve.d/{{ item }}"
+    mode: 0550
+    owner: dovecot
+    group: "{{ dovecot_users_group }}"
+  with_items:
+    - filter-spam.sieve
     - report-spam.sieve
     - report-ham.sieve
+  when: dovecot_content_filter
   notify:
     - compile sieve scripts
   tags:
     - dovecot
+    - spamassassin
+    - mail
+
+- name: ensure scripts for learning spam are present
+  copy:
+    src: "{{ item }}"
+    dest: "/var/lib/dovecot/sieve.d/{{ item }}"
+    mode: 0750
+    owner: dovecot
+    group: "{{ dovecot_users_group }}"
+  with_items:
+    - sa-learn-ham.sh
+    - sa-learn-spam.sh
+  when: dovecot_content_filter
+  tags:
+    - dovecot
+    - spamassassin
     - mail
-  when: content_filter is defined
 
 - name: ensure dsync config is present
-  template: src=templates/conf.d/99-dsync.conf.j2 dest=/etc/dovecot/conf.d/99-dsync.conf
-  when: dsync == True
+  template:
+    src: conf.d/99-dsync.conf.j2
+    dest: /etc/dovecot/conf.d/99-dsync.conf
+  when: dovecot_dsync
   notify:
     - restart dovecot
   tags:
     - dovecot
     - mail
 
+- name: ensure dovecot is enabled and running
+  service:
+    name: dovecot
+    state: started
+    enabled: yes
+  tags:
+    - dovecot
+    - mail
+
diff --git a/dovecot/templates/conf.d/10-auth.conf.j2 b/dovecot/templates/conf.d/10-auth.conf.j2
index 664cd8eca8f44b15fd28e0022783774af3146413..86b5cf4a17fc01662ec1d8663895e2fb544c8fe8 100644
--- a/dovecot/templates/conf.d/10-auth.conf.j2
+++ b/dovecot/templates/conf.d/10-auth.conf.j2
@@ -7,7 +7,7 @@
 # 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 = no
+disable_plaintext_auth = yes
 
 # Authentication cache size (e.g. 10M). 0 means it's disabled. Note that
 # bsdauth, PAM and vpopmail require cache_key to be set for caching to be used.
@@ -116,13 +116,13 @@ auth_mechanisms = plain
 #
 # <doc/wiki/UserDatabase.txt>
 
-#!include auth-deny.conf.ext
-#!include auth-master.conf.ext
+!include auth-deny.conf.ext
+{{ '' if dovecot_auth_system else '#' }}!include auth-system.conf.ext
+{{ '' if dovecot_auth_virtual else '#' }}!include auth-passwdfile.conf.ext
 
-#!include auth-system.conf.ext
+#!include auth-master.conf.ext
 #!include auth-sql.conf.ext
 #!include auth-ldap.conf.ext
-!include auth-passwdfile.conf.ext
 #!include auth-checkpassword.conf.ext
 #!include auth-vpopmail.conf.ext
 #!include auth-static.conf.ext
diff --git a/dovecot/templates/conf.d/10-mail.conf.j2 b/dovecot/templates/conf.d/10-mail.conf.j2
index d4ecb3a41813365a9fe90c3bf5013d921ca61cf7..2f5843a12501cf57b7c0b7b8a9f54d4254169494 100644
--- a/dovecot/templates/conf.d/10-mail.conf.j2
+++ b/dovecot/templates/conf.d/10-mail.conf.j2
@@ -27,7 +27,7 @@
 #
 # <doc/wiki/MailLocation.txt>
 #
-mail_location = {{ mail_location }} 
+mail_location = {{ dovecot_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.
@@ -46,7 +46,7 @@ namespace inbox {
   # 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 = {{ seperator }}
+  separator = {{ dovecot_maildir_separator }}
  
   # Prefix required to access this namespace. This needs to be different for
   # all namespaces. For example "Public/".
@@ -140,7 +140,7 @@ namespace inbox {
 # 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_server_admin = {{ dovecot_admin_mail }}
 
 ##
 ## Mail processes
@@ -172,8 +172,8 @@ namespace inbox {
 # 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
+first_valid_uid = {{ dovecot_min_uid }}
+last_valid_uid = {{ dovecot_max_uid }}
 
 # 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
@@ -212,12 +212,7 @@ namespace inbox {
 
 # 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.
-{% if dsync is defined  %}
-mail_plugins = $mail_plugins notify replication
-{% else %}
-mail_plugins = $mail_plugins notify
-{% endif %}
-#mail_plugins = 
+mail_plugins = $mail_plugins notify {{ "replication" if dovecot_dsync else "" }}
 
 ##
 ## Mailbox handling optimizations
diff --git a/dovecot/templates/conf.d/10-ssl.conf.j2 b/dovecot/templates/conf.d/10-ssl.conf.j2
index 7aadb4b754d5ea25cf58833e147ece7a16c39aa5..d00ff9153d55324401199754bc3e12ebf6c8e0cc 100644
--- a/dovecot/templates/conf.d/10-ssl.conf.j2
+++ b/dovecot/templates/conf.d/10-ssl.conf.j2
@@ -9,8 +9,8 @@ ssl = required
 # 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 = <{{ ssl_cert }}
-ssl_key = <{{ ssl_key }}
+ssl_cert = <{{ dovecot_tls_cert }}
+ssl_key = <{{ dovecot_tls_key }}
 
 # If key file is password protected, give the password here. Alternatively
 # give it when starting dovecot with -p parameter. Since this file is often
@@ -30,7 +30,7 @@ ssl_key = <{{ ssl_key }}
 # when Dovecot needs to act as an SSL client (e.g. imapc backend). The
 # directory is usually /etc/ssl/certs in Debian-based systems and the file is
 # /etc/pki/tls/cert.pem in RedHat-based systems.
-#ssl_client_ca_dir =
+ssl_client_ca_dir = {{ dovecot_tls_ca_dir }}
 #ssl_client_ca_file =
 
 # Request client to send a certificate. If you also want to require it, set
@@ -43,15 +43,15 @@ ssl_key = <{{ ssl_key }}
 #ssl_cert_username_field = commonName
 
 # DH parameters length to use.
-ssl_dh_parameters_length = 4096
+ssl_dh_parameters_length = {{ dovecot_tls_dh_length }}
 
 # SSL protocols to use
-ssl_protocols = TLSv1.1 TLSv1.2 !SSLv3
+ssl_protocols = {{ dovecot_tls_protocols }}
 
 # SSL ciphers to use
 #ssl_cipher_list = HIGH:!LOW:!SSLv2:!EXP:!aNULL:!MD5:!RC4:!SHA1
 #Supported Ciphers downto Android 2.3
-ssl_cipher_list = {{ tls_ciphers }}
+ssl_cipher_list = {{ dovecot_tls_ciphers }}
 
 # Prefer the server's order of ciphers over client's.
 ssl_prefer_server_ciphers = yes
diff --git a/dovecot/templates/conf.d/15-lda.conf.j2 b/dovecot/templates/conf.d/15-lda.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c67cfd6622b011091ffbf24fe2d434b0ff2a5805
--- /dev/null
+++ b/dovecot/templates/conf.d/15-lda.conf.j2
@@ -0,0 +1,48 @@
+##
+## LDA specific settings (also used by LMTP)
+##
+
+# Address to use when sending rejection mails.
+# Default is postmaster@<your domain>. %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 sieve
+}
diff --git a/dovecot/templates/conf.d/20-imap.conf.j2 b/dovecot/templates/conf.d/20-imap.conf.j2
index 6d73b13537b66c32fe10b768572263ca54b825e4..b65b1b7c9f5c14910560b163750d961ae80fdd48 100644
--- a/dovecot/templates/conf.d/20-imap.conf.j2
+++ b/dovecot/templates/conf.d/20-imap.conf.j2
@@ -76,24 +76,22 @@ protocol imap {
   mail_max_userip_connections = 40
 }
 
-{% if content_filter is defined %}
-
+{% if dovecot_content_filter %}
 plugin {
   sieve_plugins = sieve_imapsieve sieve_extprograms
 
   # From elsewhere to Spam folder
-  imapsieve_mailbox1_name = Junk
+  imapsieve_mailbox1_name = {{ dovecot_spam_folder }}
   imapsieve_mailbox1_causes = COPY
   imapsieve_mailbox1_before = file:/var/lib/dovecot/sieve.d/report-spam.sieve
 
   # From Spam folder to elsewhere
   imapsieve_mailbox2_name = *
-  imapsieve_mailbox2_from = Junk
+  imapsieve_mailbox2_from = {{ dovecot_spam_folder }}
   imapsieve_mailbox2_causes = COPY
   imapsieve_mailbox2_before = file:/var/lib/dovecot/sieve.d/report-ham.sieve
 
   sieve_pipe_bin_dir = /var/lib/dovecot/sieve.d
-
   sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
 }
 {% endif %}
diff --git a/dovecot/templates/conf.d/20-managesieve.conf.j2 b/dovecot/templates/conf.d/20-managesieve.conf.j2
index d549e70ec9a623839277c5f7bc4d2efe16dd9104..11cf0656e6bb2ee05ea35e4c95b85dd400fc7736 100644
--- a/dovecot/templates/conf.d/20-managesieve.conf.j2
+++ b/dovecot/templates/conf.d/20-managesieve.conf.j2
@@ -12,10 +12,6 @@ service managesieve-login {
     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>
diff --git a/dovecot/templates/conf.d/90-sieve.conf.j2 b/dovecot/templates/conf.d/90-sieve.conf.j2
index bee89e3712b1d11bcaa65836930cfeccc297c470..2e9aebddd7b1bd0dc656e267dd358a9b74a170be 100644
--- a/dovecot/templates/conf.d/90-sieve.conf.j2
+++ b/dovecot/templates/conf.d/90-sieve.conf.j2
@@ -76,8 +76,8 @@ plugin {
   #sieve_before = /var/lib/dovecot/sieve.d/
   #sieve_before2 = ldap:/etc/sieve-ldap.conf;name=ldap-domain
   #sieve_before3 = (etc...)
-{% if content_filter is defined %}
-  sieve_before = /var/lib/dovecot/sieve.d/filter_junk.sieve
+{% if dovecot_content_filter %}
+  sieve_before = /var/lib/dovecot/sieve.d/filter-spam.sieve
 {% endif %}
 
   # Identical to sieve_before, only the specified scripts are executed after the
diff --git a/dovecot/templates/conf.d/99-dsync.conf.j2 b/dovecot/templates/conf.d/99-dsync.conf.j2
index e76a63d7d47b996ddb5063c98624f2274a5f668a..71e490732d241437c84d057c358827c9e125c287 100644
--- a/dovecot/templates/conf.d/99-dsync.conf.j2
+++ b/dovecot/templates/conf.d/99-dsync.conf.j2
@@ -4,26 +4,22 @@ service replicator {
     mode = 0666
     user = dovecot
   }
-  group = vmail
+  group = {{ dovecot_dsync_group }}
 }
 
 replication_max_conns = 10
 
-
-# there was a problem with the oom-killer 
-#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 = 2 
-#}
-
 service doveadm {
   inet_listener {
-    address = {{ tinc_vpnip  }}
+{% if dovecot_dsync_address != '0.0.0.0' %}
+    address = {{ dovecot_dsync_address }}
+{% endif %}
     port = 37962
+{% if dovecot_dsync_tls %}
+    ssl = yes
+{% endif %}
   }
-  group = vmail
+  group = {{ dovecot_dsync_group }}
 }
 
 service aggregator {
@@ -38,14 +34,13 @@ service aggregator {
 }
 
 doveadm_port = 37962
-
-doveadm_password = {{ lookup('passwordstore', 'wolfscloud/dsync_secret create=true length=20') }}
+doveadm_password = {{ dovecot_dsync_password }}
 
 plugin {
 
 {% for partner in groups['mail'] %}
   {% if partner != ansible_hostname %}
-mail_replica = tcp:{{hostvars[partner]["tinc_vpnip"]}}:37962
+mail_replica = tcp{{ 's' if dovecot_dsync_tls else '' }}:{{ hostvars[partner][dovecot_dsync_host_attribute] }}:37962
   {% endif %}
 {% endfor %}
 
diff --git a/dovecot/templates/deny-users.j2 b/dovecot/templates/deny-users.j2
new file mode 100644
index 0000000000000000000000000000000000000000..2cedf80cc1e24c167bae5db7de689c2f91de1e1d
--- /dev/null
+++ b/dovecot/templates/deny-users.j2
@@ -0,0 +1 @@
+{{ dovecot_deny_users|join('\n') }}
diff --git a/dovecot/templates/dovecot.conf.j2 b/dovecot/templates/dovecot.conf.j2
index 5288a5722ebdb0c72a997ffcab95eed59a8ce35b..ae11aca874ac5d9fd129a08606f8e72d9e2e377c 100644
--- a/dovecot/templates/dovecot.conf.j2
+++ b/dovecot/templates/dovecot.conf.j2
@@ -96,7 +96,7 @@ dict {
 # 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
-protocols = {{ protocols }}
+protocols = {{ dovecot_protocols }}
 
 # A config file can also tried to be included without giving an error if
 # it's not found:
diff --git a/dovecot/templates/sieve/filter-spam.sieve.j2 b/dovecot/templates/sieve/filter-spam.sieve.j2
new file mode 100644
index 0000000000000000000000000000000000000000..34cf03e77231e8462fb1b488a98cb4ad401234de
--- /dev/null
+++ b/dovecot/templates/sieve/filter-spam.sieve.j2
@@ -0,0 +1,5 @@
+require ["fileinto", "mailbox"];
+
+if header :contains "X-Spam-Flag" "YES" {
+	fileinto :create "{{ dovecot_spam_folder }}";
+}
diff --git a/dovecot/files/report-ham.sieve b/dovecot/templates/sieve/report-ham.sieve.j2
similarity index 100%
rename from dovecot/files/report-ham.sieve
rename to dovecot/templates/sieve/report-ham.sieve.j2
diff --git a/dovecot/files/report-spam.sieve b/dovecot/templates/sieve/report-spam.sieve.j2
similarity index 100%
rename from dovecot/files/report-spam.sieve
rename to dovecot/templates/sieve/report-spam.sieve.j2