/// <summary> /// Constructs the message body based on the text-based bodies, the linked resources, and the attachments. /// </summary> /// <remarks> /// Combines the <see cref="Attachments"/>, <see cref="LinkedResources"/>, <see cref="TextBody"/>, /// and <see cref="HtmlBody"/> into the proper MIME structure suitable for display in many common /// mail clients. /// </remarks> /// <returns>The message body.</returns> public MimeEntity ToMessageBody() { Multipart alternative = null; MimeEntity body = null; if (!string.IsNullOrEmpty(TextBody)) { var text = new TextPart("plain"); text.Text = TextBody; if (!string.IsNullOrEmpty(HtmlBody)) { alternative = new Multipart("alternative"); alternative.Add(text); body = alternative; } else { body = text; } } if (!string.IsNullOrEmpty(HtmlBody)) { var text = new TextPart("html"); MimeEntity html; text.ContentId = MimeUtils.GenerateMessageId(); text.Text = HtmlBody; if (LinkedResources.Count > 0) { var related = new MultipartRelated { Root = text }; foreach (var resource in LinkedResources) { related.Add(resource); } html = related; } else { html = text; } if (alternative != null) { alternative.Add(html); } else { body = html; } } if (Attachments.Count > 0) { var mixed = new Multipart("mixed"); if (body != null) { mixed.Add(body); } foreach (var attachment in Attachments) { mixed.Add(attachment); } body = mixed; } return(body ?? new TextPart("plain") { Text = string.Empty }); }
/// <summary> /// Splits the specified message into multiple messages. /// </summary> /// <remarks> /// Splits the specified message into multiple messages, each with a /// message/partial body no larger than the max size specified. /// </remarks> /// <returns>An enumeration of partial messages.</returns> /// <param name="message">The message.</param> /// <param name="maxSize">The maximum size for each message body.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="message"/> is <c>null</c>. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="maxSize"/> is less than <c>1</c>. /// </exception> public static IEnumerable <MimeMessage> Split(MimeMessage message, int maxSize) { if (message == null) { throw new ArgumentNullException("message"); } if (maxSize < 1) { throw new ArgumentOutOfRangeException("maxSize"); } using (var memory = new MemoryStream()) { message.WriteTo(memory); memory.Seek(0, SeekOrigin.Begin); if (memory.Length <= maxSize) { yield return(message); yield break; } var streams = new List <Stream> (); #if PORTABLE var buf = memory.ToArray(); #else var buf = memory.GetBuffer(); #endif long startIndex = 0; while (startIndex < memory.Length) { // Preferably, we'd split on whole-lines if we can, // but if that's not possible, split on max size long endIndex = Math.Min(memory.Length, startIndex + maxSize); if (endIndex < memory.Length) { long ebx = endIndex; while (ebx > (startIndex + 1) && buf[ebx] != (byte)'\n') { ebx--; } if (buf[ebx] == (byte)'\n') { endIndex = ebx + 1; } } streams.Add(new BoundStream(memory, startIndex, endIndex, true)); startIndex = endIndex; } var id = message.MessageId ?? MimeUtils.GenerateMessageId(); int number = 1; foreach (var stream in streams) { var part = new MessagePartial(id, number++, streams.Count); part.ContentObject = new ContentObject(stream); var submessage = CloneMessage(message); submessage.MessageId = MimeUtils.GenerateMessageId(); submessage.Body = part; yield return(submessage); } } yield break; }
// function called from HTTPPUT add to send an email after a purchased order private async Task SendEmail(string ID, Order order) { // make sure the model bound correctly if (ModelState.IsValid) { // get the html template document used to build the email var fp = "Template" + Path.DirectorySeparatorChar.ToString() + "ConfirmOrder.html"; // subject line of the email var subject = "qc-capstone Order Confirmation"; // a new body for the email being sent var builder = new BodyBuilder(); // read the email template - located at ./Template/ConfrimOrder.html using (StreamReader reader = System.IO.File.OpenText(fp)) { builder.HtmlBody = reader.ReadToEnd(); } string orders = null; // build the name that will be formated into the email string name = order.Shipping.Full_name.First_name + " " + order.Shipping.Full_name.Last_name; // add the images to the email (never seemed to work correctly but everything I found shows this is how it was done) var image = builder.LinkedResources.Add("Template/Email_Templatehtml_files/right.gif"); image.ContentId = MimeUtils.GenerateMessageId(); // Add a section of html code for each of the individual offering that were purchased by the user in this order foreach (Offerings offering in order.Offerings) { orders += $@"<tr> <td style=""padding: 20px 0 20px 0; color: #153643; font-family: Arial, sans-serif; font-size: 16px; line-height: 20px;"" align = ""left""> <table width = ""100%"" cellspacing = ""0"" cellpadding = ""0"" border = ""0""> <tbody> <tr> <td> <img src=""cid:{image.ContentId}"" style = ""display: block;"" width = """" height = ""100""> </td> <td> {offering.Product_name} </td> <td style = ""padding: 0px 20px 0px 20px;""> x{offering.Quantity} </td> <td>${offering.Unit_retail} </td> </tr> </tbody> </table> </td> </tr> "; } // format all the variables and html body into a string that will be our email messages body string messageBody = string.Format(builder.HtmlBody, name, order.OrderId, orders ); // send the email: uses the interface located in CheckoutApi/Services await _emailSender.SendEmailAsync(order.Shipping.Email, subject, messageBody, name); } }
public string SendEmail(string sender, string to, string subject, string body, string hostname, int port, string username, string password, string thumbprint, string inReplyTo, Dictionary <string, string> extraHeaders) { var mailMessage = new MimeMessage(); mailMessage.From.Add(MailboxAddress.Parse(sender)); mailMessage.To.Add(MailboxAddress.Parse(to)); mailMessage.Subject = subject; mailMessage.Body = new TextPart("plain") { Text = body }; mailMessage.MessageId = MimeUtils.GenerateMessageId("eyeinthesky.im"); if (!string.IsNullOrWhiteSpace(inReplyTo)) { mailMessage.InReplyTo = inReplyTo; } if (extraHeaders != null && extraHeaders.Any()) { foreach (var kvp in extraHeaders) { mailMessage.Headers.Add("X-EITS-" + kvp.Key, kvp.Value); } } using (var client = new SmtpClient()) { client.ServerCertificateValidationCallback = (o, cert, chain, errors) => { if (thumbprint == "any") { return(true); } return(((X509Certificate2)cert).Thumbprint == thumbprint); }; client.Connect(hostname, port, SecureSocketOptions.StartTls); if (username != null && password != null) { client.Authenticate(username, password); } client.Send(mailMessage); client.Disconnect(true); } return(mailMessage.MessageId); }
static void Main(string[] args) { Console.WriteLine("Subject:"); var subject = Console.ReadLine(); Console.WriteLine("Receiver EMAIL: "); var receiver = Console.ReadLine(); Console.WriteLine("Sender EMAIL:"); var sender = Console.ReadLine(); Console.WriteLine("Sender PASSWORD:"******"Type Message:"); var messagetext = Console.ReadLine(); var message = new MimeMessage(); message.From.Add(new MailboxAddress(sender)); message.To.Add(new MailboxAddress(receiver)); message.Subject = subject; var builder = new BodyBuilder(); builder.TextBody = messagetext; var image = builder.LinkedResources.Add(@"C:\Users\Daniela\Desktop\simba.png"); image.ContentId = MimeUtils.GenerateMessageId(); builder.HtmlBody = string.Format($"<p>{messagetext} </p><br> " + @"<center><img src=""cid:{0}""></center>", image.ContentId); builder.Attachments.Add(@"C:\Users\Daniela\Desktop\WordFile.docx"); message.Body = builder.ToMessageBody(); try { using (var client = new SmtpClient(new ProtocolLogger(Console.OpenStandardOutput()))) { client.ServerCertificateValidationCallback = (s, c, h, e) => true; client.Connect("smtp.gmail.com", 587, MailKit.Security.SecureSocketOptions.StartTls); client.Authenticate(sender, psender); client.Send(message); client.Disconnect(true); Console.WriteLine("Send Mail Success."); } Console.WriteLine("Nummber of message to receive:"); var maxCount = Convert.ToInt32(Console.ReadLine()); using (var clientreceive = new Pop3Client()) { clientreceive.Connect("pop.gmail.com", 995, true); clientreceive.Authenticate(sender, psender); var emails = new List <MimeMessage>(); for (var i = 0; i < clientreceive.Count && i < maxCount; i++) { emails.Add(clientreceive.GetMessage(i)); } emails.ForEach(x => Console.WriteLine($"From: {x.From.Mailboxes.First()}\n" + $"Subject: {x.Subject}\nContent: {x.TextBody}")); clientreceive.Disconnect(true); Console.WriteLine("Receive Mail Success."); } } catch (Exception e) { Console.WriteLine("Send Mail Failed : " + e.Message); } Console.ReadLine(); }
static IDictionary <string, ThreadableNode> CreateIdTable(IEnumerable <IMessageSummary> messages) { var ids = new Dictionary <string, ThreadableNode> (StringComparer.OrdinalIgnoreCase); ThreadableNode node; foreach (var message in messages) { if (message.Envelope == null) { throw new ArgumentException("One or more messages is missing information needed for threading.", nameof(messages)); } var id = message.Envelope.MessageId; if (string.IsNullOrEmpty(id)) { id = MimeUtils.GenerateMessageId(); } if (ids.TryGetValue(id, out node)) { if (node.Message == null) { // a previously processed message referenced this message node.Message = message; } else { // a duplicate message-id, just create a dummy id and use that id = MimeUtils.GenerateMessageId(); node = null; } } if (node == null) { // create a new ThreadContainer for this message and add it to ids node = new ThreadableNode(message); ids.Add(id, node); } ThreadableNode parent = null; foreach (var reference in message.References) { ThreadableNode referenced; if (!ids.TryGetValue(reference, out referenced)) { // create a dummy container for the referenced message referenced = new ThreadableNode(null); ids.Add(reference, referenced); } // chain up the references, disallowing loops if (parent != null && referenced.Parent == null && parent != referenced && !parent.Children.Contains(referenced)) { parent.Children.Add(referenced); referenced.Parent = parent; } parent = referenced; } // don't allow loops if (parent != null && (parent == node || node.Children.Contains(parent))) { parent = null; } if (node.HasParent) { // unlink from our old parent node.Parent.Children.Remove(node); node.Parent = null; } if (parent != null) { // add it as a child of our new parent parent.Children.Add(node); node.Parent = parent; } } return(ids); }
public Task SendEmailAsync(EmailMessageDto emailMessage) { var message = new MimeMessage(); message.From.Add(new MailboxAddress(_emailConfiguration.SenderName, _emailConfiguration.SmtpUsername)); message.To.Add(new MailboxAddress(emailMessage.ReceiverName, emailMessage.ReceiverEmailAddress)); message.Subject = emailMessage.Subject; var builder = new BodyBuilder(); builder.TextBody = $@" ++++++++++++++++++++ Certification-System ++++++++++++++++++++ {emailMessage.Header} ******************************************* {emailMessage.BodyMessage} ******************************************* {emailMessage.LinkText}: {emailMessage.Link} ______________________ ZIAD Bielsko-Biała SA al. Armii Krajowej 220 43-316 Bielsko-Biała "; var logo = builder.LinkedResources.Add(Path.Combine(_environment.WebRootPath, @"Image\logo_ziad_medium.jpg")); logo.ContentId = MimeUtils.GenerateMessageId(); string html = File.ReadAllText(Path.Combine(_environment.WebRootPath, @"resources\emailTemplate\index.htm")); builder.HtmlBody = html .Replace("{ContentId}", logo.ContentId) .Replace("{Header}", emailMessage.Header) .Replace("{BodyMessage}", emailMessage.BodyMessage); if (!string.IsNullOrWhiteSpace(emailMessage.Link)) { builder.HtmlBody = builder.HtmlBody .Replace("display: none", "display: inline-block") .Replace("{LinkButtonValue}", emailMessage.Link) .Replace("{LinkButtonText}", emailMessage.LinkText); } ; if (!string.IsNullOrWhiteSpace(emailMessage.ObjectClassifier) && !string.IsNullOrWhiteSpace(emailMessage.Indexer)) { builder.HtmlBody = builder.HtmlBody .Replace("Margin-top: 0;Margin-bottom: 0;display:none;", "Margin-top: 0;Margin-bottom: 0;display:inline-block;") .Replace("{ObjectClassifier}", emailMessage.ObjectClassifier) .Replace("{Indexer}", emailMessage.Indexer); } ; message.Body = builder.ToMessageBody(); using (var client = new SmtpClient()) { client.ServerCertificateValidationCallback = (s, c, h, e) => true; client.AuthenticationMechanisms.Remove("XOAUTH2"); client.Connect(_emailConfiguration.SmtpServer, _emailConfiguration.SmtpPort, false); client.Authenticate(_emailConfiguration.SmtpUsername, _emailConfiguration.SmtpPassword); client.Send(message); client.Disconnect(true); } return(Task.CompletedTask); }
public void TestClearHeaders() { var message = new MimeMessage(); message.Subject = "Clear the headers!"; message.Sender = new MailboxAddress("Sender", "*****@*****.**"); message.ReplyTo.Add(new MailboxAddress("Reply-To", "*****@*****.**")); message.From.Add(new MailboxAddress("From", "*****@*****.**")); message.To.Add(new MailboxAddress("To", "*****@*****.**")); message.Cc.Add(new MailboxAddress("Cc", "*****@*****.**")); message.Bcc.Add(new MailboxAddress("Bcc", "*****@*****.**")); message.MessageId = MimeUtils.GenerateMessageId(); message.Date = DateTimeOffset.Now; message.ResentSender = new MailboxAddress("Sender", "*****@*****.**"); message.ResentReplyTo.Add(new MailboxAddress("Reply-To", "*****@*****.**")); message.ResentFrom.Add(new MailboxAddress("From", "*****@*****.**")); message.ResentTo.Add(new MailboxAddress("To", "*****@*****.**")); message.ResentCc.Add(new MailboxAddress("Cc", "*****@*****.**")); message.ResentBcc.Add(new MailboxAddress("Bcc", "*****@*****.**")); message.ResentMessageId = MimeUtils.GenerateMessageId(); message.ResentDate = DateTimeOffset.Now; message.Importance = MessageImportance.High; message.Priority = MessagePriority.Urgent; message.References.Add("<id1@localhost>"); message.InReplyTo = "<id1@localhost>"; message.MimeVersion = new Version(1, 0); message.Headers.Clear(); Assert.IsNull(message.Subject, "Subject has not been cleared."); Assert.IsNull(message.Sender, "Sender has not been cleared."); Assert.AreEqual(0, message.ReplyTo.Count, "Reply-To has not been cleared."); Assert.AreEqual(0, message.From.Count, "From has not been cleared."); Assert.AreEqual(0, message.To.Count, "To has not been cleared."); Assert.AreEqual(0, message.Cc.Count, "Cc has not been cleared."); Assert.AreEqual(0, message.Bcc.Count, "Bcc has not been cleared."); Assert.IsNull(message.MessageId, "Message-Id has not been cleared."); Assert.AreEqual(DateTimeOffset.MinValue, message.Date, "Date has not been cleared."); Assert.IsNull(message.ResentSender, "Resent-Sender has not been cleared."); Assert.AreEqual(0, message.ResentReplyTo.Count, "Resent-Reply-To has not been cleared."); Assert.AreEqual(0, message.ResentFrom.Count, "Resent-From has not been cleared."); Assert.AreEqual(0, message.ResentTo.Count, "Resent-To has not been cleared."); Assert.AreEqual(0, message.ResentCc.Count, "Resent-Cc has not been cleared."); Assert.AreEqual(0, message.ResentBcc.Count, "Resent-Bcc has not been cleared."); Assert.IsNull(message.ResentMessageId, "Resent-Message-Id has not been cleared."); Assert.AreEqual(DateTimeOffset.MinValue, message.ResentDate, "Resent-Date has not been cleared."); Assert.AreEqual(MessageImportance.Normal, message.Importance, "Importance has not been cleared."); Assert.AreEqual(MessagePriority.Normal, message.Priority, "Priority has not been cleared."); Assert.AreEqual(0, message.References.Count, "References has not been cleared."); Assert.IsNull(message.InReplyTo, "In-Reply-To has not been cleared."); Assert.IsNull(message.MimeVersion, "MIME-Version has not been cleared."); }
/// <summary> /// Splits the specified message into multiple messages. /// </summary> /// <remarks> /// Splits the specified message into multiple messages, each with a /// message/partial body no larger than the max size specified. /// </remarks> /// <returns>An enumeration of partial messages.</returns> /// <param name="message">The message.</param> /// <param name="maxSize">The maximum size for each message body.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="message"/> is <c>null</c>. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="maxSize"/> is less than <c>1</c>. /// </exception> public static IEnumerable <MimeMessage> Split(MimeMessage message, int maxSize) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (maxSize < 1) { throw new ArgumentOutOfRangeException(nameof(maxSize)); } var options = FormatOptions.CloneDefault(); foreach (HeaderId id in Enum.GetValues(typeof(HeaderId))) { switch (id) { case HeaderId.Subject: case HeaderId.MessageId: case HeaderId.Encrypted: case HeaderId.MimeVersion: case HeaderId.ContentAlternative: case HeaderId.ContentBase: case HeaderId.ContentClass: case HeaderId.ContentDescription: case HeaderId.ContentDisposition: case HeaderId.ContentDuration: case HeaderId.ContentFeatures: case HeaderId.ContentId: case HeaderId.ContentIdentifier: case HeaderId.ContentLanguage: case HeaderId.ContentLength: case HeaderId.ContentLocation: case HeaderId.ContentMd5: case HeaderId.ContentReturn: case HeaderId.ContentTransferEncoding: case HeaderId.ContentTranslationType: case HeaderId.ContentType: break; default: options.HiddenHeaders.Add(id); break; } } var memory = new MemoryStream(); message.WriteTo(options, memory); memory.Seek(0, SeekOrigin.Begin); if (memory.Length <= maxSize) { memory.Dispose(); yield return(message); yield break; } var streams = new List <Stream> (); #if !NETSTANDARD1_3 && !NETSTANDARD1_6 var buf = memory.GetBuffer(); #else var buf = memory.ToArray(); #endif long startIndex = 0; while (startIndex < memory.Length) { // Preferably, we'd split on whole-lines if we can, // but if that's not possible, split on max size long endIndex = Math.Min(memory.Length, startIndex + maxSize); if (endIndex < memory.Length) { long ebx = endIndex; while (ebx > (startIndex + 1) && buf[ebx] != (byte)'\n') { ebx--; } if (buf[ebx] == (byte)'\n') { endIndex = ebx + 1; } } streams.Add(new BoundStream(memory, startIndex, endIndex, true)); startIndex = endIndex; } var msgid = message.MessageId ?? MimeUtils.GenerateMessageId(); int number = 1; foreach (var stream in streams) { var part = new MessagePartial(msgid, number++, streams.Count) { Content = new MimeContent(stream) }; var submessage = CloneMessage(message); submessage.MessageId = MimeUtils.GenerateMessageId(); submessage.Body = part; yield return(submessage); } yield break; }
/// <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 = TextTransferEncoding }; 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 static void ProcessHtmlContent(BodyBuilder builder) { if (builder == null) { return; } if (string.IsNullOrWhiteSpace(builder.HtmlBody)) { return; } try { var htmlDoc = new HtmlDocument(); htmlDoc.Load(new MemoryStream(Encoding.UTF8.GetBytes(builder.HtmlBody))); if (htmlDoc.DocumentNode == null) { return; } foreach (HtmlNode node in htmlDoc.DocumentNode.SelectNodes("//img[@src]")) { var src = node.Attributes["src"].Value.Split('?', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); if (!string.IsNullOrWhiteSpace(src) && src.StartsWith("/fs")) { try { Uri uri = new Uri(src); src = uri.AbsolutePath; } catch { } if (src.StartsWith("/fs")) { src = src.Substring(3); } DbFileRepository fsRepository = new DbFileRepository(); var file = fsRepository.Find(src); if (file == null) { continue; } var bytes = file.GetBytes(); var extension = Path.GetExtension(src).ToLowerInvariant(); new FileExtensionContentTypeProvider().Mappings.TryGetValue(extension, out string mimeType); var imagePart = new MimePart(mimeType) { ContentId = MimeUtils.GenerateMessageId(), Content = new MimeContent(new MemoryStream(bytes)), ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = Path.GetFileName(src) }; builder.LinkedResources.Add(imagePart); node.SetAttributeValue("src", $"cid:{imagePart.ContentId}"); } } builder.HtmlBody = htmlDoc.DocumentNode.OuterHtml; if (string.IsNullOrWhiteSpace(builder.TextBody) && !string.IsNullOrWhiteSpace(builder.HtmlBody)) { builder.TextBody = ConvertToPlainText(builder.HtmlBody); } } catch { return; } }
protected Dictionary <string, ImageInfo> GenerateContentIdsForImageUrlsFromHtmlContent() { var result = new Dictionary <string, ImageInfo>(); // cid:{0} if (HtmlContent != null) { var originalMessageContent = HtmlContent; // TODO: save this somewhere // not sure if needed string html = string.Format("<html><head></head><body>{0}</body></html>", HtmlContent); List <Tuple <HtmlNode, string> > nodesToReplaceWithTextSmiley = new List <Tuple <HtmlNode, string> >(); HtmlDocument doc = new HtmlDocument(); doc.LoadHtml(html); var imageNodes = doc.DocumentNode.SelectNodes("//img"); if (imageNodes != null) { foreach (var imageNode in imageNodes) { var imgUrl = imageNode.GetAttributeValue("src", ""); var textSmiley = MessageUtils.GetTextReplacementForImageUrl(imgUrl); if (!string.IsNullOrWhiteSpace(textSmiley)) { nodesToReplaceWithTextSmiley.Add(Tuple.Create(imageNode, textSmiley)); continue; } if (string.IsNullOrWhiteSpace(imgUrl)) { continue; } var cid = MimeUtils.GenerateMessageId(); imageNode.SetAttributeValue("src", $"cid:{cid}"); var imageInfo = new ImageInfo(imgUrl, imgUrl, ImageType.Public); // Handles URLs like this: src =\"https://eu-api.asm.skype.com/v1/objects/0-weu-d11-00000000000000000000000000000000/views/imgo\" var teamsImageUrlPattern = @"http.*?/objects/([0-9a-zA-Z-]+?)/views/imgo"; var match = Regex.Match(HtmlContent, teamsImageUrlPattern); if (match.Success) { imageInfo.CacheKey = match.Value; imageInfo.ImageType = ImageType.TeamsWithAuthentication; } result.Add(cid, imageInfo); } foreach (var textReplacement in nodesToReplaceWithTextSmiley) { try { logger.Debug("Replacing image node with smiley {0} (HTML was: {1})", textReplacement.Item2, textReplacement.Item1.OuterHtml); textReplacement.Item1.ParentNode.ReplaceChild(HtmlNode.CreateNode($"<span>{textReplacement.Item2}</span>"), textReplacement.Item1); } catch (Exception e) { logger.Error(e, "Exception while replacing image node with smiley"); continue; } } } var bodyElement = doc.DocumentNode.SelectSingleNode("//body"); HtmlContent = bodyElement.InnerHtml; } return(result); }
/// <summary> /// This will load up the Email template and generate the HTML /// </summary> /// <param name="model"></param> /// <param name="settings"></param> /// <returns></returns> public async Task SendAdHoc(NotificationMessage model, EmailNotificationSettings settings) { try { var email = new EmailBasicTemplate(); var customization = await CustomizationSettings.GetSettingsAsync(); var html = email.LoadTemplate(model.Subject, model.Message, null, customization.Logo); var messageId = MimeUtils.GenerateMessageId(); if (customization.ApplicationUrl.HasValue()) { if (Uri.TryCreate(customization.ApplicationUrl, UriKind.RelativeOrAbsolute, out var url)) { messageId = MimeUtils.GenerateMessageId(url.IdnHost); } } var textBody = string.Empty; model.Other.TryGetValue("PlainTextBody", out textBody); var body = new BodyBuilder { HtmlBody = html, TextBody = textBody }; var message = new MimeMessage { Body = body.ToMessageBody(), Subject = model.Subject, MessageId = messageId }; message.From.Add(new MailboxAddress(string.IsNullOrEmpty(settings.SenderName) ? settings.SenderAddress : settings.SenderName, settings.SenderAddress)); message.To.Add(new MailboxAddress(model.To, model.To)); using (var client = new SmtpClient()) { if (settings.DisableCertificateChecking) { // Disable validation of the certificate associated with the SMTP service // Helpful when the TLS certificate is not in the certificate store of the server // Does carry the risk of man in the middle snooping client.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; } if (settings.DisableTLS) { // Does not attempt to use either TLS or SSL // Helpful when MailKit finds a TLS certificate, but it unable to use it client.Connect(settings.Host, settings.Port, MailKit.Security.SecureSocketOptions.None); } else { client.Connect(settings.Host, settings.Port); // Let MailKit figure out the correct SecureSocketOptions. } // Note: since we don't have an OAuth2 token, disable // the XOAUTH2 authentication mechanism. client.AuthenticationMechanisms.Remove("XOAUTH2"); if (settings.Authentication) { client.Authenticate(settings.Username, settings.Password); } _log.LogDebug("sending message to {0} \r\n from: {1}\r\n Are we authenticated: {2}", message.To, message.From, client.IsAuthenticated); try { await client.SendAsync(message); } catch (MailKit.Net.Smtp.SmtpCommandException e) when(e.ErrorCode.Equals(MailKit.Net.Smtp.SmtpErrorCode.RecipientNotAccepted) && e.StatusCode.Equals(MailKit.Net.Smtp.SmtpStatusCode.MailboxUnavailable)) { _log.LogError("Could not send email '{0}', address <{1}> does not exist.", message.Subject, model.To); } await client.DisconnectAsync(true); } } catch (Exception e) { _log.LogError(e, "Exception when attempting to send an email"); throw; } }
public string Send(EmailMessage emailMessage) { string NameFrom = emailMessage.FromAddresses.Substring(1, emailMessage.FromAddresses.IndexOf("/") - 1); string NameTo = emailMessage.ToAddresses.Substring(1, emailMessage.ToAddresses.IndexOf("/") - 1); var message = new MimeMessage(); try { message.From.Add(new MailboxAddress(NameFrom, emailMessage.FromAddresses)); message.To.Add(new MailboxAddress(NameTo, emailMessage.ToAddresses)); message.Subject = emailMessage.Subject; var bodyBuilder1 = new BodyBuilder(); bodyBuilder1.HtmlBody = emailMessage.Content; var builder = new BodyBuilder(); var image = builder.LinkedResources.Add(@"./poulinalogo.png"); image.ContentId = MimeUtils.GenerateMessageId(); builder.HtmlBody = string.Format(@"<br><br><br> <table> <thead> <tr> <td> {0} </td> </tr> </thead> <tbody> <tr> <td>E-Mail : {1}</td> </tr> <tr> <td>Service : Informatique Operationnelle</td> </tr> <tr> <td>Poste : 801249</td> </tr> <tr> <td>GSM : 58278855</td> </tr> </tbody> <tfoot> <center><img src=""cid:{2}""></center> </tfoot> </table>", NameFrom, message.From.ToString(), image.ContentId); var multipart = new Multipart("mixed"); multipart.Add(bodyBuilder1.ToMessageBody()); multipart.Add(builder.ToMessageBody()); var multipart1 = new Multipart("Attachements"); message.Body = multipart; using (var emailClient = new SmtpClient()) { emailClient.Connect(_emailConfiguration.SmtpServer, _emailConfiguration.SmtpPort, false); emailClient.Send(message); emailClient.Disconnect(true); EmailFrom emailFrom = new EmailFrom(); emailFrom.FromAddresses = emailMessage.FromAddresses; emailFrom.FromName = NameFrom; emailFrom.Subject = emailMessage.Subject; emailFrom.Content = emailMessage.Content; emailFrom.SendDate = DateTime.Now; emailFrom.MessageType = "info"; emailFrom.ExceptionMessage = "0"; _context.EmailFroms.Add(emailFrom); EmailTo emailTo = new EmailTo(); emailTo.IdMail = emailFrom.IdMail; emailTo.Seen = false; emailTo.ToAddresses = emailMessage.ToAddresses; emailTo.ToName = NameTo; emailTo.ReceiveType = "A"; _context.EmailTos.Add(emailTo); //if (emailMessage.CcAddresses != "") //{ // EmailTo emailTo2 = new EmailTo(); // emailTo2.IdMail = emailFrom.IdMail; // emailTo2.Seen = false; // emailTo2.ToAddresses = emailMessage.CcAddresses; // string NameCc= emailMessage.CcAddresses.Remove(emailMessage.CcAddresses.IndexOf("/")); // emailTo2.ToName = NameCc; // emailTo2.ReceiveType = "Cc"; // _context.EmailTos.Add(emailTo2); //} //if (emailMessage.CccAddresses != "") //{ // EmailTo emailTo3 = new EmailTo(); // emailTo3.IdMail = emailFrom.IdMail; // emailTo3.Seen = false; // emailTo3.ToAddresses = emailMessage.CccAddresses; // string NameCcc = emailMessage.CccAddresses.Remove(emailMessage.CccAddresses.IndexOf("/")); // emailTo3.ToName = NameCcc; // emailTo3.ReceiveType = "Ccc"; // _context.EmailTos.Add(emailTo3); //} _context.SaveChanges(); return("Mail success"); } } catch (Exception ex) { EmailFrom emailFrom = new EmailFrom(); emailFrom.FromAddresses = emailMessage.FromAddresses; emailFrom.FromName = NameFrom; emailFrom.Subject = emailMessage.Subject; emailFrom.Content = emailMessage.Content; emailFrom.SendDate = DateTime.Now; emailFrom.MessageType = "info"; emailFrom.ExceptionMessage = ex.Message; _context.EmailFroms.Add(emailFrom); EmailTo emailTo = new EmailTo(); emailTo.IdMail = emailFrom.IdMail; emailTo.Seen = false; emailTo.ToAddresses = emailMessage.ToAddresses; emailTo.ToName = NameTo; emailTo.ReceiveType = "A"; _context.EmailTos.Add(emailTo); //if (emailMessage.CcAddresses != "") //{ // EmailTo emailTo2 = new EmailTo(); // emailTo2.IdMail = emailFrom.IdMail; // emailTo2.Seen = false; // emailTo2.ToAddresses = emailMessage.CcAddresses; // string NameCc = emailTo2.ToAddresses.Remove(emailTo2.ToAddresses.IndexOf("/")); // emailTo2.ToName = NameCc; // emailTo2.ReceiveType = "Cc"; // _context.EmailTos.Add(emailTo2); //} //if (emailMessage.CccAddresses != "") //{ // EmailTo emailTo3 = new EmailTo(); // emailTo3.IdMail = emailFrom.IdMail; // emailTo3.Seen = false; // emailTo3.ToAddresses = emailMessage.CccAddresses; // string NameCcc = emailTo3.ToAddresses.Remove(emailTo3.ToAddresses.IndexOf("/")); // emailTo3.ToName = NameCcc; // emailTo3.ReceiveType = "Ccc"; // _context.EmailTos.Add(emailTo3); //} _context.SaveChanges(); return(ex.Message); } }
public void ExampleContextBuild() { // // Context // var contextBuilder = new ContextBuilder(); contextBuilder .WithContentId(MimeUtils.GenerateMessageId()) .WithDisposition("metadata.txt") .WithTransferEncoding(ContentEncoding.Base64) .WithVersion("1.0") .WithId(MimeUtils.GenerateMessageId()) .WithPatientId( new PatientInstance { PidContext = "2.16.840.1.113883.19.999999", LocalPatientId = "123456" }.ToList() ) .WithType(ContextStandard.Type.CategoryRadiology, ContextStandard.Type.ActionReport) .WithPurpose(ContextStandard.Purpose.PurposeResearch) .WithPatient( new Patient { GivenName = "John", SurName = "Doe", MiddleName = "Jacob", DateOfBirth = "1961-12-31", Gender = "M", PostalCode = "12345" } ); var context = contextBuilder.Build(); // // Mime message and simple body // var message = new MimeMessage(); message.From.Add(new MailboxAddress("HoboJoe", "*****@*****.**")); message.To.Add(new MailboxAddress("Toby", "*****@*****.**")); message.Subject = "Sample message with pdf and context attached"; message.Headers.Add(MailStandard.Headers.DirectContext, context.Headers[ContextStandard.ContentIdHeader]); Assert.StartsWith("<", context.Headers[HeaderId.ContentId]); Assert.EndsWith(">", context.Headers[HeaderId.ContentId]); var body = new TextPart("plain") { Text = @"Simple Body" }; // // Mime message and simple body // var pdf = new MimePart("application/pdf") { ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), FileName = "report.pdf", ContentTransferEncoding = ContentEncoding.Base64 }; var byteArray = Encoding.UTF8.GetBytes("Fake PDF (invalid)"); var stream = new MemoryStream(byteArray); pdf.Content = new MimeContent(stream); // // Multi part construction // var multiPart = new Multipart("mixed") { body, contextBuilder.BuildMimePart(), pdf }; message.Body = multiPart; // // Assert context can be serialized and parsed. // var messageParsed = MimeMessage.Load(message.ToString().ToStream()); Assert.True(messageParsed.ContainsDirectContext()); Assert.Equal(context.ContentId, messageParsed.DirectContextId()); Assert.StartsWith("<", messageParsed.Headers[MailStandard.Headers.DirectContext]); Assert.EndsWith(">", messageParsed.Headers[MailStandard.Headers.DirectContext]); var contextParsed = message.DirectContext(); Assert.NotNull(contextParsed); // // Headers // Assert.Equal("text", contextParsed.ContentType.MediaType); Assert.Equal("plain", contextParsed.ContentType.MediaSubtype); Assert.Equal("attachment", contextParsed.ContentDisposition.Disposition); Assert.Equal("metadata.txt", contextParsed.ContentDisposition.FileName); Assert.Equal(context.ContentId, contextParsed.ContentId); // // Metadata // Assert.Equal("1.0", contextParsed.Metadata.Version); Assert.Equal(context.Metadata.Id, contextParsed.Metadata.Id); // // Metatdata PatientId // Assert.Equal("2.16.840.1.113883.19.999999:123456", contextParsed.Metadata.PatientId); Assert.Single(contextParsed.Metadata.PatientIdentifier); var patientIdentifiers = Enumerable.ToList(contextParsed.Metadata.PatientIdentifier); Assert.Equal("2.16.840.1.113883.19.999999", patientIdentifiers[0].PidContext); Assert.Equal("123456", patientIdentifiers[0].LocalPatientId); // // Metatdata Type // Assert.Equal("radiology/report", contextParsed.Metadata.Type.ToString()); Assert.Equal("radiology", contextParsed.Metadata.Type.Category); Assert.Equal("report", contextParsed.Metadata.Type.Action); // // Metatdata Purpose // Assert.Equal("research", contextParsed.Metadata.Purpose); // // Metadata Patient // Assert.Equal("givenName=John; surname=Doe; middleName=Jacob; dateOfBirth=1961-12-31; gender=M; postalCode=12345", contextParsed.Metadata.Patient.ToString()); Assert.Equal("John", contextParsed.Metadata.Patient.GivenName); Assert.Equal("Doe", contextParsed.Metadata.Patient.SurName); Assert.Equal("1961-12-31", contextParsed.Metadata.Patient.DateOfBirth); }