From 7d396a51f54a6ba5a766d5c8a3eca2f777037e5d Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Wed, 12 Apr 2017 08:59:29 -0400 Subject: [PATCH] (feat) email alarms now have pretty formatting (fixes #805) --- .../English.lproj/Localizable.strings | 2 + SoObjects/Appointments/GNUmakefile | 1 + SoObjects/Appointments/SOGoAptMailReminder.h | 32 ++++ SoObjects/Appointments/SOGoAptMailReminder.m | 162 ++++++++++++++++++ Tools/GNUmakefile.preamble | 2 +- Tools/SOGoEAlarmsNotifier.m | 79 +++++++-- .../Appointments/SOGoAptMailReminder.wox | 74 ++++++++ 7 files changed, 339 insertions(+), 13 deletions(-) create mode 100644 SoObjects/Appointments/SOGoAptMailReminder.h create mode 100644 SoObjects/Appointments/SOGoAptMailReminder.m create mode 100644 UI/Templates/Appointments/SOGoAptMailReminder.wox diff --git a/SoObjects/Appointments/English.lproj/Localizable.strings b/SoObjects/Appointments/English.lproj/Localizable.strings index f25897d4a6..0e23d13d03 100644 --- a/SoObjects/Appointments/English.lproj/Localizable.strings +++ b/SoObjects/Appointments/English.lproj/Localizable.strings @@ -22,6 +22,8 @@ vtodo_class2 = "(Confidential task)"; "location_label" = "Location"; "summary_label" = "Summary"; "comment_label" = "Comment"; +"organizer_label" = "Organizer"; +"attendee_label" = "Attendee"; /* Invitation */ "Event Invitation: \"%{Summary}\"" = "Event Invitation: \"%{Summary}\""; "(sent by %{SentBy}) " = "(sent by %{SentBy}) "; diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index bb1821d49d..e455834408 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -43,6 +43,7 @@ Appointments_OBJC_FILES = \ SOGoAptMailICalReply.m \ SOGoAptMailUpdate.m \ SOGoAptMailReceipt.m \ + SOGoAptMailReminder.m \ \ SOGoEMailAlarmsManager.m \ \ diff --git a/SoObjects/Appointments/SOGoAptMailReminder.h b/SoObjects/Appointments/SOGoAptMailReminder.h new file mode 100644 index 0000000000..724e2ec7c1 --- /dev/null +++ b/SoObjects/Appointments/SOGoAptMailReminder.h @@ -0,0 +1,32 @@ +/* SOGoAptMailReminder.h - this file is part of SOGo + + */ + +#ifndef SOGOAPTMAILRECEIPT_H +#define SOGOAPTMAILRECEIPT_H + +#import "SOGoAptMailNotification.h" + +@class NSArray; +@class NSString; +@class iCalPerson; + + +@interface SOGoAptMailReminder : SOGoAptMailNotification +{ + NSArray *attendees; + iCalPerson *currentRecipient; + NSString *calendarName; +} + +- (void) setAttendees: (NSArray *) theAttendees; +- (void) setCalendarName: (NSString *) theCalendarName; + +- (NSString *) aptSummary; +- (NSString *) aptStartDate; +- (NSString *) calendarName; +- (iCalPerson *) organizer; + +@end + +#endif /* SOGOAPTMAILRECEIPT_H */ diff --git a/SoObjects/Appointments/SOGoAptMailReminder.m b/SoObjects/Appointments/SOGoAptMailReminder.m new file mode 100644 index 0000000000..69d6e0109e --- /dev/null +++ b/SoObjects/Appointments/SOGoAptMailReminder.m @@ -0,0 +1,162 @@ +/* SOGoAptMailReminder.m - this file is part of SOGo + + */ + +#import +#import + +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import + +#import "SOGoAptMailReminder.h" + +static SOGoUserManager *um = nil; +static NSCharacterSet *wsSet = nil; + +@implementation SOGoAptMailReminder + ++ (void) initialize +{ + if (!um) + um = [SOGoUserManager sharedUserManager]; + + if (!wsSet) + wsSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain]; +} + +- (id) init +{ + if ((self = [super init])) + { + attendees = nil; + currentRecipient = nil; + calendarName = nil; + } + + return self; +} + +- (void) dealloc +{ + [attendees release]; + [calendarName release]; + [super dealloc]; +} + +- (void) setupValues +{ + [super setupValues]; + + [values setObject: [self aptStartDate] + forKey: @"StartDate"]; +} + +- (NSString *) getBody +{ + NSString *body; + + if (!values) + [self setupValues]; + + body = [[self generateResponse] contentAsString]; + + return [body stringByTrimmingCharactersInSet: wsSet]; +} + +- (void) setAttendees: (NSArray *) theAttendees +{ + ASSIGN (attendees, theAttendees); +} + +- (NSArray *) attendees +{ + return attendees; +} + +- (void) setCurrentRecipient: (iCalPerson *) newCurrentRecipient +{ + ASSIGN (currentRecipient, newCurrentRecipient); +} + +- (iCalPerson *) currentRecipient +{ + return currentRecipient; +} + +- (void) setCalendarName: (NSString *) theCalendarName +{ + ASSIGN (calendarName, theCalendarName); +} + +- (NSString *) calendarName +{ + return calendarName; +} + +- (NSString *) aptSummary +{ + NSString *s; + + if (!values) + [self setupValues]; + + s = [self labelForKey: @"Reminder: \"%{Summary}\" - %{StartDate}" + inContext: context]; + + return [values keysWithFormat: s]; +} + +- (NSString *) getSubject +{ + return [[[self aptSummary] stringByTrimmingCharactersInSet: wsSet] asQPSubjectString: @"utf-8"]; +} + +- (NSString *) _formattedUserDate: (NSCalendarDate *) date +{ + SOGoDateFormatter *formatter; + NSCalendarDate *tzDate; + SOGoUser *currentUser; + + currentUser = [context activeUser]; + + tzDate = [date copy]; + [tzDate setTimeZone: viewTZ]; + [tzDate autorelease]; + + formatter = [currentUser dateFormatterInContext: context]; + + if ([apt isAllDay]) + return [formatter formattedDate: tzDate]; + else + return [NSString stringWithFormat: @"%@, %@", + [formatter formattedDate: tzDate], + [formatter formattedTime: tzDate]]; +} + +- (NSString *) aptStartDate +{ + return [self _formattedUserDate: [apt startDate]]; +} + +- (NSString *) aptEndDate +{ + return [self _formattedUserDate: [(iCalEvent *) apt endDate]]; +} + +- (iCalPerson *) organizer +{ + return [apt organizer]; +} + +@end diff --git a/Tools/GNUmakefile.preamble b/Tools/GNUmakefile.preamble index f6ed0bb7fa..9e55c1e3eb 100644 --- a/Tools/GNUmakefile.preamble +++ b/Tools/GNUmakefile.preamble @@ -13,4 +13,4 @@ ADDITIONAL_LIB_DIRS += \ -L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \ -L../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \ -L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \ - -lEOControl -lNGStreams -lNGMime -lNGExtensions -lNGObjWeb + -lEOControl -lNGStreams -lNGMime -lNGExtensions -lNGObjWeb -lWEExtensions diff --git a/Tools/SOGoEAlarmsNotifier.m b/Tools/SOGoEAlarmsNotifier.m index f31da6f0fc..3f432e0760 100644 --- a/Tools/SOGoEAlarmsNotifier.m +++ b/Tools/SOGoEAlarmsNotifier.m @@ -30,6 +30,7 @@ #import #import +#import #import #import @@ -37,9 +38,19 @@ #import #import #import +#import +#import +#import +#import #import #import #import +#import + +#import +#import +#import +#import #import "SOGoEAlarmsNotifier.h" @@ -81,14 +92,14 @@ - (NSString *) _messageID - (NGMutableHashMap *) _headersForAlarm: (iCalAlarm *) alarm withOwner: (SOGoUser *) owner + withSubject: (NSString *) subject { NGMutableHashMap *headers; - NSString *dateString, *subject, *fullName, *email; + NSString *dateString, *fullName, *email; NSDictionary *identity; headers = [NGMutableHashMap hashMap]; - subject = [[alarm summary] asQPSubjectString: @"utf-8"]; [headers addObject: subject forKey: @"Subject"]; dateString = [[NSCalendarDate date] rfc822DateString]; [headers addObject: dateString forKey: @"Date"]; @@ -96,11 +107,11 @@ - (NGMutableHashMap *) _headersForAlarm: (iCalAlarm *) alarm [headers addObject: @"SOGo Alarms Notifier/1.0" forKey: @"User-Agent"]; [headers addObject: @"high" forKey: @"Importance"]; [headers addObject: @"1" forKey: @"X-Priority"]; - [headers setObject: @"text/plain; charset=\"utf-8\"" forKey: @"Content-Type"]; + [headers setObject: @"text/html; charset=\"utf-8\"" forKey: @"Content-Type"]; [headers setObject: @"quoted-printable" forKey: @"Content-Transfer-Encoding"]; identity = [owner primaryIdentity]; - fullName = [[identity objectForKey: @"fullName"] asQPSubjectString: @"utf-8"]; + fullName = [identity objectForKey: @"fullName"]; if ([fullName length]) email = [NSString stringWithFormat: @"%@ <%@>", fullName, [identity objectForKey: @"email"]]; @@ -140,20 +151,63 @@ - (void) _sendMessageWithHeaders: (NGMutableHashMap *) headers - (void) _processAlarm: (iCalAlarm *) alarm withOwner: (NSString *) ownerId + andContainerPath: (NSString *) containerPath { NGMutableHashMap *headers; - NSArray *attendees; + NSArray *attendees, *parts; NSData *content, *qpContent; int count, max; SOGoMailer *mailer; - NSString *from; + NSString *from, *subject; SOGoUser *owner; + WOContext *localContext; + WOApplication *app; + SOGoAptMailReminder *p; + NSString *pageName; + WOResourceManager *rm; + + SOGoAppointmentFolders *folders; + SOGoAppointmentFolder *folder; + SOGoUserFolder *userFolder; + + owner = [SOGoUser userWithLogin: ownerId]; mailer = [SOGoMailer mailerWithDomainDefaults: [owner domainDefaults]]; - headers = [self _headersForAlarm: alarm withOwner: owner]; - content = [[alarm comment] dataUsingEncoding: NSUTF8StringEncoding]; + localContext = [WOContext context]; + [localContext setActiveUser: owner]; + app = [[WOApplication alloc] initWithName: @"SOGo"]; + + rm = [[WEResourceManager alloc] init]; + [app setResourceManager:rm]; + [rm release]; + [app _setCurrentContext:localContext]; + + userFolder = [[localContext activeUser] homeFolderInContext: localContext ]; + folders = [userFolder privateCalendars: @"Calendar" + inContext: localContext]; + + pageName = [NSString stringWithFormat: @"SOGoAptMail%@", @"Reminder"]; + + p = [app pageWithName: pageName inContext: localContext]; + + parts = [containerPath componentsSeparatedByString: @"/"]; + if ([parts count] > 4) + { + folder = [folders lookupName: [parts objectAtIndex: 4] + inContext: localContext + acquire: NO]; + [p setCalendarName: [folder displayName]]; + } + + [p setApt: [alarm parent]]; + [p setAttendees: [[alarm parent] attendees]]; + + content = [[p getBody] dataUsingEncoding: NSUTF8StringEncoding]; + subject = [p getSubject]; + + headers = [self _headersForAlarm: alarm withOwner: owner withSubject: subject]; qpContent = [content dataByEncodingQuotedPrintable]; from = [[owner primaryIdentity] objectForKey: @"email"]; @@ -191,6 +245,8 @@ - (BOOL) run int count, max; + [[SOGoProductLoader productLoader] loadAllProducts: YES]; + if ([[NSUserDefaults standardUserDefaults] stringForKey: @"h"]) { [self usage]; @@ -209,9 +265,6 @@ - (BOOL) run [staticAuthenticator retain]; } - [[SOGoProductLoader productLoader] - loadProducts: [NSArray arrayWithObject: @"Appointments.SOGo"]]; - eaMgr = [NSClassFromString (@"SOGoEMailAlarmsManager") sharedEMailAlarmsManager]; @@ -225,10 +278,12 @@ - (BOOL) run second: 0] toDate: toDate withMetadata: metadata]; + max = [alarms count]; for (count = 0; count < max; count++) [self _processAlarm: [alarms objectAtIndex: count] - withOwner: [[metadata objectAtIndex: count] objectForKey: @"owner"]]; + withOwner: [[metadata objectAtIndex: count] objectForKey: @"owner"] + andContainerPath: [[[metadata objectAtIndex: count] objectForKey: @"record"] objectForKey: @"c_path"]]; // We now update the next alarm date (if any, for recurring // events or tasks for example). This will also delete any emai diff --git a/UI/Templates/Appointments/SOGoAptMailReminder.wox b/UI/Templates/Appointments/SOGoAptMailReminder.wox new file mode 100644 index 0000000000..1c3caad040 --- /dev/null +++ b/UI/Templates/Appointments/SOGoAptMailReminder.wox @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ +