public static void LoadCalendarInfo(this MailMessageData mail, MimeMessage message, ILog log = null) { if (!message.BodyParts.Any()) { return; } log = log ?? new NullLog(); try { var calendarParts = message.BodyParts.Where(p => p.ContentType.IsMimeType("text", "calendar")).ToList(); if (!calendarParts.Any()) { return; } log.DebugFormat("LoadCalendarInfo found {0} calendars", calendarParts.Count); foreach (var calendarPart in calendarParts) { var p = calendarPart as TextPart; if (p == null) { continue; } var ics = p.Text; var calendar = MailUtil.ParseValidCalendar(ics, log); if (calendar == null) { continue; } if (calendar.Events[0].Organizer == null && calendar.Method.Equals(Defines.ICAL_REPLY, StringComparison.OrdinalIgnoreCase)) { // Fix reply organizer (Outlook style of Reply) var toAddress = message.To.Mailboxes.FirstOrDefault(); if (toAddress != null) { calendar.Events[0].Organizer = new Ical.Net.DataTypes.Organizer("mailto:" + toAddress.Address) { CommonName = string.IsNullOrEmpty(toAddress.Name) ? toAddress.Address : toAddress.Name }; ics = MailUtil.SerializeCalendar(calendar); } } mail.CalendarUid = calendar.Events[0].Uid; mail.CalendarId = -1; mail.CalendarEventIcs = ics; mail.CalendarEventCharset = string.IsNullOrEmpty(p.ContentType.Charset) ? Encoding.UTF8.HeaderName : p.ContentType.Charset; mail.CalendarEventMimeType = p.ContentType.MimeType; log.DebugFormat("Calendar UID: {0} Method: {1} ics: {2}", mail.CalendarUid, calendar.Method, mail.CalendarEventIcs); var calendarExists = message.Attachments .Any( attach => { var subType = attach.ContentType.MediaSubtype.ToLower().Trim(); if (string.IsNullOrEmpty(subType) || (!subType.Equals("ics") && !subType.Equals("ical") && !subType.Equals("ifb") && !subType.Equals("icalendar") && !subType.Equals("calendar"))) { return(false); } var icsTextPart = attach as TextPart; string icsAttach; if (icsTextPart != null) { icsAttach = icsTextPart.Text; } else { using (var stream = new MemoryStream()) { p.Content.DecodeTo(stream); var bytes = stream.ToArray(); var encoding = MailUtil.GetEncoding(p.ContentType.Charset); icsAttach = encoding.GetString(bytes); } } var cal = MailUtil.ParseValidCalendar(icsAttach, log); if (cal == null) { return(false); } return(mail.CalendarUid == cal.Events[0].Uid); }); if (calendarExists) { log.Debug("Calendar exists as attachment"); continue; } if (calendarPart.ContentDisposition == null) { calendarPart.ContentDisposition = new ContentDisposition(); } if (string.IsNullOrEmpty(calendarPart.ContentDisposition.FileName)) { calendarPart.ContentDisposition.FileName = calendar.Method == Defines.ICAL_REQUEST ? "invite.ics" : calendar.Method == Defines.ICAL_REPLY ? "reply.ics" : "cancel.ics"; } mail.LoadAttachments(new List <MimeEntity> { calendarPart }, true); } } catch (Exception ex) { log.ErrorFormat("LoadCalendarInfo() \r\n Exception: \r\n{0}\r\n", ex.ToString()); } }
public static void ExtractMainParts(this MailMessageData mail, MimeMessage message) { var htmlStream = new MemoryStream(); var textStream = new MemoryStream(); Action <MimeEntity> loadRealAttachment = (part) => { if ((part.ContentDisposition != null && !string.IsNullOrEmpty(part.ContentDisposition.FileName)) || part.ContentType != null && !string.IsNullOrEmpty(part.ContentType.Name)) { mail.LoadAttachments(new List <MimeEntity> { part }); } }; Action <MimePart> setBodyOrAttachment = (part) => { var entity = part as TextPart; if (htmlStream == null || textStream == null) { throw new Exception("Streams are not initialized"); } if ((entity == null || htmlStream.Length != 0 && entity.IsHtml || textStream.Length != 0 && !entity.IsHtml)) { loadRealAttachment(part); } else { if (mail.Introduction.Length < 200 && (!entity.IsHtml && !string.IsNullOrEmpty(entity.Text))) { if (string.IsNullOrEmpty(mail.Introduction)) { mail.Introduction = (entity.Text.Length > 200 ? entity.Text.Substring(0, 200) : entity.Text); } else { var need = 200 - mail.Introduction.Length; mail.Introduction += (entity.Text.Length > need ? entity.Text.Substring(0, need) : entity.Text); } mail.Introduction = mail.Introduction.Replace("\r\n", " ").Replace("\n", " ").Trim(); } var body = ConvertToHtml(entity); if (entity.IsHtml) { using (var sw = new StreamWriter(htmlStream, Encoding.UTF8, 1024, true)) { sw.Write(body); sw.Flush(); htmlStream.Seek(0, SeekOrigin.Begin); } } else { using (var sw = new StreamWriter(textStream, Encoding.UTF8, 1024, true)) { sw.Write(body); sw.Flush(); textStream.Seek(0, SeekOrigin.Begin); } } } }; var newPathIndex = ""; using (var sw = new StreamWriter(mail.HtmlBodyStream, Encoding.UTF8, 1024, true)) { using (var iter = new MimeIterator(message)) { while (string.IsNullOrEmpty(newPathIndex) ? iter.MoveNext() : iter.MoveTo(newPathIndex)) { if (!string.IsNullOrEmpty(newPathIndex)) { newPathIndex = ""; } var multipart = iter.Parent as Multipart; var part = iter.Current as MimePart; var subMessage = iter.Current as MessagePart; if (subMessage != null) { if ((subMessage.ContentDisposition != null && !string.IsNullOrEmpty(subMessage.ContentDisposition.FileName)) || subMessage.ContentType != null && !string.IsNullOrEmpty(subMessage.ContentType.Name)) { mail.LoadAttachments(new List <MimeEntity> { subMessage }, true); } else { subMessage.ContentDisposition = new ContentDisposition { Disposition = ContentDisposition.Attachment, FileName = "message.eml" }; mail.LoadAttachments(new List <MimeEntity> { subMessage }, true); } float pathIndex; if (float.TryParse(iter.PathSpecifier, out pathIndex)) { pathIndex++; newPathIndex = ((int)pathIndex).ToString(); continue; } } if (part == null || iter.Parent is MessagePart) { continue; } if (part.IsAttachment) { if (part is TnefPart) { var tnefPart = iter.Current as TnefPart; if (tnefPart != null) { mail.LoadAttachments(tnefPart.ExtractAttachments(), true); } } else { mail.LoadAttachments(new List <MimeEntity> { part }, multipart == null || !multipart.ContentType.MimeType.ToLowerInvariant().Equals("multipart/related")); } } else if (multipart != null) { switch (multipart.ContentType.MimeType.ToLowerInvariant()) { case "multipart/report": if (part is TextPart) { var entity = part as TextPart; if (entity == null) { entity = new TextPart(TextFormat.Plain); entity.SetText(Encoding.UTF8, part.ToString()); } var body = ConvertToHtml(entity); if (mail.HtmlBodyStream.Length == 0) { sw.Write(body); } else { sw.Write("<hr /><br/>"); sw.Write(body); } sw.Flush(); } else if (part is MessageDeliveryStatus) { var entity = new TextPart(TextFormat.Plain); var mds = (MessageDeliveryStatus)part; using (var memory = new MemoryStream()) { mds.Content.DecodeTo(memory); var text = Encoding.ASCII.GetString(memory.GetBuffer(), 0, (int)memory.Length) .Replace("\r\n", "\n"); entity.SetText(Encoding.UTF8, text); } var body = ConvertToHtml(entity); if (mail.HtmlBodyStream.Length == 0) { sw.Write(body); } else { sw.Write("<hr /><br/>"); sw.Write(body); } sw.Flush(); } else { loadRealAttachment(part); } break; case "multipart/mixed": if (part is TextPart) { var entity = part as TextPart; var body = ConvertToHtml(entity); if (mail.HtmlBodyStream.Length == 0) { sw.Write(body); } else { sw.Write("<hr /><br/>"); sw.Write(body); } sw.Flush(); } else { if (part.ContentType != null && part.ContentType.MediaType.Equals("image", StringComparison.InvariantCultureIgnoreCase) && part.ContentDisposition != null && part.ContentDisposition.Disposition.Equals(ContentDisposition.Inline, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(part.ContentId)) { part.ContentId = Guid.NewGuid().ToString("N").ToLower(); } mail.LoadAttachments(new List <MimeEntity> { part }); sw.Write("<hr /><br/>"); sw.Write("<img src=\"cid:{0}\">", part.ContentId); sw.Flush(); } else { loadRealAttachment(part); } } break; case "multipart/alternative": if (part is TextPart) { setBodyOrAttachment(part); } else { loadRealAttachment(part); } break; case "multipart/related": if (part is TextPart) { setBodyOrAttachment(part); } else if (!string.IsNullOrEmpty(part.ContentId) || part.ContentLocation != null) { mail.LoadAttachments(new List <MimeEntity> { part }); } else { loadRealAttachment(part); } break; default: if (part is TextPart) { setBodyOrAttachment(part); } else { loadRealAttachment(part); } break; } } else { if (part is TextPart) { setBodyOrAttachment(part); } else { loadRealAttachment(part); } } } } if (htmlStream.Length != 0) { if (mail.HtmlBodyStream.Length > 0) { sw.Write("<hr /><br/>"); sw.Flush(); } htmlStream.CopyTo(sw.BaseStream); } else if (textStream.Length != 0) { if (mail.HtmlBodyStream.Length == 0) { mail.TextBodyOnly = true; } else { sw.Write("<hr /><br/>"); sw.Flush(); } textStream.CopyTo(sw.BaseStream); } htmlStream.Dispose(); textStream.Dispose(); } if (mail.HtmlBodyStream.Length != 0) { return; } mail.HtmlBody = "<body><pre> </pre></body>"; mail.Introduction = ""; mail.TextBodyOnly = true; }