2020-05-23 16:40:28 +02:00
|
|
|
from smtplib import SMTPRecipientsRefused
|
|
|
|
|
2020-05-23 19:18:35 +02:00
|
|
|
from flask import g
|
2020-05-23 16:09:06 +02:00
|
|
|
from flask import jsonify
|
|
|
|
from flask import request
|
|
|
|
|
2024-07-30 13:36:48 +02:00
|
|
|
from app import mailbox_utils
|
2020-05-23 16:09:06 +02:00
|
|
|
from app.api.base import api_bp, require_api_auth
|
2020-05-23 16:40:28 +02:00
|
|
|
from app.dashboard.views.mailbox_detail import verify_mailbox_change
|
2021-10-12 14:36:47 +02:00
|
|
|
from app.db import Session
|
2020-05-23 16:09:06 +02:00
|
|
|
from app.email_utils import (
|
|
|
|
mailbox_already_used,
|
2020-10-15 16:05:47 +02:00
|
|
|
email_can_be_used_as_mailbox,
|
2020-05-23 16:09:06 +02:00
|
|
|
)
|
2024-07-30 13:36:48 +02:00
|
|
|
from app.models import Mailbox
|
2021-03-31 14:41:32 +02:00
|
|
|
from app.utils import sanitize_email
|
2020-05-23 16:09:06 +02:00
|
|
|
|
|
|
|
|
2020-11-03 11:22:01 +01:00
|
|
|
def mailbox_to_dict(mailbox: Mailbox):
|
|
|
|
return {
|
|
|
|
"id": mailbox.id,
|
|
|
|
"email": mailbox.email,
|
|
|
|
"verified": mailbox.verified,
|
|
|
|
"default": mailbox.user.default_mailbox_id == mailbox.id,
|
|
|
|
"creation_timestamp": mailbox.created_at.timestamp,
|
|
|
|
"nb_alias": mailbox.nb_alias(),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-23 16:09:06 +02:00
|
|
|
@api_bp.route("/mailboxes", methods=["POST"])
|
|
|
|
@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:
|
2020-11-03 11:22:01 +01:00
|
|
|
the new mailbox dict
|
2020-05-23 16:09:06 +02:00
|
|
|
"""
|
|
|
|
user = g.user
|
2021-01-11 12:29:40 +01:00
|
|
|
mailbox_email = sanitize_email(request.get_json().get("email"))
|
2020-05-23 16:09:06 +02:00
|
|
|
|
2024-07-30 13:36:48 +02:00
|
|
|
try:
|
|
|
|
new_mailbox = mailbox_utils.create_mailbox(user, mailbox_email)
|
|
|
|
except mailbox_utils.MailboxError as e:
|
|
|
|
return jsonify(error=e.msg), 400
|
2023-05-09 18:04:04 +02:00
|
|
|
|
2024-07-30 13:36:48 +02:00
|
|
|
return (
|
|
|
|
jsonify(mailbox_to_dict(new_mailbox)),
|
|
|
|
201,
|
|
|
|
)
|
2020-05-23 16:18:12 +02:00
|
|
|
|
|
|
|
|
2022-07-15 17:10:00 +02:00
|
|
|
@api_bp.route("/mailboxes/<int:mailbox_id>", methods=["DELETE"])
|
2020-05-23 16:18:12 +02:00
|
|
|
@require_api_auth
|
|
|
|
def delete_mailbox(mailbox_id):
|
|
|
|
"""
|
|
|
|
Delete mailbox
|
|
|
|
Input:
|
|
|
|
mailbox_id: in url
|
2023-01-17 11:55:34 +01:00
|
|
|
(optional) transfer_aliases_to: in body. Id of the new mailbox for the aliases.
|
|
|
|
If omitted or the value is set to -1,
|
|
|
|
the aliases of the mailbox will be deleted too.
|
2020-05-23 16:18:12 +02:00
|
|
|
Output:
|
|
|
|
200 if deleted successfully
|
|
|
|
|
|
|
|
"""
|
|
|
|
user = g.user
|
2023-01-17 11:55:34 +01:00
|
|
|
data = request.get_json() or {}
|
|
|
|
transfer_mailbox_id = data.get("transfer_aliases_to")
|
|
|
|
if transfer_mailbox_id and int(transfer_mailbox_id) >= 0:
|
2024-07-30 13:36:48 +02:00
|
|
|
transfer_mailbox_id = int(transfer_mailbox_id)
|
|
|
|
else:
|
|
|
|
transfer_mailbox_id = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
mailbox_utils.delete_mailbox(user, mailbox_id, transfer_mailbox_id)
|
|
|
|
except mailbox_utils.MailboxError as e:
|
|
|
|
return jsonify(error=e.msg), 400
|
2020-05-23 16:18:12 +02:00
|
|
|
|
|
|
|
return jsonify(deleted=True), 200
|
2020-05-23 16:26:26 +02:00
|
|
|
|
|
|
|
|
2022-07-15 17:10:00 +02:00
|
|
|
@api_bp.route("/mailboxes/<int:mailbox_id>", methods=["PUT"])
|
2020-05-23 16:26:26 +02:00
|
|
|
@require_api_auth
|
|
|
|
def update_mailbox(mailbox_id):
|
|
|
|
"""
|
|
|
|
Update mailbox
|
|
|
|
Input:
|
|
|
|
mailbox_id: in url
|
2020-05-23 16:40:28 +02:00
|
|
|
(optional) default: in body. Set a mailbox as the default mailbox.
|
|
|
|
(optional) email: in body. Change a mailbox email.
|
2020-05-23 16:43:48 +02:00
|
|
|
(optional) cancel_email_change: in body. Cancel mailbox email change.
|
2020-05-23 16:26:26 +02:00
|
|
|
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:
|
2020-11-03 12:43:01 +01:00
|
|
|
if not mailbox.verified:
|
|
|
|
return (
|
|
|
|
jsonify(
|
|
|
|
error="Unverified mailbox cannot be used as default mailbox"
|
|
|
|
),
|
|
|
|
400,
|
|
|
|
)
|
2020-05-23 16:26:26 +02:00
|
|
|
user.default_mailbox_id = mailbox.id
|
|
|
|
changed = True
|
|
|
|
|
2020-05-23 16:40:28 +02:00
|
|
|
if "email" in data:
|
2021-01-11 12:29:40 +01:00
|
|
|
new_email = sanitize_email(data.get("email"))
|
2020-05-23 16:40:28 +02:00
|
|
|
|
|
|
|
if mailbox_already_used(new_email, user):
|
|
|
|
return jsonify(error=f"{new_email} already used"), 400
|
2020-10-15 16:05:47 +02:00
|
|
|
elif not email_can_be_used_as_mailbox(new_email):
|
2020-05-23 16:40:28 +02:00
|
|
|
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
|
|
|
|
|
2020-05-23 16:43:48 +02:00
|
|
|
if "cancel_email_change" in data:
|
|
|
|
cancel_email_change = data.get("cancel_email_change")
|
|
|
|
if cancel_email_change:
|
|
|
|
mailbox.new_email = None
|
|
|
|
changed = True
|
|
|
|
|
2020-05-23 16:26:26 +02:00
|
|
|
if changed:
|
2021-10-12 14:36:47 +02:00
|
|
|
Session.commit()
|
2020-05-23 16:26:26 +02:00
|
|
|
|
2020-05-23 16:40:28 +02:00
|
|
|
return jsonify(updated=True), 200
|
2020-05-23 16:46:10 +02:00
|
|
|
|
|
|
|
|
|
|
|
@api_bp.route("/mailboxes", methods=["GET"])
|
|
|
|
@require_api_auth
|
|
|
|
def get_mailboxes():
|
|
|
|
"""
|
2020-11-03 12:14:13 +01:00
|
|
|
Get verified mailboxes
|
2020-05-23 16:46:10 +02:00
|
|
|
Output:
|
2020-11-03 12:14:13 +01:00
|
|
|
- mailboxes: list of mailbox dict
|
2020-05-23 16:46:10 +02:00
|
|
|
"""
|
|
|
|
user = g.user
|
|
|
|
|
|
|
|
return (
|
2020-11-03 11:22:01 +01:00
|
|
|
jsonify(mailboxes=[mailbox_to_dict(mb) for mb in user.mailboxes()]),
|
2020-05-23 16:46:10 +02:00
|
|
|
200,
|
|
|
|
)
|
2020-11-03 12:14:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
@api_bp.route("/v2/mailboxes", methods=["GET"])
|
|
|
|
@require_api_auth
|
|
|
|
def get_mailboxes_v2():
|
|
|
|
"""
|
|
|
|
Get all mailboxes - including unverified mailboxes
|
|
|
|
Output:
|
|
|
|
- mailboxes: list of mailbox dict
|
|
|
|
"""
|
|
|
|
user = g.user
|
|
|
|
mailboxes = []
|
|
|
|
|
2021-10-12 14:36:47 +02:00
|
|
|
for mailbox in Mailbox.filter_by(user_id=user.id):
|
2020-11-03 12:14:13 +01:00
|
|
|
mailboxes.append(mailbox)
|
|
|
|
|
|
|
|
return (
|
|
|
|
jsonify(mailboxes=[mailbox_to_dict(mb) for mb in mailboxes]),
|
|
|
|
200,
|
|
|
|
)
|