From bdb14d5b5fff9c53ea2684a8180f7a9e55dcc8f3 Mon Sep 17 00:00:00 2001 From: "Jannis M. Hoffmann" Date: Thu, 5 Dec 2024 21:51:33 +0100 Subject: allow rendering of an attachment for multipart/alternative --- deploy.yml | 34 ++++++++++++++++++++++ depoly.yml | 35 ----------------------- src/jwebmail/read_mails.py | 2 +- src/jwebmail/render_mail.py | 69 +++++++++++++++++++++++++-------------------- 4 files changed, 74 insertions(+), 66 deletions(-) create mode 100644 deploy.yml delete mode 100644 depoly.yml diff --git a/deploy.yml b/deploy.yml new file mode 100644 index 0000000..2ecdad5 --- /dev/null +++ b/deploy.yml @@ -0,0 +1,34 @@ +- name: Depoly jwebmail + hosts: myhosts + + vars: + wheels: "{{ lookup('ansible.builtin.fileglob', 'dist/*.whl', wantlist=True)|map('basename') }}" + latest_version: "{{ wheels|map('split', '-')|map(attribute=1)|community.general.version_sort|last }}" + + tasks: + - name: Info + ansible.builtin.debug: + var: latest_version + - name: Copy + ansible.builtin.copy: + src: "dist/jwebmail-{{ latest_version }}-py3-none-any.whl" + dest: "jwebmail-{{ latest_version }}-py3-none-any.whl" + register: new_version + - name: Update + ansible.builtin.pip: + name: + - "file:///home/{{ ansible_facts.user_id }}/jwebmail-{{ latest_version }}-py3-none-any.whl" + virtualenv: "/usr/local/jwebmail" + become: true + - name: Extract + ansible.builtin.copy: + src: "script/extract-release" + dest: "/usr/local/bin/jwebmail-extract" + mode: "0755" + become: true + - name: Restart + ansible.builtin.systemd_service: + name: jwebmail + state: restarted + become: true + when: new_version is changed diff --git a/depoly.yml b/depoly.yml deleted file mode 100644 index 369ba6d..0000000 --- a/depoly.yml +++ /dev/null @@ -1,35 +0,0 @@ -- name: Depoly jwebmail - hosts: myhosts - - vars: - wheels: "{{ lookup('ansible.builtin.fileglob', 'dist/*.whl', wantlist=True)|map('basename') }}" - latest_version: "{{ wheels|map('split', '-')|map(attribute=1)|community.general.version_sort|last }}" - - tasks: - - name: Info - ansible.builtin.debug: - var: latest_version - - name: Copy - ansible.builtin.copy: - src: "dist/jwebmail-{{ latest_version }}-py3-none-any.whl" - dest: "jwebmail-{{ latest_version }}-py3-none-any.whl" - register: new_version - - name: Update - ansible.builtin.pip: - name: - - "file:///home/{{ ansible_facts.user_id }}/jwebmail-{{ latest_version }}-py3-none-any.whl" - - "toml" - virtualenv: "/usr/local/jwebmail" - become: true - - name: Extract - ansible.builtin.copy: - src: "script/extract-release" - dest: "/usr/local/bin/jwebmail-extract" - mode: "0755" - become: true - - name: Restart - ansible.builtin.systemd_service: - name: jwebmail - state: restarted - become: true - when: new_version is changed diff --git a/src/jwebmail/read_mails.py b/src/jwebmail/read_mails.py index f0f37c6..4e2b0c7 100644 --- a/src/jwebmail/read_mails.py +++ b/src/jwebmail/read_mails.py @@ -164,7 +164,7 @@ def _build_qma(username, password): def login(username, password): try: - qma = _build_qma(username, password).open() + _build_qma(username, password).open() except QMAuthError as err: if err.rc == 1: return False diff --git a/src/jwebmail/render_mail.py b/src/jwebmail/render_mail.py index f76c40a..3f72d19 100644 --- a/src/jwebmail/render_mail.py +++ b/src/jwebmail/render_mail.py @@ -40,18 +40,20 @@ def render_multipart_alternative(_subtype, content, path): T += f"
  • {to_mime_type(init['head'])}
  • " C += "
    \n" - C += mime_render( - *to_mime_types(init["head"]), init["body"], path + (len(parts) - 1,) - ) + if init["head"].get("content_disposition", "").lower() == "attachment": + C += _as_download(init, path + (len(parts) - 1,)) + else: + C += mime_render(init["head"], init.get("body"), path + (len(parts) - 1,)) C += "
    \n" for i, r in enumerate(rest, 1): T += f"
  • {to_mime_type(r['head'])}
  • \n" C += '\n" C += "" @@ -70,24 +72,9 @@ def render_multipart(_subtype, content, path): or p["head"]["content_disposition"].lower() == "none" or p["head"]["content_disposition"].lower() == "inline" ): - R += mime_render(*to_mime_types(p["head"]), p["body"], path + (i,)) + R += mime_render(p["head"], p["body"], path + (i,)) elif p["head"]["content_disposition"].lower() == "attachment": - link_text = gettext("Attachment {filename} of type {filetype}").format( - filename=p["head"]["filename"], filetype=to_mime_type(p["head"]) - ) - - ref_url = url_for( - "read", - folder=request.view_args.get("folder"), - msgid=request.view_args["msgid"], - path=".".join(map(str, [*path, i])), - format="raw", - ) - - R += "

    " - R += f'\n' - R += f"{escape(link_text)}\n" - R += "

    \n" + R += _as_download(p, [*path, i]) else: current_app.log.warning( "unknown Content-Disposition %s", p["head"]["content_disposition"] @@ -99,6 +86,26 @@ def render_multipart(_subtype, content, path): return R + "\n" +def _as_download(part, path): + link_text = gettext("Attachment {filename} of type {filetype}").format( + filename=part["head"]["filename"], filetype=to_mime_type(part["head"]) + ) + + ref_url = url_for( + "read", + folder=request.view_args.get("folder"), + msgid=request.view_args["msgid"], + path=".".join(map(str, path)), + format="raw", + ) + + R = "

    " + R += f'\n' + R += f"{escape(link_text)}\n" + R += "

    \n" + return R + + def _format_header(category, value): R = "" @@ -135,7 +142,7 @@ def render_message(subtype, msg, path): R += f"
    {to_mime_type(msg['head']['mime'])}
    \n" R += "\n" - R += mime_render(*to_mime_types(msg["head"]["mime"]), msg["body"], path + (0,)) + R += mime_render(msg["head"]["mime"], msg["body"], path + (0,)) return R + "\n" @@ -150,7 +157,9 @@ MIMERenderSubs = { } -def mime_render(maintype, subtype, content, path): +def mime_render(mime_header, content, path): + maintype = escape(mime_header["content_maintype"]) + subtype = escape(mime_header["content_subtype"]) renderer = MIMERenderSubs.get((maintype, subtype)) or MIMERenderSubs.get(maintype) if not renderer: @@ -165,9 +174,9 @@ def to_mime_type(mime): return escape(f"{mime['content_maintype']}/{mime['content_subtype']}".lower()) -def to_mime_types(mime): - return escape(mime["content_maintype"]), escape(mime["content_subtype"]) - - def format_mail(mail): - return Markup(mime_render("message", "rfc822", mail, tuple())) + return Markup( + mime_render( + {"content_maintype": "message", "content_subtype": "rfc822"}, mail, tuple() + ) + ) -- cgit v1.2.3