From 08a9ab9a56c81072fd47680bb8b2e889443fe028 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 13 Nov 2022 17:15:50 +0100 Subject: [PATCH 1/9] Improve fetchmail --- core/admin/mailu/internal/views/fetch.py | 2 ++ core/admin/mailu/models.py | 2 ++ core/admin/mailu/ui/forms.py | 15 ++++++-- .../mailu/ui/templates/fetch/create.html | 2 ++ core/admin/mailu/ui/templates/fetch/list.html | 4 +++ core/admin/mailu/ui/views/fetches.py | 4 +++ .../migrations/versions/f4f0f89e0047_.py | 25 ++++++++++++++ optional/fetchmail/fetchmail.py | 34 ++++++++++++++++--- setup/flavors/compose/docker-compose.yml | 5 ++- towncrier/newsfragments/1231.bugfix | 1 + towncrier/newsfragments/2246.bugfix | 1 + towncrier/newsfragments/711.feature | 1 + 12 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 core/admin/migrations/versions/f4f0f89e0047_.py create mode 100644 towncrier/newsfragments/1231.bugfix create mode 100644 towncrier/newsfragments/2246.bugfix create mode 100644 towncrier/newsfragments/711.feature diff --git a/core/admin/mailu/internal/views/fetch.py b/core/admin/mailu/internal/views/fetch.py index 1945b9c7..e813c33b 100644 --- a/core/admin/mailu/internal/views/fetch.py +++ b/core/admin/mailu/internal/views/fetch.py @@ -12,10 +12,12 @@ def fetch_list(): "id": fetch.id, "tls": fetch.tls, "keep": fetch.keep, + "scan": fetch.scan, "user_email": fetch.user_email, "protocol": fetch.protocol, "host": fetch.host, "port": fetch.port, + "folders": fetch.folders, "username": fetch.username, "password": fetch.password } for fetch in models.Fetch.query.all() diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 48ce8b33..4b048c45 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -771,6 +771,8 @@ class Fetch(Base): username = db.Column(db.String(255), nullable=False) password = db.Column(db.String(255), nullable=False) keep = db.Column(db.Boolean, nullable=False, default=False) + scan = db.Column(db.Boolean, nullable=False, default=False) + folders = db.Column(CommaSeparatedList, nullable=True, default=list) last_check = db.Column(db.DateTime, nullable=True) error = db.Column(db.String(1023), nullable=True) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index beb44092..f6d03fc2 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -41,6 +41,15 @@ class MultipleEmailAddressesVerify(object): if not pattern.match(field.data.replace(" ", "")): raise validators.ValidationError(self.message) +class MultipleFoldersVerify(object): + def __init__(self,message=_('Invalid list of folders.')): + self.message = message + + def __call__(self, form, field): + pattern = re.compile(r'^\w+(,\w+)*$') + if not pattern.match(field.data.replace(" ", "")): + raise validators.ValidationError(self.message) + class ConfirmationForm(flask_wtf.FlaskForm): submit = fields.SubmitField(_('Confirm')) @@ -164,11 +173,13 @@ class FetchForm(flask_wtf.FlaskForm): ('imap', 'IMAP'), ('pop3', 'POP3') ]) host = fields.StringField(_('Hostname or IP'), [validators.DataRequired()]) - port = fields.IntegerField(_('TCP port'), [validators.DataRequired(), validators.NumberRange(min=0, max=65535)]) - tls = fields.BooleanField(_('Enable TLS')) + port = fields.IntegerField(_('TCP port'), [validators.DataRequired(), validators.NumberRange(min=0, max=65535)], default=993) + tls = fields.BooleanField(_('Enable TLS'), default=True) username = fields.StringField(_('Username'), [validators.DataRequired()]) password = fields.PasswordField(_('Password')) keep = fields.BooleanField(_('Keep emails on the server')) + scan = fields.BooleanField(_('Rescan emails locally')) + folders = fields.StringField(_('Folders to fetch on the server'), [validators.Optional(), MultipleFoldersVerify()], default='INBOX,Junk') submit = fields.SubmitField(_('Submit')) diff --git a/core/admin/mailu/ui/templates/fetch/create.html b/core/admin/mailu/ui/templates/fetch/create.html index 00698329..69584d15 100644 --- a/core/admin/mailu/ui/templates/fetch/create.html +++ b/core/admin/mailu/ui/templates/fetch/create.html @@ -24,6 +24,8 @@ {%- call macros.card(title="Settings") %} {{ macros.form_field(form.keep) }} + {{ macros.form_field(form.scan) }} + {{ macros.form_field(form.folders) }} {%- endcall %} {{ macros.form_field(form.submit) }} diff --git a/core/admin/mailu/ui/templates/fetch/list.html b/core/admin/mailu/ui/templates/fetch/list.html index 7a527ce8..63968e96 100644 --- a/core/admin/mailu/ui/templates/fetch/list.html +++ b/core/admin/mailu/ui/templates/fetch/list.html @@ -20,6 +20,8 @@ {% trans %}Endpoint{% endtrans %} {% trans %}Username{% endtrans %} {% trans %}Keep emails{% endtrans %} + {% trans %}Rescan emails{% endtrans %} + {% trans %}Folders{% endtrans %} {% trans %}Last check{% endtrans %} {% trans %}Status{% endtrans %} {% trans %}Created{% endtrans %} @@ -36,6 +38,8 @@ {{ fetch.protocol }}{{ 's' if fetch.tls else '' }}://{{ fetch.host }}:{{ fetch.port }} {{ fetch.username }} {% if fetch.keep %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %} + {% if fetch.scan %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %} + {% for folder in fetch.folders %}{{ folder }},{% endfor %} {{ fetch.last_check | format_datetime or '-' }} {{ fetch.error or '-' }} {{ fetch.created_at | format_date }} diff --git a/core/admin/mailu/ui/views/fetches.py b/core/admin/mailu/ui/views/fetches.py index ec208af1..3c03a351 100644 --- a/core/admin/mailu/ui/views/fetches.py +++ b/core/admin/mailu/ui/views/fetches.py @@ -26,6 +26,8 @@ def fetch_create(user_email): if form.validate_on_submit(): fetch = models.Fetch(user=user) form.populate_obj(fetch) + if form.folders.data: + fetch.folders = form.folders.data.replace(' ','').split(',') models.db.session.add(fetch) models.db.session.commit() flask.flash('Fetch configuration created') @@ -43,6 +45,8 @@ def fetch_edit(fetch_id): if not form.password.data: form.password.data = fetch.password form.populate_obj(fetch) + if form.folders.data: + fetch.folders = form.folders.data.replace(' ','').split(',') models.db.session.commit() flask.flash('Fetch configuration updated') return flask.redirect( diff --git a/core/admin/migrations/versions/f4f0f89e0047_.py b/core/admin/migrations/versions/f4f0f89e0047_.py new file mode 100644 index 00000000..5843e9d2 --- /dev/null +++ b/core/admin/migrations/versions/f4f0f89e0047_.py @@ -0,0 +1,25 @@ +"""empty message + +Revision ID: f4f0f89e0047 +Revises: 8f9ea78776f4 +Create Date: 2022-11-13 16:29:01.246509 + +""" + +# revision identifiers, used by Alembic. +revision = 'f4f0f89e0047' +down_revision = '8f9ea78776f4' + +from alembic import op +import sqlalchemy as sa +import mailu + +def upgrade(): + with op.batch_alter_table('fetch') as batch: + batch.add_column(sa.Column('scan', sa.Boolean(), nullable=False, server_default=sa.sql.expression.false())) + batch.add_column(sa.Column('folders', mailu.models.CommaSeparatedList(), nullable=True)) + +def downgrade(): + with op.batch_alter_table('fetch') as batch: + batch.drop_column('fetch', 'folders') + batch.drop_column('fetch', 'scan') diff --git a/optional/fetchmail/fetchmail.py b/optional/fetchmail/fetchmail.py index 32751ed7..9dc4a14c 100755 --- a/optional/fetchmail/fetchmail.py +++ b/optional/fetchmail/fetchmail.py @@ -2,11 +2,14 @@ import time import os +from pathlib import Path +from pwd import getpwnam import tempfile import shlex import subprocess import re import requests +from socrate import system import sys import traceback @@ -14,6 +17,7 @@ import traceback FETCHMAIL = """ fetchmail -N \ --idfile /data/fetchids --uidl \ + --pidfile /dev/shm/fetchmail.pid \ --sslcertck --sslcertpath /etc/ssl/certs \ -f {} """ @@ -24,7 +28,9 @@ poll "{host}" proto {protocol} port {port} user "{username}" password "{password}" is "{user_email}" smtphost "{smtphost}" + {folders} {options} + {lmtp} """ @@ -48,26 +54,37 @@ def fetchmail(fetchmailrc): def run(debug): try: - fetches = requests.get("http://" + os.environ.get("HOST_ADMIN", "admin") + "/internal/fetch").json() - smtphost, smtpport = extract_host_port(os.environ.get("HOST_SMTP", "smtp"), None) + os.environ["SMTP_ADDRESS"] = system.get_host_address_from_environment("SMTP", "smtp") + os.environ["ADMIN_ADDRESS"] = system.get_host_address_from_environment("ADMIN", "admin") + fetches = requests.get(f"http://{os.environ['ADMIN_ADDRESS']}/internal/fetch").json() + smtphost, smtpport = extract_host_port(os.environ["SMTP_ADDRESS"], None) if smtpport is None: smtphostport = smtphost else: smtphostport = "%s/%d" % (smtphost, smtpport) + os.environ["LMTP_ADDRESS"] = system.get_host_address_from_environment("LMTP", "imap:2525") + lmtphost, lmtpport = extract_host_port(os.environ["LMTP_ADDRESS"], None) + if lmtpport is None: + lmtphostport = lmtphost + else: + lmtphostport = "%s/%d" % (lmtphost, lmtpport) for fetch in fetches: fetchmailrc = "" options = "options antispam 501, 504, 550, 553, 554" options += " ssl" if fetch["tls"] else "" options += " keep" if fetch["keep"] else " fetchall" + folders = "folders %s" % ((','.join('"' + item + '"' for item in fetch['folders'])) if fetch['folders'] else '"INBOX"') fetchmailrc += RC_LINE.format( user_email=escape_rc_string(fetch["user_email"]), protocol=fetch["protocol"], host=escape_rc_string(fetch["host"]), port=fetch["port"], - smtphost=smtphostport, + smtphost=smtphostport if fetch['scan'] else lmtphostport, username=escape_rc_string(fetch["username"]), password=escape_rc_string(fetch["password"]), - options=options + options=options, + folders=folders, + lmtp='' if fetch['scan'] else 'lmtp', ) if debug: print(fetchmailrc) @@ -86,7 +103,7 @@ def run(debug): user_info in error_message): print(error_message) finally: - requests.post("http://" + os.environ.get("HOST_ADMIN", "admin") + "/internal/fetch/{}".format(fetch["id"]), + requests.post("http://" + os.environ["ADMIN_ADDRESS"] + "/internal/fetch/{}".format(fetch["id"]), json=error_message.split("\n")[0] ) except Exception: @@ -94,6 +111,13 @@ def run(debug): if __name__ == "__main__": + id_fetchmail = getpwnam('fetchmail') + Path('/data/fetchids').touch() + os.chown("/data/fetchids", id_fetchmail.pw_uid, id_fetchmail.pw_gid) + os.chown("/data/", id_fetchmail.pw_uid, id_fetchmail.pw_gid) + os.chmod("/data/fetchids", 0o700) + os.setgid(id_fetchmail.pw_gid) + os.setuid(id_fetchmail.pw_uid) while True: time.sleep(int(os.environ.get("FETCHMAIL_DELAY", 60))) run(os.environ.get("DEBUG", None) == "True") diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 6dac166b..11596729 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -157,8 +157,11 @@ services: env_file: {{ env }} volumes: - "{{ root }}/data/fetchmail:/data" - {% if resolver_enabled %} depends_on: + - admin + - smtp + - imap + {% if resolver_enabled %} - resolver dns: - {{ dns }} diff --git a/towncrier/newsfragments/1231.bugfix b/towncrier/newsfragments/1231.bugfix new file mode 100644 index 00000000..333ae35f --- /dev/null +++ b/towncrier/newsfragments/1231.bugfix @@ -0,0 +1 @@ +Add an option so that emails fetched with fetchmail don't go through the filters (closes #1231) diff --git a/towncrier/newsfragments/2246.bugfix b/towncrier/newsfragments/2246.bugfix new file mode 100644 index 00000000..92e90ac6 --- /dev/null +++ b/towncrier/newsfragments/2246.bugfix @@ -0,0 +1 @@ +Fetchmail: Missing support for '*_ADDRESS' env vars diff --git a/towncrier/newsfragments/711.feature b/towncrier/newsfragments/711.feature new file mode 100644 index 00000000..aa605aa2 --- /dev/null +++ b/towncrier/newsfragments/711.feature @@ -0,0 +1 @@ +Allow other folders to be synced by fetchmail From 9c7dfbeb24efc14c8fb7d21a1cd4dce241d42ecd Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 13:43:42 +0100 Subject: [PATCH 2/9] Doc --- docs/webadministration.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/webadministration.rst b/docs/webadministration.rst index e17d12f0..247b66a7 100644 --- a/docs/webadministration.rst +++ b/docs/webadministration.rst @@ -157,7 +157,11 @@ You can add a fetched account by clicking on the `Add an account` button on the * Keep emails on the server. When ticked, retains the email message in the email account after retrieving it. -Click the submit button to apply settings. With the default polling interval, fetchmail will start polling the email account after 10 minutes. +* Scan emails. When ticked, all the fetched emails will go through the local filters (rspamd, clamav, ...). + +* Folders. A comma separated list of folders to fetch from the server. + +Click the submit button to apply settings. With the default polling interval, fetchmail will start polling the email account after ``FETCHMAIL_DELAY``. Authentication tokens From c0c91691fd6364e6f4e82cf9c36a61f65c4eed06 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 16:24:09 +0100 Subject: [PATCH 3/9] Fix the issue on /admin/fetch/edit --- core/admin/mailu/ui/templates/fetch/create.html | 2 ++ core/admin/mailu/ui/templates/fetch/edit.html | 12 ++++++++++++ core/admin/run_dev.sh | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/admin/mailu/ui/templates/fetch/create.html b/core/admin/mailu/ui/templates/fetch/create.html index 69584d15..a48c1a48 100644 --- a/core/admin/mailu/ui/templates/fetch/create.html +++ b/core/admin/mailu/ui/templates/fetch/create.html @@ -25,7 +25,9 @@ {%- call macros.card(title="Settings") %} {{ macros.form_field(form.keep) }} {{ macros.form_field(form.scan) }} +{%- block folders %} {{ macros.form_field(form.folders) }} +{%- endblock %} {%- endcall %} {{ macros.form_field(form.submit) }} diff --git a/core/admin/mailu/ui/templates/fetch/edit.html b/core/admin/mailu/ui/templates/fetch/edit.html index 62af51a9..c7ff5a87 100644 --- a/core/admin/mailu/ui/templates/fetch/edit.html +++ b/core/admin/mailu/ui/templates/fetch/edit.html @@ -7,3 +7,15 @@ {%- block subtitle %} {{ user }} {%- endblock %} + +{%- block folders %} +
+
+
+ + + +
+
+
+{%- endblock %} diff --git a/core/admin/run_dev.sh b/core/admin/run_dev.sh index 4ab76e74..c12bb9ee 100755 --- a/core/admin/run_dev.sh +++ b/core/admin/run_dev.sh @@ -48,7 +48,7 @@ sed -E '/^#/d;s:^FROM system$:FROM system AS base:' "${base}/Dockerfile" >Docker # assets cp "${assets}/package.json" . -cp -r "${assets}/assets/" . +cp -r "${assets}/assets" ./assets awk '/new compress/{f=1}!f{print}/}),/{f=0}' <"${assets}/webpack.config.js" >webpack.config.js sed -E '/^#/d;s:^(FROM [^ ]+$):\1 AS assets:' "${assets}/Dockerfile" >>Dockerfile @@ -65,7 +65,7 @@ RUN set -euxo pipefail \ ; ln -s /app/start.py / ENV \ - FLASK_ENV="development" \ + FLASK_DEBUG="true" \ MEMORY_SESSIONS="true" \ RATELIMIT_STORAGE_URL="memory://" \ SESSION_COOKIE_SECURE="false" \ @@ -82,7 +82,7 @@ ENV \ REDIS_ADDRESS="127.0.0.1" \ WEBMAIL_ADDRESS="127.0.0.1" -CMD ["/bin/bash", "-c", "flask db upgrade &>/dev/null && flask mailu admin '${DEV_ADMIN/@*}' '${DEV_ADMIN#*@}' '${DEV_PASSWORD}' --mode ifmissing >/dev/null && flask run --host=0.0.0.0 --port=8080"] +CMD ["/bin/bash", "-c", "flask db upgrade &>/dev/null && flask mailu admin '${DEV_ADMIN/@*}' '${DEV_ADMIN#*@}' '${DEV_PASSWORD}' --mode ifmissing >/dev/null; flask run --debugger --host=0.0.0.0 --port=8080"] EOF # build From 647410805692ae538f8a63e848ebffa6001711cd Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 16:36:37 +0100 Subject: [PATCH 4/9] Use a join() instead --- core/admin/mailu/ui/templates/fetch/list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/ui/templates/fetch/list.html b/core/admin/mailu/ui/templates/fetch/list.html index 63968e96..e502d96a 100644 --- a/core/admin/mailu/ui/templates/fetch/list.html +++ b/core/admin/mailu/ui/templates/fetch/list.html @@ -39,7 +39,7 @@ {{ fetch.username }} {% if fetch.keep %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %} {% if fetch.scan %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %} - {% for folder in fetch.folders %}{{ folder }},{% endfor %} + {{ fetch.folders.data | join(',') }} {{ fetch.last_check | format_datetime or '-' }} {{ fetch.error or '-' }} {{ fetch.created_at | format_date }} From 385b6ac85d3fcdee97d5743c4e5da8b6c0c9f728 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 16:47:43 +0100 Subject: [PATCH 5/9] Use string formatting --- optional/fetchmail/fetchmail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/optional/fetchmail/fetchmail.py b/optional/fetchmail/fetchmail.py index 9dc4a14c..137a061a 100755 --- a/optional/fetchmail/fetchmail.py +++ b/optional/fetchmail/fetchmail.py @@ -103,8 +103,8 @@ def run(debug): user_info in error_message): print(error_message) finally: - requests.post("http://" + os.environ["ADMIN_ADDRESS"] + "/internal/fetch/{}".format(fetch["id"]), - json=error_message.split("\n")[0] + requests.post("http://{}/internal/fetch/{}".format(os.environ['ADMIN_ADDRESS'],fetch['id']), + json=error_message.split('\n')[0] ) except Exception: traceback.print_exc() From 19af2944d7ac2c660a2b1aabcc35dd63464443cb Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 19:05:41 +0100 Subject: [PATCH 6/9] Refactor as requested --- core/admin/mailu/ui/forms.py | 2 +- core/admin/mailu/ui/templates/fetch/create.html | 2 -- core/admin/mailu/ui/templates/fetch/edit.html | 12 ------------ core/admin/mailu/ui/views/fetches.py | 4 +++- core/admin/mailu/ui/views/users.py | 6 +----- core/admin/mailu/utils.py | 7 +++++++ 6 files changed, 12 insertions(+), 21 deletions(-) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index f6d03fc2..fa81adc3 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -46,7 +46,7 @@ class MultipleFoldersVerify(object): self.message = message def __call__(self, form, field): - pattern = re.compile(r'^\w+(,\w+)*$') + pattern = re.compile(r'^\w+(\s*,\s*\w+)*$') if not pattern.match(field.data.replace(" ", "")): raise validators.ValidationError(self.message) diff --git a/core/admin/mailu/ui/templates/fetch/create.html b/core/admin/mailu/ui/templates/fetch/create.html index a48c1a48..69584d15 100644 --- a/core/admin/mailu/ui/templates/fetch/create.html +++ b/core/admin/mailu/ui/templates/fetch/create.html @@ -25,9 +25,7 @@ {%- call macros.card(title="Settings") %} {{ macros.form_field(form.keep) }} {{ macros.form_field(form.scan) }} -{%- block folders %} {{ macros.form_field(form.folders) }} -{%- endblock %} {%- endcall %} {{ macros.form_field(form.submit) }} diff --git a/core/admin/mailu/ui/templates/fetch/edit.html b/core/admin/mailu/ui/templates/fetch/edit.html index c7ff5a87..62af51a9 100644 --- a/core/admin/mailu/ui/templates/fetch/edit.html +++ b/core/admin/mailu/ui/templates/fetch/edit.html @@ -7,15 +7,3 @@ {%- block subtitle %} {{ user }} {%- endblock %} - -{%- block folders %} -
-
-
- - - -
-
-
-{%- endblock %} diff --git a/core/admin/mailu/ui/views/fetches.py b/core/admin/mailu/ui/views/fetches.py index 3c03a351..69018ba9 100644 --- a/core/admin/mailu/ui/views/fetches.py +++ b/core/admin/mailu/ui/views/fetches.py @@ -1,4 +1,4 @@ -from mailu import models +from mailu import models, utils from mailu.ui import ui, forms, access import flask @@ -23,6 +23,7 @@ def fetch_create(user_email): user = models.User.query.get(user_email) or flask.abort(404) form = forms.FetchForm() form.password.validators = [wtforms.validators.DataRequired()] + utils.formatCSVField(form.folders) if form.validate_on_submit(): fetch = models.Fetch(user=user) form.populate_obj(fetch) @@ -41,6 +42,7 @@ def fetch_create(user_email): def fetch_edit(fetch_id): fetch = models.Fetch.query.get(fetch_id) or flask.abort(404) form = forms.FetchForm(obj=fetch) + utils.formatCSVField(form.folders) if form.validate_on_submit(): if not form.password.data: form.password.data = fetch.password diff --git a/core/admin/mailu/ui/views/users.py b/core/admin/mailu/ui/views/users.py index 85a5c2db..b5e7304c 100644 --- a/core/admin/mailu/ui/views/users.py +++ b/core/admin/mailu/ui/views/users.py @@ -99,11 +99,7 @@ def user_settings(user_email): user_email_or_current = user_email or flask_login.current_user.email user = models.User.query.get(user_email_or_current) or flask.abort(404) form = forms.UserSettingsForm(obj=user) - if isinstance(form.forward_destination.data,str): - data = form.forward_destination.data.replace(" ","").split(",") - else: - data = form.forward_destination.data - form.forward_destination.data = ", ".join(data) + utils.formatCSVField(form.forward_destination) if form.validate_on_submit(): form.forward_destination.data = form.forward_destination.data.replace(" ","").split(",") form.populate_obj(user) diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index f160fe3f..b432192d 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -518,3 +518,10 @@ def isBadOrPwned(form): if breaches > 0: return f"This password appears in {breaches} data breaches! It is not unique; please change it." return None + +def formatCSVField(field): + if isinstance(field.data,str): + data = field.data.replace(" ","").split(",") + else: + data = field.data + field.data = ", ".join(data) From b9564c0bc9beab80e4a64f6f2871843bfa524db1 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 14 Nov 2022 19:37:04 +0100 Subject: [PATCH 7/9] This shouldn't have been commited --- core/admin/run_dev.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/run_dev.sh b/core/admin/run_dev.sh index c12bb9ee..dbe3368a 100755 --- a/core/admin/run_dev.sh +++ b/core/admin/run_dev.sh @@ -82,7 +82,7 @@ ENV \ REDIS_ADDRESS="127.0.0.1" \ WEBMAIL_ADDRESS="127.0.0.1" -CMD ["/bin/bash", "-c", "flask db upgrade &>/dev/null && flask mailu admin '${DEV_ADMIN/@*}' '${DEV_ADMIN#*@}' '${DEV_PASSWORD}' --mode ifmissing >/dev/null; flask run --debugger --host=0.0.0.0 --port=8080"] +CMD ["/bin/bash", "-c", "flask db upgrade &>/dev/null && flask mailu admin '${DEV_ADMIN/@*}' '${DEV_ADMIN#*@}' '${DEV_PASSWORD}' --mode ifmissing >/dev/null; flask --debug run --host=0.0.0.0 --port=8080"] EOF # build From 15b889fac812ce4da29d29b572b9f3bd39f56381 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 16 Nov 2022 14:17:56 +0100 Subject: [PATCH 8/9] Specify that this is optional --- docs/webadministration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/webadministration.rst b/docs/webadministration.rst index 247b66a7..fde4a271 100644 --- a/docs/webadministration.rst +++ b/docs/webadministration.rst @@ -159,7 +159,7 @@ You can add a fetched account by clicking on the `Add an account` button on the * Scan emails. When ticked, all the fetched emails will go through the local filters (rspamd, clamav, ...). -* Folders. A comma separated list of folders to fetch from the server. +* Folders. A comma separated list of folders to fetch from the server. This is optional, by default only the INBOX will be pulled. Click the submit button to apply settings. With the default polling interval, fetchmail will start polling the email account after ``FETCHMAIL_DELAY``. From f802601a08b6c2e399a4520a76ef8cb028238359 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 20 Nov 2022 15:00:04 +0100 Subject: [PATCH 9/9] Update f4f0f89e0047_.py --- core/admin/migrations/versions/f4f0f89e0047_.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/migrations/versions/f4f0f89e0047_.py b/core/admin/migrations/versions/f4f0f89e0047_.py index 5843e9d2..8d20063c 100644 --- a/core/admin/migrations/versions/f4f0f89e0047_.py +++ b/core/admin/migrations/versions/f4f0f89e0047_.py @@ -1,4 +1,4 @@ -"""empty message +""" Add fetch.scan and fetch.folders Revision ID: f4f0f89e0047 Revises: 8f9ea78776f4