2020-02-11 21:06:34 +01:00
'use strict' ;
2020-09-01 16:31:23 +02:00
/* global $, angular, TASK_TYPES */
2024-01-09 14:59:29 +01:00
/* global async */
2020-02-11 21:06:34 +01:00
2020-11-12 16:38:48 +01:00
angular . module ( 'Application' ) . controller ( 'EmailsController' , [ '$scope' , '$location' , '$translate' , '$timeout' , 'Client' , function ( $scope , $location , $translate , $timeout , Client ) {
2021-12-02 09:29:33 -08:00
Client . onReady ( function ( ) { if ( ! Client . getUserInfo ( ) . isAtLeastMailManager ) $location . path ( '/' ) ; } ) ;
2020-02-11 21:06:34 +01:00
$scope . ready = false ;
$scope . config = Client . getConfig ( ) ;
2020-02-12 14:51:06 +01:00
$scope . user = Client . getUserInfo ( ) ;
2020-02-11 21:06:34 +01:00
$scope . domains = [ ] ;
2020-08-20 23:06:22 -07:00
$scope . mailLocation = {
2020-08-17 22:44:01 +02:00
busy : false ,
2020-09-02 14:12:38 +02:00
percent : 0 ,
2020-09-09 21:05:06 -07:00
message : '' ,
errorMessage : '' ,
2020-08-17 22:44:01 +02:00
2023-07-10 21:25:25 +05:30
currentLocation : { domain : null , subdomain : '' } ,
domain : null ,
subdomain : '' ,
tasks : [ ] ,
refreshTasks : function ( ) {
Client . getTasksByType ( TASK _TYPES . TASK _CHANGE _MAIL _LOCATION , function ( error , tasks ) {
2021-12-13 20:39:23 +01:00
if ( error ) return console . error ( error ) ;
2023-07-10 21:25:25 +05:30
$scope . mailLocation . tasks = tasks . slice ( 0 , 10 ) ;
if ( $scope . mailLocation . tasks . length && $scope . mailLocation . tasks [ 0 ] . active ) $scope . mailLocation . updateStatus ( ) ;
} ) ;
} ,
2021-12-13 20:39:23 +01:00
2023-07-10 21:25:25 +05:30
stop : function ( ) {
Client . stopTask ( $scope . mailLocation . tasks [ 0 ] . id , function ( error ) {
if ( error ) console . error ( error ) ;
$scope . mailLocation . busy = false ;
$scope . mailLocation . refreshTasks ( ) ;
2021-12-13 20:39:23 +01:00
} ) ;
} ,
2020-08-22 19:34:06 -07:00
refresh : function ( ) {
Client . getMailLocation ( function ( error , location ) {
if ( error ) return console . error ( 'Failed to get max email location' , error ) ;
2023-07-10 21:25:25 +05:30
$scope . mailLocation . currentLocation . subdomain = $scope . mailLocation . subdomain = location . subdomain ;
$scope . mailLocation . currentLocation . domain = $scope . mailLocation . domain = $scope . domains . find ( function ( d ) { return location . domain === d . domain ; } ) ;
2020-09-01 16:31:23 +02:00
2023-07-10 21:25:25 +05:30
$scope . mailLocation . refreshTasks ( ) ;
2020-08-22 19:34:06 -07:00
} ) ;
} ,
2020-09-01 16:31:23 +02:00
updateStatus : function ( ) {
2023-07-10 21:25:25 +05:30
var taskId = $scope . mailLocation . tasks [ 0 ] . id ;
Client . getTask ( taskId , function ( error , data ) {
2020-09-01 16:31:23 +02:00
if ( error ) return window . setTimeout ( $scope . mailLocation . updateStatus , 5000 ) ;
if ( ! data . active ) {
$scope . mailLocation . busy = false ;
$scope . mailLocation . message = '' ;
2023-07-10 21:25:25 +05:30
$scope . mailLocation . percent = 100 ;
2020-09-01 16:31:23 +02:00
$scope . mailLocation . errorMessage = data . success ? '' : data . error . message ;
2020-09-09 21:33:39 -07:00
2023-07-10 21:25:25 +05:30
$scope . mailLocation . refreshTasks ( ) ; // update the tasks list dropdown
2020-09-09 21:33:39 -07:00
2020-09-01 16:31:23 +02:00
return ;
}
$scope . mailLocation . busy = true ;
$scope . mailLocation . percent = data . percent ;
$scope . mailLocation . message = data . message ;
window . setTimeout ( $scope . mailLocation . updateStatus , 1000 ) ;
} ) ;
} ,
2023-07-10 21:25:25 +05:30
change : function ( ) {
2020-08-20 23:06:22 -07:00
$scope . mailLocation . busy = true ;
2023-07-10 21:25:25 +05:30
$scope . mailLocation . percent = 0 ;
$scope . mailLocation . message = '' ;
$scope . mailLocation . errorMessage = '' ;
2020-08-20 23:06:22 -07:00
2024-04-18 13:30:01 +02:00
Client . setMailLocation ( $scope . mailLocation . subdomain , $scope . mailLocation . domain . domain , function ( error ) {
2020-08-20 23:06:22 -07:00
if ( error ) {
2023-07-10 21:25:25 +05:30
console . error ( error ) ;
$scope . mailLocation . errorMessage = error . message ;
2020-08-20 23:06:22 -07:00
$scope . mailLocation . busy = false ;
2023-07-10 21:25:25 +05:30
} else {
$scope . mailLocation . refreshTasks ( ) ;
2020-08-20 23:06:22 -07:00
}
2021-02-16 12:40:27 -08:00
Client . refreshConfig ( ) ; // update config.mailFqdn
2020-08-20 23:06:22 -07:00
} ) ;
2020-08-17 22:44:01 +02:00
}
} ;
$scope . maxEmailSize = {
busy : false ,
error : null ,
size : 0 ,
currentSize : 0 ,
2020-08-22 19:34:06 -07:00
refresh : function ( ) {
Client . getMaxEmailSize ( function ( error , size ) {
if ( error ) return console . error ( 'Failed to get max email size' , error ) ;
$scope . maxEmailSize . currentSize = size ;
} ) ;
} ,
2020-08-17 22:44:01 +02:00
show : function ( ) {
$scope . maxEmailSize . busy = false ;
$scope . maxEmailSize . error = null ;
2020-08-20 22:07:20 -07:00
$scope . maxEmailSize . size = $scope . maxEmailSize . currentSize ;
2020-08-17 22:44:01 +02:00
$scope . maxEmailSizeChangeForm . $setUntouched ( ) ;
$scope . maxEmailSizeChangeForm . $setPristine ( ) ;
$ ( '#maxEmailSizeChangeModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
2020-08-20 22:07:20 -07:00
$scope . maxEmailSize . busy = true ;
2024-03-12 15:35:20 +01:00
Client . setMaxEmailSize ( parseInt ( $scope . maxEmailSize . size ) , function ( error ) {
2020-08-20 22:07:20 -07:00
$scope . maxEmailSize . busy = false ;
if ( error ) return console . error ( error ) ;
$scope . maxEmailSize . currentSize = $scope . maxEmailSize . size ;
$ ( '#maxEmailSizeChangeModal' ) . modal ( 'hide' ) ;
} ) ;
2020-08-17 22:44:01 +02:00
}
} ;
2023-09-20 21:55:24 +05:30
$scope . virtualAllMail = {
busy : false ,
error : null ,
enabled : false ,
refresh : function ( ) {
Client . getVirtualAllMail ( function ( error , enabled ) {
if ( error ) return console . error ( 'Failed to get max email size' , error ) ;
$scope . virtualAllMail . enabled = enabled ;
} ) ;
} ,
show : function ( ) {
$scope . virtualAllMail . busy = false ;
$scope . virtualAllMail . error = null ;
$ ( '#virtualAllMailChangeModal' ) . modal ( 'show' ) ;
} ,
submit : function ( enable ) {
$scope . virtualAllMail . busy = true ;
Client . setVirtualAllMail ( enable , function ( error ) {
$scope . virtualAllMail . busy = false ;
if ( error ) return console . error ( error ) ;
$scope . virtualAllMail . enabled = enable ;
$ ( '#virtualAllMailChangeModal' ) . modal ( 'hide' ) ;
} ) ;
}
} ;
2021-12-08 11:33:36 -08:00
$scope . mailboxSharing = {
busy : false ,
error : null ,
2021-12-08 11:33:36 -08:00
enabled : null , // null means we have not refreshed yet
2021-12-08 11:33:36 -08:00
refresh : function ( ) {
Client . getMailboxSharing ( function ( error , enabled ) {
if ( error ) return console . error ( 'Failed to get mailbox sharing' , error ) ;
$scope . mailboxSharing . enabled = enabled ;
} ) ;
} ,
submit : function ( ) {
$scope . mailboxSharing . busy = true ;
2021-12-08 11:33:36 -08:00
Client . setMailboxSharing ( ! $scope . mailboxSharing . enabled , function ( error ) {
// give sometime for mail server to restart
$timeout ( function ( ) {
$scope . mailboxSharing . busy = false ;
if ( error ) return console . error ( error ) ;
$scope . mailboxSharing . enabled = ! $scope . mailboxSharing . enabled ;
} , 3000 ) ;
2021-12-08 11:33:36 -08:00
} ) ;
}
} ;
2024-11-30 17:42:26 +01:00
$scope . ftsConfig = {
2020-11-19 17:45:16 -08:00
busy : false ,
error : { } ,
2020-12-02 17:33:54 -08:00
currentConfig : null , // null means not loaded yet
2020-11-19 17:45:16 -08:00
enabled : false ,
2020-12-02 17:16:59 -08:00
running : false ,
2020-12-02 17:33:54 -08:00
enoughMemory : false ,
2020-11-19 17:45:16 -08:00
refresh : function ( ) {
2020-12-02 17:16:59 -08:00
Client . getService ( 'mail' , function ( error , result ) {
if ( error ) return console . log ( 'Error getting status of mail conatiner' , error ) ;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . enoughMemory = result . config . memoryLimit > ( 1024 * 1024 * 1024 * 2 ) ;
$scope . ftsConfig . running = result . healthcheck && result . healthcheck . solr . status && result . healthcheck . tika . status ;
2020-12-02 17:33:54 -08:00
2024-11-30 17:42:26 +01:00
Client . getFtsConfig ( function ( error , config ) {
2020-12-02 17:16:59 -08:00
if ( error ) return console . error ( 'Failed to get solr config' , error ) ;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . currentConfig = config ;
2020-12-02 17:16:59 -08:00
} ) ;
2020-11-19 17:45:16 -08:00
} ) ;
} ,
show : function ( ) {
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . busy = false ;
$scope . ftsConfig . error = null ;
$scope . ftsConfig . enabled = $scope . ftsConfig . currentConfig . enabled ;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$ ( '#ftsConfigModal' ) . modal ( 'show' ) ;
2020-11-19 17:45:16 -08:00
} ,
2022-02-09 16:22:44 +01:00
submit : function ( newState ) {
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . busy = true ;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
Client . setFtsConfig ( newState , function ( error ) {
2020-11-19 17:45:16 -08:00
if ( error ) return console . error ( error ) ;
2020-12-02 16:48:20 -08:00
$timeout ( function ( ) {
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . busy = false ;
2020-12-04 15:51:36 -08:00
// FIXME: these values are fake. but cannot get current status from mail server since it might be restarting
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . currentConfig . enabled = newState ;
$scope . ftsConfig . running = newState ;
2020-12-04 15:51:36 -08:00
2024-11-30 17:42:26 +01:00
$timeout ( function ( ) { $scope . ftsConfig . refresh ( ) ; } , 20000 ) ; // get real values after 20 seconds
2020-12-04 15:51:36 -08:00
2024-11-30 17:42:26 +01:00
$ ( '#ftsConfigModal' ) . modal ( 'hide' ) ;
2020-12-02 16:48:20 -08:00
} , 5000 ) ;
2020-11-19 17:45:16 -08:00
} ) ;
}
} ;
2020-08-22 13:01:25 -07:00
$scope . spamConfig = {
2020-08-17 22:44:01 +02:00
busy : false ,
2020-08-22 13:01:25 -07:00
error : { } ,
2024-05-23 16:35:35 +02:00
acl : { allowlist : [ ] , blocklist : [ ] } ,
2020-08-22 13:01:25 -07:00
customConfig : '' ,
config : '' ,
2024-05-23 16:35:35 +02:00
blocklist : '' , // currently, we don't support allowlist because it requires user to understand a bit more of what he is doing
2020-08-22 13:01:25 -07:00
refresh : function ( ) {
Client . getSpamCustomConfig ( function ( error , config ) {
if ( error ) return console . error ( 'Failed to get custom spam config' , error ) ;
$scope . spamConfig . customConfig = config ;
} ) ;
Client . getSpamAcl ( function ( error , acl ) {
if ( error ) return console . error ( 'Failed to get spam acl' , error ) ;
$scope . spamConfig . acl = acl ;
} ) ;
} ,
2020-08-17 22:44:01 +02:00
show : function ( ) {
2020-08-22 13:01:25 -07:00
$scope . spamConfig . busy = false ;
$scope . spamConfig . error = { } ;
2024-05-23 16:35:35 +02:00
$scope . spamConfig . blocklist = $scope . spamConfig . acl . blocklist . join ( '\n' ) ;
2020-08-22 13:01:25 -07:00
$scope . spamConfig . config = $scope . spamConfig . customConfig ;
2020-08-17 22:44:01 +02:00
2020-08-22 13:01:25 -07:00
$scope . spamConfigChangeForm . $setUntouched ( ) ;
$scope . spamConfigChangeForm . $setPristine ( ) ;
2020-08-17 22:44:01 +02:00
2020-08-22 13:01:25 -07:00
$ ( '#spamConfigChangeModal' ) . modal ( 'show' ) ;
2020-08-17 22:44:01 +02:00
} ,
submit : function ( ) {
2020-08-22 13:01:25 -07:00
$scope . spamConfig . busy = true ;
$scope . spamConfig . error = { } ;
2024-05-23 16:35:35 +02:00
var blocklist = $scope . spamConfig . blocklist . split ( '\n' ) . filter ( function ( l ) { return l !== '' ; } ) ;
2020-08-22 13:01:25 -07:00
2024-05-23 16:35:35 +02:00
Client . setSpamAcl ( { blocklist : blocklist , allowlist : [ ] } , function ( error ) {
2020-08-22 13:01:25 -07:00
if ( error ) {
$scope . spamConfig . busy = false ;
2024-05-23 16:35:35 +02:00
$scope . spamConfig . error . blocklist = error . message ;
$scope . spamConfigChangeForm . blocklist . $setPristine ( ) ;
2020-08-22 13:01:25 -07:00
return ;
}
Client . setSpamCustomConfig ( $scope . spamConfig . config , function ( error ) {
if ( error ) {
$scope . spamConfig . busy = false ;
$scope . spamConfig . error . config = error . message ;
$scope . spamConfigChangeForm . config . $setPristine ( ) ;
return ;
}
$scope . spamConfig . busy = false ;
$scope . spamConfig . refresh ( ) ;
$ ( '#spamConfigChangeModal' ) . modal ( 'hide' ) ;
} ) ;
} ) ;
2020-08-17 22:44:01 +02:00
}
2020-08-20 23:06:22 -07:00
} ,
2020-08-17 22:44:01 +02:00
2021-10-13 14:22:37 -07:00
$scope . acl = {
busy : false ,
error : { } ,
dnsblZones : '' ,
dnsblZonesCount : 0 ,
refresh : function ( ) {
Client . getDnsblConfig ( function ( error , result ) {
if ( error ) return console . error ( 'Failed to get email acl' , error ) ;
$scope . acl . dnsblZones = result . zones . join ( '\n' ) ;
$scope . acl . dnsblZonesCount = result . zones . length ;
} ) ;
} ,
show : function ( ) {
$scope . acl . busy = false ;
$scope . acl . error = { } ;
$scope . aclChangeForm . $setUntouched ( ) ;
$scope . aclChangeForm . $setPristine ( ) ;
$ ( '#aclChangeModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
$scope . acl . busy = true ;
$scope . acl . error = { } ;
var zones = $scope . acl . dnsblZones . split ( '\n' ) . filter ( function ( l ) { return l !== '' ; } ) ;
Client . setDnsblConfig ( zones , function ( error ) {
if ( error ) {
$scope . acl . busy = false ;
$scope . acl . error . dnsblZones = error . message ;
$scope . aclChangeForm . dnsblZones . $setPristine ( ) ;
return ;
}
$scope . acl . busy = false ;
$scope . acl . refresh ( ) ;
$ ( '#aclChangeModal' ) . modal ( 'hide' ) ;
} ) ;
}
} ,
2020-02-12 14:51:06 +01:00
$scope . testEmail = {
busy : false ,
error : { } ,
mailTo : '' ,
domain : null ,
clearForm : function ( ) {
$scope . testEmail . mailTo = '' ;
} ,
show : function ( domain ) {
$scope . testEmail . error = { } ;
$scope . testEmail . busy = false ;
$scope . testEmail . domain = domain ;
$scope . testEmail . mailTo = $scope . user . email ;
$ ( '#testEmailModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
$scope . testEmail . error = { } ;
$scope . testEmail . busy = true ;
Client . sendTestMail ( $scope . testEmail . domain . domain , $scope . testEmail . mailTo , function ( error ) {
$scope . testEmail . busy = false ;
if ( error ) {
$scope . testEmail . error . generic = error . message ;
console . error ( error ) ;
$ ( '#inputTestMailTo' ) . focus ( ) ;
return ;
}
$ ( '#testEmailModal' ) . modal ( 'hide' ) ;
} ) ;
}
} ;
2024-01-09 14:59:29 +01:00
function refreshMailStatus ( domain , done ) {
Client . getMailStatusForDomain ( domain . domain , function ( error , result ) {
if ( error ) {
console . error ( 'Failed to fetch mail status for domain' , domain . domain , error ) ;
return done ( ) ;
}
2020-02-12 14:10:21 +01:00
2024-01-09 14:59:29 +01:00
domain . status = result ;
2020-02-27 13:27:45 +01:00
2024-01-09 14:59:29 +01:00
domain . statusOk = Object . keys ( result ) . every ( function ( k ) {
if ( k === 'dns' ) return Object . keys ( result . dns ) . every ( function ( k ) { return result . dns [ k ] . status ; } ) ;
2020-02-27 10:37:21 -08:00
2024-01-09 14:59:29 +01:00
if ( ! ( 'status' in result [ k ] ) ) return true ; // if status is not present, the test was not run
2020-02-27 10:37:21 -08:00
2024-01-09 14:59:29 +01:00
return result [ k ] . status ;
2020-02-12 14:10:21 +01:00
} ) ;
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
done ( ) ;
} ) ;
}
function refreshMailConfig ( domain , done ) {
Client . getMailConfigForDomain ( domain . domain , function ( error , mailConfig ) {
if ( error ) {
console . error ( 'Failed to fetch mail config for domain' , domain . domain , error ) ;
return done ( ) ;
}
domain . inbound = mailConfig . enabled ;
domain . outbound = mailConfig . relay . provider !== 'noop' ;
// do this even if no outbound since people forget to remove mailboxes
Client . getMailboxCount ( domain . domain , function ( error , count ) {
if ( error ) {
console . error ( 'Failed to fetch mailboxes for domain' , domain . domain , error ) ;
return done ( ) ;
}
domain . mailboxCount = count ;
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
done ( ) ;
} ) ;
} ) ;
}
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
function refreshMailUsage ( domain , done ) {
Client . getMailUsage ( domain . domain , function ( error , usage ) {
if ( error ) {
console . error ( 'Failed to fetch usage for domain' , domain . domain , error ) ;
return done ( ) ;
}
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
domain . usage = 0 ;
// we used to use quotaValue here but it's quite different wrt diskSize. so choose diskSize consistently
// also, quotaValue can be missing for deleted mailboxes that are on disk but removed from dovecot/ldap itself
Object . keys ( usage ) . forEach ( function ( m ) { domain . usage += usage [ m ] . diskSize ; } ) ;
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
done ( ) ;
} ) ;
}
2020-02-20 12:35:51 -08:00
2024-01-09 14:59:29 +01:00
function refreshDomainStatuses ( ) {
async . each ( $scope . domains , function ( domain , iteratorDone ) {
async . series ( [
refreshMailStatus . bind ( null , domain ) ,
refreshMailConfig . bind ( null , domain ) ,
] , function ( ) {
domain . loading = false ;
iteratorDone ( ) ;
} ) ;
} , function ( ) {
// mail usage is loaded separately with a cancellation check. when there are a lot of domains, it runs a long time in background and slows down loading of new views
async . eachLimit ( $scope . domains , 5 , function ( domain , itemDone ) {
if ( $scope . $$destroyed ) return itemDone ( ) ; // abort!
refreshMailUsage ( domain , function ( ) {
domain . loadingUsage = false ;
itemDone ( ) ;
2020-02-20 12:35:51 -08:00
} ) ;
} ) ;
2020-02-12 14:10:21 +01:00
} ) ;
}
2020-02-11 21:06:34 +01:00
Client . onReady ( function ( ) {
Client . getDomains ( function ( error , domains ) {
if ( error ) return console . error ( 'Unable to get domain listing.' , error ) ;
2024-01-09 14:59:29 +01:00
domains . forEach ( function ( domain ) { domain . loading = true ; domain . loadingUsage = true ; } ) ; // used by ui to show 'loading'
2020-02-11 21:06:34 +01:00
$scope . domains = domains ;
2024-01-09 14:59:29 +01:00
2020-02-11 21:06:34 +01:00
$scope . ready = true ;
2020-02-11 22:07:58 -08:00
2024-01-04 21:20:26 +01:00
if ( $scope . user . isAtLeastAdmin ) {
2021-12-02 09:29:33 -08:00
$scope . mailLocation . refresh ( ) ;
$scope . maxEmailSize . refresh ( ) ;
2023-09-20 21:55:24 +05:30
$scope . virtualAllMail . refresh ( ) ;
2021-12-08 11:33:36 -08:00
$scope . mailboxSharing . refresh ( ) ;
2021-12-02 09:29:33 -08:00
$scope . spamConfig . refresh ( ) ;
2024-11-30 17:42:26 +01:00
$scope . ftsConfig . refresh ( ) ;
2021-12-02 09:29:33 -08:00
$scope . acl . refresh ( ) ;
}
2020-09-01 16:31:23 +02:00
2020-02-12 14:10:21 +01:00
refreshDomainStatuses ( ) ;
2020-02-11 21:06:34 +01:00
} ) ;
} ) ;
2020-02-12 14:51:06 +01:00
// setup all the dialog focus handling
[ 'testEmailModal' ] . forEach ( function ( id ) {
$ ( '#' + id ) . on ( 'shown.bs.modal' , function ( ) {
$ ( this ) . find ( '[autofocus]:first' ) . focus ( ) ;
} ) ;
} ) ;
2020-02-11 21:06:34 +01:00
$ ( '.modal-backdrop' ) . remove ( ) ;
} ] ) ;