diff --git a/NEWS b/NEWS index 3ad0c3c01..68df3bffb 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ 3.2.6 (2017-02-DD) ------------------ +New features + - [web] use "date" extension of Sieve to enable/disable vacation auto-reply (#1530, #1949) + Enhancements - [web] show locale codes beside language names in Preferences module - [web] fixed visual glitches in Month view with Firefox diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m index 0df2f1bc5..30979a082 100644 --- a/SoObjects/SOGo/SOGoSieveManager.m +++ b/SoObjects/SOGo/SOGoSieveManager.m @@ -365,7 +365,7 @@ static NSString *sieveScriptName = @"sogo"; } else scriptError = @"Rule lacks a 'value' parameter"; - + return (scriptError == nil); } @@ -783,7 +783,7 @@ static NSString *sieveScriptName = @"sogo"; SOGoDomainDefaults *dd; NGSieveClient *client; NSString *filterScript, *v; - BOOL b; + BOOL b, dateCapability; unsigned int now; dd = [user domainDefaults]; @@ -797,7 +797,7 @@ static NSString *sieveScriptName = @"sogo"; if (!client) return NO; - // We adjust the "methodRequirements" based on the server's + // We adjust the "methodRequirements" based on the server's // capabilities. Cyrus exposes "imapflags" while Dovecot (and // potentially others) expose "imap4flags" as specified in RFC5332 if ([client hasCapability: @"imap4flags"]) @@ -806,7 +806,9 @@ static NSString *sieveScriptName = @"sogo"; [methodRequirements setObject: @"imap4flags" forKey: @"removeflag"]; [methodRequirements setObject: @"imap4flags" forKey: @"flag"]; } - + + dateCapability = [client hasCapability: @"date"] && [client hasCapability: @"relational"]; + // // Now let's generate the script // @@ -835,16 +837,22 @@ static NSString *sieveScriptName = @"sogo"; now = [[NSCalendarDate calendarDate] timeIntervalSince1970]; if (values && [[values objectForKey: @"enabled"] boolValue] && - (![values objectForKey: @"startDateEnabled"] || [[values objectForKey: @"startDate"] intValue] < now)) + (![values objectForKey: @"startDateEnabled"] || + dateCapability || [[values objectForKey: @"startDate"] intValue] < now) && + (![values objectForKey: @"endDateEnabled"] || + dateCapability || [[values objectForKey: @"endDate"] intValue] > now)) { + NSCalendarDate *startDate, *endDate; + NSMutableArray *allConditions; NSMutableString *vacation_script; NSArray *addresses; NSString *text, *templateFilePath, *customSubject; SOGoTextTemplateFile *templateFile; - + BOOL ignore, alwaysSend, useCustomSubject; int days, i; - + + allConditions = [NSMutableArray array]; days = [[values objectForKey: @"daysBetweenResponse"] intValue]; addresses = [values objectForKey: @"autoReplyEmailAddresses"]; alwaysSend = [[values objectForKey: @"alwaysSend"] boolValue]; @@ -883,12 +891,43 @@ static NSString *sieveScriptName = @"sogo"; days = 7; vacation_script = [NSMutableString string]; - + [req addObjectUniquely: @"vacation"]; // Skip mailing lists if (ignore) - [vacation_script appendString: @"if allof ( not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"], not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"], not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\" ) { "]; + { + [allConditions addObject: @"not exists [\"list-help\", \"list-unsubscribe\", \"list-subscribe\", \"list-owner\", \"list-post\", \"list-archive\", \"list-id\", \"Mailing-List\"]"]; + [allConditions addObject: @"not header :comparator \"i;ascii-casemap\" :is \"Precedence\" [\"list\", \"bulk\", \"junk\"]"]; + [allConditions addObject: @"not header :comparator \"i;ascii-casemap\" :matches \"To\" \"Multiple recipients of*\""]; + } + + // Start date of auto-reply + if ([[values objectForKey: @"startDateEnabled"] boolValue] && dateCapability) + { + [req addObjectUniquely: @"date"]; + [req addObjectUniquely: @"relational"]; + startDate = [NSCalendarDate dateWithTimeIntervalSince1970: + [[values objectForKey: @"startDate"] intValue]]; + [allConditions addObject: [NSString stringWithFormat: @"currentdate :value \"ge\" \"date\" \"%@\"", + [startDate descriptionWithCalendarFormat: @"%Y-%m-%d"]]]; + } + + // End date of auto-reply + if ([[values objectForKey: @"endDateEnabled"] boolValue] && dateCapability) + { + [req addObjectUniquely: @"date"]; + [req addObjectUniquely: @"relational"]; + endDate = [NSCalendarDate dateWithTimeIntervalSince1970: + [[values objectForKey: @"endDate"] intValue]]; + [allConditions addObject: [NSString stringWithFormat: @"currentdate :value \"le\" \"date\" \"%@\"", + [endDate descriptionWithCalendarFormat: @"%Y-%m-%d"]]]; + } + + // Apply conditions + if ([allConditions count]) + [vacation_script appendFormat: @"if allof ( %@ ) { ", + [allConditions componentsJoinedByString: @", "]]; // Custom subject if (useCustomSubject) @@ -910,20 +949,21 @@ static NSString *sieveScriptName = @"sogo"; for (i = 0; i < [addresses count]; i++) { [vacation_script appendFormat: @"\"%@\"", [addresses objectAtIndex: i]]; - + if (i == [addresses count]-1) [vacation_script appendString: @"] "]; else [vacation_script appendString: @", "]; } - + [vacation_script appendFormat: @"text:\r\n%@\r\n.\r\n;\r\n", text]; - - if (ignore) + + // Closing bracket of conditions + if ([allConditions count]) [vacation_script appendString: @"}\r\n"]; // - // See http://sogo.nu/bugs/view.php?id=2332 for details + // See https://sogo.nu/bugs/view.php?id=2332 for details // if (alwaysSend) [script insertString: vacation_script atIndex: 0]; @@ -941,7 +981,7 @@ static NSString *sieveScriptName = @"sogo"; int i; b = YES; - + addresses = [values objectForKey: @"forwardAddress"]; if ([addresses isKindOfClass: [NSString class]]) addresses = [NSArray arrayWithObject: addresses]; @@ -952,11 +992,11 @@ static NSString *sieveScriptName = @"sogo"; if (v && [v length] > 0) [script appendFormat: @"redirect \"%@\";\r\n", v]; } - + if ([[values objectForKey: @"keepCopy"] boolValue]) [script appendString: @"keep;\r\n"]; } - + if ([req count]) { header = [NSString stringWithFormat: @"require [\"%@\"];\r\n", @@ -970,7 +1010,7 @@ static NSString *sieveScriptName = @"sogo"; result = [client setActiveScript: @""]; // We delete the existing Sieve script result = [client deleteScript: sieveScriptName]; - + if (![[result valueForKey:@"result"] boolValue]) { [self logWithFormat: @"WARNING: Could not delete Sieve script - continuing...: %@", result]; } @@ -980,13 +1020,13 @@ static NSString *sieveScriptName = @"sogo"; if (b && [script length]) { result = [client putScript: sieveScriptName script: script]; - + if (![[result valueForKey:@"result"] boolValue]) { [self logWithFormat: @"Could not upload Sieve script: %@", result]; - [client closeConnection]; + [client closeConnection]; return NO; } - + result = [client setActiveScript: sieveScriptName]; if (![[result valueForKey:@"result"] boolValue]) { [self logWithFormat: @"Could not enable Sieve script: %@", result];