/// <summary> /// Visit the children of a <see cref="MailKit.BodyPartMultipart"/>. /// </summary> /// <remarks> /// Visits the children of a <see cref="MailKit.BodyPartMultipart"/>. /// </remarks> /// <param name="multipart">The multipart.</param> protected virtual void VisitChildren(BodyPartMultipart multipart) { for (int i = 0; i < multipart.BodyParts.Count; i++) { multipart.BodyParts[i].Accept(this); } }
async void RenderMultipartRelated(IMailFolder folder, UniqueId uid, BodyPartMultipart bodyPart) { // download the entire multipart/related for simplicity since we'll probably end up needing all of the image attachments anyway... var related = await folder.GetBodyPartAsync(uid, bodyPart) as MultipartRelated; RenderMultipartRelated(related); }
public void TestMultipartWithNoChildren() { var original = new BodyPartMultipart { ContentType = new ContentType("multipart", "mixed") { Boundary = "----=_NextPart_000_001" } }; original.BodyParts.Add(new BodyPartMultipart { ContentType = new ContentType("multipart", "alternative") { Boundary = "----=_AlternativePart_001_001" } }); var serialized = original.ToString(); Assert.IsTrue(BodyPart.TryParse(serialized, out var body), "Failed to parse."); Assert.IsInstanceOf <BodyPartMultipart> (body, "Body types did not match."); var multipart = (BodyPartMultipart)body; Assert.IsTrue(multipart.ContentType.IsMimeType("multipart", "mixed"), "Content-Type did not match."); Assert.AreEqual(original.ContentType.Boundary, multipart.ContentType.Boundary, "boundary param did not match"); Assert.AreEqual(1, multipart.BodyParts.Count, "BodyParts count does not match."); Assert.IsInstanceOf <BodyPartMultipart> (multipart.BodyParts[0], "The type of the first child does not match."); var alternative = (BodyPartMultipart)multipart.BodyParts[0]; Assert.IsTrue(alternative.ContentType.IsMimeType("multipart", "alternative"), "Inner Content-Type did not match."); Assert.AreEqual(original.BodyParts[0].ContentType.Boundary, alternative.ContentType.Boundary, "Inner boundary param did not match"); Assert.AreEqual(0, alternative.BodyParts.Count, "Inner BodyParts count does not match."); }
static BodyPartMultipart CreateMultipart(string type, string subtype, string partSpecifier, params BodyPart[] bodyParts) { var multipart = new BodyPartMultipart { ContentType = CreateContentType(type, subtype, partSpecifier) }; foreach (var bodyPart in bodyParts) { multipart.BodyParts.Add(bodyPart); } return(multipart); }
public void fill(BodyPartMultipart part) { attachmentList.AddRange( part .BodyParts .OfType <BodyPartBasic>() ); foreach (var mp in part.BodyParts.Where(p => p is BodyPartMultipart)) { fill((BodyPartMultipart)mp); } }
/// <summary> /// Visit the abstract multipart MIME entity. /// </summary> /// <remarks> /// Visits the abstract multipart MIME entity. /// </remarks> /// <param name="multipart">The multipart body part.</param> protected internal virtual void VisitBodyPartMultipart(BodyPartMultipart multipart) { VisitBodyPart(multipart); VisitChildren(multipart); }
static BodyPart ParseMultipart (ImapEngine engine, string path, string subtype, CancellationToken cancellationToken) { var prefix = path.Length > 0 ? path + "." : string.Empty; var body = new BodyPartMultipart (); ImapToken token; int index = 1; // Note: if subtype is not null, then we are working around a GMail bug... if (subtype == null) { do { body.BodyParts.Add (ParseBody (engine, prefix + index, cancellationToken)); token = engine.PeekToken (cancellationToken); index++; } while (token.Type == ImapTokenType.OpenParen); subtype = ReadStringToken (engine, cancellationToken); } body.ContentType = new ContentType ("multipart", subtype); body.PartSpecifier = path; token = engine.PeekToken (cancellationToken); if (token.Type != ImapTokenType.CloseParen) { token = engine.ReadToken (cancellationToken); if (token.Type != ImapTokenType.OpenParen) throw ImapEngine.UnexpectedToken (token, false); var builder = new StringBuilder (); ContentType contentType; builder.AppendFormat ("{0}/{1}", body.ContentType.MediaType, body.ContentType.MediaSubtype); ParseParameterList (builder, engine, cancellationToken); if (ContentType.TryParse (builder.ToString (), out contentType)) body.ContentType = contentType; token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentDisposition = ParseContentDisposition (engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLanguage = ParseContentLanguage (engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLocation = ParseContentLocation (engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) SkipBodyExtensions (engine, cancellationToken); // read the ')' token = engine.ReadToken (cancellationToken); if (token.Type != ImapTokenType.CloseParen) throw ImapEngine.UnexpectedToken (token, false); return body; }
protected override void VisitChildren(BodyPartMultipart multipart) { indent++; base.VisitChildren(multipart); indent--; }
static BodyPart ParseMultipart(ImapEngine engine, string path, CancellationToken cancellationToken) { var prefix = path.Length > 0 ? path + "." : string.Empty; var body = new BodyPartMultipart(); ImapToken token; int index = 1; do { body.BodyParts.Add(ParseBody(engine, prefix + index, cancellationToken)); token = engine.PeekToken(cancellationToken); index++; } while (token.Type == ImapTokenType.OpenParen); var subtype = ReadStringToken(engine, cancellationToken); body.ContentType = new ContentType("multipart", subtype); body.PartSpecifier = path; token = engine.PeekToken(cancellationToken); if (token.Type != ImapTokenType.CloseParen) { token = engine.ReadToken(cancellationToken); if (token.Type != ImapTokenType.OpenParen) { throw ImapEngine.UnexpectedToken(token, false); } var builder = new StringBuilder(); ContentType contentType; builder.AppendFormat("{0}/{1}", body.ContentType.MediaType, body.ContentType.MediaSubtype); ParseParameterList(builder, engine, cancellationToken); if (ContentType.TryParse(builder.ToString(), out contentType)) { body.ContentType = contentType; } token = engine.PeekToken(cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentDisposition = ParseContentDisposition(engine, cancellationToken); token = engine.PeekToken(cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLanguage = ParseContentLocation(engine, cancellationToken); token = engine.PeekToken(cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLocation = ReadNStringToken(engine, false, cancellationToken); token = engine.PeekToken(cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { SkipBodyExtensions(engine, cancellationToken); } // read the ')' token = engine.ReadToken(cancellationToken); if (token.Type != ImapTokenType.CloseParen) { throw ImapEngine.UnexpectedToken(token, false); } return(body); }
static BodyPart ParseMultipart(ImapEngine engine, string path, CancellationToken cancellationToken) { var prefix = path.Length > 0 ? path + "." : string.Empty; var body = new BodyPartMultipart (); ImapToken token; int index = 1; do { body.BodyParts.Add (ParseBody (engine, prefix + index, cancellationToken)); token = engine.PeekToken (cancellationToken); index++; } while (token.Type == ImapTokenType.OpenParen); var subtype = ReadStringToken (engine, cancellationToken); body.ContentType = new ContentType ("multipart", subtype); body.PartSpecifier = path; token = engine.PeekToken (cancellationToken); if (token.Type != ImapTokenType.CloseParen) { token = engine.ReadToken (cancellationToken); if (token.Type != ImapTokenType.OpenParen) throw ImapEngine.UnexpectedToken (token, false); ParseParameterList (body.ContentType.Parameters, engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentDisposition = ParseContentDisposition (engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLanguage = ParseContentLocation (engine, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) { body.ContentLocation = ReadNStringToken (engine, false, cancellationToken); token = engine.PeekToken (cancellationToken); } if (token.Type != ImapTokenType.CloseParen) SkipBodyExtensions (engine, cancellationToken); // read the ')' token = engine.ReadToken (cancellationToken); if (token.Type != ImapTokenType.CloseParen) throw ImapEngine.UnexpectedToken (token, false); return body; }
public async Task <string> RenderMultipartRelatedAsync(IMailFolder folder, UniqueId uid, BodyPartMultipart bodyPart) { var related = await folder.GetBodyPartAsync(uid, bodyPart) as MultipartRelated; return(RenderMultipartRelated(related)); }
async void RenderRelated(IMailFolder folder, UniqueId uid, BodyPartMultipart related) { var start = related.ContentType.Parameters["start"]; BodyPartText root = null; if (!string.IsNullOrEmpty(start)) { // if the 'start' parameter is set, it overrides the default behavior of using the first // body part as the main document. root = related.BodyParts.OfType <BodyPartText> ().FirstOrDefault(x => x.ContentId == start); } else if (related.BodyParts.Count > 0) { // this will generally either be a text/html part (which is what we are looking for) or a multipart/alternative var multipart = related.BodyParts[0] as BodyPartMultipart; if (multipart != null) { if (multipart.ContentType.Matches("multipart", "alternative") && multipart.BodyParts.Count > 0) { // find the last text/html part (which will be the closest to what the sender saw in their WYSIWYG editor) // or, failing that, the last text part. for (int i = multipart.BodyParts.Count; i > 0; i--) { var bodyPart = multipart.BodyParts[i - 1] as BodyPartText; if (bodyPart == null) { continue; } if (bodyPart.ContentType.Matches("text", "html")) { root = bodyPart; break; } if (root == null) { root = bodyPart; } } } } else { root = related.BodyParts[0] as BodyPartText; } } if (root == null) { return; } var text = await folder.GetBodyPartAsync(uid, root) as TextPart; if (text != null && text.ContentType.Matches("text", "html")) { var doc = new HtmlAgilityPack.HtmlDocument(); var saved = new Dictionary <MimePart, string> (); TextPart html; doc.LoadHtml(text.Text); // find references to related MIME parts and replace them with links to links to the saved attachments foreach (var img in doc.DocumentNode.SelectNodes("//img[@src]")) { var src = img.Attributes["src"]; int index; 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) if ((index = related.BodyParts.IndexOf(uri)) != -1) { var bodyPart = related.BodyParts[index] as BodyPartBasic; if (bodyPart == null) { // the body part is not a basic leaf part (IOW it's a multipart or message-part) continue; } var attachment = await folder.GetBodyPartAsync(uid, bodyPart) as MimePart; // make sure the referenced part is a MimePart (as opposed to another Multipart or MessagePart) if (attachment == null) { continue; } string fileName; // save the attachment (if we haven't already saved it) if (!saved.TryGetValue(attachment, out fileName)) { fileName = attachment.FileName; if (string.IsNullOrEmpty(fileName)) { fileName = Guid.NewGuid().ToString(); } if (!Directory.Exists(uid.ToString())) { Directory.CreateDirectory(uid.ToString()); } fileName = Path.Combine(uid.ToString(), fileName); using (var stream = File.Create(fileName)) attachment.ContentObject.DecodeTo(stream); saved.Add(attachment, fileName); } // replace the <img src=...> value with the local file name src.Value = "file://" + Path.GetFullPath(fileName); } } if (saved.Count > 0) { // we had to make some modifications to the original html part, so create a new // (temporary) text/html part to render html = new TextPart("html"); using (var writer = new StringWriter()) { doc.Save(writer); html.Text = writer.GetStringBuilder().ToString(); } } else { html = text; } RenderText(html); } else if (text != null) { RenderText(text); } }
public AttachmentBox(BodyPartMultipart multipart) { top = multipart; attachmentList = new List <BodyPartBasic>(); }
public static async void RenderMultipartRelated(IMailFolder folder, UniqueId uid, BodyPartMultipart bodyPart, WebBrowserEditabil pWebBrowser) { var related = await folder.GetBodyPartAsync(uid, bodyPart) as MultipartRelated; RenderMultipartRelated(related, pWebBrowser); }
/// <summary> /// Visit the abstract multipart MIME entity. /// </summary> /// <remarks> /// Visits the abstract multipart MIME entity. /// </remarks> /// <param name="multipart">The multipart body part.</param> protected internal virtual void VisitBodyPartMultipart (BodyPartMultipart multipart) { VisitBodyPart (multipart); VisitChildren (multipart); }
/// <summary> /// Visit the children of a <see cref="MailKit.BodyPartMultipart"/>. /// </summary> /// <remarks> /// Visits the children of a <see cref="MailKit.BodyPartMultipart"/>. /// </remarks> /// <param name="multipart">The multipart.</param> protected virtual void VisitChildren (BodyPartMultipart multipart) { for (int i = 0; i < multipart.BodyParts.Count; i++) multipart.BodyParts[i].Accept (this); }