/// <summary> /// Called when a card must be read from back-end storage. /// </summary> /// <param name="output">Stream to write vCard content.</param> /// <param name="startIndex">Index to start reading data from back-end storage. Used for segmented reads, not used by CardDAV clients.</param> /// <param name="count">Number of bytes to read. Used for segmented reads, not used by CardDAV clients.</param> public override async Task ReadAsync(Stream output, long startIndex, long count) { string vCard = null; using (StreamReader reader = File.OpenText(this.fileSystemInfo.FullName)) { vCard = await reader.ReadToEndAsync(); } // Typically the stream contains a single vCard. IEnumerable <IComponent> cards = new vFormatter().Deserialize(vCard); ICard2 card = cards.First() as ICard2; // We store a business card in the original vCard form sent by the CardDAV client app. // This form may not be understood by some CardDAV client apps. // Here we convert card to the form understood by the client CardDAV application. if (AppleCardInteroperability.Convert(context.Request.UserAgent, card)) { // Write modified vCard to output. new vFormatter().Serialize(output, card); } else { // No conversion is needed. await base.ReadAsync(output, startIndex, count); } }
/// <summary> /// Called when client application deletes this file. /// </summary> /// <param name="multistatus">Error description if case delate failed. Ignored by most clients.</param> public override async Task DeleteAsync(MultistatusException multistatus) { // Notify attendees that event is canceled if deletion is successful. string calendarObjectContent = File.ReadAllText(fileSystemInfo.FullName); await base.DeleteAsync(multistatus); IEnumerable <IComponent> calendars = new vFormatter().Deserialize(calendarObjectContent); ICalendar2 calendar = calendars.First() as ICalendar2; calendar.Method = calendar.CreateMethodProp(MethodType.Cancel); await iMipEventSchedulingTransport.NotifyAttendeesAsync(context, calendar); }
/// <summary> /// Called when event or to-do is being saved to back-end storage. /// </summary> /// <param name="stream">Stream containing VCALENDAR, typically with a single VEVENT ot VTODO component.</param> /// <param name="contentType">Content type.</param> /// <param name="startIndex">Starting byte in target file /// for which data comes in <paramref name="content"/> stream.</param> /// <param name="totalFileSize">Size of file as it will be after all parts are uploaded. -1 if unknown (in case of chunked upload).</param> /// <returns>Whether the whole stream has been written.</returns> public override async Task <bool> WriteAsync(Stream content, string contentType, long startIndex, long totalFileSize) { bool result = await base.WriteAsync(content, contentType, startIndex, totalFileSize); // Notify attendees that event is created or modified. string calendarObjectContent = File.ReadAllText(fileSystemInfo.FullName); IEnumerable <IComponent> calendars = new vFormatter().Deserialize(calendarObjectContent); ICalendar2 calendar = calendars.First() as ICalendar2; calendar.Method = calendar.CreateMethodProp(MethodType.Request); await iMipEventSchedulingTransport.NotifyAttendeesAsync(context, calendar); return(result); }
/// <summary> /// Sends an e-mail with event/to-do attachment to every attendee found in <see cref="ICalendar2.Attendees"/> list. /// </summary> /// <param name="calendar">Calendar object with event or to-do. The <see cref="ICalendar2.Method"/> property must be specified in this calendar object.</param> public static async Task NotifyAttendeesAsync(DavContext context, ICalendar2 calendar) { IEnumerable <IEventBase> components = calendar.Events.Cast <IEventBase>(); if (!components.Any()) { components = calendar.ToDos.Cast <IEventBase>(); } IEventBase component = components.First(); ICalAddress organizer = component.Organizer; string iCalendarContent = new vFormatter().Serialize(calendar); foreach (IAttendee attendee in component.Attendees) { try { using (MailMessage mail = new MailMessage()) { mail.From = GetMailAddress(organizer); mail.To.Add(GetMailAddress(attendee)); mail.Subject = string.Format("Event: {0}", component.Summary.Text); using (AlternateView alternateView = AlternateView.CreateAlternateViewFromString(iCalendarContent, Encoding.UTF8, "text/calendar")) { alternateView.TransferEncoding = TransferEncoding.EightBit; // Method must be specified both in iCalendar METHOD property and in Content-Type. alternateView.ContentType = new ContentType(string.Format(ContentTypePattern, calendar.Method.Method.Name)); mail.AlternateViews.Add(alternateView); using (SmtpClient smtpClient = new SmtpClient()) { smtpClient.EnableSsl = true; await smtpClient.SendMailAsync(mail); } } } } catch (Exception ex) { // Probably SMTP server is not configured in web.config/app.config string message = "Faled to notify attendees about event change. SMTP server is not configured in web.config/app.config" + Environment.NewLine; context.Logger.LogError(message, ex); } } }