浏览代码

Support multiple mailboxes in custom alias page

Son NK 5 年之前
父节点
当前提交
e52f2ca6de

+ 23 - 5
app/dashboard/templates/dashboard/custom_alias.html

@@ -56,15 +56,16 @@
 
       <div class="row mb-2">
         <div class="col p-1">
-          <select class="form-control" name="mailbox">
+          <select class="form-control custom-select selectpicker" id="mailboxes" multiple name="mailboxes">
             {% for mailbox in mailboxes %}
-              <option value="{{ mailbox }}">
-                {{ mailbox }}
+              <option value="{{ mailbox.id }}" {% if mailbox.id == current_user.default_mailbox_id %}
+                      selected {% endif %}>
+                {{ mailbox.email }}
               </option>
             {% endfor %}
           </select>
           <div class="small-text">
-            The mailbox that owns this alias.
+            The mailbox(es) that owns this alias.
           </div>
         </div>
       </div>
@@ -81,7 +82,7 @@
 
       <div class="row">
         <div class="col p-1">
-          <button class="btn btn-primary mt-1">Create</button>
+          <span id="submit" class="btn btn-primary mt-1">Create</span>
         </div>
       </div>
     </form>
@@ -89,3 +90,20 @@
 
 {% endblock %}
 
+{% block script %}
+  <script>
+    $("#submit").on("click", async function () {
+      let that = $(this);
+      let mailbox_ids = $(`#mailboxes`).val();
+
+      if (mailbox_ids.length == 0) {
+        toastr.error("You must select at least a mailbox", "Error");
+        return;
+      }
+
+      that.closest("form").submit();
+
+    })
+  </script>
+{% endblock %}
+

+ 25 - 9
app/dashboard/views/custom_alias.py

@@ -11,7 +11,7 @@ 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 Alias, CustomDomain, DeletedAlias, Mailbox, User
+from app.models import Alias, CustomDomain, DeletedAlias, Mailbox, User, AliasMailbox
 from app.utils import convert_to_id, random_word, word_exist
 
 signer = TimestampSigner(CUSTOM_ALIAS_SECRET)
@@ -54,20 +54,30 @@ def custom_alias():
     # List of (is_custom_domain, alias-suffix, time-signed alias-suffix)
     suffixes = available_suffixes(current_user)
 
-    mailboxes = [mb.email for mb in current_user.mailboxes()]
+    mailboxes = current_user.mailboxes()
 
     if request.method == "POST":
         alias_prefix = request.form.get("prefix")
         signed_suffix = request.form.get("suffix")
-        mailbox_email = request.form.get("mailbox")
+        mailbox_ids = request.form.getlist("mailboxes")
         alias_note = request.form.get("note")
 
         # check if mailbox is not tempered with
-        if mailbox_email != current_user.email:
-            mailbox = Mailbox.get_by(email=mailbox_email, user_id=current_user.id)
-            if not mailbox or mailbox.user_id != current_user.id:
+        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)
+
+        if not mailboxes:
+            flash("At least one mailbox must be selected", "error")
+            return redirect(url_for("dashboard.custom_alias"))
 
         # hypothesis: user will click on the button in the 600 secs
         try:
@@ -91,14 +101,20 @@ def custom_alias():
                     "warning",
                 )
             else:
-                mailbox = Mailbox.get_by(email=mailbox_email, user_id=current_user.id)
-
                 alias = Alias.create(
                     user_id=current_user.id,
                     email=full_alias,
                     note=alias_note,
-                    mailbox_id=mailbox.id,
+                    mailbox_id=mailboxes[0].id,
                 )
+                db.session.flush()
+
+                for i in range(1, len(mailboxes)):
+                    AliasMailbox.create(
+                        user_id=alias.user_id,
+                        alias_id=alias.id,
+                        mailbox_id=mailboxes[i].id,
+                    )
 
                 # get the custom_domain_id if alias is created with a custom domain
                 if alias_suffix.startswith("@"):

+ 37 - 2
tests/dashboard/test_custom_alias.py

@@ -7,7 +7,7 @@ from app.dashboard.views.custom_alias import (
     available_suffixes,
 )
 from app.extensions import db
-from app.models import Mailbox, CustomDomain
+from app.models import Mailbox, CustomDomain, Alias
 from app.utils import random_word
 from tests.utils import login
 
@@ -20,15 +20,50 @@ def test_add_alias_success(flask_client):
     suffix = f".{word}@{EMAIL_DOMAIN}"
     suffix = signer.sign(suffix).decode()
 
+    # create with a single mailbox
     r = flask_client.post(
         url_for("dashboard.custom_alias"),
-        data={"prefix": "prefix", "suffix": suffix, "mailbox": user.email,},
+        data={
+            "prefix": "prefix",
+            "suffix": suffix,
+            "mailboxes": [user.default_mailbox_id],
+        },
         follow_redirects=True,
     )
+    assert r.status_code == 200
+    assert f"Alias prefix.{word}@{EMAIL_DOMAIN} has been created" in str(r.data)
+
+    alias = Alias.query.order_by(Alias.created_at.desc()).first()
+    assert not alias._mailboxes
+
+
+def test_add_alias_multiple_mailboxes(flask_client):
+    user = login(flask_client)
+    db.session.commit()
+
+    word = random_word()
+    suffix = f".{word}@{EMAIL_DOMAIN}"
+    suffix = signer.sign(suffix).decode()
 
+    # create with a multiple mailboxes
+    mb1 = Mailbox.create(user_id=user.id, email="m1@example.com", verified=True)
+    db.session.commit()
+
+    r = flask_client.post(
+        url_for("dashboard.custom_alias"),
+        data={
+            "prefix": "prefix",
+            "suffix": suffix,
+            "mailboxes": [user.default_mailbox_id, mb1.id],
+        },
+        follow_redirects=True,
+    )
     assert r.status_code == 200
     assert f"Alias prefix.{word}@{EMAIL_DOMAIN} has been created" in str(r.data)
 
+    alias = Alias.query.order_by(Alias.created_at.desc()).first()
+    assert alias._mailboxes
+
 
 def test_not_show_unverified_mailbox(flask_client):
     """make sure user unverified mailbox is not shown to user"""