aboutsummaryrefslogtreecommitdiffstats
path: root/roles/dovecot
diff options
context:
space:
mode:
Diffstat (limited to 'roles/dovecot')
-rw-r--r--roles/dovecot/defaults/main.yml24
-rw-r--r--roles/dovecot/files/etc/dovecot/sieve.before.d/10-rspamd.sieve5
-rw-r--r--roles/dovecot/files/etc/dovecot/sieve/report-ham.sieve15
-rw-r--r--roles/dovecot/files/etc/dovecot/sieve/report-spam.sieve7
-rw-r--r--roles/dovecot/files/etc/dovecot/virtual/All Messages/dovecot-virtual2
-rw-r--r--roles/dovecot/files/etc/dovecot/virtual/Flagged/dovecot-virtual2
-rw-r--r--roles/dovecot/files/etc/dovecot/virtual/INBOX/dovecot-virtual2
-rw-r--r--roles/dovecot/files/etc/systemd/system/dovecot.service.d/override.conf6
-rw-r--r--roles/dovecot/files/var/lib/solr/dovecot/conf/schema.xml48
-rw-r--r--roles/dovecot/handlers/main.yml4
-rw-r--r--roles/dovecot/meta/main.yml12
-rw-r--r--roles/dovecot/tasks/freeipa.yml109
-rw-r--r--roles/dovecot/tasks/main.yml127
-rw-r--r--roles/dovecot/tasks/rspamd.yml43
-rw-r--r--roles/dovecot/tasks/solr.yml40
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/10-auth.conf.j210
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/10-mail.conf.j231
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/10-master.conf.j231
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/10-ssl.conf.j210
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/15-lda.conf.j210
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/15-mailboxes.conf.j236
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/20-imap.conf.j23
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/20-lmtp.conf.j23
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/20-managesieve.conf.j211
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/90-fts.conf.j26
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/90-quota.conf.j234
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/90-sieve-extprograms.conf.j25
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/90-sieve.conf.j230
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/auth-ldap.conf.ext.j24
-rw-r--r--roles/dovecot/templates/etc/dovecot/conf.d/auth-system.conf.ext.j23
-rw-r--r--roles/dovecot/templates/etc/dovecot/dovecot-ldap.conf.ext.j216
-rw-r--r--roles/dovecot/templates/etc/dovecot/dovecot.conf.j25
-rw-r--r--roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-ham.sh.j27
-rw-r--r--roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-spam.sh.j27
-rw-r--r--roles/dovecot/templates/usr/local/bin/dovecot-archive.sh.j219
-rw-r--r--roles/dovecot/templates/usr/local/bin/dovecot-quota-warning.sh.j219
-rw-r--r--roles/dovecot/templates/var/lib/solr/dovecot/conf/solrconfig.xml.j291
-rw-r--r--roles/dovecot/vars/main.yml64
38 files changed, 901 insertions, 0 deletions
diff --git a/roles/dovecot/defaults/main.yml b/roles/dovecot/defaults/main.yml
new file mode 100644
index 0000000..e4f3842
--- /dev/null
+++ b/roles/dovecot/defaults/main.yml
@@ -0,0 +1,24 @@
+dovecot_recipient_delimiter: '+'
+dovecot_default_user_quota: 5G
+dovecot_quota_grace_percent: 5
+dovecot_default_domain: '{{ email_domain }}'
+
+dovecot_rspamd_host: '{{ rspamd_host }}'
+dovecot_rspamd_password: '{{ rspamd_password }}'
+dovecot_rspamd_pubkey: '{{ rspamd_pubkey }}'
+
+dovecot_access_group: role-imap-access
+
+dovecot_archive_on_calendar: weekly
+
+dovecot_lmtp_port: 24
+dovecot_quota_status_port: 10993
+
+dovecot_tika_port: 9998
+dovecot_solr_port: 8983
+
+dovecot_max_mail_size: 64M
+dovecot_quota_warning_percent:
+ - 95
+ - 90
+ - 80
diff --git a/roles/dovecot/files/etc/dovecot/sieve.before.d/10-rspamd.sieve b/roles/dovecot/files/etc/dovecot/sieve.before.d/10-rspamd.sieve
new file mode 100644
index 0000000..7931a71
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/sieve.before.d/10-rspamd.sieve
@@ -0,0 +1,5 @@
+require ["fileinto"];
+
+if header :is "X-Spam" "Yes" {
+ fileinto "Junk";
+}
diff --git a/roles/dovecot/files/etc/dovecot/sieve/report-ham.sieve b/roles/dovecot/files/etc/dovecot/sieve/report-ham.sieve
new file mode 100644
index 0000000..578e7b2
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/sieve/report-ham.sieve
@@ -0,0 +1,15 @@
+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.email" "*" {
+ set "email" "${1}";
+}
+
+pipe :copy "report-ham.sh" [ "${email}" ];
diff --git a/roles/dovecot/files/etc/dovecot/sieve/report-spam.sieve b/roles/dovecot/files/etc/dovecot/sieve/report-spam.sieve
new file mode 100644
index 0000000..d34c71b
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/sieve/report-spam.sieve
@@ -0,0 +1,7 @@
+require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
+
+if environment :matches "imap.email" "*" {
+ set "email" "${1}";
+}
+
+pipe :copy "report-spam.sh" [ "${email}" ];
diff --git a/roles/dovecot/files/etc/dovecot/virtual/All Messages/dovecot-virtual b/roles/dovecot/files/etc/dovecot/virtual/All Messages/dovecot-virtual
new file mode 100644
index 0000000..a7f3148
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/virtual/All Messages/dovecot-virtual
@@ -0,0 +1,2 @@
+*
+ all
diff --git a/roles/dovecot/files/etc/dovecot/virtual/Flagged/dovecot-virtual b/roles/dovecot/files/etc/dovecot/virtual/Flagged/dovecot-virtual
new file mode 100644
index 0000000..883f49e
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/virtual/Flagged/dovecot-virtual
@@ -0,0 +1,2 @@
+*
+ flagged
diff --git a/roles/dovecot/files/etc/dovecot/virtual/INBOX/dovecot-virtual b/roles/dovecot/files/etc/dovecot/virtual/INBOX/dovecot-virtual
new file mode 100644
index 0000000..139e4b0
--- /dev/null
+++ b/roles/dovecot/files/etc/dovecot/virtual/INBOX/dovecot-virtual
@@ -0,0 +1,2 @@
+Virtual/All Messages
+ inthread refs x-mailbox INBOX
diff --git a/roles/dovecot/files/etc/systemd/system/dovecot.service.d/override.conf b/roles/dovecot/files/etc/systemd/system/dovecot.service.d/override.conf
new file mode 100644
index 0000000..0e524e8
--- /dev/null
+++ b/roles/dovecot/files/etc/systemd/system/dovecot.service.d/override.conf
@@ -0,0 +1,6 @@
+[Unit]
+Wants=gssproxy.service
+After=local-fs.target network-online.target dovecot-init.service gssproxy.service
+
+[Service]
+Environment=GSS_USE_PROXY=yes
diff --git a/roles/dovecot/files/var/lib/solr/dovecot/conf/schema.xml b/roles/dovecot/files/var/lib/solr/dovecot/conf/schema.xml
new file mode 100644
index 0000000..601a290
--- /dev/null
+++ b/roles/dovecot/files/var/lib/solr/dovecot/conf/schema.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/roles/dovecot/handlers/main.yml b/roles/dovecot/handlers/main.yml
new file mode 100644
index 0000000..344cf91
--- /dev/null
+++ b/roles/dovecot/handlers/main.yml
@@ -0,0 +1,4 @@
+- name: restart dovecot
+ systemd:
+ name: dovecot
+ state: restarted
diff --git a/roles/dovecot/meta/main.yml b/roles/dovecot/meta/main.yml
new file mode 100644
index 0000000..c4f4b18
--- /dev/null
+++ b/roles/dovecot/meta/main.yml
@@ -0,0 +1,12 @@
+dependencies:
+ - role: yum
+ yum_repositories:
+ - epel
+ - rspamd
+ tags: yum
+
+ - role: solr
+ tags: solr
+
+ - role: tika
+ tags: tika
diff --git a/roles/dovecot/tasks/freeipa.yml b/roles/dovecot/tasks/freeipa.yml
new file mode 100644
index 0000000..1e1ee29
--- /dev/null
+++ b/roles/dovecot/tasks/freeipa.yml
@@ -0,0 +1,109 @@
+- name: create IMAP access group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ dovecot_access_group }}'
+ description: users with IMAP access
+ nonposix: yes
+ state: present
+ run_once: True
+
+- name: create service principals
+ ipaservice:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ item }}/{{ ansible_fqdn }}'
+ state: present
+ loop:
+ - imap
+ - sieve
+
+- name: retrieve service keytabs
+ include_role:
+ name: freeipa_keytab
+ vars:
+ keytab_principal: '{{ item }}/{{ ansible_fqdn }}'
+ keytab_path: '{{ dovecot_keytab }}'
+ loop:
+ - imap
+ - sieve
+
+- name: configure gssproxy
+ include_role:
+ name: gssproxy_client
+ vars:
+ gssproxy_name: dovecot
+ gssproxy_section: service/dovecot
+ gssproxy_keytab: '{{ dovecot_keytab }}'
+ gssproxy_client_keytab: '{{ dovecot_keytab }}'
+ gssproxy_cred_usage: both
+ gssproxy_euid: dovecot
+
+- name: create SELinux policy for dovecot to access gssproxy
+ include_role:
+ name: selinux_policy
+ apply:
+ tags: selinux
+ vars:
+ selinux_policy_name: dovecot_gssproxy
+ selinux_policy_te: '{{ dovecot_selinux_policy_te }}'
+ tags: selinux
+
+- name: generate PAM configuration for dovecot
+ copy:
+ content: |
+ auth required pam_sss.so
+ account required pam_sss.so
+ dest: /etc/pam.d/dovecot
+
+- name: create HBAC service
+ ipahbacsvc:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ dovecot_hbac_service }}'
+ description: Dovecot IMAP server
+ state: present
+ run_once: True
+
+- name: create imap-servers hostgroup
+ ipahostgroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ dovecot_hbac_hostgroup }}'
+ description: IMAP Servers
+ host: "{{ groups[dovecot_hbac_hostgroup] | map('regex_replace', '$', '.' ~ ansible_domain) }}"
+ state: present
+ run_once: True
+
+# Note: we explicitly allow all here. SSSD will only be consulted when a user performs
+# a PLAIN login, falling back to PAM authentication. Users with a valid Kerberos ticket
+# bypass the PAM stack entirely, so a restrictive HBAC rule is pointless.
+- name: create HBAC rule
+ ipahbacrule:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: allow_dovecot_on_imap_servers
+ description: Allow IMAP on imap servers
+ hostgroup:
+ - '{{ dovecot_hbac_hostgroup }}'
+ usercategory: all
+ hbacsvc:
+ - '{{ dovecot_hbac_service }}'
+ run_once: True
+
+- name: create systemd override directory
+ file:
+ path: /etc/systemd/system/dovecot.service.d
+ state: directory
+
+- name: create systemd override file
+ copy:
+ src: etc/systemd/system/dovecot.service.d/override.conf
+ dest: /etc/systemd/system/dovecot.service.d/override.conf
+ notify: restart dovecot
+ register: dovecot_systemd_unit
+
+- name: reload systemd daemons
+ systemd:
+ daemon_reload: yes
+ when: dovecot_systemd_unit.changed
diff --git a/roles/dovecot/tasks/main.yml b/roles/dovecot/tasks/main.yml
new file mode 100644
index 0000000..09f2e2e
--- /dev/null
+++ b/roles/dovecot/tasks/main.yml
@@ -0,0 +1,127 @@
+- name: install dovecot
+ dnf:
+ name: '{{ dovecot_packages }}'
+ state: present
+
+- name: add vmail user
+ user:
+ name: '{{ dovecot_vmail_user }}'
+ system: yes
+ home: '{{ dovecot_vmail_dir }}'
+ shell: /sbin/nologin
+ create_home: no
+ register: dovecot_vmail_user_result
+
+- name: create vmail directory
+ file:
+ path: '{{ dovecot_vmail_dir }}'
+ state: directory
+ owner: '{{ dovecot_vmail_user }}'
+ group: '{{ dovecot_vmail_user }}'
+ setype: mail_spool_t
+ mode: 0770
+
+- name: set selinux context for vmail directory
+ sefcontext:
+ target: '{{ dovecot_vmail_dir }}(/.*)?'
+ setype: mail_spool_t
+ state: present
+ register: dovecot_vmail_sefcontext
+
+- name: apply selinux context to vmail directory
+ command: 'restorecon -R {{ dovecot_vmail_dir }}'
+ when: dovecot_vmail_sefcontext.changed
+
+- name: set up FreeIPA integration for IMAP
+ import_tasks: freeipa.yml
+
+- name: request TLS certificate
+ include_role:
+ name: getcert_request
+ vars:
+ certificate_service: imap
+ certificate_path: '{{ dovecot_certificate_path }}'
+ certificate_key_path: '{{ dovecot_certificate_key_path }}'
+ certificate_owner: dovecot
+ certificate_hook: systemctl reload dovecot
+
+- name: generate dhparams
+ openssl_dhparam:
+ path: '{{ dovecot_dhparams_path }}'
+ size: 2048
+
+- name: configure Apache Solr for full-text search
+ import_tasks: solr.yml
+ tags: solr
+
+- name: create virtual config directory
+ file:
+ path: /etc/dovecot/virtual
+ state: directory
+
+- name: create global sieve directories
+ file:
+ path: '{{ item }}'
+ state: directory
+ recurse: yes
+ loop:
+ - '{{ dovecot_sieve_dir }}'
+ - '{{ dovecot_sieve_before_dir }}'
+ - '{{ dovecot_sieve_pipe_bin_dir }}'
+
+- name: create virtual mailbox definitions
+ copy:
+ src: etc/dovecot/virtual/
+ dest: /etc/dovecot/virtual/
+
+- name: generate dovecot configuration
+ template:
+ src: '{{ item.src }}'
+ dest: /etc/dovecot/{{ item.path | splitext | first }}
+ loop: "{{ lookup('filetree', '../templates/etc/dovecot', wantlist=True) }}"
+ loop_control:
+ label: '{{ item.path }}'
+ when: item.state == 'file'
+ notify: restart dovecot
+
+- name: copy quota warn script
+ template:
+ src: '{{ dovecot_quota_warning_script[1:] }}.j2'
+ dest: '{{ dovecot_quota_warning_script }}'
+ mode: 0555
+
+- name: start dovecot
+ systemd:
+ name: dovecot
+ enabled: yes
+ state: started
+
+- import_tasks: rspamd.yml
+
+- name: open firewall ports
+ firewalld:
+ service: '{{ item }}'
+ permanent: yes
+ immediate: yes
+ state: enabled
+ loop:
+ - imaps
+ - managesieve
+ tags: firewalld
+
+- name: open firewall ports
+ firewalld:
+ port: '{{ item }}'
+ permanent: yes
+ immediate: yes
+ state: enabled
+ loop:
+ - '{{ dovecot_quota_status_port }}/tcp'
+ - '{{ dovecot_lmtp_port }}/tcp'
+ tags: firewalld
+
+- name: generate archive script
+ template:
+ src: '{{ dovecot_archive_script[1:] }}.j2'
+ dest: '{{ dovecot_archive_script }}'
+ mode: 0555
diff --git a/roles/dovecot/tasks/rspamd.yml b/roles/dovecot/tasks/rspamd.yml
new file mode 100644
index 0000000..90686ee
--- /dev/null
+++ b/roles/dovecot/tasks/rspamd.yml
@@ -0,0 +1,43 @@
+- name: install rspamd
+ dnf:
+ name: rspamd
+ state: present
+
+- name: copy rspamd X-SPAM sieve script
+ copy:
+ src: '{{ dovecot_sieve_before_dir[1:] }}/10-rspamd.sieve'
+ dest: '{{ dovecot_sieve_before_dir }}/10-rspamd.sieve'
+ register: dovecot_rspamd_sieve_script
+
+- name: compile rspamd X-SPAM sieve script
+ command: sievec '{{ dovecot_sieve_before_dir }}/10-rspamd.sieve'
+ when: dovecot_rspamd_sieve_script.changed
+
+- name: copy rspamd sieve reporting scripts
+ copy:
+ src: '{{ dovecot_sieve_dir[1:] }}/{{ item }}'
+ dest: '{{ dovecot_sieve_dir }}/{{ item }}'
+ loop:
+ - report-spam.sieve
+ - report-ham.sieve
+ register: dovecot_rspamd_report_sieve_scripts
+
+- name: compile rspamd sieve reporting scripts
+ command: sievec {{ dovecot_sieve_dir }}/{{ item }}
+ when: dovecot_rspamd_report_sieve_scripts.results[index].changed
+ loop:
+ - report-spam.sieve
+ - report-ham.sieve
+ loop_control:
+ index_var: index
+
+- name: generate rpsmad bash reporting scripts
+ template:
+ src: '{{ dovecot_sieve_pipe_bin_dir[1:] }}/{{ item }}.j2'
+ dest: '{{ dovecot_sieve_pipe_bin_dir }}/{{ item }}'
+ owner: root
+ group: dovecot
+ mode: 0550
+ loop:
+ - report-spam.sh
+ - report-ham.sh
diff --git a/roles/dovecot/tasks/solr.yml b/roles/dovecot/tasks/solr.yml
new file mode 100644
index 0000000..0751192
--- /dev/null
+++ b/roles/dovecot/tasks/solr.yml
@@ -0,0 +1,40 @@
+- name: add solr collection for dovecot
+ command:
+ cmd: '{{ solr_install_dir }}/bin/solr create -c dovecot'
+ creates: '{{ solr_data_dir }}/dovecot'
+ become: True
+ become_user: solr
+
+- name: check if dovecot schema exists
+ stat:
+ path: '{{ solr_data_dir }}/dovecot/conf/schema.xml.bak'
+ register: schema_xml_bak
+
+- name: copy dovecot solr schema
+ copy:
+ src: '{{ solr_data_dir[1:] }}/dovecot/conf/schema.xml'
+ dest: '{{ solr_data_dir }}/dovecot/conf/schema.xml'
+ owner: solr
+ group: solr
+ register: solr_schema
+ changed_when: no
+
+- name: stat new schema
+ stat:
+ path: '{{ solr_data_dir }}/dovecot/conf/schema.xml'
+ register: schema_xml
+
+- name: remove managed-schema file
+ file:
+ path: '{{ solr_data_dir }}/dovecot/conf/managed-schema.xml'
+ state: absent
+ when: (not schema_xml_bak.stat.exists) or (schema_xml_bak.stat.checksum != schema_xml.stat.checksum)
+ notify: restart solr
+
+- name: generate dovecot solr config
+ template:
+ src: '{{ solr_data_dir[1:] }}/dovecot/conf/solrconfig.xml.j2'
+ dest: '{{ solr_data_dir }}/dovecot/conf/solrconfig.xml'
+ owner: solr
+ group: solr
+ notify: restart solr
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/10-auth.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/10-auth.conf.j2
new file mode 100644
index 0000000..2185d6d
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/10-auth.conf.j2
@@ -0,0 +1,10 @@
+auth_default_realm = {{ freeipa_realm }}
+
+auth_username_format = %Ln
+
+auth_gssapi_hostname = "$ALL"
+
+auth_mechanisms = gssapi plain login
+
+!include auth-system.conf.ext
+!include auth-ldap.conf.ext
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/10-mail.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/10-mail.conf.j2
new file mode 100644
index 0000000..9a3884a
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/10-mail.conf.j2
@@ -0,0 +1,31 @@
+mail_location = mdbox:~/mdbox
+
+namespace inbox {
+ type = private
+ separator = /
+ inbox = yes
+ subscriptions = yes
+}
+
+namespace virtual {
+ location = virtual:/etc/dovecot/virtual:INDEX=~/.virtual:CONTROL=~/.virtual:VOLATILEDIR=~/.virtual:LAYOUT=fs
+
+ type = private
+ separator = /
+ prefix = Virtual/
+}
+
+mail_plugins = $mail_plugins quota virtual fts fts_solr
+
+mail_privileged_group = {{ dovecot_vmail_user }}
+
+first_valid_uid = {{ dovecot_vmail_user_result.uid }}
+last_valid_uid = {{ dovecot_vmail_user_result.uid }}
+
+first_valid_gid = {{ dovecot_vmail_user_result.group }}
+last_valid_gid = {{ dovecot_vmail_user_result.group }}
+
+# recommended configuration for quota:count
+protocol !indexer-worker {
+ mail_vsize_bg_after_count = 100
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/10-master.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/10-master.conf.j2
new file mode 100644
index 0000000..a2af8b3
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/10-master.conf.j2
@@ -0,0 +1,31 @@
+service imap-login {
+ inet_listener imap {
+ port = 143
+ }
+
+ inet_listener imaps {
+ port = 993
+ ssl = yes
+ }
+}
+
+service lmtp {
+ user = {{ dovecot_vmail_user }}
+ inet_listener lmtp {
+ port = {{ dovecot_lmtp_port }}
+ }
+}
+
+service auth-worker {
+ user = $default_internal_user
+}
+
+# Allow the vmail user to write to stats. This isn't strictly necessary, but
+# prevents dovecot-lda from spamming the mail log with errors.
+service stats {
+ unix_listener stats-writer {
+ user = dovecot
+ group = {{ dovecot_vmail_user }}
+ mode = 0660
+ }
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/10-ssl.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/10-ssl.conf.j2
new file mode 100644
index 0000000..e677b44
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/10-ssl.conf.j2
@@ -0,0 +1,10 @@
+ssl = required
+
+ssl_cert = <{{ dovecot_certificate_path }}
+ssl_key = <{{ dovecot_certificate_key_path }}
+
+ssl_dh = <{{ dovecot_dhparams_path }}
+
+ssl_min_protocol = TLSv1.2
+
+ssl_cipher_list = {{ dovecot_ssl_cipher_list }}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/15-lda.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/15-lda.conf.j2
new file mode 100644
index 0000000..0ed20f5
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/15-lda.conf.j2
@@ -0,0 +1,10 @@
+recipient_delimiter = {{ dovecot_recipient_delimiter }}
+lda_original_recipient_header = X-Original-To
+
+lda_mailbox_autocreate = yes
+
+lda_mailbox_autosubscribe = no
+
+protocol lda {
+ mail_plugins = $mail_plugins sieve
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/15-mailboxes.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/15-mailboxes.conf.j2
new file mode 100644
index 0000000..af47fcc
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/15-mailboxes.conf.j2
@@ -0,0 +1,36 @@
+namespace inbox {
+
+ mailbox Drafts {
+ auto = subscribe
+ special_use = \Drafts
+ }
+
+ mailbox Junk {
+ auto = subscribe
+ special_use = \Junk
+ }
+
+ mailbox Trash {
+ auto = subscribe
+ special_use = \Trash
+ }
+
+ mailbox Sent {
+ auto = subscribe
+ special_use = \Sent
+ }
+
+ mailbox Archive {
+ auto = subscribe
+ special_use = \Archive
+ }
+
+ # "auto = subscribe" on virtual folders causes dovecot to coredump.
+ mailbox "Virtual/All Messages" {
+ special_use = \All
+ }
+
+ mailbox Virtual/Flagged {
+ special_use = \Flagged
+ }
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/20-imap.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/20-imap.conf.j2
new file mode 100644
index 0000000..ae67bae
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/20-imap.conf.j2
@@ -0,0 +1,3 @@
+protocol imap {
+ mail_plugins = $mail_plugins imap_quota imap_sieve
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/20-lmtp.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/20-lmtp.conf.j2
new file mode 100644
index 0000000..2619ce5
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/20-lmtp.conf.j2
@@ -0,0 +1,3 @@
+protocol lmtp {
+ mail_plugins = $mail_plugins sieve
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/20-managesieve.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/20-managesieve.conf.j2
new file mode 100644
index 0000000..f4adea9
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/20-managesieve.conf.j2
@@ -0,0 +1,11 @@
+protocols = $protocols sieve
+
+service managesieve-login {
+ inet_listener sieve {
+ port = 4190
+ }
+
+ inet_listener sieve_deprecated {
+ port = 0
+ }
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/90-fts.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/90-fts.conf.j2
new file mode 100644
index 0000000..dbe2102
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/90-fts.conf.j2
@@ -0,0 +1,6 @@
+plugin {
+ fts_autoindex = yes
+ fts = solr
+ fts_solr = url=http://localhost:{{ dovecot_solr_port }}/solr/dovecot/
+ fts_tika = http://localhost:{{ dovecot_tika_port }}/tika/
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/90-quota.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/90-quota.conf.j2
new file mode 100644
index 0000000..e1d4449
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/90-quota.conf.j2
@@ -0,0 +1,34 @@
+plugin {
+ quota = count:User quota
+ quota_vsizes = yes
+ quota_rule = *:storage={{ dovecot_default_user_quota }}
+ quota_grace = {{ dovecot_quota_grace_percent }}%%
+
+ quota_max_mail_size = {{ dovecot_max_mail_size }}
+
+ quota_status_success = DUNNO
+ quota_status_nouser = DUNNO
+ quota_status_overquota = "552 5.2.2 Mailbox is full"
+
+ {% for percent in dovecot_quota_warning_percent | sort(reverse=True) %}
+ quota_warning{% if not loop.first %}{{ loop.index }}{% endif %} = storage={{ percent }}%% quota-warning {{ percent }} %u
+ {% endfor %}
+}
+
+service quota-warning {
+ executable = script {{ dovecot_quota_warning_script }}
+ user = {{ dovecot_vmail_user }}
+ unix_listener quota-warning {
+ user = dovecot
+ group = {{ dovecot_vmail_user }}
+ mode = 0660
+ }
+}
+
+service quota-status {
+ executable = quota-status -p postfix
+ inet_listener {
+ port = {{ dovecot_quota_status_port }}
+ }
+ client_limit = 5
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve-extprograms.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve-extprograms.conf.j2
new file mode 100644
index 0000000..bab3d4f
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve-extprograms.conf.j2
@@ -0,0 +1,5 @@
+plugin {
+ sieve_pipe_bin_dir = {{ dovecot_sieve_pipe_bin_dir }}
+ sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter
+ sieve_execute_bin_dir = /usr/lib/dovecot/sieve-execute
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve.conf.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve.conf.j2
new file mode 100644
index 0000000..51ec533
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/90-sieve.conf.j2
@@ -0,0 +1,30 @@
+plugin {
+ sieve = file:~/sieve;active=~/.dovecot.sieve
+
+ sieve_before = {{ dovecot_sieve_before_dir }}
+
+ sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
+
+ sieve_plugins = sieve_extprograms sieve_imapsieve
+
+ sieve_quota_max_scripts = 10
+ sieve_quota_max_storage = 2M
+
+ sieve_user_email = %Ln@{{ dovecot_default_domain }}
+
+ # The default value for this is "sender", but that will totally break SPF
+ sieve_redirect_envelope_from = orig_recipient
+
+ # From elsewhere to Junk folder
+ imapsieve_mailbox1_name = Junk
+ imapsieve_mailbox1_causes = COPY
+ imapsieve_mailbox1_before = file:{{ dovecot_sieve_dir }}/report-spam.sieve
+
+ # From Junk folder to elsewhere
+ imapsieve_mailbox2_name = *
+ imapsieve_mailbox2_from = Junk
+ imapsieve_mailbox2_causes = COPY
+ imapsieve_mailbox2_before = file:{{ dovecot_sieve_dir }}/report-ham.sieve
+
+ sieve_global_extensions = +vnd.dovecot.pipe
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/auth-ldap.conf.ext.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/auth-ldap.conf.ext.j2
new file mode 100644
index 0000000..7b5ab0e
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/auth-ldap.conf.ext.j2
@@ -0,0 +1,4 @@
+userdb {
+ driver = ldap
+ args = /etc/dovecot/dovecot-ldap.conf.ext
+}
diff --git a/roles/dovecot/templates/etc/dovecot/conf.d/auth-system.conf.ext.j2 b/roles/dovecot/templates/etc/dovecot/conf.d/auth-system.conf.ext.j2
new file mode 100644
index 0000000..a53dd53
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/conf.d/auth-system.conf.ext.j2
@@ -0,0 +1,3 @@
+passdb {
+ driver = pam
+}
diff --git a/roles/dovecot/templates/etc/dovecot/dovecot-ldap.conf.ext.j2 b/roles/dovecot/templates/etc/dovecot/dovecot-ldap.conf.ext.j2
new file mode 100644
index 0000000..3f03c82
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/dovecot-ldap.conf.ext.j2
@@ -0,0 +1,16 @@
+hosts = {{ freeipa_hosts | join(' ') }}
+
+sasl_bind = yes
+sasl_mech = gssapi
+sasl_realm = {{ freeipa_realm }}
+
+base = {{ freeipa_user_basedn }}
+
+user_filter = (&(uid=%Ln)(memberof=cn={{ dovecot_access_group }},{{ freeipa_group_basedn }}))
+user_attrs= \
+ =uid={{ dovecot_vmail_user }}, \
+ =gid={{ dovecot_vmail_user }}, \
+ =home={{ dovecot_vmail_dir }}/%{ldap:uid}
+
+iterate_attrs = uid=user
+iterate_filter = (memberof=cn={{ dovecot_access_group }},{{ freeipa_group_basedn }})
diff --git a/roles/dovecot/templates/etc/dovecot/dovecot.conf.j2 b/roles/dovecot/templates/etc/dovecot/dovecot.conf.j2
new file mode 100644
index 0000000..bfc16bf
--- /dev/null
+++ b/roles/dovecot/templates/etc/dovecot/dovecot.conf.j2
@@ -0,0 +1,5 @@
+protocols = imap lmtp
+
+import_environment = $import_environment GSS_USE_PROXY=yes
+
+!include conf.d/*.conf
diff --git a/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-ham.sh.j2 b/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-ham.sh.j2
new file mode 100644
index 0000000..fbce0bc
--- /dev/null
+++ b/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-ham.sh.j2
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+exec /usr/bin/rspamc \
+ --hostname={{ dovecot_rspamd_host | quote }} \
+ --password={{ dovecot_rspamd_password | quote }} \
+ --key={{ dovecot_rspamd_pubkey | quote }} \
+ learn_ham
diff --git a/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-spam.sh.j2 b/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-spam.sh.j2
new file mode 100644
index 0000000..393c5ec
--- /dev/null
+++ b/roles/dovecot/templates/usr/lib/dovecot/sieve-pipe/report-spam.sh.j2
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+exec /usr/bin/rspamc \
+ --hostname={{ dovecot_rspamd_host | quote }} \
+ --password={{ dovecot_rspamd_password | quote }} \
+ --key={{ dovecot_rspamd_pubkey | quote }} \
+ learn_spam
diff --git a/roles/dovecot/templates/usr/local/bin/dovecot-archive.sh.j2 b/roles/dovecot/templates/usr/local/bin/dovecot-archive.sh.j2
new file mode 100644
index 0000000..8f34b6a
--- /dev/null
+++ b/roles/dovecot/templates/usr/local/bin/dovecot-archive.sh.j2
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -Eeu -o pipefail
+
+VMAIL_USER={{ dovecot_vmail_user | quote }}
+{% raw %}
+TMPDIR=$(mktemp -d .dovecot-XXXXXX)
+trap 'rm -rf -- "$TMPDIR"' EXIT
+
+chown "$VMAIL_USER" "$TMPDIR"
+
+doveadm user '*' | xargs -r -I{} doveadm -o plugin/quota= backup -n inbox -f -u {} "mdbox:${TMPDIR}/{}/mdbox:LAYOUT=fs"
+
+TIMESTAMP=$(date +%Y%m%d%H%M%S)
+
+tar czf "mailboxes-${TIMESTAMP}.tar.gz" \
+ --transform "s|^\.|mailboxes-${TIMESTAMP}|" \
+ -C "$TMPDIR" .
+{% endraw %}
diff --git a/roles/dovecot/templates/usr/local/bin/dovecot-quota-warning.sh.j2 b/roles/dovecot/templates/usr/local/bin/dovecot-quota-warning.sh.j2
new file mode 100644
index 0000000..5ffe4b8
--- /dev/null
+++ b/roles/dovecot/templates/usr/local/bin/dovecot-quota-warning.sh.j2
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -Eeu -o pipefail
+
+PERCENT=$1
+USER=$2
+
+cat << EOF | /usr/libexec/dovecot/dovecot-lda -d "$USER" -o "plugin/quota=count:User quota:noenforcing"
+From: postmaster@{{ dovecot_default_domain }}
+Subject: Mailbox quota warning
+
+This is an automatically generated message.
+
+Your mailbox is now ${PERCENT}% full.
+
+When your mailbox exceeds its quota, you will no longer receive new mail.
+
+Please delete some messages to free up space.
+EOF
diff --git a/roles/dovecot/templates/var/lib/solr/dovecot/conf/solrconfig.xml.j2 b/roles/dovecot/templates/var/lib/solr/dovecot/conf/solrconfig.xml.j2
new file mode 100644
index 0000000..af29a84
--- /dev/null
+++ b/roles/dovecot/templates/var/lib/solr/dovecot/conf/solrconfig.xml.j2
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<config>
+ <luceneMatchVersion>{{ solr_lucene_version }}</luceneMatchVersion>
+
+ <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" />
+
+ <dataDir>${solr.data.dir:}</dataDir>
+
+ <updateHandler class="solr.DirectUpdateHandler2">
+
+ <updateLog>
+ <str name="dir">${solr.ulog.dir:}</str>
+ <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
+ </updateLog>
+
+ <autoCommit>
+ <maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
+ <openSearcher>false</openSearcher>
+ </autoCommit>
+
+ <autoSoftCommit>
+ <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
+ </autoSoftCommit>
+
+ </updateHandler>
+
+ <query>
+ <filterCache class="solr.CaffeineCache"
+ size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+
+ <queryResultCache class="solr.CaffeineCache"
+ size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+
+ <documentCache class="solr.CaffeineCache"
+ size="512"
+ initialSize="512"
+ autowarmCount="0"/>
+
+ <cache name="perSegFilter"
+ class="solr.search.CaffeineCache"
+ size="10"
+ initialSize="0"
+ autowarmCount="10"
+ regenerator="solr.NoOpRegenerator" />
+
+ <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+ <queryResultWindowSize>20</queryResultWindowSize>
+
+ <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+ <useColdSearcher>false</useColdSearcher>
+
+ </query>
+
+ <requestDispatcher>
+ <httpCaching never304="true" />
+ </requestDispatcher>
+
+ <requestHandler name="/select" class="solr.SearchHandler">
+ <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>
+
+ <queryResponseWriter name="xml"
+ default="true"
+ class="solr.XMLResponseWriter" />
+</config>
diff --git a/roles/dovecot/vars/main.yml b/roles/dovecot/vars/main.yml
new file mode 100644
index 0000000..5069aa5
--- /dev/null
+++ b/roles/dovecot/vars/main.yml
@@ -0,0 +1,64 @@
+dovecot_packages:
+ - dovecot
+ - dovecot-pigeonhole
+
+dovecot_vmail_user: vmail
+dovecot_vmail_dir: /var/vmail
+
+dovecot_hbac_hostgroup: imap_servers
+dovecot_hbac_service: dovecot
+
+dovecot_certificate_path: /etc/pki/dovecot/certs/dovecot.pem
+dovecot_certificate_key_path: /etc/pki/dovecot/private/dovecot.key
+dovecot_dhparams_path: /etc/pki/dovecot/dhparams-dovecot.pem
+dovecot_ssl_cipher_list: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
+
+dovecot_quota_warning_script: /usr/local/bin/dovecot-quota-warning.sh
+dovecot_archive_script: /usr/local/bin/dovecot-archive.sh
+
+dovecot_keytab: /var/lib/gssproxy/clients/dovecot.keytab
+
+dovecot_sieve_dir: /etc/dovecot/sieve
+dovecot_sieve_before_dir: /etc/dovecot/sieve.before.d
+dovecot_sieve_pipe_bin_dir: /usr/lib/dovecot/sieve-pipe
+
+dovecot_solr_schema_path: /usr/share/doc/dovecot/solr-schema-7.7.0.xml
+dovecot_solr_config_path: /usr/share/doc/dovecot/solr-config-7.7.0.xml
+
+dovecot_selinux_policy_te: |
+ require {
+ type autofs_t;
+ type dovecot_t;
+ type dovecot_auth_t;
+ type dovecot_auth_exec_t;
+ type dovecot_deliver_exec_t;
+ type gssd_t;
+ type gssproxy_t;
+ type gssproxy_var_lib_t;
+ class dir search;
+ class sock_file write;
+ class unix_stream_socket connectto;
+ class process noatsecure;
+ class file { read execute open getattr execute_no_trans map };
+ class dir search;
+ class key { read write };
+ }
+
+ ### The following rules are needed for dovecot to access gssproxy:
+ #============= dovecot_auth_t ==============
+ allow dovecot_auth_t gssproxy_t:unix_stream_socket connectto;
+ allow dovecot_auth_t gssproxy_var_lib_t:dir search;
+ allow dovecot_auth_t gssproxy_var_lib_t:sock_file write;
+ allow dovecot_auth_t autofs_t:dir search;
+ allow dovecot_auth_t gssd_t:key { read write };
+
+ #============= dovecot_t ==============
+ allow dovecot_t dovecot_auth_t:process noatsecure;
+ allow dovecot_t dovecot_deliver_exec_t:file { read execute open getattr execute_no_trans };
+
+ #============= gssproxy_t ==============
+ allow gssproxy_t dovecot_auth_exec_t:file getattr;
+
+ ### The following rules are needed for the delivery process to exec quota warning scripts:
+ #============= dovecot_t ==============
+ allow dovecot_t dovecot_deliver_exec_t:file { read execute open getattr execute_no_trans map };