Index: /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.controller.js
===================================================================
--- /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.controller.js	(revision 9230)
+++ /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.controller.js	(working copy)
@@ -33,11 +33,63 @@
                 email: '',
                 password: ''
             };
+            avxViewModel.showPassword = false;
             avxViewModel.relay = {
                 enable: false
             };
             avxViewModel.relay_data = [];
             
+            // Form validation function
+            avxViewModel.isFormInvalid = function(form, fromString) {
+                return form.$invalid || 
+                       form.from_string.$error.email || 
+                       form.from_string.$error.maxlength || 
+                       (fromString && fromString.length > 64);
+            };
+            
+            // External sender form validation function
+            avxViewModel.isExternalSenderFormInvalid = function(form, email) {
+                var password = avxViewModel.externalSender.password;
+                return form.$invalid || 
+                       form.external_sender_email.$error.email || 
+                       form.external_sender_email.$error.maxlength || 
+                       (email && email.length > 32) ||
+                       !password || // Password required
+                       password.length === 0 ||
+                       (password && password.length > 64); // Password length check
+            };
+            
+            // Hostname validation function
+            avxViewModel.isValidHostname = function(hostname) {
+                if (!hostname) return true; // Empty is valid
+                
+                // IP address regex (IPv4)
+                var ipRegex = /^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$/;
+                
+                // FQDN regex
+                var fqdnRegex = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$/;
+                
+                return ipRegex.test(hostname) || fqdnRegex.test(hostname);
+            };
+            
+            // Alert form validation function
+            avxViewModel.isAlertFormInvalid = function(form, hostname) {
+                return (hostname && hostname.length > 128) || 
+                       (hostname && !avxViewModel.isValidHostname(hostname));
+            };
+            
+            // External server form validation function
+            avxViewModel.isExternalServerFormInvalid = function(form, emailServer) {
+                var port = avxViewModel.externalServer.server_port;
+                var isPortValid = (port === null || port === undefined || port === '' || (port >= 0 && port <= 65535));
+                
+                return !emailServer || // Required field check
+                       emailServer.length === 0 ||
+                       (emailServer && emailServer.length > 64) || 
+                       (emailServer && !avxViewModel.isValidHostname(emailServer)) ||
+                       !isPortValid; // Port validation - allow empty
+            };
+            
             // Define showProgressBar function early so it can be used by all functions
             var showProgressBar = function() {
                 var modalInstance = $uibModal.open({
@@ -329,22 +381,11 @@
             avxViewModel.refreshRelayList();
             
             avxViewModel.saveEmail = function(from) {
-                var reminder = $filter('T')('Warning: This operation will take approximately 1–2 minutes. Please do not refresh the page or perform other actions until it is completed.');
-                var action_reminder = confirm(reminder);
-                
-                if (!action_reminder) {
-                    avxViewModel.email.from_string = avxViewModel.originalFromString;
-                    from.$dirty = true;
-                    return;
-                }
-                
                 showProgressBar();
                 sysResourceService
                     .update_email(avxViewModel.email.from_string || "")
                     .then(function(res) {
-                        setTimeout(function() {
-                            $rootScope.$broadcast('endLoading', true);
-                        }, 60000);
+                        $rootScope.$broadcast('endLoading', true);
                         
                         if (res&&res.status === 200) {
                             if (!res.data[0]) {
@@ -352,23 +393,20 @@
                                 from.$dirty=true;
                             } else {
                                 from.$dirty=false;
-
                                 avxViewModel.originalFromString = avxViewModel.email.from_string;
                             }
                         } else {
                             alert("Internal error.");
                             from.$dirty=true;
                         }
-                });
+                    })
+                    .catch(function(error) {
+                        $rootScope.$broadcast('endLoading', true);
+                        alert("Internal error.");
+                        from.$dirty=true;
+                    });
             };
             avxViewModel.saveAlert = function(form) {
-                var reminder = $filter('T')('Warning: This operation will take approximately 1–2 minutes. Please do not refresh the page or perform other actions until it is completed.');
-                var action_reminder = confirm(reminder);
-                
-                if (!action_reminder) {
-                    return;
-                }
-                
                 showProgressBar();
                 var post_data = {
                     host_string: avxViewModel.alert.hostname || "",
@@ -409,6 +447,8 @@
                                 form.$dirty=true;
                             } else {
                                 form.$dirty=false;
+                                // Refresh external mail server data after successful save
+                                get_external_mail_info();
                             }
                         } else {
                             alert("Internal error.");
@@ -507,6 +547,31 @@
             };
             avxViewModel.loading = false;
             
+            // Hostname validation function (same as main email controller)
+            avxViewModel.isValidHostname = function(hostname) {
+                if (!hostname) return true; // Empty is valid
+                
+                // IP address regex (IPv4)
+                var ipRegex = /^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$/;
+                
+                // FQDN regex
+                var fqdnRegex = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$/;
+                
+                return ipRegex.test(hostname) || fqdnRegex.test(hostname);
+            };
+            
+            // Form validation function
+            avxViewModel.isFormInvalid = function(form, hostname, relayServer) {
+                return !hostname || // Required field check
+                       !relayServer || // Required field check
+                       hostname.length === 0 ||
+                       relayServer.length === 0 ||
+                       (hostname && hostname.length > 50) || 
+                       (relayServer && relayServer.length > 30) ||
+                       (hostname && !avxViewModel.isValidHostname(hostname)) ||
+                       (relayServer && !avxViewModel.isValidHostname(relayServer));
+            };
+            
             var showProgressBar = function() {
                 var modalInstance = $uibModal.open({
                     templateUrl: 'app/modules/common/templates/progress.html',
@@ -537,6 +602,16 @@
                             if (!res.data[0]) {
                                 alert(res.data[1]);
                             } else {
+                                // Check for warnings even when API call succeeds
+                                if (res.data[2] && Array.isArray(res.data[2])) {
+                                    var warnings = res.data[2];
+                                    for (var i = 0; i < warnings.length; i++) {
+                                        if (warnings[i][0] === "warning") {
+                                            alert(warnings[i][1]);
+                                            return; // Don't close modal if there's a warning
+                                        }
+                                    }
+                                }
                                 $uibModalInstance.close();
                             }
                         } else {
Index: /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.html
===================================================================
--- /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.html	(revision 9230)
+++ /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/email.html	(working copy)
@@ -8,12 +8,14 @@
                     <div class="form-group">
                         <label class="col-md-3 control-label">{{'From'|T}}</label>
                         <div class="col-md-6">
-                            <input ng-verify="required:false" type="email" name="from_string" class="form-control" placeholder="{{sys_email.emailPlaceholder}}" ng-model="sys_email.email.from_string" resettable>
+                            <input ng-verify="required:false, maxlength:64" type="email" name="from_string" class="form-control" placeholder="{{sys_email.emailPlaceholder}}" ng-model="sys_email.email.from_string" resettable>
+                            <p class="help-block" ng-show="sender.from_string.$error.email && (sender.from_string.$dirty || sender.$submitted)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please enter a valid email address'|T}}</p>
+                            <p class="help-block" ng-show="sys_email.email.from_string && sys_email.email.from_string.length > 64" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please do not exceed 64 characters'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group" ng-show="sys_email.email.from_string !== sys_email.originalFromString">
                         <div class="col-md-offset-3 col-md-9">
-                            <button type="submit" ng-verify="control:'sender'" class="btn btn-primary" ng-click="sys_email.saveEmail(sys_email.email.from_string, sender)">{{'Apply Changes'|T}}</button>
+                            <button type="submit" class="btn btn-primary" ng-click="sys_email.saveEmail(sys_email.email.from_string, sender)" ng-disabled="sys_email.isFormInvalid(sender, sys_email.email.from_string)">{{'Apply Changes'|T}}</button>
                             <button type="reset" class="btn btn-default btn-cancel" ng-click="sys_email.email.from_string=sys_email.originalFromString">{{'Cancel'|T}}</button>
                         </div>
                     </div>
@@ -33,7 +35,9 @@
                     <div class="form-group">
                         <label class="col-md-3 control-label">{{'Hostname'|T}}</label>
                         <div class="col-md-6">
-                            <input type="text" name="hostname" class="form-control" placeholder="{{sys_email.alertHostnamePlaceholder}}" ng-model="sys_email.alert.hostname" resettable>
+                            <input ng-verify="required:false, maxlength:128" type="text" name="hostname" class="form-control" placeholder="{{sys_email.alertHostnamePlaceholder}}" ng-model="sys_email.alert.hostname" resettable>
+                            <p class="help-block" ng-show="sys_email.alert.hostname && sys_email.alert.hostname.length > 128" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please do not exceed 128 characters'|T}}</p>
+                            <p class="help-block" ng-show="sys_email.alert.hostname && !sys_email.isValidHostname(sys_email.alert.hostname)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please enter a valid IP address or FQDN'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group">
@@ -44,7 +48,7 @@
                     </div>
                     <div class="form-group" ng-show="alert.$dirty">
                         <div class="col-md-offset-3 col-md-9">
-                            <button type="submit" class="btn btn-primary" ng-click="sys_email.saveAlert(alert)">{{'Apply Changes'|T}}</button>
+                            <button type="submit" class="btn btn-primary" ng-click="sys_email.saveAlert(alert)" ng-disabled="sys_email.isAlertFormInvalid(alert, sys_email.alert.hostname)">{{'Apply Changes'|T}}</button>
                             <button type="reset" class="btn btn-default btn-cancel" ng-click="alert.$dirty=false;sys_email.cancel()">{{'Cancel'|T}}</button>
                         </div>
                     </div>
@@ -72,12 +76,15 @@
                         <label class="col-md-3 control-label">{{'External Email Server'|T}}</label>
                         <div class="col-md-6">
                             <input type="text" name="email_server" class="form-control" placeholder="" ng-model="sys_email.externalServer.email_server" ng-verify="required:true, minlength:1, maxlength:64, pattern:'^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?)$'" resettable>
+                            <p class="help-block" ng-show="sys_email.externalServer.email_server && sys_email.externalServer.email_server.length > 64" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please do not exceed 64 characters'|T}}</p>
+                            <p class="help-block" ng-show="sys_email.externalServer.email_server && !sys_email.isValidHostname(sys_email.externalServer.email_server)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please enter a valid IP address or hostname'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group">
                         <label class="col-md-3 control-label">{{'Server Port'|T}}</label>
                         <div class="col-md-6">
-                            <input type="number" name="server_port" class="form-control" placeholder="25" ng-model="sys_email.externalServer.server_port" min="0" max="65535" ng-verify="required:true" resettable>
+                            <input type="number" name="server_port" class="form-control" placeholder="25" ng-model="sys_email.externalServer.server_port" resettable>
+                            <p class="help-block" ng-show="sys_email.externalServer.server_port !== null && sys_email.externalServer.server_port !== undefined && sys_email.externalServer.server_port !== '' && (sys_email.externalServer.server_port > 65535 || sys_email.externalServer.server_port < 0)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please enter a valid port number (0-65535)'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group">
@@ -93,7 +100,7 @@
                     </div>
                     <div class="form-group" ng-show="externalServer.$dirty">
                         <div class="col-md-offset-3 col-md-9">
-                            <button type="submit" ng-verify="control:'externalServer'" class="btn btn-primary" ng-click="sys_email.saveExternalMailServer(externalServer)">{{'Apply Changes'|T}}</button>
+                            <button type="submit" class="btn btn-primary" ng-click="sys_email.saveExternalMailServer(externalServer)" ng-disabled="sys_email.isExternalServerFormInvalid(externalServer, sys_email.externalServer.email_server)">{{'Apply Changes'|T}}</button>
                             <button type="reset" class="btn btn-default btn-cancel" ng-click="externalServer.$dirty=false;sys_email.cancel()">{{'Cancel'|T}}</button>
                         </div>
                     </div>
@@ -114,17 +121,28 @@
                         <label class="col-md-3 control-label">{{'Email'|T}}</label>
                         <div class="col-md-6">
                             <input type="email" name="external_sender_email" class="form-control" placeholder="" ng-model="sys_email.externalSender.email" ng-verify="required:true, minlength:1, maxlength:32" resettable>
+                            <p class="help-block" ng-show="externalSender.external_sender_email.$error.email && (externalSender.external_sender_email.$dirty || externalSender.$submitted)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please enter a valid email address'|T}}</p>
+                            <p class="help-block" ng-show="sys_email.externalSender.email && sys_email.externalSender.email.length > 32" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please do not exceed 32 characters'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group">
                         <label class="col-md-3 control-label">{{'Password'|T}}</label>
                         <div class="col-md-6">
-                            <input type="password" name="external_sender_password" class="form-control" placeholder="" ng-model="sys_email.externalSender.password" ng-verify="required:true, minlength:1, maxlength:64" resettable>
+                            <div class="input-group">
+                                <input type="{{sys_email.showPassword ? 'text' : 'password'}}" name="external_sender_password" class="form-control" placeholder="" ng-model="sys_email.externalSender.password" ng-verify="required:true, minlength:1, maxlength:64" resettable>
+                                <span class="input-group-btn" ng-show="!sys_email.externalSender.password || !sys_email.externalSender.password.match(/^\*+$/)">
+                                    <button class="btn btn-default" type="button" ng-click="sys_email.showPassword = !sys_email.showPassword" title="{{sys_email.showPassword ? 'Hide Password' : 'Show Password'}}">
+                                        <i class="fa" ng-class="sys_email.showPassword ? 'fa-eye-slash' : 'fa-eye'"></i>
+                                    </button>
+                                </span>
+                            </div>
+                            <p class="help-block" ng-show="!sys_email.externalSender.password && (externalSender.external_sender_password.$dirty || externalSender.external_sender_password.$touched || externalSender.$submitted)" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Password is required'|T}}</p>
+                            <p class="help-block" ng-show="sys_email.externalSender.password && sys_email.externalSender.password.length > 64" style="font-size:12px; margin-top:5px; color:#d9534f;">{{'Please do not exceed 64 characters'|T}}</p>
                         </div>
                     </div>
                     <div class="form-group" ng-show="externalSender.$dirty">
                         <div class="col-md-offset-3 col-md-9">
-                            <button type="submit" ng-verify="control:'externalSender'" class="btn btn-primary" ng-click="sys_email.saveExternalSender(externalSender)">{{'Apply Changes'|T}}</button>
+                            <button type="submit" class="btn btn-primary" ng-click="sys_email.saveExternalSender(externalSender)" ng-disabled="sys_email.isExternalSenderFormInvalid(externalSender, sys_email.externalSender.email)">{{'Apply Changes'|T}}</button>
                             <button type="reset" class="btn btn-default btn-cancel" ng-click="externalSender.$dirty=false;sys_email.cancel()">{{'Cancel'|T}}</button>
                         </div>
                     </div>
@@ -152,10 +170,9 @@
                         </div>
                     </div>
                 </div>
-                <div class="table-toolbar"> 
+                <div class="table-toolbar">
                     <div class="">
                         <div class="btn-group">
-                            <button class="btn btn-link hive_enable_active" title="{{'Refresh'|T}}" ng-click="sys_email.refreshRelayList()"><i class="fa fa-refresh"></i></button>
                             <button class="btn btn-link" title="{{'Add'|T}}" ng-click="sys_email.showRelayAddModal()"><i class="fa fa-plus-circle"></i></button>
                             <button class="btn btn-link" title="{{'Clear All'|T}}" ng-click="sys_email.clearAllRelayServers()"><i class="fa fa-times-circle"></i></button>
                         </div>
@@ -176,7 +193,7 @@
                                     <td>{{row.host_name}}</td>
                                     <td>{{row.relay_server}}</td>
                                     <td>
-                                        <a title="{{'Delete'|T}}" class="fa fa-times-circle" href="" ng-click="sys_email.deleteRelay(row)"><span style="margin-left: 8px; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;">{{'Delete'|T}}</span></a>
+                                        <a title="{{'Delete'|T}}" class="fa fa-times-circle" href="" ng-click="sys_email.deleteRelay(row)"><span style="margin-left: 8px; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;"></span></a>
                                     </td>
                                 </tr>
                             </tbody>
Index: /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/relay-add.html
===================================================================
--- /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/relay-add.html	(revision 9230)
+++ /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/app/modules/system/submenu/sys_mgmt/email/relay-add.html	(working copy)
@@ -11,12 +11,16 @@
                     <label class="col-md-3 control-label">{{'Hostname'|T}}</label>
                     <div class="col-md-9">
                         <input ng-verify="required:true, minlength:1, maxlength:50" type="text" class="form-control" placeholder="" ng-model="relayAdd.data.host_name" name="host_name">
+                        <p class="help-block" ng-show="relayAdd.data.host_name && relayAdd.data.host_name.length > 50" style="font-size:12px; margin-top:5px; color:#d9534f;">Please do not exceed 50 characters</p>
+                        <p class="help-block" ng-show="relayAdd.data.host_name && !relayAdd.isValidHostname(relayAdd.data.host_name)" style="font-size:12px; margin-top:5px; color:#d9534f;">Please enter a valid IP address or FQDN</p>
                     </div>
                 </div>
                 <div class="form-group">
                     <label class="col-md-3 control-label">{{'Relay Server'|T}}</label>
                     <div class="col-md-9">
                         <input ng-verify="required:true, minlength:1, maxlength:30" type="text" class="form-control" placeholder="" ng-model="relayAdd.data.relay_server" name="relay_server">
+                        <p class="help-block" ng-show="relayAdd.data.relay_server && relayAdd.data.relay_server.length > 30" style="font-size:12px; margin-top:5px; color:#d9534f;">Please do not exceed 30 characters</p>
+                        <p class="help-block" ng-show="relayAdd.data.relay_server && !relayAdd.isValidHostname(relayAdd.data.relay_server)" style="font-size:12px; margin-top:5px; color:#d9534f;">Please enter a valid IP address or FQDN</p>
                     </div>
                 </div>
             </form>
@@ -25,5 +29,5 @@
 </div>
 <div class="modal-footer">
     <button type="button" class="btn btn-default" ng-click="relayAdd.modalClose()">{{'Cancel'|T}}</button>
-    <button ng-verify="control:'relayForm'" type="button" disabled="relayAdd.loading" class="btn btn-primary" ng-click="relayAdd.add(relayAdd.data)">{{'Save'|T}}</button>
+    <button type="button" disabled="relayAdd.loading" class="btn btn-primary" ng-click="relayAdd.add(relayAdd.data)" ng-disabled="relayAdd.isFormInvalid(relayForm, relayAdd.data.host_name, relayAdd.data.relay_server)">{{'Save'|T}}</button>
 </div>
Index: /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/index.html
===================================================================
--- /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/index.html	(revision 9230)
+++ /branches/rel_avx_2_7_5/src/webui/webui/htdocs/new/src/client/index.html	(working copy)
@@ -16,6 +16,6 @@
     </head>
     <body ng-controller="avxCtrl">
         <div ui-view></div>
-        <script src="app/scripts/avx.built.9920aa1e.js"></script>
+        <script src="app/scripts/avx.built.fcd117a5.js"></script>
     </body>
 </html>
