diff --git a/NEWS b/NEWS index d550f2352..6f4ca0cc5 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,7 @@ Bug fixes - [web] fixed responsive condition of login page (960px to 1023px) - [core] newly subscribed calendars are excluded from freebusy (#3354) - [core] strip cr during LDIF import process (#4172) + - [core] email alarms are sent too many times (#4100) 3.2.9 (2017-05-09) ------------------ diff --git a/SoObjects/Appointments/iCalAlarm+SOGo.h b/SoObjects/Appointments/iCalAlarm+SOGo.h index 741be01fa..6a7b84fb6 100644 --- a/SoObjects/Appointments/iCalAlarm+SOGo.h +++ b/SoObjects/Appointments/iCalAlarm+SOGo.h @@ -1,6 +1,6 @@ /* iCalAlarm+SOGo.h - this file is part of SOGo * - * Copyright (C) 2015 Inverse inc. + * Copyright (C) 2015-2017 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #import @class iCalEntityObject; +@class SOGoUser; @interface iCalAlarm (SOGoExtensions) @@ -34,4 +35,6 @@ emailAttendees: (BOOL) reminderEmailAttendees emailOrganizer: (BOOL) reminderEmailOrganizer; +- (BOOL) userIsAttendee: (SOGoUser *) user; + @end diff --git a/SoObjects/Appointments/iCalAlarm+SOGo.m b/SoObjects/Appointments/iCalAlarm+SOGo.m index 4f98fc5eb..51e0d8a75 100644 --- a/SoObjects/Appointments/iCalAlarm+SOGo.m +++ b/SoObjects/Appointments/iCalAlarm+SOGo.m @@ -1,6 +1,6 @@ /* iCalAlarm+SOGo.m - this file is part of SOGo * - * Copyright (C) 2015 Inverse inc. + * Copyright (C) 2015-2017 Inverse inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -125,4 +125,24 @@ return AUTORELEASE(anAlarm); } +- (BOOL) userIsAttendee: (SOGoUser *) user +{ + NSEnumerator *attendees; + iCalPerson *currentAttendee; + BOOL isAttendee; + + isAttendee = NO; + + attendees = [[self attendees] objectEnumerator]; + currentAttendee = [attendees nextObject]; + while (!isAttendee + && currentAttendee) + if ([user hasEmail: [currentAttendee rfc822Email]]) + isAttendee = YES; + else + currentAttendee = [attendees nextObject]; + + return isAttendee; +} + @end diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m index 3db197ee0..679eb59b1 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m @@ -690,6 +690,7 @@ NSNumber *iCalDistantFutureNumber = nil; { NSCalendarDate *nextAlarmDate; GCSAlarmsFolder *af; + SOGoUser *alarmOwner; NSString *path; int email_alarm_number; @@ -698,11 +699,13 @@ NSNumber *iCalDistantFutureNumber = nil; { af = [[GCSFolderManager defaultFolderManager] alarmsFolder]; path = [theContainer ocsPath]; + alarmOwner = [SOGoUser userWithLogin: [[path componentsSeparatedByString: @"/"] objectAtIndex: 2]]; } else { af = nil; path = nil; + alarmOwner = nil; } nextAlarmDate = nil; @@ -736,7 +739,8 @@ NSNumber *iCalDistantFutureNumber = nil; email_alarm_number = [[self alarms] indexOfObject: anAlarm]; // The email alarm is too old, let's just remove it - if ([nextAlarmDate earlierDate: [NSDate date]] == nextAlarmDate) + if ([nextAlarmDate earlierDate: [NSDate date]] == nextAlarmDate || + ![anAlarm userIsAttendee: alarmOwner]) nextAlarmDate = nil; else { @@ -831,17 +835,21 @@ NSNumber *iCalDistantFutureNumber = nil; nextAlarmDate = [NSDate dateWithTimeIntervalSince1970: [[[alarms objectAtIndex: i] objectForKey: @"c_nextalarm"] intValue]]; } else if ((anAlarm = [self firstEmailAlarm]) && af) + { nextAlarmDate = [NSDate dateWithTimeIntervalSince1970: [[[alarms objectAtIndex: i] objectForKey: @"c_nextalarm"] intValue]]; email_alarm_number = [[self alarms] indexOfObject: anAlarm]; - [af writeRecordForEntryWithCName: nameInContainer - inCalendarAtPath: path - forUID: [self uid] - recurrenceId: [self recurrenceId] - alarmNumber: [NSNumber numberWithInt: email_alarm_number] - andAlarmDate: nextAlarmDate]; - } + if ([anAlarm userIsAttendee: alarmOwner]) + [af writeRecordForEntryWithCName: nameInContainer + inCalendarAtPath: path + forUID: [self uid] + recurrenceId: [self recurrenceId] + alarmNumber: [NSNumber numberWithInt: email_alarm_number] + andAlarmDate: nextAlarmDate]; + else + nextAlarmDate = nil; + } } } } // for ( ... ) diff --git a/Tools/SOGoEAlarmsNotifier.m b/Tools/SOGoEAlarmsNotifier.m index 5999d11c4..2a2a49dcf 100644 --- a/Tools/SOGoEAlarmsNotifier.m +++ b/Tools/SOGoEAlarmsNotifier.m @@ -124,28 +124,22 @@ - (void) _sendMessageWithHeaders: (NGMutableHashMap *) headers content: (NSData *) content - toAttendee: (iCalPerson *) attendee - from: (NSString *) from + to: (NSDictionary *) to withMailer: (SOGoMailer *) mailer { NGMimeMessage *message; - NSString *to, *headerTo, *attendeeName; + NSString *headerTo; - attendeeName = [attendee cnWithoutQuotes]; - if ([attendeeName length]) - headerTo = [NSString stringWithFormat: @"%@ <%@>", attendeeName, - [attendee rfc822Email]]; - else - headerTo = [attendee rfc822Email]; + headerTo = [NSString stringWithFormat: @"%@ <%@>", [to objectForKey: @"fullName"], + [to objectForKey: @"email"]]; [headers setObject: headerTo forKey: @"To"]; [headers setObject: [self _messageID] forKey: @"Message-Id"]; message = [NGMimeMessage messageWithHeader: headers]; [message setBody: content]; - to = [attendee rfc822Email]; [mailer sendMimePart: message - toRecipients: [NSArray arrayWithObject: to] - sender: from + toRecipients: [NSArray arrayWithObject: [to objectForKey: @"email"]] + sender: [to objectForKey: @"email"] withAuthenticator: staticAuthenticator inContext: nil]; } @@ -154,11 +148,10 @@ andContainerPath: (NSString *) containerPath { NGMutableHashMap *headers; - NSArray *attendees, *parts; + NSArray *parts; NSData *content, *qpContent; - int count, max; SOGoMailer *mailer; - NSString *from, *subject; + NSString *subject; SOGoUser *owner; WOContext *localContext; @@ -171,7 +164,6 @@ SOGoAppointmentFolder *folder; SOGoUserFolder *userFolder; - owner = [SOGoUser userWithLogin: ownerId]; mailer = [SOGoMailer mailerWithDomainDefaults: [owner domainDefaults]]; @@ -180,13 +172,13 @@ app = [[WOApplication alloc] initWithName: @"SOGo"]; rm = [[WEResourceManager alloc] init]; - [app setResourceManager:rm]; + [app setResourceManager: rm]; [rm release]; [app _setCurrentContext:localContext]; userFolder = [[localContext activeUser] homeFolderInContext: localContext ]; folders = [userFolder privateCalendars: @"Calendar" - inContext: localContext]; + inContext: localContext]; pageName = [NSString stringWithFormat: @"SOGoAptMail%@", @"Reminder"]; @@ -209,16 +201,10 @@ headers = [self _headersForAlarm: alarm withOwner: owner withSubject: subject]; qpContent = [content dataByEncodingQuotedPrintable]; - from = [[owner primaryIdentity] objectForKey: @"email"]; - - attendees = [alarm attendees]; - max = [attendees count]; - for (count = 0; count < max; count++) - [self _sendMessageWithHeaders: headers - content: qpContent - toAttendee: [attendees objectAtIndex: count] - from: from - withMailer: mailer]; + [self _sendMessageWithHeaders: headers + content: qpContent + to: [owner primaryIdentity] + withMailer: mailer]; } - (void) usage