support ALIAS_DOMAINS
- use verify_prefix_suffix() in /api/alias/custom/new -
This commit is contained in:
parent
d7ed0d77bd
commit
bdf75951f1
|
@ -3,7 +3,7 @@ from flask_cors import cross_origin
|
|||
from sqlalchemy import desc
|
||||
|
||||
from app.api.base import api_bp, verify_api_key
|
||||
from app.config import EMAIL_DOMAIN
|
||||
from app.config import ALIAS_DOMAINS
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import AliasUsedOn, GenEmail, User
|
||||
|
@ -67,9 +67,11 @@ def options():
|
|||
else:
|
||||
ret["custom"]["suggestion"] = ""
|
||||
|
||||
ret["custom"]["suffixes"] = []
|
||||
# maybe better to make sure the suffix is never used before
|
||||
# but this is ok as there's a check when creating a new custom alias
|
||||
ret["custom"]["suffixes"] = [f".{random_word()}@{EMAIL_DOMAIN}"]
|
||||
for domain in ALIAS_DOMAINS:
|
||||
ret["custom"]["suffixes"].append(f".{random_word()}@{domain}")
|
||||
|
||||
for custom_domain in user.verified_custom_domains():
|
||||
ret["custom"]["suffixes"].append("@" + custom_domain.domain)
|
||||
|
@ -144,7 +146,9 @@ def options_v2():
|
|||
|
||||
# maybe better to make sure the suffix is never used before
|
||||
# but this is ok as there's a check when creating a new custom alias
|
||||
ret["suffixes"] = [f".{random_word()}@{EMAIL_DOMAIN}"]
|
||||
# todo: take into account DISABLE_ALIAS_SUFFIX
|
||||
for domain in ALIAS_DOMAINS:
|
||||
ret["suffixes"].append(f".{random_word()}@{domain}")
|
||||
|
||||
for custom_domain in user.verified_custom_domains():
|
||||
ret["suffixes"].append("@" + custom_domain.domain)
|
||||
|
|
|
@ -3,7 +3,8 @@ from flask import jsonify, request
|
|||
from flask_cors import cross_origin
|
||||
|
||||
from app.api.base import api_bp, verify_api_key
|
||||
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.config import MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.dashboard.views.custom_alias import verify_prefix_suffix
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import GenEmail, AliasUsedOn
|
||||
|
@ -43,35 +44,12 @@ def new_custom_alias():
|
|||
if not data:
|
||||
return jsonify(error="request body cannot be empty"), 400
|
||||
|
||||
alias_prefix = data.get("alias_prefix", "")
|
||||
alias_suffix = data.get("alias_suffix", "")
|
||||
|
||||
# make sure alias_prefix is not empty
|
||||
alias_prefix = alias_prefix.strip()
|
||||
alias_prefix = data.get("alias_prefix", "").strip()
|
||||
alias_suffix = data.get("alias_suffix", "").strip()
|
||||
alias_prefix = convert_to_id(alias_prefix)
|
||||
if not alias_prefix: # should be checked on frontend
|
||||
LOG.d("user %s submits an empty alias with the prefix %s", user, alias_prefix)
|
||||
return jsonify(error="alias prefix cannot be empty"), 400
|
||||
|
||||
# make sure alias_suffix is either .random_letters@simplelogin.co or @my-domain.com
|
||||
alias_suffix = alias_suffix.strip()
|
||||
if alias_suffix.startswith("@"):
|
||||
custom_domain = alias_suffix[1:]
|
||||
if custom_domain not in user_custom_domains:
|
||||
LOG.d("user %s submits a wrong custom domain %s ", user, custom_domain)
|
||||
return jsonify(error="error"), 400
|
||||
else:
|
||||
if not alias_suffix.startswith("."):
|
||||
LOG.d("user %s submits a wrong alias suffix %s", user, alias_suffix)
|
||||
return jsonify(error="error"), 400
|
||||
if not alias_suffix.endswith(EMAIL_DOMAIN):
|
||||
LOG.d("user %s submits a wrong alias suffix %s", user, alias_suffix)
|
||||
return jsonify(error="error"), 400
|
||||
|
||||
random_letters = alias_suffix[1 : alias_suffix.find("@")]
|
||||
if len(random_letters) < 5:
|
||||
LOG.d("user %s submits a wrong alias suffix %s", user, alias_suffix)
|
||||
return jsonify(error="error"), 400
|
||||
if not verify_prefix_suffix(user, alias_prefix, alias_suffix, user_custom_domains):
|
||||
return jsonify(error="wrong alias prefix or suffix"), 400
|
||||
|
||||
full_alias = alias_prefix + alias_suffix
|
||||
if GenEmail.get_by(email=full_alias):
|
||||
|
|
|
@ -5,7 +5,8 @@ from wtforms import StringField, validators
|
|||
|
||||
from app import email_utils
|
||||
from app.auth.base import auth_bp
|
||||
from app.config import URL, EMAIL_DOMAIN
|
||||
from app.config import URL
|
||||
from app.email_utils import email_belongs_to_alias_domains
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import User, ActivationCode
|
||||
|
@ -31,8 +32,7 @@ def register():
|
|||
|
||||
if form.validate_on_submit():
|
||||
email = form.email.data
|
||||
|
||||
if email.endswith(EMAIL_DOMAIN):
|
||||
if email_belongs_to_alias_domains(email):
|
||||
flash(
|
||||
"You cannot use alias as your personal inbox. Nice try though 😉",
|
||||
"error",
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
from flask import render_template, redirect, url_for, flash, request, session
|
||||
from flask_login import login_required, current_user
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, validators, SelectField
|
||||
|
||||
from app.config import EMAIL_DOMAIN, HIGHLIGHT_GEN_EMAIL_ID, DISABLE_ALIAS_SUFFIX
|
||||
from app.config import (
|
||||
HIGHLIGHT_GEN_EMAIL_ID,
|
||||
DISABLE_ALIAS_SUFFIX,
|
||||
ALIAS_DOMAINS,
|
||||
)
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.email_utils import email_belongs_to_alias_domains
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import GenEmail, DeletedAlias, CustomDomain
|
||||
from app.models import GenEmail
|
||||
from app.utils import convert_to_id, random_word, word_exist
|
||||
|
||||
|
||||
|
@ -29,9 +32,10 @@ def custom_alias():
|
|||
suffixes.append("@" + alias_domain)
|
||||
|
||||
# then default domain
|
||||
suffixes.append(
|
||||
("" if DISABLE_ALIAS_SUFFIX else ".") + random_word() + "@" + EMAIL_DOMAIN
|
||||
)
|
||||
for domain in ALIAS_DOMAINS:
|
||||
suffixes.append(
|
||||
("" if DISABLE_ALIAS_SUFFIX else "." + random_word()) + "@" + domain
|
||||
)
|
||||
|
||||
if request.method == "POST":
|
||||
alias_prefix = request.form.get("prefix")
|
||||
|
@ -73,9 +77,12 @@ def verify_prefix_suffix(user, alias_prefix, alias_suffix, user_custom_domains)
|
|||
alias_suffix = alias_suffix.strip()
|
||||
if alias_suffix.startswith("@"):
|
||||
alias_domain = alias_suffix[1:]
|
||||
# alias_domain can be either custom_domain or if DISABLE_ALIAS_SUFFIX, EMAIL_DOMAIN
|
||||
# alias_domain can be either custom_domain or if DISABLE_ALIAS_SUFFIX, one of the default ALIAS_DOMAINS
|
||||
if DISABLE_ALIAS_SUFFIX:
|
||||
if alias_domain not in user_custom_domains and alias_domain != EMAIL_DOMAIN:
|
||||
if (
|
||||
alias_domain not in user_custom_domains
|
||||
and alias_domain not in ALIAS_DOMAINS
|
||||
):
|
||||
LOG.error("wrong alias suffix %s, user %s", alias_suffix, user)
|
||||
return False
|
||||
else:
|
||||
|
@ -86,9 +93,11 @@ def verify_prefix_suffix(user, alias_prefix, alias_suffix, user_custom_domains)
|
|||
if not alias_suffix.startswith("."):
|
||||
LOG.error("User %s submits a wrong alias suffix %s", user, alias_suffix)
|
||||
return False
|
||||
if not alias_suffix.endswith(EMAIL_DOMAIN):
|
||||
|
||||
full_alias = alias_prefix + alias_suffix
|
||||
if not email_belongs_to_alias_domains(full_alias):
|
||||
LOG.error(
|
||||
"Alias suffix should end with default alias domain %s",
|
||||
"Alias suffix should end with one of the alias domains %s",
|
||||
user,
|
||||
alias_suffix,
|
||||
)
|
||||
|
|
|
@ -9,8 +9,9 @@ from flask_wtf.file import FileField
|
|||
from wtforms import StringField, validators
|
||||
|
||||
from app import s3, email_utils
|
||||
from app.config import URL, EMAIL_DOMAIN
|
||||
from app.config import URL
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.email_utils import email_belongs_to_alias_domains
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import (
|
||||
|
@ -92,7 +93,7 @@ def setting():
|
|||
or DeletedAlias.get_by(email=new_email)
|
||||
):
|
||||
flash(f"Email {new_email} already used", "error")
|
||||
elif new_email.endswith(EMAIL_DOMAIN):
|
||||
elif email_belongs_to_alias_domains(new_email):
|
||||
flash(
|
||||
"You cannot use alias as your personal inbox. Nice try though 😉",
|
||||
"error",
|
||||
|
|
|
@ -38,7 +38,7 @@ from smtplib import SMTP
|
|||
|
||||
from aiosmtpd.controller import Controller
|
||||
|
||||
from app.config import EMAIL_DOMAIN, POSTFIX_SERVER, URL
|
||||
from app.config import EMAIL_DOMAIN, POSTFIX_SERVER, URL, ALIAS_DOMAINS
|
||||
from app.email_utils import (
|
||||
get_email_name,
|
||||
get_email_part,
|
||||
|
@ -49,6 +49,7 @@ from app.email_utils import (
|
|||
delete_header,
|
||||
send_cannot_create_directory_alias,
|
||||
send_cannot_create_domain_alias,
|
||||
email_belongs_to_alias_domains,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
|
@ -120,7 +121,7 @@ class MailHandler:
|
|||
on_the_fly = False
|
||||
|
||||
# check if alias belongs to a directory, ie having directory/anything@EMAIL_DOMAIN format
|
||||
if alias.endswith(EMAIL_DOMAIN):
|
||||
if email_belongs_to_alias_domains(alias):
|
||||
if "/" in alias or "+" in alias or "#" in alias:
|
||||
if "/" in alias:
|
||||
sep = "/"
|
||||
|
@ -284,10 +285,10 @@ class MailHandler:
|
|||
|
||||
forward_email = ForwardEmail.get_by(reply_email=reply_email)
|
||||
alias: str = forward_email.gen_email.email
|
||||
|
||||
# alias must end with EMAIL_DOMAIN or custom-domain
|
||||
alias_domain = alias[alias.find("@") + 1 :]
|
||||
if alias_domain != EMAIL_DOMAIN:
|
||||
|
||||
# alias must end with one of the ALIAS_DOMAINS or custom-domain
|
||||
if not email_belongs_to_alias_domains(alias):
|
||||
if not CustomDomain.get_by(domain=alias_domain):
|
||||
return "550 alias unknown by SimpleLogin"
|
||||
|
||||
|
@ -338,9 +339,9 @@ class MailHandler:
|
|||
envelope.rcpt_options,
|
||||
)
|
||||
|
||||
if alias_domain == EMAIL_DOMAIN:
|
||||
add_dkim_signature(msg, EMAIL_DOMAIN)
|
||||
# add DKIM-Signature for non-custom-domain alias
|
||||
if alias_domain in ALIAS_DOMAINS:
|
||||
add_dkim_signature(msg, alias_domain)
|
||||
# add DKIM-Signature for custom-domain alias
|
||||
else:
|
||||
custom_domain: CustomDomain = CustomDomain.get_by(domain=alias_domain)
|
||||
if custom_domain.dkim_verified:
|
||||
|
|
|
@ -27,7 +27,8 @@ def test_different_scenarios(flask_client):
|
|||
assert r.status_code == 200
|
||||
assert r.json["can_create_custom"]
|
||||
assert len(r.json["existing"]) == 1
|
||||
assert r.json["custom"]["suffixes"]
|
||||
assert len(r.json["custom"]["suffixes"]) == 3
|
||||
|
||||
assert r.json["custom"]["suggestion"] == "" # no hostname => no suggestion
|
||||
|
||||
# <<< with hostname >>>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from flask import url_for
|
||||
|
||||
from app.config import EMAIL_DOMAIN
|
||||
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
|
||||
from app.extensions import db
|
||||
from app.models import User, ApiKey, GenEmail
|
||||
from app.utils import random_word
|
||||
|
||||
|
||||
def test_success(flask_client):
|
||||
|
@ -15,14 +16,16 @@ def test_success(flask_client):
|
|||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
|
||||
word = random_word()
|
||||
|
||||
r = flask_client.post(
|
||||
url_for("api.new_custom_alias", hostname="www.test.com"),
|
||||
headers={"Authentication": api_key.code},
|
||||
json={"alias_prefix": "prefix", "alias_suffix": f".abcdef@{EMAIL_DOMAIN}"},
|
||||
json={"alias_prefix": "prefix", "alias_suffix": f".{word}@{EMAIL_DOMAIN}"},
|
||||
)
|
||||
|
||||
assert r.status_code == 201
|
||||
assert r.json["alias"] == f"prefix.abcdef@{EMAIL_DOMAIN}"
|
||||
assert r.json["alias"] == f"prefix.{word}@{EMAIL_DOMAIN}"
|
||||
|
||||
|
||||
def test_out_of_quota(flask_client):
|
||||
|
@ -35,15 +38,15 @@ def test_out_of_quota(flask_client):
|
|||
api_key = ApiKey.create(user.id, "for test")
|
||||
db.session.commit()
|
||||
|
||||
# create 3 custom alias to run out of quota
|
||||
GenEmail.create_new(user.id, prefix="test")
|
||||
GenEmail.create_new(user.id, prefix="test")
|
||||
GenEmail.create_new(user.id, prefix="test")
|
||||
# create MAX_NB_EMAIL_FREE_PLAN custom alias to run out of quota
|
||||
for _ in range(MAX_NB_EMAIL_FREE_PLAN):
|
||||
GenEmail.create_new(user.id, prefix="test")
|
||||
|
||||
word = random_word()
|
||||
r = flask_client.post(
|
||||
url_for("api.new_custom_alias", hostname="www.test.com"),
|
||||
headers={"Authentication": api_key.code},
|
||||
json={"alias_prefix": "prefix", "alias_suffix": f".abcdef@{EMAIL_DOMAIN}"},
|
||||
json={"alias_prefix": "prefix", "alias_suffix": f".{word}@{EMAIL_DOMAIN}"},
|
||||
)
|
||||
|
||||
assert r.status_code == 400
|
||||
|
|
|
@ -5,6 +5,7 @@ URL=http://localhost
|
|||
# Only print email content, not sending it
|
||||
NOT_SEND_EMAIL=true
|
||||
EMAIL_DOMAIN=sl.local
|
||||
OTHER_ALIAS_DOMAINS=["d1.test", "d2.test"]
|
||||
SUPPORT_EMAIL=support@sl.local
|
||||
ADMIN_EMAIL=to_fill
|
||||
# Max number emails user can generate for free plan
|
||||
|
|
Loading…
Reference in New Issue