示例#1
0
        public void LoadEmbeddedAttachments(MimeMessage message)
        {
            var embeddedAttachments = new List <MimeEntity>();

            var iter = new MimeIterator(message);

            while (iter.MoveNext())
            {
                var part = iter.Current as MimePart;
                if (part == null)
                {
                    continue;
                }

                if (string.IsNullOrEmpty(part.ContentId) && part.ContentLocation == null)
                {
                    continue;
                }

                if (part is TextPart)
                {
                    continue;
                }

                embeddedAttachments.Add(part);
            }

            if (embeddedAttachments.Any())
            {
                LoadAttachments(embeddedAttachments);
            }
        }
示例#2
0
        public void TestMoveTo()
        {
            var expectedTypes          = new Type[] { typeof(Multipart), typeof(TextPart), typeof(MimePart), typeof(MessagePart), typeof(Multipart), typeof(TextPart), typeof(MimePart), typeof(Multipart), typeof(MimePart), typeof(MessagePart), typeof(Multipart), typeof(TextPart), typeof(MultipartAlternative), typeof(TextPart), typeof(TextPart) };
            var expectedPathSpecifiers = new List <string> {
                "0", "1", "2", "3", "3.0", "3.1", "3.2", "4", "4.1", "4.2", "4.2.0", "4.2.1", "4.2.2", "4.2.2.1", "4.2.2.2"
            };
            var paths           = new string[] { "3.1", "3.2", "4", "4.2.1", "4.2.2.2", "4.2", "3.2" };
            var expectedDepths  = new int[] { 0, 1, 1, 1, 2, 3, 3, 1, 2, 2, 3, 4, 4, 5, 5 };
            var expectedParents = new List <MimeEntity> {
                null
            };
            var message = CreateImapExampleMessage(expectedParents);
            var iter    = new MimeIterator(message);

            foreach (var path in paths)
            {
                int i = expectedPathSpecifiers.IndexOf(path);

                Assert.IsTrue(iter.MoveTo(expectedPathSpecifiers[i]), "MoveTo {0}", expectedPathSpecifiers[i]);
                Assert.AreEqual(expectedPathSpecifiers[i], iter.PathSpecifier, "PathSpecifier {0}", expectedPathSpecifiers[i]);
                Assert.AreEqual(expectedParents[i], iter.Parent, "Parent {0}", expectedPathSpecifiers[i]);
                Assert.IsInstanceOf(expectedTypes[i], iter.Current, "Type {0}", expectedPathSpecifiers[i]);
                Assert.AreEqual(expectedDepths[i], iter.Depth, "Depth {0}", expectedPathSpecifiers[i]);
            }
        }
示例#3
0
        public void TestArgumentExceptions()
        {
            var iter = new MimeIterator(new MimeMessage {
                Body = new TextPart("plain")
            });

            Assert.Throws <ArgumentNullException> (() => new MimeIterator(null));
            Assert.Throws <InvalidOperationException> (() => { var x = iter.Depth; });
            Assert.Throws <InvalidOperationException> (() => { var x = iter.Current; });
            Assert.Throws <InvalidOperationException> (() => { var x = iter.Parent; });
            Assert.Throws <InvalidOperationException> (() => { var x = iter.PathSpecifier; });
            Assert.Throws <ArgumentNullException> (() => iter.MoveTo(null));
            Assert.Throws <ArgumentException> (() => iter.MoveTo(string.Empty));
            Assert.Throws <FormatException> (() => iter.MoveTo("xyz"));
        }
示例#4
0
        static void DumpMimeTree(StringBuilder builder, MimeMessage message)
        {
            using (var iter = new MimeIterator(message)) {
                while (iter.MoveNext())
                {
                    var ctype = iter.Current.ContentType;

                    if (iter.Depth > 0)
                    {
                        builder.Append(new string (' ', iter.Depth * 3));
                    }

                    builder.AppendFormat("Content-Type: {0}/{1}", ctype.MediaType, ctype.MediaSubtype).Append('\n');
                }
            }
        }
示例#5
0
        public void TestPathSpecifiers()
        {
            var expectedTypes          = new Type[] { typeof(Multipart), typeof(TextPart), typeof(MimePart), typeof(MessagePart), typeof(Multipart), typeof(TextPart), typeof(MimePart), typeof(Multipart), typeof(MimePart), typeof(MessagePart), typeof(Multipart), typeof(TextPart), typeof(MultipartAlternative), typeof(TextPart), typeof(TextPart) };
            var expectedPathSpecifiers = new string[] { "0", "1", "2", "3", "3.0", "3.1", "3.2", "4", "4.1", "4.2", "4.2.0", "4.2.1", "4.2.2", "4.2.2.1", "4.2.2.2" };
            var expectedDepths         = new int[] { 0, 1, 1, 1, 2, 3, 3, 1, 2, 2, 3, 4, 4, 5, 5 };
            var expectedParents        = new List <MimeEntity> {
                null
            };
            var message = CreateImapExampleMessage(expectedParents);
            var iter    = new MimeIterator(message);
            int i       = 0;

            Assert.IsTrue(iter.MoveNext(), "Initialize");
            do
            {
                var current = iter.Current;
                var parent  = iter.Parent;

                Assert.AreEqual(expectedDepths[i], iter.Depth, "Depth #{0}", i);
                Assert.AreEqual(expectedParents[i], parent, "Parent #{0}", i);
                Assert.IsInstanceOf(expectedTypes[i], current, "Type #{0}", i);
                Assert.AreEqual(expectedPathSpecifiers[i], iter.PathSpecifier, "PathSpecifier #{0}", i);
                i++;
            } while (iter.MoveNext());

            Assert.AreEqual(expectedTypes.Length, i);

            iter.Reset();
            i = 0;

            Assert.IsTrue(iter.MoveNext(), "Reset");
            do
            {
                var current = iter.Current;
                var parent  = iter.Parent;

                Assert.AreEqual(expectedDepths[i], iter.Depth, "Reset Depth #{0}", i);
                Assert.AreEqual(expectedParents[i], parent, "Reset Parent #{0}", i);
                Assert.IsInstanceOf(expectedTypes[i], current, "Reset Type #{0}", i);
                Assert.AreEqual(expectedPathSpecifiers[i], iter.PathSpecifier, "Reset PathSpecifier #{0}", i);
                i++;
            } while (iter.MoveNext());
        }
示例#6
0
 static void insert_attachments(int post_id, int issue_id, MimeMessage message)
 {
     using (var iter = new MimeIterator(message))
     {
         // collect our list of attachments and their parent multiparts
         while (iter.MoveNext())
         {
             var multipart = iter.Parent as Multipart;
             var part      = iter.Current as MimePart;
             if (part is not null)
             {
                 if (part.FileName is not null)
                 {
                     bd_issue.insert_post_attachment_from_email_attachment(post_id, issue_id, part);
                 }
             }
         }
     }
 }
示例#7
0
        private static IList <MimePart> GetMessageAttachments(MimeMessage message)
        {
            var attachments = new List <MimePart>();
            var iter        = new MimeIterator(message);

            // collect our list of attachments and their parent multiparts
            while (iter.MoveNext())
            {
                var multipart = iter.Parent as Multipart;
                var part      = iter.Current as MimePart;

                if (multipart != null && part != null && part.IsAttachment)
                {
                    attachments.Add(part);
                }
            }

            return(attachments);
        }
示例#8
0
        /// <summary>
        /// Save the given message to the underlying storage system.
        /// </summary>
        /// <param name="context">The session context.</param>
        /// <param name="transaction">The SMTP message transaction to store.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A unique identifier that represents this message in the underlying message store.</returns>
        public override Task <SmtpResponse> SaveAsync(ISessionContext context, IMessageTransaction transaction, CancellationToken cancellationToken)
        {
            Init();

            var         textMessage = (ITextMessage)transaction.Message;
            MimeMessage mailMessage = MimeMessage.Load(textMessage.Content);

            Message message = new Message();

            message.Id          = Guid.NewGuid();
            message.RetryCount  = 0;
            message.ErrorReason = "";
            message.Timestamp   = DateTime.UtcNow;

            var inboundMessage = new InboundMessage();

            string fromAddress = String.Empty;

            if (mailMessage.From != null && mailMessage.From.Count > 0)
            {
                var from = ((MailboxAddress)mailMessage.From[0]);
                inboundMessage.From     = from.Address;
                fromAddress             = from.Address;
                inboundMessage.FromFull = new FromFull()
                {
                    Email = from.Address, Name = from.Name
                };
            }

            string toAddress = String.Empty;

            if (mailMessage.To != null && mailMessage.To.Count > 0)
            {
                inboundMessage.ToFull = new List <ToFull>();
                foreach (var to in mailMessage.To)
                {
                    var toAdd = (MailboxAddress)to;

                    if (String.IsNullOrWhiteSpace(inboundMessage.To))
                    {
                        inboundMessage.To = toAdd.Address;
                        toAddress         = toAdd.Address;
                    }

                    inboundMessage.ToFull.Add(new ToFull()
                    {
                        Email = toAdd.Address, Name = toAdd.Name
                    });
                }
            }

            _logger.Information("Email Received {id} {fromAddress} {toAddress}", message.Id, fromAddress, toAddress);

            var attachments = new List <MimePart>();
            var multiparts  = new List <Multipart>();
            var iter        = new MimeIterator(mailMessage);

            // collect our list of attachments and their parent multiparts
            while (iter.MoveNext())
            {
                var multipart = iter.Parent as Multipart;
                var part      = iter.Current as MimePart;

                if (multipart != null && part != null && part.IsAttachment)
                {
                    // keep track of each attachment's parent multipart
                    multiparts.Add(multipart);
                    attachments.Add(part);
                }
            }

            // now remove each attachment from its parent multipart...
            for (int i = 0; i < attachments.Count; i++)
            {
                multiparts[i].Remove(attachments[i]);
            }

            inboundMessage.TextBody  = mailMessage.GetTextBody(MimeKit.Text.TextFormat.Plain);
            inboundMessage.HtmlBody  = mailMessage.HtmlBody;
            inboundMessage.Subject   = mailMessage.Subject;
            inboundMessage.MessageID = mailMessage.MessageId;

            inboundMessage.Attachments = new List <Attachment>();
            foreach (var attachment in attachments)
            {
                var att = new Attachment();

                StreamReader reader = new StreamReader(attachment.Content.Stream);
                att.Content = reader.ReadToEnd();

                att.Name        = attachment.FileName;
                att.ContentID   = attachment.ContentId;
                att.ContentType = attachment.ContentType.MimeType;

                inboundMessage.Attachments.Add(att);
            }

            message.InboundMessage = inboundMessage;

            var fileText = JsonConvert.SerializeObject(message);
            var filePath = _fileService.CreateFile($"{message.Id.ToString()}.rgm", "emails", fileText);

            if (!String.IsNullOrWhiteSpace(filePath))
            {
                _logger.Information("Email Saved {id}", message.Id);
                return(Task.FromResult(SmtpResponse.Ok));
            }
            else
            {
                _logger.Information("Email Not Saved {id}", message.Id);
                return(Task.FromResult(new SmtpResponse(SmtpReplyCode.MessageTimeout)));
            }
        }
示例#9
0
        public IList <EmailMessage> GetNewMessages(int accountId)
        {
            var account     = _context.Accounts.Include(a => a.EmailAccount).FirstOrDefault(a => a.Id == accountId);
            var newMessages = new List <EmailMessage>();

            if (account != null)
            {
                EmailAccount eAcc = account.EmailAccount;

                using (var client = new ImapClient())
                {
                    var credentials = new NetworkCredential(eAcc.UserName, eAcc.Password);

                    client.Connect(eAcc.ServerUri, eAcc.ServerPort, eAcc.ServerUseSSL);

                    client.AuthenticationMechanisms.Remove("XOAUTH2");
                    client.Authenticate(credentials);

                    client.Inbox.Open(FolderAccess.ReadOnly);

                    // Обрабатываем сами письма

                    foreach (var summary in client.Inbox.Fetch((int)eAcc.LastMessageUid, -1, MessageSummaryItems.UniqueId))
                    {
                        MimeMessage iMessage = client.Inbox.GetMessage(summary.UniqueId);

                        // Если в белом списке есть запись "*", то принимаем письма от всех отправителей
                        if (eAcc.WhileListFrom.Contains("*") || eAcc.WhileListFrom.Contains(iMessage.From.Mailboxes.First().Address))
                        {
                            // Текстовое содержимое

                            var message = new EmailMessage
                            {
                                Id           = (int)summary.UniqueId.Id,
                                From         = iMessage.From.Mailboxes.First().Name,
                                Subject      = iMessage.Subject,
                                Body         = iMessage.TextBody,
                                ReceivedDate = iMessage.Date.LocalDateTime
                            };

                            // Вложения

                            var multiparts  = new List <Multipart>();
                            var attachments = new List <MimePart>();
                            using (var iter = new MimeIterator(iMessage))
                            {
                                while (iter.MoveNext())
                                {
                                    var multipart = iter.Parent as Multipart;
                                    var part      = iter.Current as MimePart;

                                    if (multipart != null && part != null && part.IsAttachment)
                                    {
                                        multiparts.Add(multipart);
                                        attachments.Add(part);
                                    }
                                }
                            }

                            for (int i = 0; i < attachments.Count; i++)
                            {
                                multiparts[i].Remove(attachments[i]);
                            }

                            foreach (var attachment in attachments)
                            {
                                using (var ms = new MemoryStream())
                                {
                                    attachment.ContentObject.DecodeTo(ms);

                                    message.Attachments.Add(new Attachment
                                    {
                                        Title    = attachment.FileName,
                                        Contents = ms.ToArray()
                                    });
                                }
                            }

                            newMessages.Add(message);
                        }

                        eAcc.LastMessageUid = (int)summary.UniqueId.Id; // Учитываем Id сообщения, даже если оно не подошло
                    }
                }

                _context.SaveChanges();
            }

            return(newMessages);
        }
        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;
        }
示例#11
0
        private void SetHtmlBodyAndIntroduction(MimeMessage message)
        {
            HtmlBody     = "<br/>";
            Introduction = "";

            var htmlBodyBuilder = new StringBuilder().Append(message.HtmlBody);

            ContentType contentType = null;
            var         subMessages = new ItemList <MimeMessage>();

            var iter = new MimeIterator(message);

            while (iter.MoveNext())
            {
                var multipart  = iter.Parent as Multipart;
                var part       = iter.Current as MimePart;
                var subMessage = iter.Current as MessagePart;

                if (multipart != null && part != null && !part.IsAttachment)
                {
                    if (contentType == null &&
                        (part.ContentType.IsMimeType("text", "plain") || part.ContentType.IsMimeType("text", "html")))
                    {
                        contentType = multipart.ContentType;
                    }
                }

                if (subMessage != null)
                {
                    subMessages.Add(subMessage.Message);
                }
            }

            contentType = contentType ?? message.Body.ContentType;

            if (contentType.MimeType.Equals("multipart/mixed", StringComparison.InvariantCultureIgnoreCase) &&
                !string.IsNullOrEmpty(message.HtmlBody) &&
                !string.IsNullOrEmpty(message.TextBody))
            {
                htmlBodyBuilder.AppendFormat("<p>{0}</p>", MakeHtmlFromText(message.TextBody));
            }
            else if (!string.IsNullOrEmpty(message.TextBody) && string.IsNullOrEmpty(message.HtmlBody))
            {
                var html = MakeHtmlFromText(message.TextBody);
                htmlBodyBuilder.AppendFormat("<body><pre>{0}</pre></body>", html);
                TextBodyOnly = true;
            }

            foreach (var subMessage in subMessages)
            {
                var toString = string.Join(", ", subMessage.To.Select(s => s.ToString()));
                htmlBodyBuilder.Append("<hr /><br/>")
                .Append("<div style=\"padding-left:15px;\">")
                .AppendFormat("<span><b>Subject:</b> {0}</span><br/>", subMessage.Subject)
                .AppendFormat("<span><b>From:</b> {0}</span><br/>", subMessage.From)
                .AppendFormat("<span><b>Date:</b> {0}</span><br/>", subMessage.Date)
                .AppendFormat("<span><b>To:</b> {0}</span><br/></div>", toString)
                .AppendFormat("<br/>{0}", subMessage.HtmlBody);
            }

            HtmlBody     = htmlBodyBuilder.ToString();
            Introduction = GetIntroduction(HtmlBody);
        }
示例#12
0
        private void FillTreeView()
        {
            var iter = new MimeIterator(_mimeMessage);

            messageTree.BeginUpdate();

            try
            {
                messageTree.Nodes.Clear();

                TreeNode rootNode = null;

                while (iter.MoveNext())
                {
                    TreeNode createdNode = null;

                    if (rootNode == null)
                    {
                        rootNode    = messageTree.Nodes.Add(iter.Current.ContentId ?? "body");
                        createdNode = rootNode;
                    }
                    else
                    {
                        createdNode = rootNode.Nodes.Add(iter.Current.ContentId ?? "part");
                    }

                    createdNode.Tag         = iter.Current;
                    createdNode.ContextMenu = new ContextMenu();

                    var menuItem = createdNode.ContextMenu.MenuItems.Add("Save to file...");
                    menuItem.Tag = iter.Current;

                    menuItem.Click += (s, e) =>
                    {
                        var dialog = new SaveFileDialog();
                        if (dialog.ShowDialog() == DialogResult.OK)
                        {
                            using (FileStream fs = new FileStream(dialog.FileName, FileMode.OpenOrCreate))
                            {
                                if (((MenuItem)s).Tag is MimePart part)
                                {
                                    if (part.ContentObject != null)
                                    {
                                        part.ContentObject.WriteTo(fs);
                                    }
                                }

                                fs.Flush();
                            }
                            if (MessageBox.Show("Open now?", "Open attachment", MessageBoxButtons.YesNo) == DialogResult.Yes)
                            {
                                Process.Start(dialog.FileName);
                            }
                        }
                    };
                }

                if (rootNode != null)
                {
                    rootNode.Expand();

                    messageTree.SelectedNode = rootNode;
                    rootNode.EnsureVisible();
                }
            }
            finally
            {
                messageTree.EndUpdate();
            }
        }
示例#13
0
		static void DumpMimeTree (StringBuilder builder, MimeMessage message)
		{
			var iter = new MimeIterator (message);

			while (iter.MoveNext ()) {
				var ctype = iter.Current.ContentType;

				if (iter.Depth > 0)
					builder.Append (new string (' ', iter.Depth * 3));

				builder.AppendFormat ("Content-Type: {0}/{1}", ctype.MediaType, ctype.MediaSubtype).Append ('\n');
			}
		}
		void HandlePgpMime(Outlook.MailItem mailItem, Outlook.Attachment encryptedMime,
			Outlook.Attachment sigMime, string sigHash = "sha1")
		{
			logger.Trace("> HandlePgpMime");
			CryptoContext Context = null;

			byte[] cyphertext = null;
			byte[] clearbytes = null;
			var cleartext = mailItem.Body;

			// 1. Decrypt attachement

			if (encryptedMime != null)
			{
				logger.Trace("Decrypting cypher text.");

				var tempfile = Path.GetTempFileName();
				encryptedMime.SaveAsFile(tempfile);
				cyphertext = File.ReadAllBytes(tempfile);
				File.Delete(tempfile);

				clearbytes = DecryptAndVerify(mailItem.To, cyphertext, out Context);
				if (clearbytes == null)
					return;

				cleartext = this._encoding.GetString(clearbytes);
			}

			// 2. Verify signature

			if (sigMime != null)
			{
				Context = new CryptoContext(PasswordCallback, _settings.Cipher, _settings.Digest);
				var Crypto = new PgpCrypto(Context);
				var mailType = mailItem.BodyFormat;

				try
				{
					logger.Trace("Verify detached signature");

					var tempfile = Path.GetTempFileName();
					sigMime.SaveAsFile(tempfile);
					var detachedsig = File.ReadAllText(tempfile);
					File.Delete(tempfile);

					// Build up a clearsignature format for validation
					// the rules for are the same with the addition of two heaer fields.
					// Ultimately we need to get these fields out of email itself.

					// NOTE: encoding could be uppercase or lowercase. Try both.
					//       this is definetly hacky :/

					var encoding = GetEncodingFromMail(mailItem);
					var body = string.Empty;

					// Try two different methods to get the mime body
					try
					{
						body = encoding.GetString(
							(byte[])mailItem.PropertyAccessor.GetProperty(
								"http://schemas.microsoft.com/mapi/string/{4E3A7680-B77A-11D0-9DA5-00C04FD65685}/Internet Charset Body/0x00000102"));
					}
					catch (Exception)
					{
						body = (string)mailItem.PropertyAccessor.GetProperty(
								"http://schemas.microsoft.com/mapi/proptag/0x1000001F"); // PR_BODY
					}

					var clearsigUpper = new StringBuilder();

					clearsigUpper.Append(string.Format("-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: {0}\r\nCharset: {1}\r\n\r\n", sigHash, encoding.BodyName.ToUpper()));
					clearsigUpper.Append("Content-Type: text/plain; charset=");
					clearsigUpper.Append(encoding.BodyName.ToUpper());
					clearsigUpper.Append("\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n");

					clearsigUpper.Append(PgpClearDashEscapeAndQuoteEncode(body));

					clearsigUpper.Append("\r\n");
					clearsigUpper.Append(detachedsig);

					var clearsigLower = new StringBuilder(clearsigUpper.Length);

					clearsigLower.Append(string.Format("-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: {0}\r\nCharset: {1}\r\n\r\n", sigHash, encoding.BodyName.ToUpper()));
					clearsigLower.Append("Content-Type: text/plain; charset=");
					clearsigLower.Append(encoding.BodyName.ToLower());
					clearsigLower.Append("\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n");

					clearsigLower.Append(PgpClearDashEscapeAndQuoteEncode(body));

					clearsigLower.Append("\r\n");
					clearsigLower.Append(detachedsig);

					logger.Trace(clearsigUpper.ToString());

					if (Crypto.VerifyClear(_encoding.GetBytes(clearsigUpper.ToString())) || Crypto.VerifyClear(_encoding.GetBytes(clearsigLower.ToString())))
					{
						Context = Crypto.Context;

						var message = "** " + string.Format(Localized.MsgValidSig,
							Context.SignedByUserId, Context.SignedByKeyId) + "\n\n";

						if (mailType == Outlook.OlBodyFormat.olFormatPlain)
							mailItem.Body = message + mailItem.Body;
						else
							mailItem.HTMLBody = AddMessageToHtmlBody(mailItem.HTMLBody, message);
					}
					else
					{
						Context = Crypto.Context;

						var message = "** " + string.Format(Localized.MsgInvalidSig,
							Context.SignedByUserId, Context.SignedByKeyId) + "\n\n";

						if (mailType == Outlook.OlBodyFormat.olFormatPlain)
							mailItem.Body = message + mailItem.Body;
						else
							mailItem.HTMLBody = AddMessageToHtmlBody(mailItem.HTMLBody, message);
					}
				}
				catch (PublicKeyNotFoundException ex)
				{
					logger.Debug(ex.ToString());

					Context = Crypto.Context;

					var message = "** " + Localized.MsgSigMissingPubKey + "\n\n";

					if (mailType == Outlook.OlBodyFormat.olFormatPlain)
						mailItem.Body = message + mailItem.Body;
					else
						mailItem.HTMLBody = AddMessageToHtmlBody(mailItem.HTMLBody, message);
				}
				catch (Exception ex)
				{
					logger.Debug(ex.ToString());

					WriteErrorData("VerifyEmail", ex);
					MessageBox.Show(
						ex.Message,
						Localized.ErrorDialogTitle,
						MessageBoxButtons.OK,
						MessageBoxIcon.Error);
				}

				return;

			}

			if (Context == null)
				return;

			// Extract files from MIME data

			MimeMessage msg = null;
			TextPart textPart = null;
			MimeEntity htmlPart = null;
			var isHtml = false;

			using(var sin = new MemoryStream(clearbytes))
			{
				var parser = new MimeParser(sin);
				msg = parser.ParseMessage();
				var iter = new MimeIterator(msg);

				while(iter.MoveNext())
				{
					var part = iter.Current as TextPart;
					if (part == null)
						continue;

					if (part.IsAttachment)
						continue;

					// message could include both text and html
					// if we find html use that over text.
					if (part.IsHtml)
					{
						htmlPart = part;
						isHtml = true;
					}
					else
					{
						textPart = part;
					}
				}
			}

			var DecryptAndVerifyHeaderMessage = "** ";

			if (Context.IsEncrypted)
				DecryptAndVerifyHeaderMessage += Localized.MsgDecrypt + " ";

			if (Context.FailedIntegrityCheck)
				DecryptAndVerifyHeaderMessage += Localized.MsgFailedIntegrityCheck + " ";

			if (Context.IsSigned && Context.SignatureValidated)
			{
				DecryptAndVerifyHeaderMessage += string.Format(Localized.MsgValidSig,
					Context.SignedByUserId, Context.SignedByKeyId);
			}
			else if (Context.IsSigned)
			{
				DecryptAndVerifyHeaderMessage +=  string.Format(Localized.MsgInvalidSig,
					Context.SignedByUserId, Context.SignedByKeyId);
			}
			else
				DecryptAndVerifyHeaderMessage += Localized.MsgUnsigned;

			DecryptAndVerifyHeaderMessage += "\n\n";

			if(isHtml)
			{
				var htmlBody = msg.HtmlBody;
				var related = msg.Body as MultipartRelated;
				var doc = new HtmlAgilityPack.HtmlDocument();
				var savedImages = new List<MimePart>();

				doc.LoadHtml(htmlBody);

				// Find any embedded images
				foreach (var img in doc.DocumentNode.SelectNodes("//img[@src]"))
				{
					var src = img.Attributes["src"];
					Uri uri;

					if (src == null || src.Value == null)
						continue;

					// parse the <img src=...> attribute value into a Uri
					if (Uri.IsWellFormedUriString(src.Value, UriKind.Absolute))
						uri = new Uri(src.Value, UriKind.Absolute);
					else
						uri = new Uri(src.Value, UriKind.Relative);

					// locate the index of the attachment within the multipart/related (if it exists)
					string imageCid = src.Value.Substring(4);

					var iter = new MimeIterator(msg);
					MimePart attachment = null;
					while (iter.MoveNext())
					{
						if (iter.Current.ContentId == imageCid)
						{
							attachment = iter.Current as MimePart;
							break;
						}
					}

					if (attachment == null)
						continue;

					string fileName;

					// save the attachment (if we haven't already saved it)
					if (!savedImages.Contains(attachment))
					{
						fileName = attachment.FileName;

						if (string.IsNullOrEmpty(fileName))
							fileName = Guid.NewGuid().ToString();

						using (var stream = File.Create(fileName))
							attachment.ContentObject.DecodeTo(stream);

						try
						{
							var att = mailItem.Attachments.Add(fileName, Outlook.OlAttachmentType.olEmbeddeditem, null, "");
							att.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", imageCid);
							savedImages.Add(attachment);
						}
						finally
						{
							// try not to leak temp files :)
							File.Delete(fileName);
						}
					}
				}

				mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
				mailItem.HTMLBody = AddMessageToHtmlBody(htmlBody, DecryptAndVerifyHeaderMessage);
			}
			else
			{
				// NOTE: For some reason we cannot change the BodyFormat once it's set.
				//       So if we are set to HTML we need to wrap the plain text so it's
				//       displayed okay. Also of course prevent XSS.

				if (mailItem.BodyFormat == Outlook.OlBodyFormat.olFormatPlain)
				{
					mailItem.Body = DecryptAndVerifyHeaderMessage + msg.TextBody;
				}
				else
				{
					var sb = new StringBuilder(msg.TextBody.Length + 100);
					sb.Append("<html><body><pre>");
					sb.Append(WebUtility.HtmlEncode(DecryptAndVerifyHeaderMessage));
					sb.Append(WebUtility.HtmlEncode(msg.TextBody));
					sb.Append("</pre></body></html>");

					mailItem.HTMLBody = sb.ToString();
				}
			}

			// NOTE: Removing existing attachments is perminant, even if the message
			//       is not saved.

			foreach (var mimeAttachment in msg.Attachments)
			{
				var fileName = mimeAttachment.FileName;
				var tempFile = Path.Combine(Path.GetTempPath(), fileName);

				using (var fout = File.OpenWrite(tempFile))
				{
					mimeAttachment.ContentObject.DecodeTo(fout);
				}

				mailItem.Attachments.Add(tempFile, Outlook.OlAttachmentType.olByValue, 1, fileName);

				File.Delete(tempFile);
			}
		}
示例#15
0
        private void ExtractMainParts(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))
                {
                    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 (Introduction.Length < 200 && (!entity.IsHtml && !string.IsNullOrEmpty(entity.Text)))
                    {
                        if (string.IsNullOrEmpty(Introduction))
                        {
                            Introduction = (entity.Text.Length > 200 ? entity.Text.Substring(0, 200) : entity.Text);
                        }
                        else
                        {
                            var need = 200 - Introduction.Length;
                            Introduction += (entity.Text.Length > need ? entity.Text.Substring(0, need) : entity.Text);
                        }

                        Introduction = 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);
                        }
                    }
                }
            };

            using (var sw = new StreamWriter(HtmlBodyStream, Encoding.UTF8, 1024, true))
            {
                using (var iter = new MimeIterator(message))
                {
                    while (iter.MoveNext())
                    {
                        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))
                            {
                                LoadAttachments(new List <MimeEntity> {
                                    subMessage
                                }, true);
                            }
                            else
                            {
                                subMessage.ContentDisposition = new ContentDisposition
                                {
                                    Disposition = ContentDisposition.Attachment,
                                    FileName    = "message.eml"
                                };
                                LoadAttachments(new List <MimeEntity> {
                                    subMessage
                                }, true);
                            }
                        }

                        if (part == null)
                        {
                            continue;
                        }

                        if (part.IsAttachment)
                        {
                            if (part is TnefPart)
                            {
                                var tnefPart = iter.Current as TnefPart;

                                if (tnefPart != null)
                                {
                                    LoadAttachments(tnefPart.ExtractAttachments(), true);
                                }
                            }
                            else
                            {
                                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/mixed":
                                if (part is TextPart)
                                {
                                    var entity = part as TextPart;

                                    var body = ConvertToHtml(entity);

                                    if (HtmlBodyStream.Length == 0)
                                    {
                                        sw.Write(body);
                                    }
                                    else
                                    {
                                        sw.Write("<hr /><br/>");
                                        sw.Write(body);
                                    }

                                    sw.Flush();
                                }
                                else
                                {
                                    if (part.ContentType.MediaType.Equals("image",
                                                                          StringComparison.InvariantCultureIgnoreCase) &&
                                        part.ContentDisposition.Disposition == ContentDisposition.Inline)
                                    {
                                        if (string.IsNullOrEmpty(part.ContentId))
                                        {
                                            part.ContentId = Guid.NewGuid().ToString("N").ToLower();
                                        }

                                        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)
                                {
                                    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 (HtmlBodyStream.Length > 0)
                    {
                        sw.Write("<hr /><br/>");
                        sw.Flush();
                    }

                    htmlStream.CopyTo(sw.BaseStream);
                }
                else if (textStream.Length != 0)
                {
                    if (HtmlBodyStream.Length == 0)
                    {
                        TextBodyOnly = true;
                    }
                    else
                    {
                        sw.Write("<hr /><br/>");
                        sw.Flush();
                    }

                    textStream.CopyTo(sw.BaseStream);
                }

                htmlStream.Dispose();
                textStream.Dispose();
            }

            if (HtmlBodyStream.Length != 0)
            {
                return;
            }

            HtmlBody     = "<body><pre>&nbsp;</pre></body>";
            Introduction = "";
            TextBodyOnly = true;
        }