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>&nbsp;</pre></body>";
            mail.Introduction = "";
            mail.TextBodyOnly = true;
        }