From 1486216b0c25dea64650087d94f808d7ab90f2c9 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Tue, 25 Aug 2009 21:28:24 +0000 Subject: [PATCH] Monotone-Parent: 9a9029239df8b59ccf4609e50402e80e31085154 Monotone-Revision: f04c25f5f8bfb6f1876bab3f70b89ee5c99bcc01 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2009-08-25T21:28:24 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 10 +++ .../Localizable.strings | 17 ++++ .../Czech.lproj/Localizable.strings | 17 ++++ .../Dutch.lproj/Localizable.strings | 17 ++++ .../English.lproj/Localizable.strings | 17 ++++ .../French.lproj/Localizable.strings | 17 ++++ SoObjects/Appointments/GNUmakefile | 1 + .../German.lproj/Localizable.strings | 17 ++++ .../Hungarian.lproj/Localizable.strings | 17 ++++ .../Italian.lproj/Localizable.strings | 17 ++++ .../Russian.lproj/Localizable.strings | 17 ++++ .../Appointments/SOGoAppointmentFolder.m | 8 +- .../Appointments/SOGoAppointmentObject.m | 66 ++++++++++---- .../Appointments/SOGoAptMailNotification.m | 6 +- .../Appointments/SOGoCalendarComponent.h | 4 + .../Appointments/SOGoCalendarComponent.m | 86 +++++++++++++++---- SoObjects/Appointments/SOGoFreeBusyObject.m | 2 +- .../SOGoUserFolder+Appointments.m | 4 +- .../Spanish.lproj/Localizable.strings | 17 ++++ .../Welsh.lproj/Localizable.strings | 17 ++++ .../Appointments/iCalEventChanges+SOGo.m | 12 +-- SoObjects/SOGo/SOGoUser.h | 2 + SoObjects/SOGo/SOGoUser.m | 5 ++ .../SOGoAptMailDeletionReceipt.wox | 30 +++++++ .../SOGoAptMailInvitationReceipt.wox | 31 +++++++ .../Appointments/SOGoAptMailUpdateReceipt.wox | 27 ++++++ 26 files changed, 431 insertions(+), 50 deletions(-) create mode 100644 UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox create mode 100644 UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox create mode 100644 UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox diff --git a/ChangeLog b/ChangeLog index 392cd69ba..1b3cd1239 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-08-25 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoUser.m (+userWithLogin:): new constructor + designed to avoid the need to pass a nil role parameter. + + * SoObjects/Appointments/SOGoCalendarComponent.m + (-sendReceiptEmailUsingTemplateNamed:forObject:to:) new method + that enables the sending of receipts to an event modifier in case + of an invitation, modification or deletion. + 2009-08-25 Cyril Robert * SoObjects/Contacts/SOGoContactGCSList.m (copyToFolder): Implementation to diff --git a/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings b/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings index 9d0d22bbc..b90eb9a75 100644 --- a/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings +++ b/SoObjects/Appointments/BrazilianPortuguese.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Evento Confidencial)"; vtodo_class0 = "(Tarefa Pública)"; vtodo_class1 = "(Tarefa Privada)"; vtodo_class2 = "(Tarefa Confidencial)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Czech.lproj/Localizable.strings b/SoObjects/Appointments/Czech.lproj/Localizable.strings index a014854cc..5157ace4e 100644 --- a/SoObjects/Appointments/Czech.lproj/Localizable.strings +++ b/SoObjects/Appointments/Czech.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Skrytá událost)"; vtodo_class0 = "(Veřejný úkol)"; vtodo_class1 = "(Soukromý úkol)"; vtodo_class2 = "(Skrytý úkol)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Dutch.lproj/Localizable.strings b/SoObjects/Appointments/Dutch.lproj/Localizable.strings index a5bad65c8..97792b9f0 100644 --- a/SoObjects/Appointments/Dutch.lproj/Localizable.strings +++ b/SoObjects/Appointments/Dutch.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Vertrouwelijke afspraak)"; vtodo_class0 = "(Publieke taak)"; vtodo_class1 = "(Privétaak)"; vtodo_class2 = "(Vertrouwelijke taak)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/English.lproj/Localizable.strings b/SoObjects/Appointments/English.lproj/Localizable.strings index 1b0915325..e0b015ba6 100644 --- a/SoObjects/Appointments/English.lproj/Localizable.strings +++ b/SoObjects/Appointments/English.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Confidential event)"; vtodo_class0 = "(Public task)"; vtodo_class1 = "(Private task)"; vtodo_class2 = "(Confidential task)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/French.lproj/Localizable.strings b/SoObjects/Appointments/French.lproj/Localizable.strings index c3975593d..158caf124 100644 --- a/SoObjects/Appointments/French.lproj/Localizable.strings +++ b/SoObjects/Appointments/French.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Événement confidentiel)"; vtodo_class0 = "(Tâche publique)"; vtodo_class1 = "(Tâche privée)"; vtodo_class2 = "(Tâche confidentielle)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Acc. de réception : vous avez ajouté des participants à une réunion"; +"You have invited the following attendees(s):" = "Vous avez invité les personnes suivantes :"; +"... to attend the following event:" = "... à participer à cette réunion :"; + +"Receipt: invitation updated" = "Acc. de réception : invitation mise à jour"; +"The following attendees(s):" = "Les participants suivants :" +"... have been notified of the changes to the following event:" = "... ont été avisés des changements apportés à cette réunion :"; + +"Receipt: attendees removed from an event" = "Acc. de réception: invitations annulées"; +"You have removed the following attendees(s):" = "Les utilisateurs suivants :"; +"... from the following event:" = "... ne sont plus invités à cette réunion :"; diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index a3e926bf2..d74b980fa 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -33,6 +33,7 @@ Appointments_OBJC_FILES = \ SOGoAptMailDeletion.m \ SOGoAptMailICalReply.m \ SOGoAptMailUpdate.m \ + SOGoAptMailReceipt.m \ Appointments_RESOURCE_FILES += \ Version \ diff --git a/SoObjects/Appointments/German.lproj/Localizable.strings b/SoObjects/Appointments/German.lproj/Localizable.strings index 4f0c5b97c..47cb152a7 100644 --- a/SoObjects/Appointments/German.lproj/Localizable.strings +++ b/SoObjects/Appointments/German.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Vertraulicher Termin)"; vtodo_class0 = "(Öffentliche Aufgabe)"; vtodo_class1 = "(Private Aufgabe)"; vtodo_class2 = "(Vertrauliche Aufgabe)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings index 7829ea32e..5267c5886 100644 --- a/SoObjects/Appointments/Hungarian.lproj/Localizable.strings +++ b/SoObjects/Appointments/Hungarian.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Bizalmas esemény)"; vtodo_class0 = "(Nyilvános feladat)"; vtodo_class1 = "(Magán feladat)"; vtodo_class2 = "(Bizalmas feladat)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Italian.lproj/Localizable.strings b/SoObjects/Appointments/Italian.lproj/Localizable.strings index 2285941c3..de86075cb 100644 --- a/SoObjects/Appointments/Italian.lproj/Localizable.strings +++ b/SoObjects/Appointments/Italian.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Evento confidenziale)"; vtodo_class0 = "(Attività pubblica)"; vtodo_class1 = "(Attività privata)"; vtodo_class2 = "(Attività confidenziale)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Russian.lproj/Localizable.strings b/SoObjects/Appointments/Russian.lproj/Localizable.strings index 1b0915325..e0b015ba6 100644 --- a/SoObjects/Appointments/Russian.lproj/Localizable.strings +++ b/SoObjects/Appointments/Russian.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Confidential event)"; vtodo_class0 = "(Public task)"; vtodo_class1 = "(Private task)"; vtodo_class2 = "(Confidential task)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 9d670b562..20d1174d4 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -2153,7 +2153,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir login = [recipient uid]; if ([login length]) { - user = [SOGoUser userWithLogin: login roles: nil]; + user = [SOGoUser userWithLogin: login]; freebusy = [[user homeFolderInContext: context] freeBusyObject: @"freebusy.ifb" inContext: context]; @@ -2677,8 +2677,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir rc = [super create]; if (rc) { - ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context] - roles: nil]; + ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]]; userSettings = [ownerUser userSettings]; calendarSettings = [userSettings objectForKey: @"Calendar"]; if (!calendarSettings) @@ -2986,8 +2985,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir // calendarFolders = [NSMutableArray new]; // [calendarFolders autorelease]; -// calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context] -// roles: nil]; +// calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context]]; // userCalendar = [NSMutableDictionary new]; // [userCalendar autorelease]; // [userCalendar setObject: @"/" forKey: @"folder"]; diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index f1eb80da4..7801812ca 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -241,7 +241,7 @@ // present in the master component. If not, we add it with a participation // status set to "DECLINED". - user = [SOGoUser userWithLogin: theUID roles: nil]; + user = [SOGoUser userWithLogin: theUID]; person = [iCalPerson elementWithTag: @"attendee"]; [person setCn: [user cn]]; [person setEmail: [[user allEmails] objectAtIndex: 0]]; @@ -408,6 +408,8 @@ forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: oldEvent toAttendees: updateAttendees]; + [self sendReceiptEmailUsingTemplateNamed: @"Update" + forObject: newEvent to: updateAttendees]; } - (void) _handleAddedUsers: (NSArray *) attendees @@ -447,6 +449,8 @@ forObject: [newEvent itipEntryWithMethod: @"cancel"] previousObject: oldEvent toAttendees: attendees]; + [self sendReceiptEmailUsingTemplateNamed: @"Deletion" + forObject: newEvent to: attendees]; } attendees = [changes insertedAttendees]; @@ -470,8 +474,10 @@ NSEnumerator *enumerator; iCalPerson *currentAttendee; NSString *currentUID; + NSArray *updatedAttendees; - enumerator = [[newEvent attendees] objectEnumerator]; + updatedAttendees = [newEvent attendees]; + enumerator = [updatedAttendees objectEnumerator]; while ((currentAttendee = [enumerator nextObject])) { currentUID = [currentAttendee uid]; @@ -480,6 +486,10 @@ forUID: currentUID owner: owner]; } + + [self sendReceiptEmailUsingTemplateNamed: @"Update" + forObject: newEvent + to: updatedAttendees]; } } @@ -488,26 +498,28 @@ NSArray *originalAttendees; originalAttendees = [NSArray arrayWithArray: [newEvent attendees]]; - + // Send an invitation to new attendees [self _handleAddedUsers: attendees fromEvent: newEvent]; [self sendEMailUsingTemplateNamed: @"Invitation" forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: oldEvent toAttendees: attendees]; + [self sendReceiptEmailUsingTemplateNamed: @"Invitation" + forObject: newEvent to: attendees]; } } - (void) saveComponent: (iCalEvent *) newEvent { - iCalEvent *oldEvent; + iCalEvent *oldEvent, *oldMasterEvent; NSArray *attendees; NSCalendarDate *recurrenceId; NSString *recurrenceTime; SOGoUser *ownerUser; [[newEvent parent] setMethod: @""]; - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; [self expandGroupsInEvent: newEvent]; @@ -526,6 +538,8 @@ forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: nil toAttendees: attendees]; + [self sendReceiptEmailUsingTemplateNamed: @"Invitation" + forObject: newEvent to: attendees]; } } else @@ -545,8 +559,10 @@ // If no occurence found, create one oldEvent = (iCalEvent*)[self newOccurenceWithID: recurrenceTime]; } - - if ([[[oldEvent parent] firstChildWithTag: [self componentTag]] userIsOrganizer: ownerUser]) + + oldMasterEvent + = (iCalEvent *) [[oldEvent parent] firstChildWithTag: [self componentTag]]; + if ([oldMasterEvent userIsOrganizer: ownerUser]) { // The owner is the organizer of the event; handle the modifications @@ -697,7 +713,7 @@ // If the current user isn't the organizer of the event // that has just been updated, we update the event and // send a notification - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; if (!(ex || [event userIsOrganizer: ownerUser])) { if ([[attendee rsvp] isEqualToString: @"true"] @@ -802,7 +818,7 @@ newEvent = [self component: NO secure: NO]; [newEvent removeAllAlarms]; [[newEvent parent] setMethod: @""]; - + recipientsEnum = [recipients objectEnumerator]; while ((recipient = [recipientsEnum nextObject])) if ([[recipient lowercaseString] hasPrefix: @"mailto:"]) @@ -890,15 +906,16 @@ // We must add an occurence to a non-existing event -- simply retrieve // the event from the organizer's calendar if (ownerEventObject == nil) - ownerEventObject = [self _lookupEvent: [newEvent uid] forUID: ownerUID]; + ownerEventObject = [self _lookupEvent: [newEvent uid] + forUID: ownerUID]; newEvent = [ownerEventObject component: NO secure: NO]; attendees = [newEvent attendees]; found = NO; - // We check if the attendee that was added to a single occurence is - // present in the master component. If not, we add it with a participation - // status set to "DECLINED" + /* We check if the attendee that was added to a single + occurence is present in the master component. If not, we + add it with a participation status set to "DECLINED" */ for (i = 0; i < [attendees count]; i++) { if ([[attendees objectAtIndex: i] hasSameEmailAddress: person]) @@ -907,7 +924,7 @@ break; } } - + if (!found) { [person setParticipationStatus: iCalPersonPartStatDeclined]; @@ -939,6 +956,11 @@ addObject: [self _caldavSuccessCodeWithRecipient: recipient]]; } + [self sendReceiptEmailUsingTemplateNamed: (isUpdate + ? @"Update" : @"Invitation") + forObject: emailEvent + to: [newEvent participants]]; + return elements; } @@ -980,6 +1002,10 @@ addObject: [self _caldavSuccessCodeWithRecipient: recipient]]; } + [self sendReceiptEmailUsingTemplateNamed: @"Deletion" + forObject: event + to: [event participants]]; + return elements; } @@ -1091,8 +1117,7 @@ event = [self component: NO secure: NO]; [[event parent] setMethod: @""]; ownerUser = [SOGoUser userWithLogin: [[LDAPUserManager sharedUserManager] - getUIDForEmail: originator] - roles: nil]; + getUIDForEmail: originator]]; attendee = [event findParticipant: ownerUser]; eventUID = [event uid]; @@ -1173,7 +1198,7 @@ // actually occured. The particpation change will of // course be on the attendee that is the owner of the // calendar where the participation change has occured. - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; attendee = [event findParticipant: ownerUser]; if (attendee) @@ -1202,7 +1227,7 @@ if ([[context request] handledByDefaultHandler]) { - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; event = [self component: NO secure: NO]; if (occurence == nil) @@ -1235,6 +1260,9 @@ forObject: [occurence itipEntryWithMethod: @"cancel"] previousObject: nil toAttendees: attendees]; + [self sendReceiptEmailUsingTemplateNamed: @"Deletion" + forObject: occurence + to: attendees]; } } else if ([occurence userIsParticipant: ownerUser]) @@ -1266,7 +1294,7 @@ NSString *key; SOGoUser *ownerUser; - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; allEvents = [calendar events]; max = [allEvents count]; diff --git a/SoObjects/Appointments/SOGoAptMailNotification.m b/SoObjects/Appointments/SOGoAptMailNotification.m index e111b5555..3f5dfe02b 100644 --- a/SoObjects/Appointments/SOGoAptMailNotification.m +++ b/SoObjects/Appointments/SOGoAptMailNotification.m @@ -196,9 +196,13 @@ static NSTimeZone *UTC = nil; - (NSString *) getBody { + NSString *body; + [self setIsSubject:NO]; - return [[self generateResponse] contentAsString]; + body = [[self generateResponse] contentAsString]; + + return [body stringByTrimmingCharactersInSet: wsSet]; } @end diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h index fa6569bf4..76101fda2 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.h +++ b/SoObjects/Appointments/SOGoCalendarComponent.h @@ -72,6 +72,10 @@ - (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent from: (SOGoUser *) owner; +- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template + forObject: (iCalRepeatableEntityObject *) object + to: (NSArray *) recipients; + // - (BOOL) isOrganizerOrOwner: (SOGoUser *) user; - (iCalPerson *) findParticipantWithUID: (NSString *) uid; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index de3119edf..8a327dcaa 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -41,18 +41,20 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "SOGoAptMailICalReply.h" #import "SOGoAptMailNotification.h" +#import "SOGoAptMailReceipt.h" #import "iCalEntityObject+SOGo.h" #import "iCalPerson+SOGo.h" #import "iCalRepeatableEntityObject+SOGo.h" @@ -60,6 +62,7 @@ #import "SOGoComponentOccurence.h" static BOOL sendEMailNotifications = NO; +static BOOL sendEMailReceipts = NO; @implementation SOGoCalendarComponent @@ -75,6 +78,8 @@ static BOOL sendEMailNotifications = NO; ud = [NSUserDefaults standardUserDefaults]; sendEMailNotifications = [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"]; + sendEMailReceipts + = [ud boolForKey: @"SOGoAppointmentSendEMailReceipts"]; } } @@ -587,7 +592,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr uid = [[LDAPUserManager sharedUserManager] getUIDForEmail: email]; - return [[SOGoUser userWithLogin: uid roles: nil] timeZone]; + return [[SOGoUser userWithLogin: uid] timeZone]; } - (void) sendEMailUsingTemplateNamed: (NSString *) newPageName @@ -616,7 +621,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr if (count) { /* sender */ - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; //currentUser = [context activeUser]; //shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0]; // senderEmail = [NSString stringWithFormat: @"%@ <%@>", @@ -752,7 +757,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr /* get WOApplication instance */ app = [WOApplication application]; - //ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + //ownerUser = [SOGoUser userWithLogin: owner]; ownerUser = from; language = [ownerUser language]; /* create page name */ @@ -831,7 +836,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr SOGoUser *ownerUser; event = [newComponent itipEntryWithMethod: @"reply"]; - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; if (![event userIsOrganizer: ownerUser]) { organizer = [event organizer]; @@ -841,6 +846,55 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr } } +- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template + forObject: (iCalRepeatableEntityObject *) object + to: (NSArray *) attendees +{ + NSString *pageName, *mailDate, *mailText, *fullSenderEmail, *senderEmail; + SOGoAptMailReceipt *page; + NGMutableHashMap *headerMap; + NGMimeMessage *msg; + SOGoUser *currentUser; + NSDictionary *identity; + + if (sendEMailReceipts && [attendees count]) + { + pageName = [NSString stringWithFormat: @"SOGoAptMail%@Receipt", + template]; + page = [[WOApplication application] pageWithName: pageName + inContext: context]; + [page setApt: object]; + [page setRecipients: attendees]; + + currentUser = [context activeUser]; + identity = [currentUser primaryIdentity]; + + /* construct message */ + headerMap = [NGMutableHashMap hashMapWithCapacity: 5]; + fullSenderEmail = [identity keysWithFormat: @"%{fullName} <%{email}>"]; + [headerMap setObject: fullSenderEmail forKey: @"from"]; + [headerMap setObject: fullSenderEmail forKey: @"to"]; + mailDate = [[NSCalendarDate date] rfc822DateString]; + [headerMap setObject: mailDate forKey: @"date"]; + [headerMap setObject: [page getSubject] forKey: @"subject"]; + [headerMap setObject: @"1.0" forKey: @"MIME-Version"]; + [headerMap setObject: @"text/plain; charset=utf-8" + forKey: @"content-type"]; + msg = [NGMimeMessage messageWithHeader: headerMap]; + + /* text part */ + mailText = [page getBody]; + [msg setBody: [mailText dataUsingEncoding: NSUTF8StringEncoding]]; + + /* send the damn thing */ + senderEmail = [identity objectForKey: @"email"]; + [[SOGoMailer sharedMailer] + sendMimePart: msg + toRecipients: [NSArray arrayWithObject: senderEmail] + sender: senderEmail]; + } +} + // - (BOOL) isOrganizerOrOwner: (SOGoUser *) user // { // BOOL isOrganizerOrOwner; @@ -863,7 +917,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr iCalEntityObject *component; SOGoUser *user; - user = [SOGoUser userWithLogin: uid roles: nil]; + user = [SOGoUser userWithLogin: uid]; component = [self component: NO secure: NO]; return [component findParticipant: user]; @@ -943,7 +997,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr organizer = [component organizer]; if ([[organizer rfc822Email] length] > 0) { - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; if ([component userIsOrganizer: ownerUser]) role = SOGoCalendarRole_Organizer; else if ([component userIsParticipant: ownerUser]) @@ -1001,7 +1055,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr { if (component) { - aclUser = [SOGoUser userWithLogin: uid roles: nil]; + aclUser = [SOGoUser userWithLogin: uid]; if ([component userIsOrganizer: aclUser]) [roles addObject: SOGoCalendarRole_Organizer]; else if ([component userIsParticipant: aclUser]) diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.m b/SoObjects/Appointments/SOGoFreeBusyObject.m index d0a0e436a..bb30b681f 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.m +++ b/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -124,7 +124,7 @@ static unsigned int freebusyRangeEnd = 0; int i; login = [container ownerInContext: context]; - user = [SOGoUser userWithLogin: login roles: nil]; + user = [SOGoUser userWithLogin: login]; calendar = [iCalCalendar groupWithTag: @"vcalendar"]; [calendar setProdID: @"//Inverse inc./SOGo 1.0//EN"]; diff --git a/SoObjects/Appointments/SOGoUserFolder+Appointments.m b/SoObjects/Appointments/SOGoUserFolder+Appointments.m index 3031ee8df..2bfa18e69 100644 --- a/SoObjects/Appointments/SOGoUserFolder+Appointments.m +++ b/SoObjects/Appointments/SOGoUserFolder+Appointments.m @@ -55,7 +55,7 @@ addresses = [NSMutableArray array]; - ownerUser = [SOGoUser userWithLogin: owner roles: nil]; + ownerUser = [SOGoUser userWithLogin: owner]; emails = [[ownerUser allEmails] objectEnumerator]; while ((currentEmail = [emails nextObject])) { @@ -224,7 +224,7 @@ value = [value substringFromIndex: NSMaxRange (substringRange)]; substringRange = [value rangeOfString: @"/Calendar"]; value = [value substringToIndex: substringRange.location]; - collection = [[SOGoUser userWithLogin: value roles: nil] + collection = [[SOGoUser userWithLogin: value] homeFolderInContext: context]; if (collection) [collections addObject: collection]; diff --git a/SoObjects/Appointments/Spanish.lproj/Localizable.strings b/SoObjects/Appointments/Spanish.lproj/Localizable.strings index 1d091bd57..9a03e2e35 100644 --- a/SoObjects/Appointments/Spanish.lproj/Localizable.strings +++ b/SoObjects/Appointments/Spanish.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Evento confidencial)"; vtodo_class0 = "(Tarea pública)"; vtodo_class1 = "(Tarea privada)"; vtodo_class2 = "(Tarea confidencial)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/Welsh.lproj/Localizable.strings b/SoObjects/Appointments/Welsh.lproj/Localizable.strings index 97fcf57ea..fcac67fd6 100644 --- a/SoObjects/Appointments/Welsh.lproj/Localizable.strings +++ b/SoObjects/Appointments/Welsh.lproj/Localizable.strings @@ -6,3 +6,20 @@ vevent_class2 = "(Digwyddiad cyfrinachol)"; vtodo_class0 = "(Tasg gyhoeddus)"; vtodo_class1 = "(Tasg breifat)"; vtodo_class2 = "(Tasg gyfrinachol)"; + +/* Receipts */ +"Title:" = "Title:"; +"Start:" = "Start:"; +"End:" = "End:"; + +"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting"; +"You have invited the following attendees(s):" = "You have invited the following attendees(s):"; +"... to attend the following event:" = "... to attend the following event:"; + +"Receipt: invitation updated" = "Receipt: invitation updated"; +"The following attendees(s):" = "The following attendees(s):" +"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:"; + +"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event"; +"You have removed the following attendees(s):" = "You have removed the following attendees(s):"; +"... from the following event:" = "... from the following event:"; diff --git a/SoObjects/Appointments/iCalEventChanges+SOGo.m b/SoObjects/Appointments/iCalEventChanges+SOGo.m index f73dd6040..9385f13f9 100644 --- a/SoObjects/Appointments/iCalEventChanges+SOGo.m +++ b/SoObjects/Appointments/iCalEventChanges+SOGo.m @@ -30,12 +30,12 @@ - (BOOL) sequenceShouldBeIncreased { - NSString *properties[] = {@"organizer", @"startDate", @"endDate", - @"due", @"duration", - @"rdate", @"rrule", @"exdate", @"exrule", - @"status", @"location", - //@"summary", @"comment", - nil}; + static NSString *properties[] = {@"organizer", @"startDate", @"endDate", + @"due", @"duration", + @"rdate", @"rrule", @"exdate", @"exrule", + @"status", @"location", + //@"summary", @"comment", + nil}; NSString **currentProperty; BOOL updateRequired; diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index cee56d1ce..b16c12a51 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -75,6 +75,8 @@ extern NSString *SOGoWeekStartFirstFullWeek; + (NSString *) language; ++ (SOGoUser *) userWithLogin: (NSString *) newLogin; + + (SOGoUser *) userWithLogin: (NSString *) login roles: (NSArray *) roles; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index e212d7c51..8371bf42f 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -220,6 +220,11 @@ _timeValue (NSString *key) return fallbackIMAP4Server; } ++ (SOGoUser *) userWithLogin: (NSString *) newLogin +{ + return [self userWithLogin: newLogin roles: nil]; +} + + (SOGoUser *) userWithLogin: (NSString *) newLogin roles: (NSArray *) newRoles { diff --git a/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox b/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox new file mode 100644 index 000000000..ccf1bf40f --- /dev/null +++ b/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox b/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox new file mode 100644 index 000000000..91ecb52f3 --- /dev/null +++ b/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox b/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox new file mode 100644 index 000000000..2a764f5a5 --- /dev/null +++ b/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + +