diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc
index 0666bb9b3f..fbd3226025 100644
--- a/Documentation/SOGoInstallationGuide.asciidoc
+++ b/Documentation/SOGoInstallationGuide.asciidoc
@@ -2285,6 +2285,13 @@ SOGoForwardConstraintsDomains = ("gmail.com", "googlemail.com");
will allow users to forward emails to only `gmail.com` and `googlemail.com` domains.
When empty or undefined, no constraints are imposed.
+|D |SOGoNotificationEnabled
+|Parameter used to activate the edition from the preferences window of
+notifications for emails. Requires Sieve script support on the IMAP
+host.
+
+Defaults to `NO` when unset.
+
|D |SOGoSieveScriptsEnabled
|Parameter used to activate the edition from the preferences windows of
server-side mail filters. Requires Sieve script support on the IMAP
diff --git a/SoObjects/SOGo/SOGoDomainDefaults.h b/SoObjects/SOGo/SOGoDomainDefaults.h
index c03c9040d1..cd9f8b929c 100644
--- a/SoObjects/SOGo/SOGoDomainDefaults.h
+++ b/SoObjects/SOGo/SOGoDomainDefaults.h
@@ -53,6 +53,7 @@
- (BOOL) forwardEnabled;
- (int) forwardConstraints;
- (NSArray *) forwardConstraintsDomains;
+- (BOOL) notificationEnabled;
- (BOOL) vacationEnabled;
- (BOOL) vacationPeriodEnabled;
- (NSString *) vacationDefaultSubject;
diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m
index 5e5a6faf6a..86fdd8de7a 100644
--- a/SoObjects/SOGo/SOGoDomainDefaults.m
+++ b/SoObjects/SOGo/SOGoDomainDefaults.m
@@ -225,6 +225,11 @@ - (NSArray *) forwardConstraintsDomains
return [self stringArrayForKey: @"SOGoForwardConstraintsDomains"];
}
+- (BOOL) notificationEnabled
+{
+ return [self boolForKey: @"SOGoNotificationEnabled"];
+}
+
- (BOOL) vacationEnabled
{
return [self boolForKey: @"SOGoVacationEnabled"];
diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m
index 24dddf5207..7cd1d3dc53 100644
--- a/SoObjects/SOGo/SOGoSieveManager.m
+++ b/SoObjects/SOGo/SOGoSieveManager.m
@@ -206,7 +206,7 @@ + (void) initialize
@"imapflags", @"removeflag",
@"imapflags", @"flag",
@"vacation", @"vacation",
- @"notify", @"notify",
+ @"notify", @"enotify",
@"fileinto", @"fileinto",
@"reject", @"reject",
@"regex", @"regex",
@@ -543,6 +543,12 @@ - (NSString *) _extractSieveAction: (NSDictionary *) action
else if ([method isEqualToString: @"redirect"])
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
+ else if ([method isEqualToString: @"notify"])
+ {
+ argument = [NSString stringWithFormat: @"mailto:%@", argument];
+ sieveAction = [NSString stringWithFormat: @"%@ %@",
+ method, [argument asSieveQuotedString]];
+ }
else if ([method isEqualToString: @"reject"])
sieveAction = [NSString stringWithFormat: @"%@ %@",
method, [argument asSieveQuotedString]];
@@ -863,7 +869,7 @@ - (NSException *) updateFiltersForAccount: (SOGoMailAccount *) theAccount
error = nil;
dd = [user domainDefaults];
- if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled]))
+ if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled] || [dd notificationEnabled]))
return error;
req = [NSMutableArray arrayWithCapacity: 15];
@@ -1207,6 +1213,40 @@ - (NSException *) updateFiltersForAccount: (SOGoMailAccount *) theAccount
}
}
+ // We handle mail notification
+ values = [ud notificationOptions];
+
+ if (values && [[values objectForKey: @"enabled"] boolValue])
+ {
+ // BOOL alwaysSend;
+ NSString *notify;
+ id addresses;
+ int i;
+
+ // alwaysSend = [[values objectForKey: @"alwaysSend"] boolValue];
+ b = YES;
+
+ [req addObjectUniquely: @"enotify"];
+
+ addresses = [values objectForKey: @"notificationAddress"];
+ if ([addresses isKindOfClass: [NSString class]])
+ addresses = [addresses componentsSeparatedByString: @","];
+
+ for (i = 0; i < [addresses count]; i++)
+ {
+ v = [addresses objectAtIndex: i];
+ if (v && [v length] > 0)
+ {
+ notify = [NSString stringWithFormat: @"notify \"mailto:%@\";\r\n", v];
+
+ // if (alwaysSend)
+ // [script insertString: notify atIndex: 0];
+ // else
+ [script appendString: notify];
+ }
+ }
+ }
+
// We handle header/footer Sieve scripts
if ((v = [dd sieveScriptHeaderTemplateFile]))
{
diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h
index 3c81d38246..d2b4479e21 100644
--- a/SoObjects/SOGo/SOGoUserDefaults.h
+++ b/SoObjects/SOGo/SOGoUserDefaults.h
@@ -222,6 +222,9 @@ extern NSString *SOGoPasswordRecoverySecondaryEmail;
- (void) setForwardOptions: (NSDictionary *) newValue;
- (NSDictionary *) forwardOptions;
+- (void) setNotificationOptions: (NSDictionary *) newValue;
+- (NSDictionary *) notificationOptions;
+
- (void) setMailLabelsColors: (NSDictionary *) newValues;
- (NSDictionary *) mailLabelsColors;
diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m
index 28d8a494cf..5e0887ef7c 100644
--- a/SoObjects/SOGo/SOGoUserDefaults.m
+++ b/SoObjects/SOGo/SOGoUserDefaults.m
@@ -989,6 +989,16 @@ - (NSDictionary *) forwardOptions
return [self dictionaryForKey: @"Forward"];
}
+- (void) setNotificationOptions: (NSDictionary *) newValue
+{
+ [self setObject: newValue forKey: @"Notification"];
+}
+
+- (NSDictionary *) notificationOptions
+{
+ return [self dictionaryForKey: @"Notification"];
+}
+
- (void) setContactsCategories: (NSArray *) newValues
{
[self setObject: newValues forKey: @"SOGoContactsCategories"];
diff --git a/UI/PreferencesUI/English.lproj/Localizable.strings b/UI/PreferencesUI/English.lproj/Localizable.strings
index 4c5110e0d5..02da52e25b 100644
--- a/UI/PreferencesUI/English.lproj/Localizable.strings
+++ b/UI/PreferencesUI/English.lproj/Localizable.strings
@@ -80,6 +80,9 @@
"You are not allowed to forward your messages to an internal email address." = "You are not allowed to forward your messages to an internal email address.";
"You are not allowed to forward your messages to this domain:" = "You are not allowed to forward your messages to this domain:";
+/* notification */
+"Notify incoming messsages" = "Notify incoming messsages";
+
/* d & t */
"Time Zone" = "Time Zone";
"Short Date Format" = "Short Date Format";
@@ -411,6 +414,7 @@
"Keep the message" = "Keep the message";
"Forward the message to" = "Forward the message to";
+"Notify the message to" = "Notify the message to";
/* Input field label of "forward" mail filter action */
"Email" = "Email";
diff --git a/UI/PreferencesUI/French.lproj/Localizable.strings b/UI/PreferencesUI/French.lproj/Localizable.strings
index 67335a58cc..c59e693f19 100644
--- a/UI/PreferencesUI/French.lproj/Localizable.strings
+++ b/UI/PreferencesUI/French.lproj/Localizable.strings
@@ -68,7 +68,7 @@
= "La date de fin de la réponse automatique doit être dans le futur.";
/* forward messages */
-"Forward incoming messages" = "Transférer les messages entrant";
+"Forward incoming messages" = "Transférer les messages entrants";
"Always forward" = "Toujours transférer";
"Incoming messages are forwarded prior to apply your filters." = "Le courrier entrant est transféré d'appliquer vos filtres.";
"Keep a copy" = "Garder une copie";
@@ -80,6 +80,9 @@
"You are not allowed to forward your messages to an internal email address." = "Il est interdit de renvoyer vos messages vers une adresse interne.";
"You are not allowed to forward your messages to this domain:" = "Vous ne pouvez pas transférer vos messages à ce domaine :";
+/* notify messages */
+"Notify incoming messsages" = "Notifier les messages entrants";
+
/* d & t */
"Time Zone" = "Fuseau horaire";
"Short Date Format" = "Style de date courte";
@@ -411,6 +414,7 @@
"Keep the message" = "Conserver le message";
"Forward the message to" = "Faire suivre le message à";
+"Notify the message to" = "Notifier le message à";
/* Input field label of "forward" mail filter action */
"Email" = "Email";
diff --git a/UI/PreferencesUI/UIxJSONPreferences.m b/UI/PreferencesUI/UIxJSONPreferences.m
index 26ef076daa..3af2fdc9c7 100644
--- a/UI/PreferencesUI/UIxJSONPreferences.m
+++ b/UI/PreferencesUI/UIxJSONPreferences.m
@@ -395,9 +395,14 @@ - (NSString *) jsonDefaults
}
if ([domainDefaults forwardEnabled] && ![defaults forwardOptions])
- {
- [defaults setForwardOptions: [NSDictionary new]];
- }
+ {
+ [defaults setForwardOptions: [NSDictionary new]];
+ }
+
+ if ([domainDefaults notificationEnabled] && ![defaults notificationOptions])
+ {
+ [defaults setNotificationOptions: [NSDictionary new]];
+ }
if ([[defaults source] dirty])
[defaults synchronize];
diff --git a/UI/PreferencesUI/UIxPreferences.h b/UI/PreferencesUI/UIxPreferences.h
index d0de5593fe..6ff7ecebf4 100644
--- a/UI/PreferencesUI/UIxPreferences.h
+++ b/UI/PreferencesUI/UIxPreferences.h
@@ -42,7 +42,7 @@
// Sieve filtering
NSArray *daysOfWeek, *daysBetweenResponsesList;
NSArray *sieveFilters;
- NSMutableDictionary *vacationOptions, *forwardOptions;
+ NSMutableDictionary *vacationOptions, *forwardOptions, *notificationOptions;
BOOL mailCustomFromEnabled;
BOOL forwardEnabled;
diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m
index 59e3c3e6f7..643a9f8257 100644
--- a/UI/PreferencesUI/UIxPreferences.m
+++ b/UI/PreferencesUI/UIxPreferences.m
@@ -136,13 +136,20 @@ - (id) init
vacationOptions = [NSMutableDictionary new];
}
- if ([dd forwardEnabled])
+ if ([dd forwardEnabled])
{
forwardOptions = [[userDefaults forwardOptions] mutableCopy];
if (!forwardOptions)
forwardOptions = [NSMutableDictionary new];
}
+ if ([dd notificationEnabled])
+ {
+ notificationOptions = [[userDefaults notificationOptions] mutableCopy];
+ if (!notificationOptions)
+ notificationOptions = [NSMutableDictionary new];
+ }
+
mailCustomFromEnabled = [dd mailCustomFromEnabled];
forwardEnabled = [dd forwardEnabled];
@@ -160,6 +167,7 @@ - (void) dealloc
[sieveFilters release];
[vacationOptions release];
[forwardOptions release];
+ [notificationOptions release];
[daysOfWeek release];
[addressBooksIDWithDisplayName release];
[client release];
@@ -989,6 +997,15 @@ - (NSString *) forwardConstraintsDomains
return [domains jsonRepresentation];
}
+/* mail notifications */
+//
+// Used by templates
+//
+- (BOOL) isNotificationEnabled
+{
+ return [[user domainDefaults] notificationEnabled];
+}
+
//
// Used by templates
//
@@ -1727,7 +1744,8 @@ - (NSString *) forwardEnabled
dd = [[context activeUser] domainDefaults];
// We check if the Sieve server is available *ONLY* if at least one of the option is enabled
- if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled]) || [self _isSieveServerAvailable])
+ if (([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled] || [dd notificationEnabled])
+ || [self _isSieveServerAvailable])
{
BOOL forceActivation = ![[v objectForKey: @"hasActiveExternalSieveScripts"] boolValue];
diff --git a/UI/Templates/PreferencesUI/UIxFilterEditor.wox b/UI/Templates/PreferencesUI/UIxFilterEditor.wox
index eb93a8e1e1..aed0077f22 100644
--- a/UI/Templates/PreferencesUI/UIxFilterEditor.wox
+++ b/UI/Templates/PreferencesUI/UIxFilterEditor.wox
@@ -130,6 +130,12 @@
+
+
+
+
+
+
diff --git a/UI/Templates/PreferencesUI/UIxPreferences.wox b/UI/Templates/PreferencesUI/UIxPreferences.wox
index 05b4b75c9f..dcc9941972 100644
--- a/UI/Templates/PreferencesUI/UIxPreferences.wox
+++ b/UI/Templates/PreferencesUI/UIxPreferences.wox
@@ -16,6 +16,7 @@
diff --git a/UI/WebServerResources/js/Preferences/FiltersDialogController.js b/UI/WebServerResources/js/Preferences/FiltersDialogController.js
index 5d3003570c..39d1274606 100644
--- a/UI/WebServerResources/js/Preferences/FiltersDialogController.js
+++ b/UI/WebServerResources/js/Preferences/FiltersDialogController.js
@@ -12,6 +12,7 @@
var vm = this,
sieveCapabilities = $window.sieveCapabilities,
forwardEnabled = $window.forwardEnabled,
+ notificationEnabled = $window.notificationEnabled,
vacationEnabled = $window.vacationEnabled;
this.filter = filter;
@@ -40,6 +41,9 @@
if (forwardEnabled)
this.methodLabels.redirect = l("Forward the message to");
+ if (notificationEnabled)
+ this.methodLabels.notify = l("Notify the message to");
+
//if (vacationEnabled)
// this.methodLabels.vacation = l("Send a vacation message");
@@ -59,6 +63,7 @@
"keep",
"discard",
"redirect",
+ "notify",
"reject"
];
this.methods = _.intersection(this.methods, _.keys(this.methodLabels));
@@ -112,6 +117,15 @@
this.invalid = err.message;
return false;
}
+ try {
+ _.forEach(_.filter(this.filter.actions, { 'method': 'notify' }), function (action) {
+ validateForwardAddress(action.argument);
+ });
+ } catch (err) {
+ //Dialog.alert(l('Error'), err);
+ this.invalid = err.message;
+ return false;
+ }
}
$mdDialog.hide();
};
diff --git a/UI/WebServerResources/js/Preferences/Preferences.service.js b/UI/WebServerResources/js/Preferences/Preferences.service.js
index 5f1e889b54..b43c43733e 100644
--- a/UI/WebServerResources/js/Preferences/Preferences.service.js
+++ b/UI/WebServerResources/js/Preferences/Preferences.service.js
@@ -150,6 +150,13 @@
data.Forward.forwardAddress = [];
}
+ if (data.Notification) {
+ if (angular.isString(data.Notification.notificationAddress))
+ data.Notification.notificationAddress = data.Notification.notificationAddress.split(/, */);
+ else if (!angular.isArray(data.Notification.notificationAddress))
+ data.Notification.notificationAddress = [];
+ }
+
// Split calendar categories colors keys and values
if (angular.isUndefined(data.SOGoCalendarCategories))
data.SOGoCalendarCategories = [];
@@ -865,6 +872,9 @@
if (preferences.defaults.Forward && preferences.defaults.Forward.forwardAddress)
preferences.defaults.Forward.forwardAddress = _.compact(preferences.defaults.Forward.forwardAddress);
+ if (preferences.defaults.Notification && preferences.defaults.Notification.notificationAddress)
+ preferences.defaults.Notification.notificationAddress = _.compact(preferences.defaults.Notification.notificationAddress);
+
// Merge back calendar categories colors keys and values
preferences.defaults.SOGoCalendarCategoriesColors = {};
_.forEach(preferences.defaults.SOGoCalendarCategories, function(key, i) {
diff --git a/UI/WebServerResources/js/Preferences/PreferencesController.js b/UI/WebServerResources/js/Preferences/PreferencesController.js
index 066cf01f89..3d05a1a4da 100644
--- a/UI/WebServerResources/js/Preferences/PreferencesController.js
+++ b/UI/WebServerResources/js/Preferences/PreferencesController.js
@@ -17,7 +17,7 @@
this.timeZonesList = $window.timeZonesList;
this.timeZonesSearchText = '';
this.addressesSearchText = '';
- this.autocompleteForward = {};
+ this.autocomplete = {forward: [], notification: []};
this.mailLabelKeyRE = new RegExp(/^(?!^_\$)[^(){} %*\"\\\\]*?$/);
this.emailSeparatorKeys = Preferences.defaults.emailSeparatorKeys;
if (Preferences.defaults.SOGoMailAutoMarkAsReadMode == 'delay')
@@ -415,6 +415,20 @@
}
}
+ // We check if we're allowed or not to notify based on the domain defaults
+ if (this.preferences.defaults.Notification && this.preferences.defaults.Notification.enabled &&
+ this.preferences.defaults.Notification.notificationAddress) {
+ addresses = this.preferences.defaults.Notification.notificationAddress;
+ try {
+ for (i = 0; i < addresses.length; i++) {
+ validateForwardAddress(addresses[i]);
+ }
+ } catch (err) {
+ Dialog.alert(l('Error'), err);
+ sendForm = false;
+ }
+ }
+
// IMAP labels must be unique
if (this.preferences.defaults.SOGoMailLabelsColorsKeys.length !=
this.preferences.defaults.SOGoMailLabelsColorsValues.length ||
@@ -650,10 +664,10 @@
}
};
- this.addRecipient = function (contact) {
+ this.addRecipient = function (contact, element) {
var recipients, recipient, list, i, address;
- recipients = this.preferences.defaults.Forward.forwardAddress;
+ recipients = this.autocomplete[element];
if (angular.isString(contact)) {
// Examples that are handled:
@@ -678,7 +692,7 @@
if (address && recipients.indexOf(address) < 0)
recipients.push(address);
- return null;
+ return address;
}
if (contact.$isList({expandable: true})) {
@@ -712,7 +726,7 @@
else {
recipient = contact.$shortFormat();
}
-
+
if (recipient)
return recipient;
else