From 165d986561b110cc529695c675fb2f7b239770d0 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sun, 3 May 2020 15:56:45 +0200 Subject: [PATCH] add mailboxes to GET /api/v2/aliases --- README.md | 40 ++++++++++++++-------------------------- app/api/serializer.py | 37 ++++++++++++++++++++++++++++++++++--- app/api/views/alias.py | 4 +++- tests/api/test_alias.py | 5 +++++ 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 1a362923..f2ec9b24 100644 --- a/README.md +++ b/README.md @@ -881,7 +881,10 @@ If success, 200 with the list of aliases. Each alias has the following fields: - nb_block - nb_forward - nb_reply -- mailbox +- mailbox: obsolete, should use `mailboxes` instead. + - id + - email +- mailboxes: list of mailbox, contains at least 1 mailbox. - id - email - (optional) latest_activity: @@ -908,6 +911,16 @@ Here's an example: "email": "a@b.c", "id": 1 }, + "mailboxes": [ + { + "email": "m1@cd.ef", + "id": 2 + }, + { + "email": "john@wick.com", + "id": 1 + } + ], "latest_activity": { "action": "forward", "contact": { @@ -921,31 +934,6 @@ Here's an example: "nb_forward": 1, "nb_reply": 0, "note": null - }, - { - "creation_date": "2020-04-06 17:57:14+00:00", - "creation_timestamp": 1586195834, - "email": "prefix0.hey@sl.local", - "name": null, - "enabled": true, - "id": 2, - "mailbox": { - "email": "a@b.c", - "id": 1 - }, - "latest_activity": { - "action": "forward", - "contact": { - "email": "c0@example.com", - "name": null, - "reverse_alias": "\"c0 at example.com\" " - }, - "timestamp": 1586195834 - }, - "nb_block": 0, - "nb_forward": 1, - "nb_reply": 0, - "note": null } ] } diff --git a/app/api/serializer.py b/app/api/serializer.py index 47ba265c..faa4c91e 100644 --- a/app/api/serializer.py +++ b/app/api/serializer.py @@ -13,6 +13,7 @@ from app.models import Alias, Contact, EmailLog, Mailbox class AliasInfo: alias: Alias mailbox: Mailbox + mailboxes: [Mailbox] nb_forward: int nb_blocked: int @@ -21,6 +22,9 @@ class AliasInfo: latest_email_log: EmailLog = None latest_contact: Contact = None + def contain_mailbox(self, mailbox_id: int) -> bool: + return mailbox_id in [m.id for m in self.mailboxes] + def serialize_alias_info(alias_info: AliasInfo) -> dict: return { @@ -54,6 +58,10 @@ def serialize_alias_info_v2(alias_info: AliasInfo) -> dict: "nb_reply": alias_info.nb_reply, # mailbox "mailbox": {"id": alias_info.mailbox.id, "email": alias_info.mailbox.email}, + "mailboxes": [ + {"id": mailbox.id, "email": mailbox.email} + for mailbox in alias_info.mailboxes + ], } if alias_info.latest_email_log: email_log = alias_info.latest_email_log @@ -158,7 +166,13 @@ def get_alias_infos_with_pagination_v2( q = q.group_by(Alias.id, Mailbox.id) - q = q.limit(PAGE_LIMIT).offset(page_id * PAGE_LIMIT) + q = list(q.limit(PAGE_LIMIT).offset(page_id * PAGE_LIMIT)) + + # preload alias.mailboxes to speed up + alias_ids = [alias.id for alias, _, _ in q] + Alias.query.options(joinedload(Alias._mailboxes)).filter( + Alias.id.in_(alias_ids) + ).all() for alias, mailbox, latest_activity in q: ret.append(get_alias_info_v2(alias, mailbox)) @@ -174,7 +188,12 @@ def get_alias_info(alias: Alias) -> AliasInfo: ) alias_info = AliasInfo( - alias=alias, nb_blocked=0, nb_forward=0, nb_reply=0, mailbox=alias.mailbox + alias=alias, + nb_blocked=0, + nb_forward=0, + nb_reply=0, + mailbox=alias.mailbox, + mailboxes=[alias.mailbox], ) for _, el in q: @@ -200,9 +219,21 @@ def get_alias_info_v2(alias: Alias, mailbox) -> AliasInfo: latest_contact = None alias_info = AliasInfo( - alias=alias, nb_blocked=0, nb_forward=0, nb_reply=0, mailbox=mailbox + alias=alias, + nb_blocked=0, + nb_forward=0, + nb_reply=0, + mailbox=mailbox, + mailboxes=[mailbox], ) + for m in alias._mailboxes: + alias_info.mailboxes.append(m) + + # remove duplicates + # can happen that alias.mailbox_id also appears in AliasMailbox table + alias_info.mailboxes = list(set(alias_info.mailboxes)) + for contact, email_log in q: if email_log.is_reply: alias_info.nb_reply += 1 diff --git a/app/api/views/alias.py b/app/api/views/alias.py index dae0e1a0..70e70655 100644 --- a/app/api/views/alias.py +++ b/app/api/views/alias.py @@ -20,7 +20,7 @@ from app.dashboard.views.alias_log import get_alias_log from app.email_utils import parseaddr_unicode from app.extensions import db from app.log import LOG -from app.models import Alias, Contact, Mailbox +from app.models import Alias, Contact, Mailbox, AliasMailbox from app.utils import random_string @@ -85,6 +85,8 @@ def get_aliases_v2(): - nb_block - nb_reply - note + - mailbox + - mailboxes - (optional) latest_activity: - timestamp - action: forward|reply|block|bounced diff --git a/tests/api/test_alias.py b/tests/api/test_alias.py index 0df13a5b..7ab13556 100644 --- a/tests/api/test_alias.py +++ b/tests/api/test_alias.py @@ -184,6 +184,11 @@ def test_get_aliases_v2(flask_client): assert "id" in r0["mailbox"] assert "email" in r0["mailbox"] + assert r0["mailboxes"] + for mailbox in r0["mailboxes"]: + assert "id" in mailbox + assert "email" in mailbox + def test_delete_alias(flask_client): user = User.create(