private MessageEntitySummary HandleMimeEntity(MimeEntity entity) { int index = 0; return(MimeEntityVisitor.VisitWithResults <MessageEntitySummary>(entity, (e, p) => { string fileName = PunyCodeReplacer.DecodePunycode(!string.IsNullOrEmpty(e.ContentDisposition?.FileName) ? e.ContentDisposition?.FileName : e.ContentType?.Name); MessageEntitySummary result = new MessageEntitySummary() { MessageId = Id, Id = index.ToString(), ContentId = e.ContentId, Name = (fileName ?? e.ContentId ?? index.ToString()) + " - " + e.ContentType.MimeType, Headers = e.Headers.Select(h => new Header { Name = h.Field, Value = PunyCodeReplacer.DecodePunycode(h.Value) }).ToList(), ChildParts = new List <MessageEntitySummary>(), Attachments = new List <AttachmentSummary>(), Warnings = new List <MessageWarning>(), Size = e.ToString().Length, IsAttachment = (e.ContentDisposition?.Disposition != "inline" && !string.IsNullOrEmpty(fileName)) || e.ContentDisposition?.Disposition == "attachment", MimeEntity = e }; if (p != null) { p.ChildParts.Add(result); if (result.IsAttachment) { if (e.ContentDisposition?.Disposition != "attachment") { result.Warnings.Add(new MessageWarning { Details = $"Attachment '{fileName}' should have \"Content-Disposition: attachment\" header." }); } if (string.IsNullOrEmpty(fileName)) { result.Warnings.Add(new MessageWarning { Details = $"Attachment with content ID '{e.ContentId}' should have filename specified in either 'Content-Type' or 'Content-Disposition' header." }); } p.Attachments.Add(new AttachmentSummary() { Id = result.Id, ContentId = result.ContentId, FileName = fileName, Url = $"api/messages/{Id}/part/{result.Id}/content" }); } } index++; return result; })); }
public async Task <DbModel.Message> ConvertAsync(Stream messageData, string envelopeFrom, string envelopeTo) { string subject = ""; string mimeParseError = null; byte[] data = new byte[messageData.Length]; await messageData.ReadAsync(data, 0, data.Length); bool foundHeaders = false; bool foundSeparator = false; using (StreamReader dataReader = new StreamReader(new MemoryStream(data))) { while (!dataReader.EndOfStream) { if (dataReader.ReadLine().Length != 0) { foundHeaders = true; } else { foundSeparator = true; break; } } } if (!foundHeaders || !foundSeparator) { mimeParseError = "Malformed MIME message. No headers found"; } else { messageData.Seek(0, SeekOrigin.Begin); try { CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(10)); MimeMessage mime = await MimeMessage.LoadAsync(messageData, true, cts.Token).ConfigureAwait(false); subject = mime.Subject; } catch (OperationCanceledException e) { mimeParseError = e.Message; } catch (FormatException e) { mimeParseError = e.Message; } } DbModel.Message message = new DbModel.Message() { Id = Guid.NewGuid(), From = PunyCodeReplacer.DecodePunycode(envelopeFrom), To = PunyCodeReplacer.DecodePunycode(envelopeTo), ReceivedDate = DateTime.Now, Subject = PunyCodeReplacer.DecodePunycode(subject), Data = data, MimeParseError = mimeParseError, AttachmentCount = 0 }; var parts = new ApiModel.Message(message).Parts; foreach (var part in parts) { message.AttachmentCount += CountAttachments(part); } return(message); }
public Message(DbModel.Message dbMessage) { Data = dbMessage.Data; Id = dbMessage.Id; From = dbMessage.From; To = dbMessage.To; Cc = ""; Bcc = ""; ReceivedDate = dbMessage.ReceivedDate; Subject = dbMessage.Subject; Parts = new List <ApiModel.MessageEntitySummary>(); RelayError = dbMessage.RelayError; if (dbMessage.MimeParseError != null) { MimeParseError = dbMessage.MimeParseError; Headers = new List <Header>(); Parts = new List <MessageEntitySummary>(); } else { using (MemoryStream stream = new MemoryStream(dbMessage.Data)) { MimeMessage = MimeMessage.Load(stream); if (MimeMessage.From != null) { From = MimeMessage.From.ToString(); } List <string> recipients = new List <string>(dbMessage.To.Split(",") .Select(r => r.Trim()) .Where(r => !string.IsNullOrEmpty(r))); if (MimeMessage.To != null) { To = string.Join(", ", MimeMessage.To.Select(t => PunyCodeReplacer.DecodePunycode(t.ToString()))); foreach (MailboxAddress to in MimeMessage.To.Where(t => t is MailboxAddress)) { recipients.Remove(PunyCodeReplacer.DecodePunycode(to.Address)); } } if (MimeMessage.Cc != null) { Cc = string.Join(", ", MimeMessage.Cc.Select(t => PunyCodeReplacer.DecodePunycode(t.ToString()))); foreach (MailboxAddress cc in MimeMessage.Cc.Where(t => t is MailboxAddress)) { recipients.Remove(PunyCodeReplacer.DecodePunycode(cc.Address)); } } Bcc = string.Join(", ", recipients); Headers = MimeMessage.Headers.Select(h => new Header { Name = h.Field, Value = PunyCodeReplacer.DecodePunycode(h.Value) }).ToList(); Parts.Add(HandleMimeEntity(MimeMessage.Body)); } } }