diff --git a/admin/freeposte/admin/forms.py b/admin/freeposte/admin/forms.py index 06d12a11..b6ad7414 100644 --- a/admin/freeposte/admin/forms.py +++ b/admin/freeposte/admin/forms.py @@ -42,11 +42,15 @@ class UserPasswordForm(Form): class UserForwardForm(Form): - forward = fields.StringField('Destination', [validators.Email()]) + forward_enabled = fields.BooleanField('Enable forwarding', default=False) + forward = fields.StringField( + 'Destination', [validators.Optional(), validators.Email()] + ) submit = fields.SubmitField('Update') class UserReplyForm(Form): + reply_enabled = fields.BooleanField('Enable reply', default=False) reply_subject = fields.StringField('Reply subject') reply_body = fields.StringField('Reply body', widget=widgets.TextArea()) submit = fields.SubmitField('Update') diff --git a/admin/freeposte/admin/templates/user/forward.html b/admin/freeposte/admin/templates/user/forward.html index 94f38ee7..efd0f672 100644 --- a/admin/freeposte/admin/templates/user/forward.html +++ b/admin/freeposte/admin/templates/user/forward.html @@ -1,4 +1,4 @@ -{% extends "form.html" %} +{% extends "base.html" %} {% block title %} Forward emails @@ -7,3 +7,16 @@ Forward emails {% block subtitle %} {{ user }} {% endblock %} + +{% block box_content %} +
+ {{ form.hidden_tag() }} + {{ macros.form_field(form.forward_enabled, + onchange="if(this.checked){$('#forward').removeAttr('disabled')} + else{$('#forward').attr('disabled', '').val('')}", + **{("checked" if user.forward else "unchecked"): ""}) }} + {{ macros.form_field(form.forward, + **{("enabled" if user.forward else "disabled"): ""}) }} + {{ macros.form_field(form.submit) }} +
+{% endblock %} diff --git a/admin/freeposte/admin/templates/user/reply.html b/admin/freeposte/admin/templates/user/reply.html index 50864129..4a0a6153 100644 --- a/admin/freeposte/admin/templates/user/reply.html +++ b/admin/freeposte/admin/templates/user/reply.html @@ -1,4 +1,4 @@ -{% extends "form.html" %} +{% extends "base.html" %} {% block title %} Automatic reply @@ -7,3 +7,18 @@ Automatic reply {% block subtitle %} {{ user }} {% endblock %} + +{% block box_content %} +
+ {{ form.hidden_tag() }} + {{ macros.form_field(form.reply_enabled, + onchange="if(this.checked){$('#reply_subject,#reply_body').removeAttr('disabled')} + else{$('#reply_subject,#reply_body').attr('disabled', '').val('')}", + **{("checked" if user.forward else "unchecked"): ""}) }} + {{ macros.form_field(form.reply_subject, + **{("enabled" if user.reply_subject else "disabled"): ""}) }} + {{ macros.form_field(form.reply_body, rows=10, + **{("enabled" if user.reply_subject else "disabled"): ""}) }} + {{ macros.form_field(form.submit) }} +
+{% endblock %} diff --git a/admin/freeposte/admin/views/users.py b/admin/freeposte/admin/views/users.py index 048bc93a..2511e9a2 100644 --- a/admin/freeposte/admin/views/users.py +++ b/admin/freeposte/admin/views/users.py @@ -120,7 +120,10 @@ def user_forward(user_email): user = utils.get_user(user_email) form = forms.UserForwardForm(obj=user) if form.validate_on_submit(): - user.forward = form.forward.data + if form.forward_enabled: + user.forward = form.forward.data + else: + user.forward = None db.session.add(user) db.session.commit() flask.flash('Forward destination updated for %s' % user) diff --git a/dovecot/Dockerfile b/dovecot/Dockerfile index 5884c1eb..88a1d903 100644 --- a/dovecot/Dockerfile +++ b/dovecot/Dockerfile @@ -9,6 +9,9 @@ RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/re dovecot-antispam-plugin@testing \ && rm -rf /var/cache/apk/* +COPY dovecot-pigeonhole-plugin-extdata-1-r0.apk / +RUN apk add --allow-untrusted --force dovecot-pigeonhole-plugin-extdata-1-r0.apk + COPY conf /etc/dovecot COPY sieve /var/lib/dovecot diff --git a/dovecot/conf/dovecot.conf b/dovecot/conf/dovecot.conf index ab3b4768..9e740549 100644 --- a/dovecot/conf/dovecot.conf +++ b/dovecot/conf/dovecot.conf @@ -15,6 +15,10 @@ service dict { } } +dict { + sieve = sqlite:/etc/dovecot/pigeonhole-sieve.dict +} + ############### # Mailboxes ############### @@ -137,7 +141,10 @@ service managesieve-login { plugin { sieve_dir = ~/sieve + sieve_plugins = sieve_extdata + sieve_extensions = +vnd.dovecot.extdata sieve_before = /var/lib/dovecot/before.sieve sieve_default = /var/lib/dovecot/default.sieve sieve_after = /var/lib/dovecot/after.sieve + sieve_extdata_dict_uri = proxy::sieve } diff --git a/dovecot/conf/pigeonhole-sieve.dict b/dovecot/conf/pigeonhole-sieve.dict new file mode 100644 index 00000000..62f5c410 --- /dev/null +++ b/dovecot/conf/pigeonhole-sieve.dict @@ -0,0 +1,22 @@ +connect = /data/freeposte.db + +map { + pattern = priv/reply_subject + table = user + username_field = address + value_field = reply_subject +} + +map { + pattern = priv/reply_body + table = user + username_field = address + value_field = reply_body +} + +map { + pattern = priv/forward + table = user + username_field = address + value_field = forward +} diff --git a/dovecot/dovecot-pigeonhole-plugin-extdata-1-r0.apk b/dovecot/dovecot-pigeonhole-plugin-extdata-1-r0.apk new file mode 100644 index 00000000..12ad1a86 Binary files /dev/null and b/dovecot/dovecot-pigeonhole-plugin-extdata-1-r0.apk differ diff --git a/dovecot/sieve/before.sieve b/dovecot/sieve/before.sieve index e69de29b..c8fbec4f 100644 --- a/dovecot/sieve/before.sieve +++ b/dovecot/sieve/before.sieve @@ -0,0 +1,14 @@ +require ["variables", "vacation", "vnd.dovecot.extdata"]; + +if string :is "${extdata.reply_subject}" "" { + +} else { + vacation :days 1 :subject "${extdata.reply_subject}" "${extdata.reply_body}"; +} + +if string :is "${extdata.forward}" "" { + +} else { + redirect "${extdata.forward}"; + keep; +}