Browse Source

Add recipients email list support

- Add email list form to UI
- Add multiple recipients support
Alexey Edelev 5 years ago
parent
commit
0831f86a16
6 changed files with 91 additions and 9 deletions
  1. 0 0
      web/assets/cross.svg
  2. 9 1
      web/css/controls.css
  3. 12 1
      web/css/styles.css
  4. 54 0
      web/js/index.js
  5. 13 5
      web/mailbox.go
  6. 3 2
      web/templates/mailnew.html

File diff suppressed because it is too large
+ 0 - 0
web/assets/cross.svg


+ 9 - 1
web/css/controls.css

@@ -289,4 +289,12 @@
     -moz-user-select: none;
     -ms-user-select: none;
     user-select: none;
-}
+}
+
+.toEmail {
+    border-radius: var(--default-radius);
+    font-size: var(--small-text-size);
+    margin-right: 10px;
+    padding: var(--base-text-padding);
+}
+

+ 12 - 1
web/css/styles.css

@@ -14,6 +14,7 @@
     --secondary-text-color: #ffffff;
     --secondary-text-dark-color: #666666;
     --default-radius: 5px;
+    --invalid-color: #f0ad4e;
 
     --base-text-padding: 10px;
     --base-border-padding: 8px;
@@ -110,4 +111,14 @@ body {
 
 #copyrightBox {
     color: var(--secondary-dark-color)
-}
+}
+
+.toEmail.valid {
+    background-color: var(--primary-dark-color);
+    color: var(--secondary-text-color);
+}
+
+.toEmail.invalid {
+    background-color: var(--invalid-color);
+    color: var(--primary-text-color);
+}

+ 54 - 0
web/js/index.js

@@ -29,9 +29,16 @@ var currentMail = ""
 var mailbox = ""
 var pageMax = 10
 const mailboxRegex = /^(\/m\d+)/g
+const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+const emailEndRegex = /[;,\s]/g
+
 var folders = new Array()
 var notifierSocket = null
 
+var toEmailList = new Array()
+var toEmailIndex = 0
+var toEmailPreviousSelectionPosition = 0
+
 $(window).click(function(e){
     var target = $(e.target)
     var isDropDown = false
@@ -66,8 +73,49 @@ $(document).ready(function(){
 
     $("#mailNewButton").click(mailNew)
     connectNotifier()
+
+    $("#toEmailField").on("input", toEmailFieldChanged)
+    $("#toEmailField").keyup(function(e){
+        if (e.keyCode == 8 && toEmailPreviousSelectionPosition == 0 && e.target.selectionStart == 0 && toEmailList.length > 0 && $("#toEmailList").children().length > 0) {
+            removeToEmail($("#toEmailList").children().last().attr("id"), toEmailList[toEmailList.length - 1])
+        }
+        toEmailPreviousSelectionPosition = e.target.selectionStart
+    })
 })
 
+function toEmailFieldChanged(e) {
+    const selectionPosition = e.target.selectionStart - 1
+    var actualText = $("#toEmailField").val()
+
+    if (actualText.length <= 0 || selectionPosition <= 0) {
+        return
+    }
+
+    var lastChar = actualText[selectionPosition]
+    if (lastChar.match(emailEndRegex)) {
+        var toEmail = actualText.slice(0, selectionPosition)
+        $("#toEmailField").val(actualText.slice(selectionPosition + 1, actualText.length))
+        if (toEmail.length <= 0) {
+            return
+        }
+        var style = toEmail.match(emailRegex) ? "valid" : "invalid"
+        $("#toEmailList").append("<div class=\""+ style + " toEmail\" id=\"toEmail" + toEmailIndex + "\">" + toEmail + "<img class=\"iconBtn\" style=\"height: 12px; margin-left:10px; margin: auto;\" onclick=\"removeToEmail('toEmail" + toEmailIndex + "', '" + toEmail + "');\" src=\"/assets/cross.svg\"/></div>")
+        toEmailIndex++
+        toEmailList.push(toEmail)
+    }
+}
+
+function removeToEmail(id, email) {
+    const index = toEmailList.indexOf(email)
+    if (index >= 0) {
+        toEmailList.splice(index, 1)
+    }
+
+    $("#" + id).remove()
+    console.log("Remove email: " + email + " index:" + index)
+    console.log("toEmailList: " + toEmailList)
+}
+
 function mailNew(e) {
     window.location.hash = currentFolder + currentPage + "/mailNew"
 }
@@ -379,7 +427,13 @@ function toggleDropDown(dd) {
 }
 
 function sendNewMail() {
+    var composedEmailString = toEmailList[0]
+    for(var i = 1; i < toEmailList.length; i++) {
+        composedEmailString += "," + toEmailList[i]
+    }
+    $("#newMailTo").val(composedEmailString)
     var formValue = $("#mailNewForm").serialize()
+    console.log("formValue: " + formValue)
     $.ajax({
         url: mailbox + "/sendNewMail",
         data: formValue,

+ 13 - 5
web/mailbox.go

@@ -42,6 +42,7 @@ import (
 
 	common "git.semlanik.org/semlanik/gostfix/common"
 	"git.semlanik.org/semlanik/gostfix/config"
+	"git.semlanik.org/semlanik/gostfix/utils"
 )
 
 func (s *Server) handleMailbox(w http.ResponseWriter, user, email string) {
@@ -299,11 +300,18 @@ func (s *Server) handleNewMail(w http.ResponseWriter, r *http.Request, user, ema
 		return
 	}
 
-	err = client.Rcpt(rawMail.Header.To)
-	if err != nil {
-		s.error(http.StatusInternalServerError, "Unable to send message", w)
-		log.Println(err)
-		return
+	toList := strings.Split(rawMail.Header.To, ",")
+	for _, to := range toList {
+		if !utils.RegExpUtilsInstance().EmailChecker.MatchString(to) {
+			log.Println("Skip email " + to)
+			continue
+		}
+		err = client.Rcpt(to)
+		if err != nil {
+			// s.error(http.StatusInternalServerError, "Unable to send message", w)
+			log.Println(err)
+			continue
+		}
 	}
 
 	mailWriter, err := client.Data()

+ 3 - 2
web/templates/mailnew.html

@@ -1,18 +1,19 @@
 <form id="mailNewForm" style="height: 100%; width: 100%; display:flex; flex-direction: column;">
     <div class="horizontalPaddingBox" style="flex-grow: 0!important;">
         <div style="width: 100%; display: flex; flex-direction: row;">
-            <div class="btn materialLevel1" style="margin-right: 10px;" onclick="sendNewMail();">
+            <div class="btn materialLevel1" style="margin-right: 10px; min-width: 60px; max-height: 60px; max-width: 60px; min-height: 60px;" onclick="sendNewMail();">
                 <img src="/assets/send.svg" style="width: 40px"/>
                 Send
             </div>
             <div class="elidedText" style="display: block; flex: 1 1 auto;">
-                <span class="primaryText">To: <input type="text" name="to" id="newMailTo"/></span></br>
+                <div style="display: flex; flex-direction: row; max-width: 100%; flex-wrap: wrap;"><span style="flex: 0 1 auto; margin: auto;" class="primaryText">To:</span><div id="toEmailList" style="flex: 0 1 auto; display: flex; flex-wrap: wrap;"></div><input id="toEmailField" type="text" style="flex: 1 1 auto;"/></div>
                 <div style="display: flex; flex-direction: row;"><span style="flex: 0 1 auto" class="primaryText">Subject:</span><input id="newMailSubject" type="text" name="subject" style="flex: 1 1 auto"/></div></br>
             </div>
             <img class="iconBtn" style="width: 20px; margin-left:10px; margin-right: 10px;" onclick="closeDetails();" src="/assets/back.svg"/>
         </div>
     </div>
     <div class="horizontalPaddingBox">
+        <input type="hidden" id="newMailTo" name="to">
         <textarea id="newMailEditor" name="body" class="contentArea" style="height: 100%; width: 100%; resize: none;"></textarea>
     </div>
 </form>

Some files were not shown because too many files changed in this diff