mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-05-23 04:15:26 +00:00
Monotone-Parent: 54d3ea8ac154dc9b3f1789d570bac3635a6f91d0
Monotone-Revision: 214679cc73ed73085700bc8680e40fc5f830e95c Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-01-31T20:15:28 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
2007-01-31 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* SoObjects/Appointments/SOGoCalendarComponent.m
|
||||
([SOGoCalendarComponent -sendEMailNotifications]): new method that
|
||||
returns the value of ud "SOGoAppointmentSendEMailNotifications"
|
||||
(iMIP/iTIP).
|
||||
([SOGoCalendarComponent
|
||||
-sendEMailUsingTemplateNamed:_pageNameforOldObject:_oldObjectandNewObject:_newObjecttoAttendees:_attendees]): method moved from SOGoAppointmentObject/SOGoTaskObject, replacing occurences of "appointment" to "object" in its name.
|
||||
|
||||
2007-01-30 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* UI/MailerUI/UIxMailListView.m ([UIxMailListView
|
||||
|
||||
@@ -53,24 +53,20 @@
|
||||
|
||||
/* folder management */
|
||||
|
||||
- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx;
|
||||
- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx;
|
||||
|
||||
/* raw saving */
|
||||
|
||||
- (NSException *)primarySaveContentString:(NSString *)_iCalString;
|
||||
- (NSException *)primaryDelete;
|
||||
- (id) lookupHomeFolderForUID: (NSString *) _uid inContext: (id)_ctx;
|
||||
- (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids
|
||||
inContext: (id) _ctx;
|
||||
|
||||
/* "iCal multifolder saves" */
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCal baseSequence:(int)_v;
|
||||
- (NSException *)deleteWithBaseSequence:(int)_v;
|
||||
- (NSException *) saveContentString: (NSString *)_iCal
|
||||
baseSequence: (int) _v;
|
||||
- (NSException *) deleteWithBaseSequence: (int) _v;
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCalString;
|
||||
- (NSException *)delete;
|
||||
- (NSException *) saveContentString: (NSString *) _iCalString;
|
||||
|
||||
- (NSException *)changeParticipationStatus:(NSString *)_status
|
||||
inContext:(id)_ctx;
|
||||
- (NSException *) changeParticipationStatus: (NSString *) _status
|
||||
inContext: (id) _ctx;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -25,57 +25,18 @@
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalEventChanges.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGMime/NGMime.h>
|
||||
#import <NGMail/NGMail.h>
|
||||
#import <NGMail/NGSendMail.h>
|
||||
|
||||
#import <SOGo/AgenorUserManager.h>
|
||||
#import <SOGo/SOGoObject.h>
|
||||
|
||||
#import "SOGoAptMailNotification.h"
|
||||
#import "iCalEntityObject+Agenor.h"
|
||||
|
||||
#import "common.h"
|
||||
|
||||
#import "NSArray+Appointments.h"
|
||||
|
||||
@interface SOGoAppointmentObject (PrivateAPI)
|
||||
- (NSString *) homePageURLForPerson: (iCalPerson *) _person;
|
||||
|
||||
- (void)sendEMailUsingTemplateNamed:(NSString *)_pageName
|
||||
forOldAppointment:(iCalEvent *)_newApt
|
||||
andNewAppointment:(iCalEvent *)_oldApt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
|
||||
- (void)sendInvitationEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendAppointmentUpdateEMailForOldAppointment:(iCalEvent *)_oldApt
|
||||
newAppointment:(iCalEvent *)_newApt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendAttendeeRemovalEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendAppointmentDeletionEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
@end
|
||||
|
||||
@implementation SOGoAppointmentObject
|
||||
|
||||
static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
+ (void)initialize {
|
||||
NSUserDefaults *ud;
|
||||
static BOOL didInit = NO;
|
||||
|
||||
if (didInit) return;
|
||||
didInit = YES;
|
||||
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"]
|
||||
retain];
|
||||
if (!mailTemplateDefaultLanguage)
|
||||
mailTemplateDefaultLanguage = @"French";
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (iCalEvent *) event
|
||||
@@ -84,11 +45,11 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
}
|
||||
|
||||
/* iCal handling */
|
||||
|
||||
- (NSArray *)attendeeUIDsFromAppointment:(iCalEvent *)_apt {
|
||||
- (NSArray *) attendeeUIDsFromAppointment: (iCalEvent *) _apt
|
||||
{
|
||||
AgenorUserManager *um;
|
||||
NSMutableArray *uids;
|
||||
NSArray *attendees;
|
||||
NSMutableArray *uids;
|
||||
NSArray *attendees;
|
||||
unsigned i, count;
|
||||
NSString *email, *uid;
|
||||
|
||||
@@ -149,8 +110,8 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCal inUIDs:(NSArray *)_uids {
|
||||
NSEnumerator *e;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
id ctx;
|
||||
|
||||
ctx = [[WOApplication application] context];
|
||||
@@ -191,13 +152,15 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
allErrors = error;
|
||||
}
|
||||
}
|
||||
|
||||
return allErrors;
|
||||
}
|
||||
|
||||
- (NSException *)deleteInUIDs:(NSArray *)_uids {
|
||||
NSEnumerator *e;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
id ctx;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
id ctx;
|
||||
|
||||
ctx = [[WOApplication application] context];
|
||||
|
||||
@@ -262,13 +225,13 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
AgenorUserManager *um;
|
||||
iCalCalendar *newCalendar;
|
||||
iCalEvent *oldApt, *newApt;
|
||||
iCalEventChanges *changes;
|
||||
iCalPerson *organizer;
|
||||
NSString *oldContent, *uid;
|
||||
NSArray *uids, *props;
|
||||
NSMutableArray *attendees, *storeUIDs, *removedUIDs;
|
||||
NSException *storeError, *delError;
|
||||
BOOL updateForcesReconsider;
|
||||
iCalEventChanges *changes;
|
||||
iCalPerson *organizer;
|
||||
NSString *oldContent, *uid;
|
||||
NSArray *uids, *props;
|
||||
NSMutableArray *attendees, *storeUIDs, *removedUIDs;
|
||||
NSException *storeError, *delError;
|
||||
BOOL updateForcesReconsider;
|
||||
|
||||
updateForcesReconsider = NO;
|
||||
|
||||
@@ -281,7 +244,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
/* handle old content */
|
||||
|
||||
oldContent = [self iCalString]; /* if nil, this is a new appointment */
|
||||
oldContent = [self contentAsString]; /* if nil, this is a new appointment */
|
||||
if ([oldContent length] == 0)
|
||||
{
|
||||
/* new appointment */
|
||||
@@ -312,14 +275,14 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
changes = [iCalEventChanges changesFromEvent: oldApt
|
||||
toEvent: newApt];
|
||||
|
||||
uids = [um getUIDsForICalPersons:[changes deletedAttendees]
|
||||
uids = [um getUIDsForICalPersons:[changes deletedAttendees]
|
||||
applyStrictMapping:NO];
|
||||
removedUIDs = [NSMutableArray arrayWithArray:uids];
|
||||
|
||||
uids = [um getUIDsForICalPersons:[newApt attendees]
|
||||
uids = [um getUIDsForICalPersons:[newApt attendees]
|
||||
applyStrictMapping:NO];
|
||||
storeUIDs = [NSMutableArray arrayWithArray:uids];
|
||||
props = [changes updatedProperties];
|
||||
storeUIDs = [NSMutableArray arrayWithArray:uids];
|
||||
props = [changes updatedProperties];
|
||||
|
||||
/* detect whether sequence has to be increased */
|
||||
if ([changes hasChanges])
|
||||
@@ -328,7 +291,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
/* preserve organizer */
|
||||
|
||||
organizer = [newApt organizer];
|
||||
uid = [um getUIDForICalPerson:organizer];
|
||||
uid = [um getUIDForICalPerson:organizer];
|
||||
if (uid) {
|
||||
if (![storeUIDs containsObject:uid])
|
||||
[storeUIDs addObject:uid];
|
||||
@@ -379,39 +342,48 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
/* perform storing */
|
||||
|
||||
storeError = [self saveContentString:_iCal inUIDs:storeUIDs];
|
||||
delError = [self deleteInUIDs:removedUIDs];
|
||||
delError = [self deleteInUIDs:removedUIDs];
|
||||
|
||||
// TODO: make compound
|
||||
if (storeError != nil) return storeError;
|
||||
if (delError != nil) return delError;
|
||||
|
||||
/* email notifications */
|
||||
if ([self sendEMailNotifications])
|
||||
{
|
||||
attendees = [NSMutableArray arrayWithArray: [changes insertedAttendees]];
|
||||
[attendees removePerson: organizer];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forOldObject: nil
|
||||
andNewObject: newApt
|
||||
toAttendees: attendees];
|
||||
|
||||
attendees = [NSMutableArray arrayWithArray:[changes insertedAttendees]];
|
||||
[attendees removePerson:organizer];
|
||||
[self sendInvitationEMailForAppointment:newApt
|
||||
toAttendees:attendees];
|
||||
if (updateForcesReconsider) {
|
||||
attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
|
||||
[attendees removeObjectsInArray:[changes insertedAttendees]];
|
||||
[attendees removePerson:organizer];
|
||||
[self sendEMailUsingTemplateNamed: @"Update"
|
||||
forOldObject: oldApt
|
||||
andNewObject: newApt
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
if (updateForcesReconsider) {
|
||||
attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
|
||||
[attendees removeObjectsInArray:[changes insertedAttendees]];
|
||||
[attendees removePerson:organizer];
|
||||
[self sendAppointmentUpdateEMailForOldAppointment:oldApt
|
||||
newAppointment:newApt
|
||||
toAttendees:attendees];
|
||||
}
|
||||
|
||||
attendees = [NSMutableArray arrayWithArray:[changes deletedAttendees]];
|
||||
[attendees removePerson: organizer];
|
||||
if ([attendees count]) {
|
||||
iCalEvent *canceledApt;
|
||||
attendees = [NSMutableArray arrayWithArray:[changes deletedAttendees]];
|
||||
[attendees removePerson: organizer];
|
||||
if ([attendees count])
|
||||
{
|
||||
iCalEvent *canceledApt;
|
||||
|
||||
canceledApt = [newApt copy];
|
||||
[(iCalCalendar *) [canceledApt parent] setMethod: @"cancel"];
|
||||
[self sendAttendeeRemovalEMailForAppointment:canceledApt
|
||||
toAttendees: attendees];
|
||||
[canceledApt release];
|
||||
}
|
||||
canceledApt = [newApt copy];
|
||||
[(iCalCalendar *) [canceledApt parent] setMethod: @"cancel"];
|
||||
[self sendEMailUsingTemplateNamed: @"Removal"
|
||||
forOldObject: nil
|
||||
andNewObject: canceledApt
|
||||
toAttendees: attendees];
|
||||
[canceledApt release];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -431,8 +403,8 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
- send iMIP mail for all folders not found
|
||||
*/
|
||||
iCalEvent *apt;
|
||||
NSArray *removedUIDs;
|
||||
NSMutableArray *attendees;
|
||||
NSArray *removedUIDs;
|
||||
NSMutableArray *attendees;
|
||||
|
||||
/* load existing content */
|
||||
|
||||
@@ -440,118 +412,100 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
/* compare sequence if requested */
|
||||
|
||||
if (_v != 0) {
|
||||
// TODO
|
||||
}
|
||||
// if (_v != 0) {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
removedUIDs = [self attendeeUIDsFromAppointment:apt];
|
||||
|
||||
/* send notification email to attendees excluding organizer */
|
||||
attendees = [NSMutableArray arrayWithArray:[apt attendees]];
|
||||
[attendees removePerson:[apt organizer]];
|
||||
if ([self sendEMailNotifications])
|
||||
{
|
||||
/* send notification email to attendees excluding organizer */
|
||||
attendees = [NSMutableArray arrayWithArray:[apt attendees]];
|
||||
[attendees removePerson:[apt organizer]];
|
||||
|
||||
/* flag appointment as being canceled */
|
||||
[(iCalCalendar *) [apt parent] setMethod: @"cancel"];
|
||||
[apt increaseSequence];
|
||||
/* flag appointment as being canceled */
|
||||
[(iCalCalendar *) [apt parent] setMethod: @"cancel"];
|
||||
[apt increaseSequence];
|
||||
|
||||
/* remove all attendees to signal complete removal */
|
||||
[apt removeAllAttendees];
|
||||
/* remove all attendees to signal complete removal */
|
||||
[apt removeAllAttendees];
|
||||
|
||||
/* send notification email */
|
||||
[self sendAppointmentDeletionEMailForAppointment:apt
|
||||
toAttendees:attendees];
|
||||
/* send notification email */
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forOldObject: nil
|
||||
andNewObject: apt
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
/* perform */
|
||||
|
||||
|
||||
return [self deleteInUIDs:removedUIDs];
|
||||
}
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCalString {
|
||||
return [self saveContentString:_iCalString baseSequence:0];
|
||||
- (NSException *) saveContentString: (NSString *) _iCalString
|
||||
{
|
||||
return [self saveContentString: _iCalString baseSequence: 0];
|
||||
}
|
||||
|
||||
- (NSException *)changeParticipationStatus:(NSString *)_status
|
||||
inContext:(id)_ctx
|
||||
- (NSException *) changeParticipationStatus: (NSString *) _status
|
||||
inContext: (id) _ctx
|
||||
{
|
||||
iCalEvent *apt;
|
||||
iCalPerson *p;
|
||||
NSString *newContent;
|
||||
NSException *ex;
|
||||
NSString *myEMail;
|
||||
iCalPerson *p;
|
||||
NSString *newContent;
|
||||
NSException *ex;
|
||||
NSString *myEMail;
|
||||
|
||||
ex = nil;
|
||||
|
||||
// TODO: do we need to use SOGoAppointment? (prefer iCalEvent?)
|
||||
apt = [self event];
|
||||
|
||||
if (apt == nil) {
|
||||
return [NSException exceptionWithHTTPStatus:500 /* Server Error */
|
||||
reason:@"unable to parse appointment record"];
|
||||
}
|
||||
|
||||
myEMail = [[_ctx activeUser] email];
|
||||
if ((p = [apt findParticipantWithEmail:myEMail]) == nil) {
|
||||
return [NSException exceptionWithHTTPStatus:404 /* Not Found */
|
||||
reason:@"user does not participate in this "
|
||||
@"appointment"];
|
||||
}
|
||||
|
||||
[p setPartStat:_status];
|
||||
newContent = [[apt parent] versitString];
|
||||
|
||||
if (apt)
|
||||
{
|
||||
myEMail = [[_ctx activeUser] email];
|
||||
p = [apt findParticipantWithEmail: myEMail];
|
||||
if (p)
|
||||
{
|
||||
// TODO: send iMIP reply mails?
|
||||
|
||||
// [apt release]; apt = nil;
|
||||
|
||||
if (newContent == nil) {
|
||||
return [NSException exceptionWithHTTPStatus:500 /* Server Error */
|
||||
reason:@"Could not generate iCalendar data ..."];
|
||||
}
|
||||
|
||||
if ((ex = [self saveContentString:newContent]) != nil) {
|
||||
// TODO: why is the exception wrapped?
|
||||
return [NSException exceptionWithHTTPStatus:500 /* Server Error */
|
||||
reason:[ex reason]];
|
||||
}
|
||||
|
||||
return nil /* means: no error */;
|
||||
[p setPartStat:_status];
|
||||
newContent = [[apt parent] versitString];
|
||||
if (newContent)
|
||||
{
|
||||
ex = [self saveContentString:newContent];
|
||||
if (ex)
|
||||
// TODO: why is the exception wrapped?
|
||||
/* Server Error */
|
||||
ex = [NSException exceptionWithHTTPStatus: 500
|
||||
reason: [ex reason]];
|
||||
}
|
||||
else
|
||||
ex
|
||||
= [NSException exceptionWithHTTPStatus: 500 /* Server Error */
|
||||
reason: @"Could not generate iCalendar data ..."];
|
||||
}
|
||||
else
|
||||
ex = [NSException exceptionWithHTTPStatus: 404 /* Not Found */
|
||||
reason: @"user does not participate in this "
|
||||
@"appointment"];
|
||||
}
|
||||
else
|
||||
ex = [NSException exceptionWithHTTPStatus:500 /* Server Error */
|
||||
reason:@"unable to parse appointment record"];
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
/* message type */
|
||||
|
||||
- (NSString *)outlookMessageClass {
|
||||
- (NSString *) outlookMessageClass
|
||||
{
|
||||
return @"IPM.Appointment";
|
||||
}
|
||||
|
||||
/* EMail Notifications */
|
||||
|
||||
- (NSString *)homePageURLForPerson:(iCalPerson *)_person {
|
||||
static AgenorUserManager *um = nil;
|
||||
static NSString *baseURL = nil;
|
||||
NSString *uid;
|
||||
|
||||
if (!um) {
|
||||
WOContext *ctx;
|
||||
NSArray *traversalObjects;
|
||||
|
||||
um = [[AgenorUserManager sharedUserManager] retain];
|
||||
|
||||
/* generate URL from traversal stack */
|
||||
ctx = [[WOApplication application] context];
|
||||
traversalObjects = [ctx objectTraversalStack];
|
||||
if ([traversalObjects count] >= 1) {
|
||||
baseURL = [[[traversalObjects objectAtIndex:0] baseURLInContext:ctx]
|
||||
retain];
|
||||
}
|
||||
else {
|
||||
[self warnWithFormat:@"Unable to create baseURL from context!"];
|
||||
baseURL = @"http://localhost/";
|
||||
}
|
||||
}
|
||||
uid = [um getUIDForEmail:[_person rfc822Email]];
|
||||
if (!uid) return nil;
|
||||
return [NSString stringWithFormat:@"%@%@", baseURL, uid];
|
||||
}
|
||||
|
||||
- (NSException *) saveContentString: (NSString *) contentString
|
||||
baseVersion: (unsigned int) baseVersion
|
||||
{
|
||||
@@ -560,7 +514,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
iCalEvent *event;
|
||||
NSArray *organizers;
|
||||
|
||||
oldContentString = [self iCalString];
|
||||
oldContentString = [self contentAsString];
|
||||
if (oldContentString)
|
||||
newContentString = contentString;
|
||||
else
|
||||
@@ -581,182 +535,6 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
baseVersion: baseVersion];
|
||||
}
|
||||
|
||||
- (void)sendEMailUsingTemplateNamed: (NSString *)_pageName
|
||||
forOldAppointment: (iCalEvent *)_oldApt
|
||||
andNewAppointment: (iCalEvent *)_newApt
|
||||
toAttendees: (NSArray *)_attendees
|
||||
{
|
||||
NSString *pageName;
|
||||
iCalPerson *organizer;
|
||||
NSString *cn, *sender, *iCalString;
|
||||
NGSendMail *sendmail;
|
||||
WOApplication *app;
|
||||
unsigned i, count;
|
||||
|
||||
if (![_attendees count]) return; // another job neatly done :-)
|
||||
|
||||
/* sender */
|
||||
|
||||
organizer = [_newApt organizer];
|
||||
cn = [organizer cnWithoutQuotes];
|
||||
if (cn) {
|
||||
sender = [NSString stringWithFormat:@"%@ <%@>",
|
||||
cn,
|
||||
[organizer rfc822Email]];
|
||||
}
|
||||
else {
|
||||
sender = [organizer rfc822Email];
|
||||
}
|
||||
|
||||
/* generate iCalString once */
|
||||
iCalString = [[_newApt parent] versitString];
|
||||
|
||||
/* get sendmail object */
|
||||
sendmail = [NGSendMail sharedSendMail];
|
||||
|
||||
/* get WOApplication instance */
|
||||
app = [WOApplication application];
|
||||
|
||||
/* generate dynamic message content */
|
||||
|
||||
count = [_attendees count];
|
||||
for (i = 0; i < count; i++) {
|
||||
iCalPerson *attendee;
|
||||
NSString *recipient;
|
||||
SOGoAptMailNotification *p;
|
||||
NSString *subject, *text, *header;
|
||||
NGMutableHashMap *headerMap;
|
||||
NGMimeMessage *msg;
|
||||
NGMimeBodyPart *bodyPart;
|
||||
NGMimeMultipartBody *body;
|
||||
|
||||
attendee = [_attendees objectAtIndex:i];
|
||||
|
||||
/* construct recipient */
|
||||
cn = [attendee cn];
|
||||
if (cn) {
|
||||
recipient = [NSString stringWithFormat:@"%@ <%@>",
|
||||
cn,
|
||||
[attendee rfc822Email]];
|
||||
}
|
||||
else {
|
||||
recipient = [attendee rfc822Email];
|
||||
}
|
||||
|
||||
/* create page name */
|
||||
// TODO: select user's default language?
|
||||
pageName = [NSString stringWithFormat:@"SOGoAptMail%@%@",
|
||||
mailTemplateDefaultLanguage,
|
||||
_pageName];
|
||||
/* construct message content */
|
||||
p = [app pageWithName:pageName inContext:[WOContext context]];
|
||||
[p setNewApt:_newApt];
|
||||
[p setOldApt:_oldApt];
|
||||
[p setHomePageURL:[self homePageURLForPerson:attendee]];
|
||||
[p setViewTZ: [self userTimeZone: cn]];
|
||||
subject = [p getSubject];
|
||||
text = [p getBody];
|
||||
|
||||
/* construct message */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:5];
|
||||
|
||||
/* NOTE: multipart/alternative seems like the correct choice but
|
||||
* unfortunately Thunderbird doesn't offer the rich content alternative
|
||||
* at all. Mail.app shows the rich content alternative _only_
|
||||
* so we'll stick with multipart/mixed for the time being.
|
||||
*/
|
||||
[headerMap setObject:@"multipart/mixed" forKey:@"content-type"];
|
||||
[headerMap setObject:sender forKey:@"From"];
|
||||
[headerMap setObject:recipient forKey:@"To"];
|
||||
[headerMap setObject:[NSCalendarDate date] forKey:@"date"];
|
||||
[headerMap setObject:subject forKey:@"Subject"];
|
||||
msg = [NGMimeMessage messageWithHeader:headerMap];
|
||||
|
||||
/* multipart body */
|
||||
body = [[NGMimeMultipartBody alloc] initWithPart:msg];
|
||||
|
||||
/* text part */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:1];
|
||||
[headerMap setObject:@"text/plain; charset=utf-8" forKey:@"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader:headerMap];
|
||||
[bodyPart setBody:[text dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
/* attach text part to multipart body */
|
||||
[body addBodyPart:bodyPart];
|
||||
|
||||
/* calendar part */
|
||||
header = [NSString stringWithFormat:@"text/calendar; method=%@;"
|
||||
@" charset=utf-8",
|
||||
[(iCalCalendar *) [_newApt parent] method]];
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:1];
|
||||
[headerMap setObject:header forKey:@"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader:headerMap];
|
||||
[bodyPart setBody:[iCalString dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
/* attach calendar part to multipart body */
|
||||
[body addBodyPart:bodyPart];
|
||||
|
||||
/* attach multipart body to message */
|
||||
[msg setBody:body];
|
||||
[body release];
|
||||
|
||||
/* send the damn thing */
|
||||
[sendmail sendMimePart:msg
|
||||
toRecipients:[NSArray arrayWithObject:[attendee rfc822Email]]
|
||||
sender:[organizer rfc822Email]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendInvitationEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return; // another job neatly done :-)
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Invitation"
|
||||
forOldAppointment:nil
|
||||
andNewAppointment:_apt
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void)sendAppointmentUpdateEMailForOldAppointment:(iCalEvent *)_oldApt
|
||||
newAppointment:(iCalEvent *)_newApt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Update"
|
||||
forOldAppointment:_oldApt
|
||||
andNewAppointment:_newApt
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void)sendAttendeeRemovalEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Removal"
|
||||
forOldAppointment:nil
|
||||
andNewAppointment:_apt
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void)sendAppointmentDeletionEMailForAppointment:(iCalEvent *)_apt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Deletion"
|
||||
forOldAppointment:nil
|
||||
andNewAppointment:_apt
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (NSString *) davContentType
|
||||
{
|
||||
return @"text/calendar";
|
||||
}
|
||||
|
||||
- (NSString *) roleOfUser: (NSString *) login
|
||||
inContext: (WOContext *) context
|
||||
{
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
|
||||
#import <SOGo/SOGoContentObject.h>
|
||||
|
||||
@class NSArray;
|
||||
@class NSString;
|
||||
|
||||
@class iCalCalendar;
|
||||
@class iCalRepeatableEntityObject;
|
||||
|
||||
@interface SOGoCalendarComponent : SOGoContentObject
|
||||
{
|
||||
@@ -36,7 +38,6 @@
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (NSString *) iCalString;
|
||||
- (iCalCalendar *) calendar;
|
||||
|
||||
- (NSException *) primarySaveContentString: (NSString *) _iCalString;
|
||||
@@ -44,6 +45,13 @@
|
||||
|
||||
- (NSException *) delete;
|
||||
|
||||
/* mail notifications */
|
||||
- (BOOL) sendEMailNotifications;
|
||||
- (void) sendEMailUsingTemplateNamed: (NSString *) _pageName
|
||||
forOldObject: (iCalRepeatableEntityObject *) _oldObject
|
||||
andNewObject: (iCalRepeatableEntityObject *) _newObject
|
||||
toAttendees: (NSArray *) _attendees;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOCALENDARCOMPONENT_H */
|
||||
|
||||
@@ -20,12 +20,47 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||
#import <NGMime/NGMime.h>
|
||||
#import <NGMail/NGMail.h>
|
||||
#import <NGMail/NGSendMail.h>
|
||||
|
||||
#import <SOGo/AgenorUserManager.h>
|
||||
|
||||
#import "common.h"
|
||||
|
||||
#import "SOGoAptMailNotification.h"
|
||||
#import "SOGoCalendarComponent.h"
|
||||
|
||||
static NSString *mailTemplateDefaultLanguage = nil;
|
||||
static BOOL sendEMailNotifications = NO;
|
||||
|
||||
@implementation SOGoCalendarComponent
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSUserDefaults *ud;
|
||||
static BOOL didInit = NO;
|
||||
|
||||
if (!didInit)
|
||||
{
|
||||
didInit = YES;
|
||||
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"]
|
||||
retain];
|
||||
if (!mailTemplateDefaultLanguage)
|
||||
mailTemplateDefaultLanguage = @"French";
|
||||
|
||||
sendEMailNotifications
|
||||
= [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
@@ -43,10 +78,9 @@
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) iCalString
|
||||
- (NSString *) davContentType
|
||||
{
|
||||
// for UI-X appointment viewer
|
||||
return [self contentAsString];
|
||||
return @"text/calendar";
|
||||
}
|
||||
|
||||
- (iCalCalendar *) calendar
|
||||
@@ -55,7 +89,7 @@
|
||||
|
||||
if (!calendar)
|
||||
{
|
||||
iCalString = [self iCalString];
|
||||
iCalString = [self contentAsString];
|
||||
if (iCalString)
|
||||
{
|
||||
calendar = [iCalCalendar parseSingleFromSource: iCalString];
|
||||
@@ -70,7 +104,7 @@
|
||||
|
||||
- (NSException *) primarySaveContentString: (NSString *) _iCalString
|
||||
{
|
||||
return [super saveContentString:_iCalString];
|
||||
return [super saveContentString: _iCalString];
|
||||
}
|
||||
|
||||
- (NSException *) primaryDelete
|
||||
@@ -90,4 +124,159 @@
|
||||
return [self deleteWithBaseSequence:0];
|
||||
}
|
||||
|
||||
/* EMail Notifications */
|
||||
- (NSString *) homePageURLForPerson: (iCalPerson *) _person
|
||||
{
|
||||
NSString *baseURL;
|
||||
NSString *uid;
|
||||
WOContext *ctx;
|
||||
NSArray *traversalObjects;
|
||||
|
||||
/* generate URL from traversal stack */
|
||||
ctx = [[WOApplication application] context];
|
||||
traversalObjects = [ctx objectTraversalStack];
|
||||
if ([traversalObjects count] > 0)
|
||||
baseURL = [[traversalObjects objectAtIndex:0] baseURLInContext:ctx];
|
||||
else
|
||||
{
|
||||
baseURL = @"http://localhost/";
|
||||
[self warnWithFormat:@"Unable to create baseURL from context!"];
|
||||
}
|
||||
uid = [[AgenorUserManager sharedUserManager]
|
||||
getUIDForEmail: [_person rfc822Email]];
|
||||
|
||||
return ((uid)
|
||||
? [NSString stringWithFormat:@"%@%@", baseURL, uid]
|
||||
: nil);
|
||||
}
|
||||
|
||||
- (BOOL) sendEMailNotifications
|
||||
{
|
||||
return sendEMailNotifications;
|
||||
}
|
||||
|
||||
- (void) sendEMailUsingTemplateNamed: (NSString *) _pageName
|
||||
forOldObject: (iCalRepeatableEntityObject *) _oldObject
|
||||
andNewObject: (iCalRepeatableEntityObject *) _newObject
|
||||
toAttendees: (NSArray *) _attendees
|
||||
{
|
||||
NSString *pageName;
|
||||
iCalPerson *organizer;
|
||||
NSString *cn, *sender, *iCalString;
|
||||
NGSendMail *sendmail;
|
||||
WOApplication *app;
|
||||
unsigned i, count;
|
||||
iCalPerson *attendee;
|
||||
NSString *recipient;
|
||||
SOGoAptMailNotification *p;
|
||||
NSString *subject, *text, *header;
|
||||
NGMutableHashMap *headerMap;
|
||||
NGMimeMessage *msg;
|
||||
NGMimeBodyPart *bodyPart;
|
||||
NGMimeMultipartBody *body;
|
||||
|
||||
if ([_attendees count])
|
||||
{
|
||||
/* sender */
|
||||
|
||||
organizer = [_newObject organizer];
|
||||
cn = [organizer cnWithoutQuotes];
|
||||
if (cn)
|
||||
sender = [NSString stringWithFormat:@"%@ <%@>",
|
||||
cn,
|
||||
[organizer rfc822Email]];
|
||||
else
|
||||
sender = [organizer rfc822Email];
|
||||
|
||||
/* generate iCalString once */
|
||||
iCalString = [[_newObject parent] versitString];
|
||||
|
||||
/* get sendmail object */
|
||||
sendmail = [NGSendMail sharedSendMail];
|
||||
|
||||
/* get WOApplication instance */
|
||||
app = [WOApplication application];
|
||||
|
||||
/* generate dynamic message content */
|
||||
|
||||
count = [_attendees count];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
attendee = [_attendees objectAtIndex:i];
|
||||
|
||||
/* construct recipient */
|
||||
cn = [attendee cn];
|
||||
if (cn)
|
||||
recipient = [NSString stringWithFormat: @"%@ <%@>",
|
||||
cn,
|
||||
[attendee rfc822Email]];
|
||||
else
|
||||
recipient = [attendee rfc822Email];
|
||||
|
||||
/* create page name */
|
||||
// TODO: select user's default language?
|
||||
pageName = [NSString stringWithFormat: @"SOGoAptMail%@%@",
|
||||
mailTemplateDefaultLanguage,
|
||||
_pageName];
|
||||
/* construct message content */
|
||||
p = [app pageWithName: pageName inContext: [WOContext context]];
|
||||
[p setNewApt: _newObject];
|
||||
[p setOldApt: _oldObject];
|
||||
[p setHomePageURL: [self homePageURLForPerson: attendee]];
|
||||
[p setViewTZ: [self userTimeZone: cn]];
|
||||
subject = [p getSubject];
|
||||
text = [p getBody];
|
||||
|
||||
/* construct message */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity: 5];
|
||||
|
||||
/* NOTE: multipart/alternative seems like the correct choice but
|
||||
* unfortunately Thunderbird doesn't offer the rich content alternative
|
||||
* at all. Mail.app shows the rich content alternative _only_
|
||||
* so we'll stick with multipart/mixed for the time being.
|
||||
*/
|
||||
[headerMap setObject: @"multipart/mixed" forKey: @"content-type"];
|
||||
[headerMap setObject: sender forKey: @"From"];
|
||||
[headerMap setObject: recipient forKey: @"To"];
|
||||
[headerMap setObject: [NSCalendarDate date] forKey: @"date"];
|
||||
[headerMap setObject: subject forKey: @"Subject"];
|
||||
msg = [NGMimeMessage messageWithHeader: headerMap];
|
||||
|
||||
/* multipart body */
|
||||
body = [[NGMimeMultipartBody alloc] initWithPart: msg];
|
||||
|
||||
/* text part */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
|
||||
[headerMap setObject: @"text/plain; charset=utf-8"
|
||||
forKey: @"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader: headerMap];
|
||||
[bodyPart setBody: [text dataUsingEncoding: NSUTF8StringEncoding]];
|
||||
|
||||
/* attach text part to multipart body */
|
||||
[body addBodyPart: bodyPart];
|
||||
|
||||
/* calendar part */
|
||||
header = [NSString stringWithFormat: @"text/calendar; method=%@;"
|
||||
@" charset=utf-8",
|
||||
[(iCalCalendar *) [_newObject parent] method]];
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
|
||||
[headerMap setObject:header forKey: @"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader: headerMap];
|
||||
[bodyPart setBody: [iCalString dataUsingEncoding: NSUTF8StringEncoding]];
|
||||
|
||||
/* attach calendar part to multipart body */
|
||||
[body addBodyPart: bodyPart];
|
||||
|
||||
/* attach multipart body to message */
|
||||
[msg setBody: body];
|
||||
[body release];
|
||||
|
||||
/* send the damn thing */
|
||||
[sendmail sendMimePart: msg
|
||||
toRecipients: [NSArray arrayWithObject: [attendee rfc822Email]]
|
||||
sender: [organizer rfc822Email]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -54,18 +54,12 @@
|
||||
- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx;
|
||||
- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx;
|
||||
|
||||
/* raw saving */
|
||||
|
||||
- (NSException *)primarySaveContentString:(NSString *)_iCalString;
|
||||
- (NSException *)primaryDelete;
|
||||
|
||||
/* "iCal multifolder saves" */
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCal baseSequence:(int)_v;
|
||||
- (NSException *)deleteWithBaseSequence:(int)_v;
|
||||
|
||||
- (NSException *)saveContentString:(NSString *)_iCalString;
|
||||
- (NSException *)delete;
|
||||
|
||||
- (NSException *)changeParticipationStatus:(NSString *)_status
|
||||
inContext:(id)_ctx;
|
||||
|
||||
@@ -35,22 +35,9 @@
|
||||
#import "NSArray+Appointments.h"
|
||||
|
||||
@interface SOGoTaskObject (PrivateAPI)
|
||||
- (NSString *)homePageURLForPerson:(iCalPerson *)_person;
|
||||
|
||||
- (void)sendEMailUsingTemplateNamed:(NSString *)_pageName
|
||||
forOldTask:(iCalToDo *)_newApt
|
||||
andNewTask:(iCalToDo *)_oldApt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
|
||||
- (void)sendInvitationEMailForTask:(iCalToDo *)_task
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendTaskUpdateEMailForOldTask:(iCalToDo *)_oldApt
|
||||
newTask:(iCalToDo *)_newApt
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendAttendeeRemovalEMailForTask:(iCalToDo *)_task
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (void)sendTaskDeletionEMailForTask:(iCalToDo *)_task
|
||||
toAttendees:(NSArray *)_attendees;
|
||||
- (NSString *) homePageURLForPerson: (iCalPerson *) _person;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SOGoTaskObject
|
||||
@@ -277,7 +264,7 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
// /* handle old content */
|
||||
|
||||
// oldContent = [self iCalString]; /* if nil, this is a new task */
|
||||
// oldContent = [self contentAsString]; /* if nil, this is a new task */
|
||||
// if ([oldContent length] == 0)
|
||||
// {
|
||||
// /* new task */
|
||||
@@ -387,7 +374,8 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
// if (delError != nil) return delError;
|
||||
|
||||
/* email notifications */
|
||||
|
||||
// if ([self sendEMailNotifications])
|
||||
// {
|
||||
// attendees = [NSMutableArray arrayWithArray:[changes insertedAttendees]];
|
||||
// [attendees removePerson:organizer];
|
||||
// [self sendInvitationEMailForTask:newApt
|
||||
@@ -397,9 +385,10 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
// attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
|
||||
// [attendees removeObjectsInArray:[changes insertedAttendees]];
|
||||
// [attendees removePerson:organizer];
|
||||
// [self sendTaskUpdateEMailForOldTask:oldApt
|
||||
// newTask:newApt
|
||||
// toAttendees:attendees];
|
||||
// [self sendEMailUsingTemplateNamed: @"Update"
|
||||
// forOldObject: oldApt
|
||||
// andNewObject: newApt
|
||||
// toAttendees: attendees];
|
||||
// }
|
||||
|
||||
// attendees = [NSMutableArray arrayWithArray:[changes deletedAttendees]];
|
||||
@@ -409,10 +398,14 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
// canceledApt = [newApt copy];
|
||||
// [(iCalCalendar *) [canceledApt parent] setMethod: @"cancel"];
|
||||
// [self sendAttendeeRemovalEMailForTask:canceledApt
|
||||
// toAttendees:attendees];
|
||||
// [self sendEMailUsingTemplateNamed: @"Removal"
|
||||
// forOldObject: nil
|
||||
// andNewObject: canceledApt
|
||||
// toAttendees: attendees];
|
||||
// [canceledApt release];
|
||||
// }
|
||||
// }
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -447,20 +440,25 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
|
||||
removedUIDs = [self attendeeUIDsFromTask:task];
|
||||
|
||||
/* send notification email to attendees excluding organizer */
|
||||
attendees = [NSMutableArray arrayWithArray:[task attendees]];
|
||||
[attendees removePerson:[task organizer]];
|
||||
if ([self sendEMailNotifications])
|
||||
{
|
||||
/* send notification email to attendees excluding organizer */
|
||||
attendees = [NSMutableArray arrayWithArray:[task attendees]];
|
||||
[attendees removePerson:[task organizer]];
|
||||
|
||||
/* flag task as being canceled */
|
||||
[(iCalCalendar *) [task parent] setMethod: @"cancel"];
|
||||
[task increaseSequence];
|
||||
/* flag task as being canceled */
|
||||
[(iCalCalendar *) [task parent] setMethod: @"cancel"];
|
||||
[task increaseSequence];
|
||||
|
||||
/* remove all attendees to signal complete removal */
|
||||
[task removeAllAttendees];
|
||||
/* remove all attendees to signal complete removal */
|
||||
[task removeAllAttendees];
|
||||
|
||||
/* send notification email */
|
||||
[self sendTaskDeletionEMailForTask:task
|
||||
toAttendees:attendees];
|
||||
/* send notification email */
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forOldObject: nil
|
||||
andNewObject: task
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
/* perform */
|
||||
|
||||
@@ -553,180 +551,4 @@ static NSString *mailTemplateDefaultLanguage = nil;
|
||||
return [NSString stringWithFormat:@"%@%@", baseURL, uid];
|
||||
}
|
||||
|
||||
- (void)sendEMailUsingTemplateNamed:(NSString *)_pageName
|
||||
forOldTask:(iCalToDo *)_oldApt
|
||||
andNewTask:(iCalToDo *)_newApt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
NSString *pageName;
|
||||
iCalPerson *organizer;
|
||||
NSString *cn, *sender, *iCalString;
|
||||
NGSendMail *sendmail;
|
||||
WOApplication *app;
|
||||
unsigned i, count;
|
||||
|
||||
if (![_attendees count]) return; // another job neatly done :-)
|
||||
|
||||
/* sender */
|
||||
|
||||
organizer = [_newApt organizer];
|
||||
cn = [organizer cnWithoutQuotes];
|
||||
if (cn) {
|
||||
sender = [NSString stringWithFormat:@"%@ <%@>",
|
||||
cn,
|
||||
[organizer rfc822Email]];
|
||||
}
|
||||
else {
|
||||
sender = [organizer rfc822Email];
|
||||
}
|
||||
|
||||
/* generate iCalString once */
|
||||
iCalString = [[_newApt parent] versitString];
|
||||
|
||||
/* get sendmail object */
|
||||
sendmail = [NGSendMail sharedSendMail];
|
||||
|
||||
/* get WOApplication instance */
|
||||
app = [WOApplication application];
|
||||
|
||||
/* generate dynamic message content */
|
||||
|
||||
count = [_attendees count];
|
||||
for (i = 0; i < count; i++) {
|
||||
iCalPerson *attendee;
|
||||
NSString *recipient;
|
||||
SOGoAptMailNotification *p;
|
||||
NSString *subject, *text, *header;
|
||||
NGMutableHashMap *headerMap;
|
||||
NGMimeMessage *msg;
|
||||
NGMimeBodyPart *bodyPart;
|
||||
NGMimeMultipartBody *body;
|
||||
|
||||
attendee = [_attendees objectAtIndex:i];
|
||||
|
||||
/* construct recipient */
|
||||
cn = [attendee cn];
|
||||
if (cn) {
|
||||
recipient = [NSString stringWithFormat:@"%@ <%@>",
|
||||
cn,
|
||||
[attendee rfc822Email]];
|
||||
}
|
||||
else {
|
||||
recipient = [attendee rfc822Email];
|
||||
}
|
||||
|
||||
/* create page name */
|
||||
// TODO: select user's default language?
|
||||
pageName = [NSString stringWithFormat:@"SOGoAptMail%@%@",
|
||||
mailTemplateDefaultLanguage,
|
||||
_pageName];
|
||||
/* construct message content */
|
||||
p = [app pageWithName:pageName inContext:[WOContext context]];
|
||||
[p setNewApt: _newApt];
|
||||
[p setOldApt: _oldApt];
|
||||
[p setHomePageURL:[self homePageURLForPerson:attendee]];
|
||||
[p setViewTZ: [self userTimeZone: cn]];
|
||||
subject = [p getSubject];
|
||||
text = [p getBody];
|
||||
|
||||
/* construct message */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:5];
|
||||
|
||||
/* NOTE: multipart/alternative seems like the correct choice but
|
||||
* unfortunately Thunderbird doesn't offer the rich content alternative
|
||||
* at all. Mail.app shows the rich content alternative _only_
|
||||
* so we'll stick with multipart/mixed for the time being.
|
||||
*/
|
||||
[headerMap setObject:@"multipart/mixed" forKey:@"content-type"];
|
||||
[headerMap setObject:sender forKey:@"From"];
|
||||
[headerMap setObject:recipient forKey:@"To"];
|
||||
[headerMap setObject:[NSCalendarDate date] forKey:@"date"];
|
||||
[headerMap setObject:subject forKey:@"Subject"];
|
||||
msg = [NGMimeMessage messageWithHeader:headerMap];
|
||||
|
||||
/* multipart body */
|
||||
body = [[NGMimeMultipartBody alloc] initWithPart:msg];
|
||||
|
||||
/* text part */
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:1];
|
||||
[headerMap setObject:@"text/plain; charset=utf-8" forKey:@"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader:headerMap];
|
||||
[bodyPart setBody:[text dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
/* attach text part to multipart body */
|
||||
[body addBodyPart:bodyPart];
|
||||
|
||||
/* calendar part */
|
||||
header = [NSString stringWithFormat:@"text/calendar; method=%@;"
|
||||
@" charset=utf-8",
|
||||
[(iCalCalendar *) [_newApt parent] method]];
|
||||
headerMap = [NGMutableHashMap hashMapWithCapacity:1];
|
||||
[headerMap setObject:header forKey:@"content-type"];
|
||||
bodyPart = [NGMimeBodyPart bodyPartWithHeader:headerMap];
|
||||
[bodyPart setBody:[iCalString dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
/* attach calendar part to multipart body */
|
||||
[body addBodyPart:bodyPart];
|
||||
|
||||
/* attach multipart body to message */
|
||||
[msg setBody:body];
|
||||
[body release];
|
||||
|
||||
/* send the damn thing */
|
||||
[sendmail sendMimePart:msg
|
||||
toRecipients:[NSArray arrayWithObject:[attendee rfc822Email]]
|
||||
sender:[organizer rfc822Email]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendInvitationEMailForTask:(iCalToDo *)_task
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return; // another job neatly done :-)
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Invitation"
|
||||
forOldTask:nil
|
||||
andNewTask:_task
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void)sendTaskUpdateEMailForOldTask:(iCalToDo *)_oldApt
|
||||
newTask:(iCalToDo *)_newApt
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Update"
|
||||
forOldTask:_oldApt
|
||||
andNewTask:_newApt
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void) sendAttendeeRemovalEMailForTask:(iCalToDo *)_task
|
||||
toAttendees:(NSArray *)_attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Removal"
|
||||
forOldTask:nil
|
||||
andNewTask:_task
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (void) sendTaskDeletionEMailForTask: (iCalToDo *) _task
|
||||
toAttendees: (NSArray *) _attendees
|
||||
{
|
||||
if (![_attendees count]) return;
|
||||
|
||||
[self sendEMailUsingTemplateNamed:@"Deletion"
|
||||
forOldTask:nil
|
||||
andNewTask:_task
|
||||
toAttendees:_attendees];
|
||||
}
|
||||
|
||||
- (NSString *) davContentType
|
||||
{
|
||||
return @"text/calendar";
|
||||
}
|
||||
|
||||
@end /* SOGoTaskObject */
|
||||
|
||||
Reference in New Issue
Block a user