(feat) email alarms now have pretty formatting (fixes #805)
parent
dbf5039011
commit
7d396a51f5
|
@ -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}) ";
|
||||
|
|
|
@ -43,6 +43,7 @@ Appointments_OBJC_FILES = \
|
|||
SOGoAptMailICalReply.m \
|
||||
SOGoAptMailUpdate.m \
|
||||
SOGoAptMailReceipt.m \
|
||||
SOGoAptMailReminder.m \
|
||||
\
|
||||
SOGoEMailAlarmsManager.m \
|
||||
\
|
||||
|
|
|
@ -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 */
|
|
@ -0,0 +1,162 @@
|
|||
/* SOGoAptMailReminder.m - this file is part of SOGo
|
||||
|
||||
*/
|
||||
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSCharacterSet.h>
|
||||
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
|
||||
#import <SOGo/NSDictionary+Utilities.h>
|
||||
#import <SOGo/NSObject+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoUserManager.h>
|
||||
#import <SOGo/SOGoDateFormatter.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
#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
|
|
@ -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
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#import <NGMail/NGMimeMessage.h>
|
||||
|
||||
#import <NGCards/iCalAlarm.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
|
||||
#import <SOGo/NSCalendarDate+SOGo.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
|
@ -37,9 +38,19 @@
|
|||
#import <SOGo/SOGoMailer.h>
|
||||
#import <SOGo/SOGoProductLoader.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserManager.h>
|
||||
#import <SOGo/NSDictionary+Utilities.m>
|
||||
#import <SOGo/NSObject+Utilities.h>
|
||||
#import <SOGo/SOGoUserFolder.h>
|
||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||
#import <Appointments/iCalPerson+SOGo.h>
|
||||
#import <Appointments/SOGoEMailAlarmsManager.h>
|
||||
#import <Appointments/SOGoAppointmentFolder.h>
|
||||
|
||||
#import <NGObjWeb/WOApplication.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <Appointments/SOGoAptMailReminder.h>
|
||||
#import <WEExtensions/WEResourceManager.h>
|
||||
|
||||
#import "SOGoEAlarmsNotifier.h"
|
||||
|
||||
|
@ -81,14 +92,14 @@
|
|||
|
||||
- (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 @@
|
|||
[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) _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 @@
|
|||
|
||||
int count, max;
|
||||
|
||||
[[SOGoProductLoader productLoader] loadAllProducts: YES];
|
||||
|
||||
if ([[NSUserDefaults standardUserDefaults] stringForKey: @"h"])
|
||||
{
|
||||
[self usage];
|
||||
|
@ -209,9 +265,6 @@
|
|||
[staticAuthenticator retain];
|
||||
}
|
||||
|
||||
[[SOGoProductLoader productLoader]
|
||||
loadProducts: [NSArray arrayWithObject: @"Appointments.SOGo"]];
|
||||
|
||||
eaMgr = [NSClassFromString (@"SOGoEMailAlarmsManager")
|
||||
sharedEMailAlarmsManager];
|
||||
|
||||
|
@ -225,10 +278,12 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<!DOCTYPE container>
|
||||
<html
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
<head>
|
||||
<style type="text/css">
|
||||
th, td { font-family: Lucida Grande, Bitstream VeraSans, Tahoma, sans-serif; font-size: 12px; line-height: 18px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table cellpadding="2" cellspacing="2" border="0" style="width: 100%; max-width: 600px;">
|
||||
<tr>
|
||||
<th></th>
|
||||
<td><h1 style="font-size: 18px; font-weight: normal; padding-bottom: 9px; border-bottom: 1px solid #ccc;" class="ng-hide"><var:string
|
||||
value="aptSummary" const:escapeHTML="NO"/></h1></td>
|
||||
</tr>
|
||||
<var:if condition="calendarName.length"
|
||||
><tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="calendar_label" const:escapeHTML="NO"/></th>
|
||||
<td><var:string value="calendarName" const:escapeHTML="NO"/></td>
|
||||
</tr></var:if>
|
||||
<var:if condition="apt.location.length"
|
||||
><tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="location_label" const:escapeHTML="NO"/></th>
|
||||
<td><var:string value="apt.location" const:escapeHTML="NO"/></td>
|
||||
</tr></var:if>
|
||||
<tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="startDate_label" const:escapeHTML="NO"/></th>
|
||||
<td><var:string value="aptStartDate" const:escapeHTML="NO"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="endDate_label" const:escapeHTML="NO"/></th>
|
||||
<td><var:string value="aptEndDate" const:escapeHTML="NO"/></td>
|
||||
</tr>
|
||||
<var:if condition="apt.comment.length"
|
||||
><tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="comment_label" const:escapeHTML="NO"/></th>
|
||||
<td><var:string value="apt.comment" const:escapeHTML="NO"/></td>
|
||||
</tr>
|
||||
</var:if>
|
||||
|
||||
<var:if condition="attendees.count"
|
||||
><tr></tr><tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="organizer_label" const:escapeHTML="NO"/></th>
|
||||
<var:if condition="organizer.cn">
|
||||
<td><a var:href="organizer.email"><var:string value="organizer.cn" const:escapeHTML="NO"/></a></td>
|
||||
</var:if>
|
||||
<var:if condition="organizer.cn" const:negate="YES">
|
||||
<td><a var:href="organizer.email"><var:string value="organizer.rfc822Email" const:escapeHTML="NO"/></a></td>
|
||||
</var:if>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th align="right" style="font-weight: bold;"><var:string label:value="attendee_label" const:escapeHTML="NO"/></th>
|
||||
<var:foreach list="attendees" item="currentRecipient">
|
||||
<var:if condition="currentRecipient.cn">
|
||||
<td><a var:href="currentRecipient.email"><var:string value="currentRecipient.cn" const:escapeHTML="NO"/></a></td>
|
||||
</var:if>
|
||||
<var:if condition="currentRecipient.cn" const:negate="YES">
|
||||
<td><a var:href="currentRecipient.email"><var:string value="currentRecipient.rfc822Email" const:escapeHTML="NO"/></a></td>
|
||||
</var:if>
|
||||
<tr></tr><th align="right"></th>
|
||||
</var:foreach>
|
||||
</tr>
|
||||
</var:if>
|
||||
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue