From 722bff319e1b19a5427056b7bfb66e6237e79d1e Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:09:06 +0200 Subject: [PATCH 1/6] add POST /api/mailboxes: create a new mailbox --- README.md | 17 ++++++++++ app/api/__init__.py | 1 + app/api/views/mailbox.py | 58 ++++++++++++++++++++++++++++++++++ app/dashboard/views/mailbox.py | 48 ++++++++++++++-------------- tests/api/test_mailbox.py | 31 ++++++++++++++++++ 5 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 app/api/views/mailbox.py create mode 100644 tests/api/test_mailbox.py diff --git a/README.md b/README.md index 3d2a9707..a0520e13 100644 --- a/README.md +++ b/README.md @@ -1161,6 +1161,23 @@ List of mailboxes. Each mailbox has id, email field. } ``` +#### POST /api/mailboxes + +Create a new mailbox + +Input: +- `Authentication` header that contains the api key +- email: the new mailbox address + +Output: +- 201 along with the following response if new mailbox is created successfully. User is going to receive a verification email. + - id: integer + - email: the mailbox email address + - verified: boolean. + - default: whether is the default mailbox. User cannot delete the default mailbox +- 400 with error message otherwise. The error message can be displayed to user. + + ### Contact endpoints #### DELETE /api/contacts/:contact_id diff --git a/app/api/__init__.py b/app/api/__init__.py index a272e69c..71c76a3c 100644 --- a/app/api/__init__.py +++ b/app/api/__init__.py @@ -7,4 +7,5 @@ from .views import ( auth_mfa, alias, apple, + mailbox, ) diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py new file mode 100644 index 00000000..faa68604 --- /dev/null +++ b/app/api/views/mailbox.py @@ -0,0 +1,58 @@ +from flask import g +from flask import jsonify +from flask import request +from flask_cors import cross_origin + +from app.api.base import api_bp, require_api_auth +from app.dashboard.views.mailbox import send_verification_email +from app.email_utils import ( + mailbox_already_used, + email_domain_can_be_used_as_mailbox, +) +from app.extensions import db +from app.models import Mailbox + + +@api_bp.route("/mailboxes", methods=["POST"]) +@cross_origin() +@require_api_auth +def create_mailbox(): + """ + Create a new mailbox. User needs to verify the mailbox via an activation email. + Input: + email: in body + Output: + the new mailbox + - id + - email + - verified + + """ + user = g.user + mailbox_email = request.get_json().get("email").lower().strip() + + if mailbox_already_used(mailbox_email, user): + return jsonify(error=f"{mailbox_email} already used"), 400 + elif not email_domain_can_be_used_as_mailbox(mailbox_email): + return ( + jsonify( + error=f"{mailbox_email} cannot be used. Please note a mailbox cannot " + f"be a disposable email address" + ), + 400, + ) + else: + new_mailbox = Mailbox.create(email=mailbox_email, user_id=user.id) + db.session.commit() + + send_verification_email(user, new_mailbox) + + return ( + jsonify( + id=new_mailbox.id, + email=new_mailbox.email, + verified=new_mailbox.verified, + default=user.default_mailbox_id == new_mailbox.id, + ), + 201, + ) diff --git a/app/dashboard/views/mailbox.py b/app/dashboard/views/mailbox.py index 8f1a99eb..6b0da7e3 100644 --- a/app/dashboard/views/mailbox.py +++ b/app/dashboard/views/mailbox.py @@ -94,29 +94,7 @@ def mailbox_route(): ) db.session.commit() - s = Signer(MAILBOX_SECRET) - mailbox_id_signed = s.sign(str(new_mailbox.id)).decode() - verification_url = ( - URL - + "/dashboard/mailbox_verify" - + f"?mailbox_id={mailbox_id_signed}" - ) - send_email( - mailbox_email, - f"Please confirm your email {mailbox_email}", - render( - "transactional/verify-mailbox.txt", - user=current_user, - link=verification_url, - mailbox_email=mailbox_email, - ), - render( - "transactional/verify-mailbox.html", - user=current_user, - link=verification_url, - mailbox_email=mailbox_email, - ), - ) + send_verification_email(current_user, new_mailbox) flash( f"You are going to receive an email to confirm {mailbox_email}.", @@ -138,6 +116,30 @@ def mailbox_route(): ) +def send_verification_email(user, mailbox): + s = Signer(MAILBOX_SECRET) + mailbox_id_signed = s.sign(str(mailbox.id)).decode() + verification_url = ( + URL + "/dashboard/mailbox_verify" + f"?mailbox_id={mailbox_id_signed}" + ) + send_email( + mailbox.email, + f"Please confirm your email {mailbox.email}", + render( + "transactional/verify-mailbox.txt", + user=user, + link=verification_url, + mailbox_email=mailbox.email, + ), + render( + "transactional/verify-mailbox.html", + user=user, + link=verification_url, + mailbox_email=mailbox.email, + ), + ) + + @dashboard_bp.route("/mailbox_verify") def mailbox_verify(): s = Signer(MAILBOX_SECRET) diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py new file mode 100644 index 00000000..5751c65b --- /dev/null +++ b/tests/api/test_mailbox.py @@ -0,0 +1,31 @@ +from flask import url_for + +from flask import url_for + +from app.extensions import db +from app.models import User, ApiKey, Mailbox + + +def test_create_mailbox(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + r = flask_client.post( + url_for("api.create_mailbox"), + headers={"Authentication": api_key.code}, + json={"email": "mailbox@gmail.com"}, + ) + + assert r.status_code == 201 + assert r.json["email"] == "mailbox@gmail.com" + assert r.json["verified"] is False + assert r.json["id"] > 0 + assert r.json["default"] is False + + From 5ae39c85c66fed6773b0f94f6e8498e9509312f9 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:18:12 +0200 Subject: [PATCH 2/6] Add DELETE /api/mailboxes/:mailbox_id --- README.md | 12 ++++++++++++ app/api/views/mailbox.py | 27 +++++++++++++++++++++++++++ tests/api/test_mailbox.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/README.md b/README.md index a0520e13..60d2f958 100644 --- a/README.md +++ b/README.md @@ -1177,6 +1177,18 @@ Output: - default: whether is the default mailbox. User cannot delete the default mailbox - 400 with error message otherwise. The error message can be displayed to user. +#### DELETE /api/mailboxes/:mailbox_id + +Delete a mailbox. User cannot delete the default mailbox + +Input: +- `Authentication` header that contains the api key +- `mailbox_id`: in url + +Output: +- 200 if deleted successfully +- 400 if error + ### Contact endpoints diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py index faa68604..81d25828 100644 --- a/app/api/views/mailbox.py +++ b/app/api/views/mailbox.py @@ -56,3 +56,30 @@ def create_mailbox(): ), 201, ) + + +@api_bp.route("/mailboxes/", methods=["DELETE"]) +@cross_origin() +@require_api_auth +def delete_mailbox(mailbox_id): + """ + Delete mailbox + Input: + mailbox_id: in url + Output: + 200 if deleted successfully + + """ + user = g.user + mailbox = Mailbox.get(mailbox_id) + + if not mailbox or mailbox.user_id != user.id: + return jsonify(error="Forbidden"), 403 + + if mailbox.id == user.default_mailbox_id: + return jsonify(error="You cannot delete the default mailbox"), 400 + + Mailbox.delete(mailbox_id) + db.session.commit() + + return jsonify(deleted=True), 200 diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py index 5751c65b..06733092 100644 --- a/tests/api/test_mailbox.py +++ b/tests/api/test_mailbox.py @@ -29,3 +29,42 @@ def test_create_mailbox(flask_client): assert r.json["default"] is False +def test_delete_mailbox(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + # create a mailbox + mb = Mailbox.create(user_id=user.id, email="mb@gmail.com") + db.session.commit() + + r = flask_client.delete( + url_for("api.delete_mailbox", mailbox_id=mb.id), + headers={"Authentication": api_key.code}, + ) + + assert r.status_code == 200 + + +def test_delete_default_mailbox(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + # assert user cannot delete the default mailbox + r = flask_client.delete( + url_for("api.delete_mailbox", mailbox_id=user.default_mailbox_id), + headers={"Authentication": api_key.code}, + ) + + assert r.status_code == 400 From a76ad0485fe67d0ef33944009deb9c3cb1ff8eaf Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:26:26 +0200 Subject: [PATCH 3/6] PUT /api/mailboxes/:mailbox_id: update mailbox --- README.md | 13 +++++++++++++ app/api/views/mailbox.py | 33 +++++++++++++++++++++++++++++++++ tests/api/test_mailbox.py | 27 +++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/README.md b/README.md index 60d2f958..faf537fb 100644 --- a/README.md +++ b/README.md @@ -1189,6 +1189,19 @@ Output: - 200 if deleted successfully - 400 if error +#### PUT /api/mailboxes/:mailbox_id + +Update a mailbox. + +Input: +- `Authentication` header that contains the api key +- `mailbox_id`: in url +- (optional) `default`: boolean. Set a mailbox as default mailbox. + +Output: +- 200 if updated successfully +- 400 if error + ### Contact endpoints diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py index 81d25828..632f26c1 100644 --- a/app/api/views/mailbox.py +++ b/app/api/views/mailbox.py @@ -83,3 +83,36 @@ def delete_mailbox(mailbox_id): db.session.commit() return jsonify(deleted=True), 200 + + +@api_bp.route("/mailboxes/", methods=["PUT"]) +@cross_origin() +@require_api_auth +def update_mailbox(mailbox_id): + """ + Update mailbox + Input: + mailbox_id: in url + default (optional): in body + Output: + 200 if updated successfully + + """ + user = g.user + mailbox = Mailbox.get(mailbox_id) + + if not mailbox or mailbox.user_id != user.id: + return jsonify(error="Forbidden"), 403 + + data = request.get_json() or {} + changed = False + if "default" in data: + is_default = data.get("default") + if is_default: + user.default_mailbox_id = mailbox.id + changed = True + + if changed: + db.session.commit() + + return jsonify(deleted=True), 200 diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py index 06733092..802c1f03 100644 --- a/tests/api/test_mailbox.py +++ b/tests/api/test_mailbox.py @@ -68,3 +68,30 @@ def test_delete_default_mailbox(flask_client): ) assert r.status_code == 400 + + +def test_update_mailbox(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + # create a mailbox + mb = Mailbox.create(user_id=user.id, email="mb@gmail.com") + db.session.commit() + assert user.default_mailbox_id != mb.id + + r = flask_client.put( + url_for("api.delete_mailbox", mailbox_id=mb.id), + headers={"Authentication": api_key.code}, + json={"default": True}, + ) + + assert r.status_code == 200 + + mb = Mailbox.get(mb.id) + assert user.default_mailbox_id == mb.id From 2f087de0616fa7e072f313e82ca6cea86c956cad Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:40:28 +0200 Subject: [PATCH 4/6] can update mailbox email --- README.md | 1 + app/api/views/mailbox.py | 30 ++++++++++++++- app/dashboard/views/mailbox_detail.py | 54 ++++++++++++++------------- tests/api/test_mailbox.py | 28 +++++++++++++- 4 files changed, 84 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index faf537fb..9eae6fff 100644 --- a/README.md +++ b/README.md @@ -1197,6 +1197,7 @@ Input: - `Authentication` header that contains the api key - `mailbox_id`: in url - (optional) `default`: boolean. Set a mailbox as default mailbox. +- (optional) `email`: email address. Change a mailbox email address. Output: - 200 if updated successfully diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py index 632f26c1..40dc174a 100644 --- a/app/api/views/mailbox.py +++ b/app/api/views/mailbox.py @@ -1,3 +1,5 @@ +from smtplib import SMTPRecipientsRefused + from flask import g from flask import jsonify from flask import request @@ -5,6 +7,7 @@ from flask_cors import cross_origin from app.api.base import api_bp, require_api_auth from app.dashboard.views.mailbox import send_verification_email +from app.dashboard.views.mailbox_detail import verify_mailbox_change from app.email_utils import ( mailbox_already_used, email_domain_can_be_used_as_mailbox, @@ -93,7 +96,8 @@ def update_mailbox(mailbox_id): Update mailbox Input: mailbox_id: in url - default (optional): in body + (optional) default: in body. Set a mailbox as the default mailbox. + (optional) email: in body. Change a mailbox email. Output: 200 if updated successfully @@ -112,7 +116,29 @@ def update_mailbox(mailbox_id): user.default_mailbox_id = mailbox.id changed = True + if "email" in data: + new_email = data.get("email").lower().strip() + + if mailbox_already_used(new_email, user): + return jsonify(error=f"{new_email} already used"), 400 + elif not email_domain_can_be_used_as_mailbox(new_email): + return ( + jsonify( + error=f"{new_email} cannot be used. Please note a mailbox cannot " + f"be a disposable email address" + ), + 400, + ) + + try: + verify_mailbox_change(user, mailbox, new_email) + except SMTPRecipientsRefused: + return jsonify(error=f"Incorrect mailbox, please recheck {new_email}"), 400 + else: + mailbox.new_email = new_email + changed = True + if changed: db.session.commit() - return jsonify(deleted=True), 200 + return jsonify(updated=True), 200 diff --git a/app/dashboard/views/mailbox_detail.py b/app/dashboard/views/mailbox_detail.py index 53478a33..a3ec4781 100644 --- a/app/dashboard/views/mailbox_detail.py +++ b/app/dashboard/views/mailbox_detail.py @@ -60,33 +60,8 @@ def mailbox_detail_route(mailbox_id): mailbox.new_email = new_email db.session.commit() - s = Signer(MAILBOX_SECRET) - mailbox_id_signed = s.sign(str(mailbox.id)).decode() - verification_url = ( - URL - + "/dashboard/mailbox/confirm_change" - + f"?mailbox_id={mailbox_id_signed}" - ) - try: - send_email( - new_email, - f"Confirm mailbox change on SimpleLogin", - render( - "transactional/verify-mailbox-change.txt", - user=current_user, - link=verification_url, - mailbox_email=mailbox.email, - mailbox_new_email=new_email, - ), - render( - "transactional/verify-mailbox-change.html", - user=current_user, - link=verification_url, - mailbox_email=mailbox.email, - mailbox_new_email=new_email, - ), - ) + verify_mailbox_change(current_user, mailbox, new_email) except SMTPRecipientsRefused: flash( f"Incorrect mailbox, please recheck {mailbox.email}", @@ -151,6 +126,33 @@ def mailbox_detail_route(mailbox_id): return render_template("dashboard/mailbox_detail.html", **locals()) +def verify_mailbox_change(user, mailbox, new_email): + s = Signer(MAILBOX_SECRET) + mailbox_id_signed = s.sign(str(mailbox.id)).decode() + verification_url = ( + URL + "/dashboard/mailbox/confirm_change" + f"?mailbox_id={mailbox_id_signed}" + ) + + send_email( + new_email, + f"Confirm mailbox change on SimpleLogin", + render( + "transactional/verify-mailbox-change.txt", + user=user, + link=verification_url, + mailbox_email=mailbox.email, + mailbox_new_email=new_email, + ), + render( + "transactional/verify-mailbox-change.html", + user=user, + link=verification_url, + mailbox_email=mailbox.email, + mailbox_new_email=new_email, + ), + ) + + @dashboard_bp.route( "/mailbox//cancel_email_change", methods=["GET", "POST"] ) diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py index 802c1f03..a4bc9910 100644 --- a/tests/api/test_mailbox.py +++ b/tests/api/test_mailbox.py @@ -70,7 +70,7 @@ def test_delete_default_mailbox(flask_client): assert r.status_code == 400 -def test_update_mailbox(flask_client): +def test_set_mailbox_as_default(flask_client): user = User.create( email="a@b.c", password="password", name="Test User", activated=True ) @@ -95,3 +95,29 @@ def test_update_mailbox(flask_client): mb = Mailbox.get(mb.id) assert user.default_mailbox_id == mb.id + + +def test_update_mailbox_email(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + # create a mailbox + mb = Mailbox.create(user_id=user.id, email="mb@gmail.com") + db.session.commit() + + r = flask_client.put( + url_for("api.delete_mailbox", mailbox_id=mb.id), + headers={"Authentication": api_key.code}, + json={"email": "new-email@gmail.com"}, + ) + + assert r.status_code == 200 + + mb = Mailbox.get(mb.id) + assert mb.new_email == "new-email@gmail.com" From 3eb67002326bbe6c2208fbba7f448f2743a0cc0d Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:43:48 +0200 Subject: [PATCH 5/6] user can cancel mailbox email change --- README.md | 1 + app/api/views/mailbox.py | 7 +++++++ tests/api/test_mailbox.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/README.md b/README.md index 9eae6fff..b14b3c46 100644 --- a/README.md +++ b/README.md @@ -1198,6 +1198,7 @@ Input: - `mailbox_id`: in url - (optional) `default`: boolean. Set a mailbox as default mailbox. - (optional) `email`: email address. Change a mailbox email address. +- (optional) `cancel_email_change`: boolean. Cancel mailbox email change. Output: - 200 if updated successfully diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py index 40dc174a..bfebd0d6 100644 --- a/app/api/views/mailbox.py +++ b/app/api/views/mailbox.py @@ -98,6 +98,7 @@ def update_mailbox(mailbox_id): mailbox_id: in url (optional) default: in body. Set a mailbox as the default mailbox. (optional) email: in body. Change a mailbox email. + (optional) cancel_email_change: in body. Cancel mailbox email change. Output: 200 if updated successfully @@ -138,6 +139,12 @@ def update_mailbox(mailbox_id): mailbox.new_email = new_email changed = True + if "cancel_email_change" in data: + cancel_email_change = data.get("cancel_email_change") + if cancel_email_change: + mailbox.new_email = None + changed = True + if changed: db.session.commit() diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py index a4bc9910..c251668e 100644 --- a/tests/api/test_mailbox.py +++ b/tests/api/test_mailbox.py @@ -121,3 +121,40 @@ def test_update_mailbox_email(flask_client): mb = Mailbox.get(mb.id) assert mb.new_email == "new-email@gmail.com" + + +def test_cancel_mailbox_email_change(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + # create a mailbox + mb = Mailbox.create(user_id=user.id, email="mb@gmail.com") + db.session.commit() + + # update mailbox email + r = flask_client.put( + url_for("api.delete_mailbox", mailbox_id=mb.id), + headers={"Authentication": api_key.code}, + json={"email": "new-email@gmail.com"}, + ) + assert r.status_code == 200 + + mb = Mailbox.get(mb.id) + assert mb.new_email == "new-email@gmail.com" + + # cancel mailbox email change + r = flask_client.put( + url_for("api.delete_mailbox", mailbox_id=mb.id), + headers={"Authentication": api_key.code}, + json={"cancel_email_change": True}, + ) + assert r.status_code == 200 + + mb = Mailbox.get(mb.id) + assert mb.new_email is None From 6280512adf2f3c9a6fb599b06ba65ce457a3e4f0 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Sat, 23 May 2020 16:46:10 +0200 Subject: [PATCH 6/6] move get mailboxes to mailbox.py --- app/api/views/alias.py | 21 --------------------- app/api/views/mailbox.py | 23 ++++++++++++++++++++++- tests/api/test_alias.py | 27 --------------------------- tests/api/test_mailbox.py | 27 +++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/app/api/views/alias.py b/app/api/views/alias.py index cb11f375..7635a77e 100644 --- a/app/api/views/alias.py +++ b/app/api/views/alias.py @@ -120,27 +120,6 @@ def get_aliases_v2(): ) -@api_bp.route("/mailboxes", methods=["GET"]) -@cross_origin() -@require_api_auth -def get_mailboxes(): - """ - Get mailboxes - Output: - - mailboxes: list of alias: - - id - - email - """ - user = g.user - - return ( - jsonify( - mailboxes=[{"id": mb.id, "email": mb.email} for mb in user.mailboxes()] - ), - 200, - ) - - @api_bp.route("/aliases/", methods=["DELETE"]) @cross_origin() @require_api_auth diff --git a/app/api/views/mailbox.py b/app/api/views/mailbox.py index bfebd0d6..deea4bbe 100644 --- a/app/api/views/mailbox.py +++ b/app/api/views/mailbox.py @@ -1,6 +1,6 @@ from smtplib import SMTPRecipientsRefused -from flask import g +from flask import g, jsonify from flask import jsonify from flask import request from flask_cors import cross_origin @@ -149,3 +149,24 @@ def update_mailbox(mailbox_id): db.session.commit() return jsonify(updated=True), 200 + + +@api_bp.route("/mailboxes", methods=["GET"]) +@cross_origin() +@require_api_auth +def get_mailboxes(): + """ + Get mailboxes + Output: + - mailboxes: list of alias: + - id + - email + """ + user = g.user + + return ( + jsonify( + mailboxes=[{"id": mb.id, "email": mb.email} for mb in user.mailboxes()] + ), + 200, + ) diff --git a/tests/api/test_alias.py b/tests/api/test_alias.py index 3d2eaf92..923213c2 100644 --- a/tests/api/test_alias.py +++ b/tests/api/test_alias.py @@ -1,5 +1,3 @@ -import json - from flask import url_for from app.config import PAGE_LIMIT @@ -571,28 +569,3 @@ def test_get_alias(flask_client): assert "nb_reply" in res assert "enabled" in res assert "note" in res - - -def test_get_mailboxes(flask_client): - user = User.create( - email="a@b.c", password="password", name="Test User", activated=True - ) - db.session.commit() - - # create api_key - api_key = ApiKey.create(user.id, "for test") - db.session.commit() - - Mailbox.create(user_id=user.id, email="m1@example.com", verified=True) - Mailbox.create(user_id=user.id, email="m2@example.com", verified=False) - db.session.commit() - - r = flask_client.get( - url_for("api.get_mailboxes"), headers={"Authentication": api_key.code}, - ) - assert r.status_code == 200 - # m2@example.com is not returned as it's not verified - assert r.json == { - "mailboxes": [{"email": "a@b.c", "id": 1}, {"email": "m1@example.com", "id": 2}] - } - print(json.dumps(r.json, indent=2)) diff --git a/tests/api/test_mailbox.py b/tests/api/test_mailbox.py index c251668e..6faeb874 100644 --- a/tests/api/test_mailbox.py +++ b/tests/api/test_mailbox.py @@ -1,3 +1,5 @@ +import json + from flask import url_for from flask import url_for @@ -158,3 +160,28 @@ def test_cancel_mailbox_email_change(flask_client): mb = Mailbox.get(mb.id) assert mb.new_email is None + + +def test_get_mailboxes(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + Mailbox.create(user_id=user.id, email="m1@example.com", verified=True) + Mailbox.create(user_id=user.id, email="m2@example.com", verified=False) + db.session.commit() + + r = flask_client.get( + url_for("api.get_mailboxes"), headers={"Authentication": api_key.code}, + ) + assert r.status_code == 200 + # m2@example.com is not returned as it's not verified + assert r.json == { + "mailboxes": [{"email": "a@b.c", "id": 1}, {"email": "m1@example.com", "id": 2}] + } + print(json.dumps(r.json, indent=2))