/// <summary> /// Gets the ready made body part for a mail message either /// - as TextPart, if there are no inline attachments /// - as MultipartRelated with a TextPart and one or more MimeParts of type inline attachments /// </summary> public override MimeEntity GetBodyPart() { ReplaceImgSrcByCid(); var htmlTextPart = new TextPart("html") { ContentTransferEncoding = Tools.IsSevenBit(DocHtml) ? ContentEncoding.SevenBit : TextTransferEncoding != ContentEncoding.SevenBit ? TextTransferEncoding : ContentEncoding.QuotedPrintable, }; htmlTextPart.SetText(CharacterEncoding, DocHtml); // MimeKit.ContentType.Charset is set using CharacterEncodig htmlTextPart.ContentId = MimeUtils.GenerateMessageId(); if (!InlineAtt.Any()) { return(htmlTextPart); } /* * multipart/related * text/html * image/jpeg * image/png * image/gif... */ var mpr = new MultipartRelated { htmlTextPart }; // Produce attachments as part of the multipart/related MIME part, // as described in RFC2387 // Some older clients may need Inline Attachments instead of LinkedResources: // RFC2183: 2.1 The Inline Disposition Type // A bodypart should be marked `inline' if it is intended to be displayed automatically upon display of the message. Inline // bodyparts should be presented in the order in which they occur, subject to the normal semantics of multipart messages. foreach (var ia in InlineAtt) { try { // create an inline image attachment for the file located at path var attachment = new AttachmentBuilder(new FileAttachment(ia.Filename, ia.DisplayName, ia.MimeType), CharacterEncoding, TextTransferEncoding, BinaryTransferEncoding).GetAttachment(); attachment.ContentDisposition = new MimeKit.ContentDisposition(MimeKit.ContentDisposition.Inline); mpr.Add(attachment); } catch (FileNotFoundException) { BadInlineFiles.Add(ia.Filename); } catch (IOException) { BadInlineFiles.Add(ia.Filename); } } return(mpr); }
public async Task GenerateAndSendInviteMailAsync(Invite invite, string rootUrl, string vorstand) { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender message.To.Add(new MailboxAddress(invite.EMailAdress)); // Empfaenger message.Subject = "Invite Schulungsportal"; //Betreff InviteMailViewModel imwm = new InviteMailViewModel { Vorstand = vorstand, InviteURL = rootUrl + "/Manage/Register/" + invite.InviteGUID, CCLogoFile = "cclogo.png@" + Guid.NewGuid().ToString(), FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("InviteMail", imwm), ContentTransferEncoding = ContentEncoding.Base64, }; var multipart = new MultipartRelated(); multipart.Add(body); // Bilder für Corporate Design multipart.Add(LoadInlinePicture("CCLogo.png", imwm.CCLogoFile)); multipart.Add(LoadInlinePicture("FBLogo.png", imwm.FacebookLogoFile)); multipart.Add(LoadInlinePicture("InstaLogo.png", imwm.InstaLogoFile)); message.Body = multipart; await emailSender.SendEmailAsync(message); }
private static MimeEntity AppendAlternativeViews(MailMessage mail, MimeEntity originalBody) { if (mail.AlternateViews.Count == 0) { return(null); } var body = new MultipartAlternative(); if (originalBody != null) { body.Add(originalBody); } foreach (var alternativeView in mail.AlternateViews) { var part = GetMimePart(alternativeView); if (alternativeView.BaseUri != null) { part.ContentLocation = alternativeView.BaseUri; } // Determine if the alternative view have linked resources if (alternativeView.LinkedResources.Count == 0) { body.Add(part); continue; } // Create a multipart relation var type = part.ContentType.MediaType + "/" + part.ContentType.MediaSubtype; var related = new MultipartRelated(); related.ContentType.Parameters.Add("type", type); if (alternativeView.BaseUri != null) { related.ContentLocation = alternativeView.BaseUri; } related.Add(part); // Add all the linked resources to the relation foreach (var resource in alternativeView.LinkedResources) { part = GetMimePart(resource); if (resource.ContentLink != null) { part.ContentLocation = resource.ContentLink; } related.Add(part); } // Append the linked resource to the alternative view body.Add(related); } return(body); }
public void TestDocumentRoot() { var gif = new MimePart("image", "gif") { ContentDisposition = new ContentDisposition(ContentDisposition.Inline) { FileName = "empty.gif" }, ContentId = MimeUtils.GenerateMessageId() }; var jpg = new MimePart("image", "jpg") { ContentDisposition = new ContentDisposition(ContentDisposition.Inline) { FileName = "empty.jpg" }, ContentId = MimeUtils.GenerateMessageId() }; var html = new TextPart("html") { Text = "This is the html body...", ContentId = MimeUtils.GenerateMessageId() }; var related = new MultipartRelated(gif, jpg, html); string start; related.ContentType.Parameters["type"] = "text/html"; related.ContentType.Parameters["start"] = "<" + html.ContentId + ">"; Assert.AreEqual(3, related.Count, "Initial Count"); Assert.AreEqual(html, related.Root, "Initial Root"); Assert.AreEqual(html, related[2], "Initial Root should be the 3rd item."); var root = new TextPart("html") { Text = "This is the replacement root document..." }; related.Root = root; Assert.AreEqual(3, related.Count, "Count"); Assert.AreEqual(root, related.Root, "Root"); Assert.AreEqual(root, related[2], "Root should be the 3rd item."); Assert.IsNotNull(root.ContentId, "Root's Content-Id should not be null."); Assert.IsNotEmpty(root.ContentId, "Root's Content-Id should not be empty."); start = "<" + root.ContentId + ">"; Assert.AreEqual(start, related.ContentType.Parameters["start"], "The start parameter does not match."); related.Clear(); related.Add(gif); related.Add(jpg); related.Root = html; Assert.AreEqual(3, related.Count, "Count"); Assert.AreEqual(html, related.Root, "Root"); Assert.AreEqual(html, related[0], "Root should be the 1st item."); // Note: MimeKit no longer sets the "start" parameter if the root is the first MIME part due to a bug in Thunderbird. Assert.IsNull(related.ContentType.Parameters["start"], "The start parameter should be null."); }
void Render(MultipartRelated related) { var cache = new MultipartRelatedUrlCache(related); NSUrlCache.SharedCache = cache; Render(related.Root); }
protected override void VisitMultipartRelated(MultipartRelated related) { var root = related.Root; _stack.Add(related); root.Accept(this); _stack.RemoveAt(_stack.Count - 1); }
void Render(MultipartRelated related) { var client = new MultipartRelatedWebViewClient(related); webView.SetWebViewClient(client); Render(related.Root); }
public static void RenderMultipartRelated(MultipartRelated related, WebBrowserEditabil pWebBrowser) { var root = related.Root; var multipart = root as Multipart; var text = root as TextPart; if (multipart != null) { for (int i = multipart.Count; i > 0; i--) { var body = multipart[i - 1] as TextPart; if (body == null) { continue; } if (body.ContentType.IsMimeType("text", "html")) { text = body; break; } if (text == null) { text = body; } } } if (text != null) { if (text.ContentType.IsMimeType("text", "html")) { var ctx = new MultipartRelatedImageContext(related); var converter = new HtmlToHtml() { HtmlTagCallback = ctx.HtmlTagCallback }; var html = converter.Convert(text.Text); pWebBrowser.DocumentText = html; } else { RenderText(text, pWebBrowser); } } else { return; } }
protected override void VisitMultipartRelated(MultipartRelated related) { var root = related.Root; // push this multipart/related onto our stack stack.Add(related); // visit the root document root.Accept(this); // pop this multipart/related off our stack stack.RemoveAt(stack.Count - 1); }
void RenderMultipartRelated(MultipartRelated related) { var root = related.Root; if (root == null) { return; } var cache = new MultipartRelatedUrlCache(related); NSUrlCache.SharedCache = cache; Render(root); }
void RenderMultipartRelated(MultipartRelated related) { var root = related.Root; if (root == null) { return; } var client = new MultipartRelatedWebViewClient(related); webView.SetWebViewClient(client); Render(root); }
public async Task GenerateAndSendSchulungsNewsletterAsync(List <Schulung> schulungen, string vorstand) { // Kein newsletter ohne Schulungen if (schulungen.Count() == 0) { return; } try { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender // message.To.Add(new MailboxAddress("@everyone")); // Empfaenger message.Subject = "[INFO/noreply] Schulungsnewsletter"; //Betreff MailViewModel mvm = new MailViewModel { CCLogoFile = "cclogo.png@" + Guid.NewGuid().ToString(), FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), Schulungen = schulungen, Vorstand = vorstand, }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("NewsletterMail", mvm), ContentTransferEncoding = ContentEncoding.Base64, }; var multipart = new MultipartRelated(); multipart.Add(body); // Bilder für Corporate Design multipart.Add(LoadInlinePicture("CCLogo.png", mvm.CCLogoFile)); multipart.Add(LoadInlinePicture("FBLogo.png", mvm.FacebookLogoFile)); multipart.Add(LoadInlinePicture("InstaLogo.png", mvm.InstaLogoFile)); message.Body = multipart; await emailSender.SendEmailAsync(message); } catch (Exception e) { logger.Error(e); string code = "#601"; e = new Exception("Fehler beim Versenden des Newsletters (" + e.Message + ") " + code, e); throw e; } }
public string RenderMultipartRelated(MultipartRelated related) { var root = related.Root; var text = root as TextPart; if (root is Multipart multipart) { for (int i = multipart.Count; i > 0; i--) { if (!(multipart[i - 1] is TextPart body)) { continue; } if (body.ContentType.IsMimeType("text", "html")) { text = body; break; } if (text == null) { text = body; } } } if (text != null) { if (text.ContentType.IsMimeType("text", "html")) { var ctx = new MultipartRelatedImageContext(related); var converter = new HtmlToHtml() { HtmlTagCallback = ctx.HtmlTagCallback }; return(converter.Convert(text.Text)); } else { return(RenderText(text)); } } else { return("Uncknown message type."); } }
public void TestArgumentExceptions() { var related = new MultipartRelated(); string mimeType, charset; Assert.Throws <ArgumentNullException> (() => new MultipartRelated((MimeEntityConstructorArgs)null)); Assert.Throws <ArgumentNullException> (() => related.Open(null, out mimeType, out charset)); Assert.Throws <ArgumentNullException> (() => related.Open(null)); Assert.Throws <ArgumentNullException> (() => related.Contains((Uri)null)); Assert.Throws <ArgumentNullException> (() => related.IndexOf((Uri)null)); Assert.Throws <ArgumentNullException> (() => related.Accept(null)); Assert.Throws <ArgumentNullException> (() => related.Root = null); Assert.Throws <FileNotFoundException> (() => related.Open(new Uri("http://www.xamarin.com/logo.png"), out mimeType, out charset)); Assert.Throws <FileNotFoundException> (() => related.Open(new Uri("http://www.xamarin.com/logo.png"))); }
public void TestGetTextBodyAlternativeInsideRelated() { var alternative = new MultipartAlternative(); var plain = new TextPart("plain") { Text = "plain\n" }; var flowed = new TextPart(TextFormat.Flowed) { Text = "flowed\n" }; var richtext = new TextPart("rtf") { Text = "rtf\n" }; var html = new TextPart("html") { Text = "html\n" }; alternative.Add(plain); alternative.Add(richtext); alternative.Add(html); var related = new MultipartRelated(); related.Add(alternative); var outer = new MultipartAlternative(); outer.Add(related); Assert.AreEqual("plain\n", outer.TextBody.Replace("\r\n", "\n"), "TextBody"); Assert.AreEqual("html\n", outer.HtmlBody.Replace("\r\n", "\n"), "HtmlBody"); alternative.Insert(1, flowed); // Note: GetTextBody (Plain) returns Flowed because Flowed is also Plain and is listed after the text/plain part Assert.AreEqual("flowed\n", outer.GetTextBody(TextFormat.Plain).Replace("\r\n", "\n"), "Plain"); Assert.AreEqual("flowed\n", outer.GetTextBody(TextFormat.Flowed).Replace("\r\n", "\n"), "Flowed"); Assert.AreEqual("rtf\n", outer.GetTextBody(TextFormat.RichText).Replace("\r\n", "\n"), "RichText"); Assert.AreEqual("html\n", outer.GetTextBody(TextFormat.Html).Replace("\r\n", "\n"), "Html"); Assert.IsNull(outer.GetTextBody(TextFormat.Enriched), "Enriched"); }
protected override void VisitMultipartRelated(MultipartRelated related) { var multipart = new MultipartRelated(); var root = related.Root; Push(multipart); root.Accept(this); for (int i = 0; i < related.Count; i++) { if (related[i] != root) { related[i].Accept(this); } } Pop(); }
public async Task GenerateAndSendAbsageAnSchulungsdozentMailAsync(Anmeldung anmeldung, String begruendung, String vorstand) { var schulung = anmeldung.Schulung; MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender foreach (var dozent in schulung.Dozenten) { message.To.Add(GetSafeMailboxAddress(dozent.Name, dozent.EMail)); // Empfaenger } message.Subject = "Schulung " + anmeldung.Schulung.Titel + ": Abmeldung eines Teilnehmers"; //Betreff MailViewModel mwm = new MailViewModel { Vorstand = vorstand, Begruendung = begruendung, Anmeldung = anmeldung, Schulung = schulung, CCLogoFile = "cclogo.png@" + Guid.NewGuid().ToString(), FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("AbsageAnSchulungsdozentMail", mwm), ContentTransferEncoding = ContentEncoding.Base64, }; var multipart = new MultipartRelated(); multipart.Add(body); // Bilder für Corporate Design multipart.Add(LoadInlinePicture("CCLogo.png", mwm.CCLogoFile)); multipart.Add(LoadInlinePicture("FBLogo.png", mwm.FacebookLogoFile)); multipart.Add(LoadInlinePicture("InstaLogo.png", mwm.InstaLogoFile)); message.Body = multipart; await emailSender.SendEmailAsync(message); }
/// <summary> /// Diese Methode generiert und schickt eine Mail an die Dozenten der Schulungen einen Tag nach dieser um zu erinnern, /// die Anwesenheitsliste an den Schulungsbeauftragten zu senden /// </summary> /// <param name="anmeldung">Die Anmeldung.</param> /// <param name="schulung">Die Schulung, zu die abgesagt wird.</param> public async Task GenerateAndSendGeprueftReminderMail(Schulung schulung, string vorstand) { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender foreach (var dozent in schulung.Dozenten) { message.To.Add(GetSafeMailboxAddress(dozent.Name, dozent.EMail)); // Empfaenger } message.Subject = "[INFO/noreply] Reminder Teilnehmerliste " + schulung.Titel; //Betreff var multipart = new MultipartRelated(); MailViewModel mvm = new MailViewModel { CCLogoFile = "cclogo.png@" + Guid.NewGuid().ToString(), FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), Schulung = schulung, Vorstand = vorstand, }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("GeprueftReminder", mvm), ContentTransferEncoding = ContentEncoding.Base64, }; multipart.Add(body); // Bilder für Corporate Design multipart.Add(LoadInlinePicture("CCLogo.png", mvm.CCLogoFile)); multipart.Add(LoadInlinePicture("FBLogo.png", mvm.FacebookLogoFile)); multipart.Add(LoadInlinePicture("InstaLogo.png", mvm.InstaLogoFile)); message.Body = multipart; await emailSender.SendEmailAsync(message); }
public static MimeMessage ToMimeMessage(this MailMessage mail) { if (mail == null) { throw new ArgumentNullException(nameof(mail)); } var headers = new List <Header>(); foreach (var field in mail.Headers.AllKeys) { foreach (var value in mail.Headers.GetValues(field)) { headers.Add(new Header(field, value)); } } var message = new MimeMessage(headers.ToArray()); MimeEntity body = null; // Note: If the user has already sent their MailMessage via System.Net.Mail.SmtpClient, // then the following MailMessage properties will have been merged into the Headers, so // check to make sure our MimeMessage properties are empty before adding them. if (mail.Sender != null) { message.Sender = mail.Sender.ToMailboxAddress(); } if (mail.From != null) { message.Headers.Replace(HeaderId.From, string.Empty); message.From.Add(mail.From.ToMailboxAddress()); } if (mail.ReplyToList.Count > 0) { message.Headers.Replace(HeaderId.ReplyTo, string.Empty); message.ReplyTo.AddRange(mail.ReplyToList.ToInternetAddressList()); } if (mail.To.Count > 0) { message.Headers.Replace(HeaderId.To, string.Empty); message.To.AddRange(mail.To.ToInternetAddressList()); } if (mail.CC.Count > 0) { message.Headers.Replace(HeaderId.Cc, string.Empty); message.Cc.AddRange(mail.CC.ToInternetAddressList()); } if (mail.Bcc.Count > 0) { message.Headers.Replace(HeaderId.Bcc, string.Empty); message.Bcc.AddRange(mail.Bcc.ToInternetAddressList()); } if (mail.SubjectEncoding != null) { message.Headers.Replace(HeaderId.Subject, mail.SubjectEncoding, mail.Subject ?? string.Empty); } else { message.Subject = mail.Subject ?? string.Empty; } switch (mail.Priority) { case MailPriority.Normal: message.Headers.RemoveAll(HeaderId.XMSMailPriority); message.Headers.RemoveAll(HeaderId.Importance); message.Headers.RemoveAll(HeaderId.XPriority); message.Headers.RemoveAll(HeaderId.Priority); break; case MailPriority.High: message.Headers.Replace(HeaderId.Priority, "urgent"); message.Headers.Replace(HeaderId.Importance, "high"); message.Headers.Replace(HeaderId.XPriority, "2 (High)"); break; case MailPriority.Low: message.Headers.Replace(HeaderId.Priority, "non-urgent"); message.Headers.Replace(HeaderId.Importance, "low"); message.Headers.Replace(HeaderId.XPriority, "4 (Low)"); break; } if (!string.IsNullOrEmpty(mail.Body)) { var text = new TextPart(mail.IsBodyHtml ? "html" : "plain"); text.SetText(mail.BodyEncoding ?? Encoding.UTF8, mail.Body); body = text; } if (mail.AlternateViews.Count > 0) { var alternative = new MultipartAlternative(); if (body != null) { alternative.Add(body); } foreach (var view in mail.AlternateViews) { var part = GetMimePart(view); if (view.BaseUri != null) { part.ContentLocation = view.BaseUri; } if (view.LinkedResources.Count > 0) { var type = part.ContentType.MediaType + "/" + part.ContentType.MediaSubtype; var related = new MultipartRelated(); related.ContentType.Parameters.Add("type", type); if (view.BaseUri != null) { related.ContentLocation = view.BaseUri; } related.Add(part); foreach (var resource in view.LinkedResources) { part = GetMimePart(resource); if (resource.ContentLink != null) { part.ContentLocation = resource.ContentLink; } related.Add(part); } alternative.Add(related); } else { alternative.Add(part); } } body = alternative; } if (body == null) { body = new TextPart(mail.IsBodyHtml ? "html" : "plain"); } if (mail.Attachments.Count > 0) { var mixed = new Multipart("mixed"); if (body != null) { mixed.Add(body); } foreach (var attachment in mail.Attachments) { mixed.Add(GetMimePart(attachment)); } body = mixed; } message.Body = body; return(message); }
private static MimeEntity ToMimeMessageBody(MailDraftData draft) { string textBody; MailUtil.TryExtractTextFromHtml(draft.HtmlBody, out textBody); MultipartAlternative alternative = null; MimeEntity body = null; if (!string.IsNullOrEmpty(textBody)) { var textPart = new TextPart("plain") { Text = textBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; if (!string.IsNullOrEmpty(draft.HtmlBody)) { alternative = new MultipartAlternative { textPart }; body = alternative; } else { body = textPart; } } if (!string.IsNullOrEmpty(draft.HtmlBody)) { var htmlPart = new TextPart("html") { Text = draft.HtmlBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; MimeEntity html; if (draft.AttachmentsEmbedded.Any()) { htmlPart.ContentTransferEncoding = ContentEncoding.Base64; var related = new MultipartRelated { Root = htmlPart }; related.Root.ContentId = null; foreach (var emb in draft.AttachmentsEmbedded) { var linkedResource = ConvertToMimePart(emb, emb.contentId); related.Add(linkedResource); } html = related; } else { html = htmlPart; } if (alternative != null) { alternative.Add(html); } else { body = html; } } if (!string.IsNullOrEmpty(draft.CalendarIcs)) { var calendarPart = new TextPart("calendar") { Text = draft.CalendarIcs, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; calendarPart.ContentType.Parameters.Add("method", draft.CalendarMethod); if (alternative != null) { alternative.Add(calendarPart); } else { body = calendarPart; } } if (draft.Attachments.Any() || !string.IsNullOrEmpty(draft.CalendarIcs)) { var mixed = new Multipart("mixed"); if (body != null) { mixed.Add(body); } foreach (var att in draft.Attachments) { var attachment = ConvertToMimePart(att); mixed.Add(attachment); } if (!string.IsNullOrEmpty(draft.CalendarIcs)) { var filename = "calendar.ics"; switch (draft.CalendarMethod) { case Defines.ICAL_REQUEST: filename = "invite.ics"; break; case Defines.ICAL_REPLY: filename = "reply.ics"; break; case Defines.ICAL_CANCEL: filename = "cancel.ics"; break; } var contentType = new ContentType("application", "ics"); contentType.Parameters.Add("method", draft.CalendarMethod); contentType.Parameters.Add("name", filename); var calendarResource = new MimePart(contentType) { ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = filename }; var data = Encoding.UTF8.GetBytes(draft.CalendarIcs); var ms = new MemoryStream(data); calendarResource.Content = new MimeContent(ms); mixed.Add(calendarResource); } body = mixed; } if (body != null) { return(body); } return(new TextPart("plain") { Text = string.Empty }); }
public MultipartRelatedUrlCache(MultipartRelated related) { this.related = related; }
private MimeMessage BuildMailMessage(NotifyMessage m) { var mimeMessage = new MimeMessage { Subject = m.Subject }; var fromAddress = MailboxAddress.Parse(ParserOptions.Default, m.From); mimeMessage.From.Add(fromAddress); foreach (var to in m.To.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)) { mimeMessage.To.Add(MailboxAddress.Parse(ParserOptions.Default, to)); } if (m.ContentType == Pattern.HTMLContentType) { var textPart = new TextPart("plain") { Text = HtmlUtil.GetText(m.Content), ContentTransferEncoding = ContentEncoding.QuotedPrintable }; var multipartAlternative = new MultipartAlternative { textPart }; var htmlPart = new TextPart("html") { Text = GetHtmlView(m.Content), ContentTransferEncoding = ContentEncoding.QuotedPrintable }; if (m.EmbeddedAttachments != null && m.EmbeddedAttachments.Length > 0) { var multipartRelated = new MultipartRelated { Root = htmlPart }; foreach (var attachment in m.EmbeddedAttachments) { var mimeEntity = ConvertAttachmentToMimePart(attachment); if (mimeEntity != null) { multipartRelated.Add(mimeEntity); } } multipartAlternative.Add(multipartRelated); } else { multipartAlternative.Add(htmlPart); } mimeMessage.Body = multipartAlternative; } else { mimeMessage.Body = new TextPart("plain") { Text = m.Content, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; } if (!string.IsNullOrEmpty(m.ReplyTo)) { mimeMessage.ReplyTo.Add(MailboxAddress.Parse(ParserOptions.Default, m.ReplyTo)); } mimeMessage.Headers.Add("Auto-Submitted", string.IsNullOrEmpty(m.AutoSubmitted) ? "auto-generated" : m.AutoSubmitted); return(mimeMessage); }
/// <summary> /// Gets the ready made body part for a mail message either /// - as TextPart, if there are no inline attachments /// - as MultipartRelated with a TextPart and one or more MimeParts of type inline attachments /// </summary> public override MimeEntity GetBodyPart() { // remove all Script elements, because they cannot be used in mail messages foreach (var element in _htmlDocument.All.Where(e => e is IHtmlScriptElement).ToList()) { element.Remove(); } // set the HTML title tag from email subject var titleEle = _htmlDocument.All.FirstOrDefault(m => m is IHtmlTitleElement) as IHtmlTitleElement; if (titleEle != null) { titleEle.Text = _mailMergeMessage.SearchAndReplaceVars(_mailMergeMessage.Subject, _dataItem); } // read the <base href="..."> tag in order to find the embedded image files later on var baseEle = _htmlDocument.All.FirstOrDefault(m => m is IHtmlBaseElement) as IHtmlBaseElement; var baseDir = baseEle?.Href == null ? null : new Uri(baseEle.Href); // only replace the base url if it was not set programmatically if (_docBaseUri == null) { _docBaseUri = baseDir; } // remove if base tag is local file reference, because it's not usable in the resulting HTML if (baseEle != null && baseDir != null && baseDir.Scheme == UriScheme.File) { baseEle.Remove(); } ReplaceImgSrcByCid(); // replace placeholders only in the HTML Body, because e.g. // in the header there may be CSS definitions with curly brace which collide with SmartFormat {placeholders} _htmlDocument.Body.InnerHtml = _mailMergeMessage.SearchAndReplaceVars(_htmlDocument.Body.InnerHtml, _dataItem); var htmlTextPart = new TextPart("html") { ContentTransferEncoding = Tools.IsSevenBit(DocHtml) ? ContentEncoding.SevenBit : TextTransferEncoding != ContentEncoding.SevenBit ? TextTransferEncoding : ContentEncoding.QuotedPrintable, }; htmlTextPart.SetText(CharacterEncoding, DocHtml); // MimeKit.ContentType.Charset is set using CharacterEncoding htmlTextPart.ContentId = MimeUtils.GenerateMessageId(); if (!InlineAtt.Any()) { return(htmlTextPart); } /* * multipart/related * text/html * image/jpeg * image/png * image/gif... */ var mpr = new MultipartRelated { htmlTextPart }; // Produce attachments as part of the multipart/related MIME part, // as described in RFC2387 // Some older clients may need Inline Attachments instead of LinkedResources: // RFC2183: 2.1 The Inline Disposition Type // A bodypart should be marked `inline' if it is intended to be displayed automatically upon display of the message. Inline // bodyparts should be presented in the order in which they occur, subject to the normal semantics of multipart messages. foreach (var ia in InlineAtt) { try { var readyInlineAtt = new FileAttachment(_mailMergeMessage.SearchAndReplaceVarsInFilename(ia.Filename, _dataItem), _mailMergeMessage.SearchAndReplaceVars(ia.DisplayName, _dataItem)); // create an inline image attachment for the file located at path var attachment = new AttachmentBuilder(readyInlineAtt, CharacterEncoding, TextTransferEncoding, BinaryTransferEncoding).GetAttachment(); attachment.ContentDisposition = new ContentDisposition(ContentDisposition.Inline); attachment.ContentId = ia.DisplayName; attachment.FileName = null; // not needed for inline attachments, save some space mpr.Add(attachment); } catch (FileNotFoundException) { BadInlineFiles.Add(ia.Filename); } catch (IOException) { BadInlineFiles.Add(ia.Filename); } } return(mpr); }
public MultipartRelatedWebViewClient(MultipartRelated related) { this.related = related; }
public MultipartRelatedImageContext(MultipartRelated related) { this.related = related; }
protected internal override void VisitMultipartRelated(MultipartRelated related) { MultipartRelated++; base.VisitMultipartRelated(related); }
void RenderMultipartRelated(MultipartRelated related) { var root = related.Root; var multipart = root as Multipart; var text = root as TextPart; if (multipart != null) { // Note: the root document can sometimes be a multipart/alternative. // A multipart/alternative is just a collection of alternate views. // The last part is the format that most closely matches what the // user saw in his or her email client's WYSIWYG editor. for (int i = multipart.Count; i > 0; i--) { var body = multipart[i - 1] as TextPart; if (body == null) { continue; } // our preferred mime-type is text/html if (body.ContentType.Matches("text", "html")) { text = body; break; } if (text == null) { text = body; } } } // check if we have a text/html document 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.IndexOf(uri)) != -1) { var attachment = related[index] as MimePart; // make sure the referenced part is a MimePart (as opposed to another Multipart or MessagePart) if (attachment != null) { 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(); } 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; } RenderTextPart(html); } else { // we don't know what we have, so render it as an entity RenderEntity(related.Root); } }
void RenderMultipartRelated(MultipartRelated related) { var root = related.Root; var multipart = root as Multipart; var text = root as TextPart; if (multipart != null) { // Note: the root document can sometimes be a multipart/alternative. // A multipart/alternative is just a collection of alternate views. // The last part is the format that most closely matches what the // user saw in his or her email client's WYSIWYG editor. for (int i = multipart.Count; i > 0; i--) { var body = multipart[i - 1] as TextPart; if (body == null) { continue; } // our preferred mime-type is text/html if (body.ContentType.IsMimeType("text", "html")) { text = body; break; } if (text == null) { text = body; } } } // check if we have a text/html document if (text != null) { if (text.ContentType.IsMimeType("text", "html")) { // replace image src urls that refer to related MIME parts with "data:" urls // Note: we could also save the related MIME part content to disk and use // file:// urls instead. var ctx = new MultipartRelatedImageContext(related); var converter = new HtmlToHtml() { HtmlTagCallback = ctx.HtmlTagCallback }; var html = converter.Convert(text.Text); webBrowser.DocumentText = html; } else { RenderText(text); } } else { // we don't know how to render this type of content return; } }
private static MimeEntity ToMimeMessageBody(MailDraft draft) { var linkedResources = new AttachmentCollection(true); var attachments = new AttachmentCollection(); string textBody; MailUtil.TryExtractTextFromHtml(draft.HtmlBody, out textBody); MultipartAlternative multipartAlternative = null; MimeEntity body = null; if (!string.IsNullOrEmpty(textBody)) { var textPart = new TextPart("plain") { Text = textBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; if (!string.IsNullOrEmpty(draft.HtmlBody)) { multipartAlternative = new MultipartAlternative { textPart }; body = multipartAlternative; } else { body = textPart; } } if (!string.IsNullOrEmpty(draft.HtmlBody)) { var htmlPart = new TextPart("html") { Text = draft.HtmlBody, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; MimeEntity tempPart; if (draft.AttachmentsEmbedded.Any()) { var multipartRelated = new MultipartRelated { Root = htmlPart }; foreach (var emb in draft.AttachmentsEmbedded) { MimeEntity linkedResource; if (!emb.data.Any()) { var s3Key = MailStoragePathCombiner.GerStoredFilePath(emb); var contentType = ContentType.Parse(string.IsNullOrEmpty(emb.contentType) ? MimeMapping.GetMimeMapping(emb.fileName) : emb.contentType); using (var stream = StorageManager .GetDataStoreForAttachments(emb.tenant) .GetReadStream(s3Key)) { linkedResource = linkedResources.Add(emb.fileName, stream, contentType); } } else { linkedResource = linkedResources.Add(emb.fileName, emb.data); } linkedResource.ContentId = emb.contentId; multipartRelated.Add(linkedResource); } tempPart = multipartRelated; } else { tempPart = htmlPart; } if (multipartAlternative != null) { multipartAlternative.Add(tempPart); } else { body = tempPart; } } if (!string.IsNullOrEmpty(draft.CalendarIcs)) { var calendarPart = new TextPart("calendar") { Text = draft.CalendarIcs, ContentTransferEncoding = ContentEncoding.QuotedPrintable }; calendarPart.ContentType.Parameters.Add("method", draft.CalendarMethod); if (multipartAlternative != null) { multipartAlternative.Add(calendarPart); } else { body = calendarPart; } } if (draft.Attachments.Any() || !string.IsNullOrEmpty(draft.CalendarIcs)) { var multipart = new Multipart("mixed"); if (body != null) { multipart.Add(body); } foreach (var att in draft.Attachments) { MimeEntity attachmentResource; if (!att.data.Any()) { var s3Key = MailStoragePathCombiner.GerStoredFilePath(att); using (var stream = StorageManager .GetDataStoreForAttachments(att.tenant) .GetReadStream(s3Key)) { attachmentResource = attachments.Add(att.fileName, stream); } } else { attachmentResource = attachments.Add(att.fileName, att.data); } multipart.Add(attachmentResource); } if (!string.IsNullOrEmpty(draft.CalendarIcs)) { var filename = "calendar.ics"; switch (draft.CalendarMethod) { case "REQUEST": filename = "invite.ics"; break; case "REPLY": filename = "reply.ics"; break; case "CANCEL": filename = "cancel.ics"; break; } var contentType = new ContentType("application", "ics"); contentType.Parameters.Add("method", draft.CalendarMethod); contentType.Parameters.Add("name", filename); var data = Encoding.UTF8.GetBytes(draft.CalendarIcs); var calendarResource = attachments.Add(filename, data, contentType); multipart.Add(calendarResource); } body = multipart; } if (body != null) { return(body); } return(new TextPart("plain") { Text = string.Empty }); }