]> err.no Git - scalable-opengroupware.org/blobdiff - SoObjects/Appointments/SOGoAppointmentObject.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1217 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / Appointments / SOGoAppointmentObject.m
index 42e4f01e5147f504b951b29050a2390febb20b4a..c4c94371474c1e6bcc8f10ed875fa34ea2fa2d32 100644 (file)
   02111-1307, USA.
 */
 
-#import "SOGoAppointmentObject.h"
+#import <Foundation/NSCalendarDate.h>
 
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGExtensions/NSNull+misc.h>
+#import <NGExtensions/NSObject+Logs.h>
 #import <NGCards/iCalCalendar.h>
 #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 <SoObjects/SOGo/LDAPUserManager.h>
+#import <SoObjects/SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/SOGoPermissions.h>
 
 #import "NSArray+Appointments.h"
+#import "SOGoAppointmentFolder.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
+#import "SOGoAppointmentObject.h"
 
 @implementation SOGoAppointmentObject
 
-static NSString *mailTemplateDefaultLanguage = nil;
-static BOOL sendEMailNotifications = NO;
-
-+ (void) initialize
+- (NSString *) componentTag
 {
-  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"];
-    }
-}
-
-/* accessors */
-
-- (iCalEvent *) event
-{
-  return [self firstEventFromCalendar: [self calendar]];
+  return @"vevent";
 }
 
 /* iCal handling */
 - (NSArray *) attendeeUIDsFromAppointment: (iCalEvent *) _apt
 {
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   NSMutableArray *uids;
   NSArray *attendees;
   unsigned i, count;
@@ -107,13 +62,13 @@ static BOOL sendEMailNotifications = NO;
   count = [attendees count];
   uids = [NSMutableArray arrayWithCapacity:count + 1];
   
-  um = [AgenorUserManager sharedUserManager];
+  um = [LDAPUserManager sharedUserManager];
   
   /* add organizer */
   
   email = [[_apt organizer] rfc822Email];
   if ([email isNotNull]) {
-    uid = [um getUIDForEmail:email];
+    uid = [um getUIDForEmail: email];
     if ([uid isNotNull]) {
       [uids addObject:uid];
     }
@@ -123,47 +78,37 @@ static BOOL sendEMailNotifications = NO;
 
   /* add attendees */
   
-  for (i = 0; i < count; i++) {
-    iCalPerson *person;
+  for (i = 0; i < count; i++)
+    {
+      iCalPerson *person;
     
-    person = [attendees objectAtIndex:i];
-    email  = [person rfc822Email];
-    if (![email isNotNull]) continue;
+      person = [attendees objectAtIndex:i];
+      email  = [person rfc822Email];
+      if (![email isNotNull]) continue;
     
-    uid = [um getUIDForEmail:email];
-    if (![uid isNotNull]) {
-      [self logWithFormat:@"Note: got no uid for email: '%@'", email];
-      continue;
+      uid = [um getUIDForEmail:email];
+      if (![uid isNotNull]) {
+        [self logWithFormat:@"Note: got no uid for email: '%@'", email];
+        continue;
+      }
+      if (![uids containsObject:uid])
+        [uids addObject:uid];
     }
-    if (![uids containsObject:uid])
-      [uids addObject:uid];
-  }
-  
-  return uids;
-}
-
-/* folder management */
 
-- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx {
-  // TODO: what does this do? lookup the home of the organizer?
-  return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx];
-}
-- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx {
-  return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx];
+  return uids;
 }
 
 /* store in all the other folders */
 
-- (NSException *)saveContentString:(NSString *)_iCal inUIDs:(NSArray *)_uids {
+- (NSException *) saveContentString: (NSString *) _iCal
+                            inUIDs: (NSArray *) _uids
+{
   NSEnumerator *e;
   id folder;
   NSException *allErrors = nil;
-  id ctx;
-
-  ctx = [[WOApplication application] context];
   
-  e = [[self lookupCalendarFoldersForUIDs:_uids inContext:ctx]
-            objectEnumerator];
+  e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
+       objectEnumerator];
   while ((folder = [e nextObject]) != nil) {
     NSException           *error;
     SOGoAppointmentObject *apt;
@@ -171,7 +116,7 @@ static BOOL sendEMailNotifications = NO;
     if (![folder isNotNull]) /* no folder was found for given UID */
       continue;
 
-    apt = [folder lookupName: [self nameInContainer] inContext:ctx
+    apt = [folder lookupName: [self nameInContainer] inContext: context
                  acquire: NO];
     if ([apt isKindOfClass: [NSException class]])
       {
@@ -206,17 +151,14 @@ static BOOL sendEMailNotifications = NO;
   NSEnumerator *e;
   id folder;
   NSException *allErrors = nil;
-  id ctx;
   
-  ctx = [[WOApplication application] context];
-  
-  e = [[self lookupCalendarFoldersForUIDs:_uids inContext:ctx]
-            objectEnumerator];
+  e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
+       objectEnumerator];
   while ((folder = [e nextObject])) {
     NSException           *error;
     SOGoAppointmentObject *apt;
     
-    apt = [folder lookupName:[self nameInContainer] inContext:ctx
+    apt = [folder lookupName:[self nameInContainer] inContext: context
                  acquire:NO];
     if ([apt isKindOfClass: [NSException class]]) {
       [self logWithFormat: @"%@", [(NSException *) apt reason]];
@@ -232,23 +174,16 @@ static BOOL sendEMailNotifications = NO;
   return allErrors;
 }
 
-- (iCalEvent *) firstEventFromCalendar: (iCalCalendar *) aCalendar
+/* "iCal multifolder saves" */
+- (BOOL) _aptIsStillRelevant: (iCalEvent *) appointment
 {
-  iCalEvent *event;
-  NSArray *events;
+  NSCalendarDate *now;
 
-  events = [aCalendar childrenWithTag: @"vevent"];
-  if ([events count])
-    event = (iCalEvent *) [[events objectAtIndex: 0]
-                            groupWithClass: [iCalEvent class]];
-  else
-    event = nil;
+  now = [NSCalendarDate calendarDate];
 
-  return event;
+  return ([[appointment endDate] earlierDate: now] == now);
 }
 
-/* "iCal multifolder saves" */
-
 - (NSException *) saveContentString: (NSString *) _iCal
                        baseSequence: (int) _v
 {
@@ -268,8 +203,7 @@ static BOOL sendEMailNotifications = NO;
      - delete in removed folders
      - send iMIP mail for all folders not found
   */
-  AgenorUserManager *um;
-  iCalCalendar *newCalendar;
+  LDAPUserManager *um;
   iCalEvent *oldApt, *newApt;
   iCalEventChanges *changes;
   iCalPerson *organizer;
@@ -281,16 +215,15 @@ static BOOL sendEMailNotifications = NO;
   
   updateForcesReconsider = NO;
 
-  if ([_iCal length] == 0) {
-    return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
-                       reason:@"got no iCalendar content to store!"];
-  }
+  if ([_iCal length] == 0)
+    return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
+                       reason: @"got no iCalendar content to store!"];
 
-  um = [AgenorUserManager sharedUserManager];
+  um = [LDAPUserManager sharedUserManager];
 
   /* 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 */
@@ -298,7 +231,7 @@ static BOOL sendEMailNotifications = NO;
       oldApt = nil;
     }
   else
-    oldApt = [self firstEventFromCalendar: [self calendar]];
+    oldApt = (iCalEvent *) [self component: NO];
   
   /* compare sequence if requested */
 
@@ -306,28 +239,21 @@ static BOOL sendEMailNotifications = NO;
     // TODO
   }
   
-  
   /* handle new content */
   
-  newCalendar = [iCalCalendar parseSingleFromSource: _iCal];
-  newApt = [self firstEventFromCalendar: newCalendar];
-  if (newApt == nil) {
-    return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
-                       reason:@"could not parse iCalendar content!"];
-  }
-  
+  newApt = (iCalEvent *) [self component: NO];
+  if (!newApt)
+    return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
+                       reason: @"could not parse iCalendar content!"];
+
   /* diff */
   
-  changes = [iCalEventChanges changesFromEvent: oldApt
-                              toEvent: newApt];
-
-  uids = [um getUIDsForICalPersons:[changes deletedAttendees]
-                    applyStrictMapping:NO];
-  removedUIDs = [NSMutableArray arrayWithArray:uids];
+  changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
+  uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
+  removedUIDs = [NSMutableArray arrayWithArray: uids];
 
-  uids = [um getUIDsForICalPersons:[newApt attendees]
-                    applyStrictMapping:NO];
-  storeUIDs = [NSMutableArray arrayWithArray:uids];
+  uids = [self getUIDsForICalPersons: [newApt attendees]];
+  storeUIDs = [NSMutableArray arrayWithArray: uids];
   props = [changes updatedProperties];
 
   /* detect whether sequence has to be increased */
@@ -337,7 +263,9 @@ static BOOL sendEMailNotifications = NO;
   /* preserve organizer */
 
   organizer = [newApt organizer];
-  uid = [um getUIDForICalPerson:organizer];
+  uid = [self getUIDForICalPerson: organizer];
+  if (!uid)
+    uid = [self ownerInContext: nil];
   if (uid) {
     if (![storeUIDs containsObject:uid])
       [storeUIDs addObject:uid];
@@ -347,7 +275,7 @@ static BOOL sendEMailNotifications = NO;
   /* organizer might have changed completely */
 
   if (oldApt && ([props containsObject: @"organizer"])) {
-    uid = [um getUIDForICalPerson:[oldApt organizer]];
+    uid = [self getUIDForICalPerson:[oldApt organizer]];
     if (uid) {
       if (![storeUIDs containsObject:uid]) {
         if (![removedUIDs containsObject:uid]) {
@@ -365,9 +293,9 @@ static BOOL sendEMailNotifications = NO;
    */
 
   if (oldApt != nil &&
-      ([props containsObject:@"startDate"] ||
-       [props containsObject:@"endDate"]   ||
-       [props containsObject:@"duration"]))
+      ([props containsObject: @"startDate"] ||
+       [props containsObject: @"endDate"]   ||
+       [props containsObject: @"duration"]))
   {
     NSArray  *ps;
     unsigned i, count;
@@ -387,41 +315,49 @@ static BOOL sendEMailNotifications = NO;
 
   /* perform storing */
 
-  storeError = [self saveContentString:_iCal inUIDs:storeUIDs];
-  delError = [self deleteInUIDs:removedUIDs];
+  storeError = [self saveContentString: _iCal inUIDs: storeUIDs];
+  delError = [self deleteInUIDs: removedUIDs];
 
   // TODO: make compound
   if (storeError != nil) return storeError;
   if (delError   != nil) return delError;
 
   /* email notifications */
-  if (sendEMailNotifications)
+  if ([self sendEMailNotifications]
+      && [self _aptIsStillRelevant: newApt])
     {
-      attendees = [NSMutableArray arrayWithArray:[changes insertedAttendees]];
-      [attendees removePerson:organizer];
-      [self sendInvitationEMailForAppointment:newApt
-            toAttendees:attendees];
+      attendees
+       = [NSMutableArray arrayWithArray: [changes insertedAttendees]];
+      [attendees removePerson: organizer];
+      [self sendEMailUsingTemplateNamed: @"Invitation"
+            forOldObject: nil
+            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];
+        [self sendEMailUsingTemplateNamed: @"Update"
+              forOldObject: oldApt
+              andNewObject: newApt
+              toAttendees: attendees];
       }
 
-      attendees = [NSMutableArray arrayWithArray:[changes deletedAttendees]];
+      attendees
+       = [NSMutableArray arrayWithArray: [changes deletedAttendees]];
       [attendees removePerson: organizer];
       if ([attendees count])
         {
-          iCalEvent *canceledApt;
+          iCalEvent *cancelledApt;
     
-          canceledApt = [newApt copy];
-          [(iCalCalendar *) [canceledApt parent] setMethod: @"cancel"];
-          [self sendAttendeeRemovalEMailForAppointment:canceledApt
+          cancelledApt = [newApt copy];
+          [(iCalCalendar *) [cancelledApt parent] setMethod: @"cancel"];
+          [self sendEMailUsingTemplateNamed: @"Removal"
+                forOldObject: nil
+                andNewObject: cancelledApt
                 toAttendees: attendees];
-          [canceledApt release];
+          [cancelledApt release];
         }
     }
 
@@ -444,12 +380,11 @@ static BOOL sendEMailNotifications = NO;
      - send iMIP mail for all folders not found
   */
   iCalEvent *apt;
-  NSArray *removedUIDs;
-  NSMutableArray *attendees;
+  NSMutableArray *attendees, *removedUIDs;
 
   /* load existing content */
 
-  apt = [self event];  
+  apt = (iCalEvent *) [self component: NO];
   
   /* compare sequence if requested */
 
@@ -457,15 +392,19 @@ static BOOL sendEMailNotifications = NO;
 //     // TODO
 //   }
   
-  removedUIDs = [self attendeeUIDsFromAppointment:apt];
+  removedUIDs = [NSMutableArray arrayWithArray:
+                                 [self attendeeUIDsFromAppointment: apt]];
+  if (![removedUIDs containsObject: owner])
+    [removedUIDs addObject: owner];
 
-  if (sendEMailNotifications)
+  if ([self sendEMailNotifications]
+      && [self _aptIsStillRelevant: apt])
     {
       /* send notification email to attendees excluding organizer */
       attendees = [NSMutableArray arrayWithArray:[apt attendees]];
       [attendees removePerson:[apt organizer]];
   
-      /* flag appointment as being canceled */
+      /* flag appointment as being cancelled */
       [(iCalCalendar *) [apt parent] setMethod: @"cancel"];
       [apt increaseSequence];
 
@@ -473,13 +412,15 @@ static BOOL sendEMailNotifications = NO;
       [apt removeAllAttendees];
 
       /* send notification email */
-      [self sendAppointmentDeletionEMailForAppointment:apt
-            toAttendees:attendees];
+      [self sendEMailUsingTemplateNamed: @"Deletion"
+            forOldObject: nil
+            andNewObject: apt
+            toAttendees: attendees];
     }
 
   /* perform */
 
-  return [self deleteInUIDs:removedUIDs];
+  return [self deleteInUIDs: removedUIDs];
 }
 
 - (NSException *) saveContentString: (NSString *) _iCalString
@@ -487,57 +428,6 @@ static BOOL sendEMailNotifications = NO;
   return [self saveContentString: _iCalString baseSequence: 0];
 }
 
-- (NSException *) changeParticipationStatus: (NSString *) _status
-                                  inContext: (id) _ctx
-{
-  iCalEvent *apt;
-  iCalPerson *p;
-  NSString *newContent;
-  NSException *ex;
-  NSString *myEMail;
-  
-  ex = nil;
-
-  // TODO: do we need to use SOGoAppointment? (prefer iCalEvent?)
-  apt = [self event];
-
-  if (apt)
-    {
-      myEMail = [[_ctx activeUser] email];
-      p = [apt findParticipantWithEmail: myEMail];
-      if (p)
-        {
-  // TODO: send iMIP reply mails?
-  
-          [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
@@ -545,254 +435,4 @@ static BOOL sendEMailNotifications = NO;
   return @"IPM.Appointment";
 }
 
-/* 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);
-}
-
-- (NSException *) saveContentString: (NSString *) contentString
-                        baseVersion: (unsigned int) baseVersion
-{
-  NSString *newContentString, *oldContentString;
-  iCalCalendar *eventCalendar;
-  iCalEvent *event;
-  NSArray *organizers;
-
-  oldContentString = [self iCalString];
-  if (oldContentString)
-    newContentString = contentString;
-  else
-    {
-      eventCalendar = [iCalCalendar parseSingleFromSource: contentString];
-      event = [self firstEventFromCalendar: eventCalendar];
-      organizers = [event childrenWithTag: @"organizer"];
-      if ([organizers count])
-        newContentString = contentString;
-      else
-        {
-          [event setOrganizerWithUid: [[self container] ownerInContext: nil]];
-          newContentString = [eventCalendar versitString];
-        }
-    }
-
-  return [super saveContentString: newContentString
-                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;
-  iCalPerson *attendee;
-  NSString *recipient;
-  SOGoAptMailNotification *p;
-  NSString *subject, *text, *header;
-  NGMutableHashMap *headerMap;
-  NGMimeMessage *msg;
-  NGMimeBodyPart *bodyPart;
-  NGMimeMultipartBody *body;
-
-  if ([_attendees count])
-    {
-      /* 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++)
-        {
-          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])
-    [self sendEMailUsingTemplateNamed: @"Invitation"
-          forOldAppointment: nil
-          andNewAppointment: _apt
-          toAttendees: _attendees];
-}
-
-- (void) sendAppointmentUpdateEMailForOldAppointment: (iCalEvent *) _oldApt
-                                      newAppointment: (iCalEvent *) _newApt
-                                         toAttendees: (NSArray *) _attendees
-{
-  if ([_attendees count])
-    [self sendEMailUsingTemplateNamed: @"Update"
-          forOldAppointment: _oldApt
-          andNewAppointment: _newApt
-          toAttendees: _attendees];
-}
-
-- (void) sendAttendeeRemovalEMailForAppointment: (iCalEvent *) _apt
-                                    toAttendees: (NSArray *) _attendees
-{
-  if ([_attendees count])
-    [self sendEMailUsingTemplateNamed: @"Removal"
-          forOldAppointment: nil
-          andNewAppointment: _apt
-          toAttendees: _attendees];
-}
-
-- (void) sendAppointmentDeletionEMailForAppointment: (iCalEvent *) _apt
-                                        toAttendees: (NSArray *) _attendees
-{
-  if ([_attendees count])
-    [self sendEMailUsingTemplateNamed: @"Deletion"
-          forOldAppointment: nil
-          andNewAppointment: _apt
-          toAttendees: _attendees];
-}
-
-- (NSString *) davContentType
-{
-  return @"text/calendar";
-}
-
-- (NSString *) roleOfUser: (NSString *) login
-                inContext: (WOContext *) context
-{
-  AgenorUserManager *um;
-  iCalEvent *event;
-  NSString *role, *email;
-
-  um = [AgenorUserManager sharedUserManager];
-  email = [um getEmailForUID: login];
-
-  event = [self event];
-  if ([event isOrganizer: email])
-    role = @"Organizer";
-  else if ([event isParticipant: email])
-    role = @"Participant";
-  else
-    role = nil;
-
-  return role;
-}
-
 @end /* SOGoAppointmentObject */
-
-
-