@@ -105,7 +128,24 @@
Only lowercase letters, numbers, dashes (-) and underscores (_) are currently supported.
-
+
+ By default, aliases created with directory are "owned" by your default
+ mailbox {{ current_user.default_mailbox.email }}.
+ You can however choose the mailbox(es) that new alias automatically belongs to by setting this below option.
+
+
+
+
+
+
@@ -142,5 +182,8 @@
})
});
+
+ $('.mailbox-select').multipleSelect();
+
{% endblock %}
diff --git a/app/dashboard/views/directory.py b/app/dashboard/views/directory.py
index 9c992cd5..bcad92f9 100644
--- a/app/dashboard/views/directory.py
+++ b/app/dashboard/views/directory.py
@@ -6,7 +6,7 @@ from wtforms import StringField, validators
from app.config import EMAIL_DOMAIN, ALIAS_DOMAINS, MAX_NB_DIRECTORY
from app.dashboard.base import dashboard_bp
from app.extensions import db
-from app.models import Directory
+from app.models import Directory, Mailbox, DirectoryMailbox
class NewDirForm(FlaskForm):
@@ -24,6 +24,8 @@ def directory():
.all()
)
+ mailboxes = current_user.mailboxes()
+
new_dir_form = NewDirForm()
if request.method == "POST":
@@ -44,7 +46,46 @@ def directory():
flash(f"Directory {name} has been deleted", "success")
return redirect(url_for("dashboard.directory"))
+ elif request.form.get("form-name") == "update":
+ dir_id = request.form.get("dir-id")
+ dir = Directory.get(dir_id)
+ if not dir:
+ flash("Unknown error. Refresh the page", "warning")
+ return redirect(url_for("dashboard.directory"))
+ elif dir.user_id != current_user.id:
+ flash("You cannot delete this directory", "warning")
+ return redirect(url_for("dashboard.directory"))
+
+ mailbox_ids = request.form.getlist("mailbox_ids")
+ # check if mailbox is not tempered with
+ mailboxes = []
+ for mailbox_id in mailbox_ids:
+ mailbox = Mailbox.get(mailbox_id)
+ if (
+ not mailbox
+ or mailbox.user_id != current_user.id
+ or not mailbox.verified
+ ):
+ flash("Something went wrong, please retry", "warning")
+ return redirect(url_for("dashboard.directory"))
+ mailboxes.append(mailbox)
+
+ if not mailboxes:
+ flash("You must select at least 1 mailbox", "warning")
+ return redirect(url_for("dashboard.directory"))
+
+ # first remove all existing alias-mailboxes links
+ DirectoryMailbox.query.filter_by(directory_id=dir.id).delete()
+ db.session.flush()
+
+ for mailbox in mailboxes:
+ DirectoryMailbox.create(directory_id=dir.id, mailbox_id=mailbox.id)
+
+ db.session.commit()
+ flash(f"Directory {dir.name} has been updated", "success")
+
+ return redirect(url_for("dashboard.directory"))
elif request.form.get("form-name") == "create":
if not current_user.is_premium():
flash("Only premium plan can add directory", "warning")
@@ -72,6 +113,27 @@ def directory():
name=new_dir_name, user_id=current_user.id
)
db.session.commit()
+ mailbox_ids = request.form.getlist("mailbox_ids")
+ if mailbox_ids:
+ # check if mailbox is not tempered with
+ mailboxes = []
+ for mailbox_id in mailbox_ids:
+ mailbox = Mailbox.get(mailbox_id)
+ if (
+ not mailbox
+ or mailbox.user_id != current_user.id
+ or not mailbox.verified
+ ):
+ flash("Something went wrong, please retry", "warning")
+ return redirect(url_for("dashboard.custom_alias"))
+ mailboxes.append(mailbox)
+
+ for mailbox in mailboxes:
+ DirectoryMailbox.create(
+ directory_id=new_dir.id, mailbox_id=mailbox.id
+ )
+
+ db.session.commit()
flash(f"Directory {new_dir.name} is created", "success")
@@ -81,6 +143,7 @@ def directory():
"dashboard/directory.html",
dirs=dirs,
new_dir_form=new_dir_form,
+ mailboxes=mailboxes,
EMAIL_DOMAIN=EMAIL_DOMAIN,
ALIAS_DOMAINS=ALIAS_DOMAINS,
)
diff --git a/app/models.py b/app/models.py
index a5b23f04..0bc40075 100644
--- a/app/models.py
+++ b/app/models.py
@@ -1272,6 +1272,17 @@ class Directory(db.Model, ModelMixin):
user = db.relationship(User)
+ _mailboxes = db.relationship(
+ "Mailbox", secondary="directory_mailbox", lazy="joined"
+ )
+
+ @property
+ def mailboxes(self):
+ if self._mailboxes:
+ return self._mailboxes
+ else:
+ return [self.user.default_mailbox]
+
def nb_alias(self):
return Alias.filter_by(directory_id=self.id).count()
@@ -1446,6 +1457,19 @@ class AliasMailbox(db.Model, ModelMixin):
)
+class DirectoryMailbox(db.Model, ModelMixin):
+ __table_args__ = (
+ db.UniqueConstraint("directory_id", "mailbox_id", name="uq_directory_mailbox"),
+ )
+
+ directory_id = db.Column(
+ db.ForeignKey(Directory.id, ondelete="cascade"), nullable=False
+ )
+ mailbox_id = db.Column(
+ db.ForeignKey(Mailbox.id, ondelete="cascade"), nullable=False
+ )
+
+
_NB_RECOVERY_CODE = 8
_RECOVERY_CODE_LENGTH = 8