public async void DefaultPayloadWithoutAttachments() { Stream stream = new MemoryStream(); await File.OpenRead("sample_data/default_data.txt").CopyToAsync(stream); stream.Position = 0; var parser = new InboundWebhookParser(stream); InboundEmail inboundEmail = parser.Parse(); inboundEmail.ShouldNotBeNull(); inboundEmail.Headers.Except(new[] { new KeyValuePair <string, string>("MIME-Version", "1.0"), new KeyValuePair <string, string>("Received", "by 0.0.0.0 with HTTP; Wed, 10 Aug 2016 18:10:13 -0700 (PDT)"), new KeyValuePair <string, string>("From", "Example User <*****@*****.**>"), new KeyValuePair <string, string>("Date", "Wed, 10 Aug 2016 18:10:13 -0700"), new KeyValuePair <string, string>("Subject", "Inbound Parse Test Data"), new KeyValuePair <string, string>("To", "*****@*****.**"), new KeyValuePair <string, string>("Content-Type", "multipart/alternative; boundary=001a113df448cad2d00539c16e89") }).Count().ShouldBe(0); inboundEmail.Dkim.ShouldBe("{@sendgrid.com : pass}"); inboundEmail.To[0].Email.ShouldBe("*****@*****.**"); inboundEmail.To[0].Name.ShouldBe(string.Empty); inboundEmail.Html.Trim().ShouldBe("<html><body><strong>Hello SendGrid!</body></html>"); inboundEmail.Text.Trim().ShouldBe("Hello SendGrid!"); inboundEmail.From.Email.ShouldBe("*****@*****.**"); inboundEmail.From.Name.ShouldBe("Example User"); inboundEmail.SenderIp.ShouldBe("0.0.0.0"); inboundEmail.SpamReport.ShouldBeNull(); inboundEmail.Envelope.From.ShouldBe("*****@*****.**"); inboundEmail.Envelope.To.Length.ShouldBe(1); inboundEmail.Envelope.To.ShouldContain("*****@*****.**"); inboundEmail.Attachments.Length.ShouldBe(0); inboundEmail.Subject.ShouldBe("Testing non-raw"); inboundEmail.SpamScore.ShouldBeNull(); inboundEmail.Charsets.Except(new[] { new KeyValuePair <string, Encoding>("to", Encoding.UTF8), new KeyValuePair <string, Encoding>("html", Encoding.UTF8), new KeyValuePair <string, Encoding>("subject", Encoding.UTF8), new KeyValuePair <string, Encoding>("from", Encoding.UTF8), new KeyValuePair <string, Encoding>("text", Encoding.UTF8) }).Count().ShouldBe(0); inboundEmail.Spf.ShouldBe("pass"); }
public async Task <IActionResult> Email() { var parser = new WebhookParser(); InboundEmail inboundEmail = parser.ParseInboundEmailWebhook(Request.Body); await _messageSink.ProcessMessageAsync(CreateMessage(inboundEmail)); return(Ok()); }
public async Task RawPayloadWithAttachmentsAsync() { var parser = new WebhookParser(); using (Stream stream = new MemoryStream()) { using (var fileStream = File.OpenRead("InboudEmailTestData/raw_data.txt")) { await fileStream.CopyToAsync(stream).ConfigureAwait(false); } stream.Position = 0; InboundEmail inboundEmail = await parser.ParseInboundEmailWebhookAsync(stream).ConfigureAwait(false); inboundEmail.ShouldNotBeNull(); inboundEmail.Dkim.ShouldBe("{@sendgrid.com : pass}"); var rawEmailTestData = File.ReadAllText("InboudEmailTestData/raw_email.txt"); inboundEmail.RawEmail.Trim().ShouldBe(rawEmailTestData); inboundEmail.To[0].Email.ShouldBe("*****@*****.**"); inboundEmail.To[0].Name.ShouldBe(string.Empty); inboundEmail.Cc.Length.ShouldBe(0); inboundEmail.From.Email.ShouldBe("*****@*****.**"); inboundEmail.From.Name.ShouldBe("Example User"); inboundEmail.SenderIp.ShouldBe("0.0.0.0"); inboundEmail.SpamReport.ShouldBeNull(); inboundEmail.Envelope.From.ShouldBe("*****@*****.**"); inboundEmail.Envelope.To.Length.ShouldBe(1); inboundEmail.Envelope.To.ShouldContain("*****@*****.**"); inboundEmail.Subject.ShouldBe("Raw Payload"); inboundEmail.SpamScore.ShouldBeNull(); inboundEmail.Charsets.Except(new[] { new KeyValuePair <string, Encoding>("to", Encoding.UTF8), new KeyValuePair <string, Encoding>("subject", Encoding.UTF8), new KeyValuePair <string, Encoding>("from", Encoding.UTF8) }).Count().ShouldBe(0); inboundEmail.Spf.ShouldBe("pass"); } }
public async void RawPayloadWithAttachments() { Stream stream = new MemoryStream(); await File.OpenRead("sample_data/raw_data_with_attachments.txt").CopyToAsync(stream); stream.Position = 0; var parser = new InboundWebhookParser(stream); InboundEmail inboundEmail = parser.Parse(); inboundEmail.ShouldNotBeNull(); inboundEmail.Dkim.ShouldBe("{@sendgrid.com : pass}"); var rawEmailTestData = await File.ReadAllTextAsync("sample_data/raw_email_with_attachments.txt"); inboundEmail.RawEmail.Trim().ShouldBe(rawEmailTestData); inboundEmail.To[0].Email.ShouldBe("*****@*****.**"); inboundEmail.To[0].Name.ShouldBe(string.Empty); inboundEmail.Cc.Length.ShouldBe(0); inboundEmail.From.Email.ShouldBe("*****@*****.**"); inboundEmail.From.Name.ShouldBe("Example User"); inboundEmail.SenderIp.ShouldBe("0.0.0.0"); inboundEmail.SpamReport.ShouldBeNull(); inboundEmail.Envelope.From.ShouldBe("*****@*****.**"); inboundEmail.Envelope.To.Length.ShouldBe(1); inboundEmail.Envelope.To.ShouldContain("*****@*****.**"); inboundEmail.Subject.ShouldBe("Raw Payload"); inboundEmail.SpamScore.ShouldBeNull(); inboundEmail.Charsets.Except(new[] { new KeyValuePair <string, Encoding>("to", Encoding.UTF8), new KeyValuePair <string, Encoding>("subject", Encoding.UTF8), new KeyValuePair <string, Encoding>("from", Encoding.UTF8) }).Count().ShouldBe(0); inboundEmail.Spf.ShouldBe("pass"); }
public static InboundEmail IncludeAttachmentsOrDefault(this InboundEmail email, AttachmentCollection incomingAttachments) { if (incomingAttachments.Count <= 0) { return(email); } var filePath = ConfigurationManager.AppSettings["InboundAttachmentsPath"]; var attachments = incomingAttachments.GetEnumerator(); while (attachments.MoveNext()) { var attachment = attachments.Current as MimePart; if (attachment != null && attachment.HasValidExtension()) // Skip invalid attachments { var fileExtension = attachment.Filename.Split('.').LastOrDefault() ?? "INVALID"; if (filePath.Last() != '\\') { filePath = filePath + @"\"; } if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } var completeUniqueFilePath = GenerateUniqueFilePath(filePath, fileExtension); attachment.StoreToFile(completeUniqueFilePath); email.InboundAttachments.Add(new InboundAttachment { FilePath = completeUniqueFilePath, OriginalFileName = attachment.Filename, FileType = fileExtension.ToUpper() }); } } return(email); }
private MagnetMessage CreateMessage(InboundEmail inboundEmail) { var properties = new Dictionary <string, string>(); properties.Add("Html", inboundEmail.Html); properties.Add("Subject", inboundEmail.Subject); properties.Add("SendGrid-Message-ID", inboundEmail.Headers .FirstOrDefault(x => x.Key == "Message-ID").Value); return(new MagnetMessage { Type = "Email", Provider = "SendGrid", ReceivedAt = DateTime.UtcNow, From = inboundEmail.From.Email, To = inboundEmail.To.Select(x => x.Email).ToList(), Body = inboundEmail.Text, Properties = properties }); }
private static InboundEmail ParseInboundEmail(IDictionary <Encoding, MultipartFormDataParser> encodedParsers, KeyValuePair <string, Encoding>[] charsets) { // Get the default UTF8 parser var parser = encodedParsers.Single(p => p.Key.Equals(Encoding.UTF8)).Value; // Convert the 'headers' from a string into array of KeyValuePair var headers = parser .GetParameterValue("headers", string.Empty) .Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries) .Select(header => { var splitHeader = header.Split(new[] { ": " }, StringSplitOptions.RemoveEmptyEntries); var key = splitHeader[0]; var value = splitHeader.Length >= 2 ? splitHeader[1] : null; return(new KeyValuePair <string, string>(key, value)); }).ToArray(); // Raw email var rawEmail = parser.GetParameterValue("email", string.Empty); // Combine the 'attachment-info' and Files into an array of Attachments var attachmentInfoAsJObject = JObject.Parse(parser.GetParameterValue("attachment-info", "{}")); var attachments = attachmentInfoAsJObject .Properties() .Select(prop => { var attachment = prop.Value.ToObject <InboundEmailAttachment>(); attachment.Id = prop.Name; var file = parser.Files.FirstOrDefault(f => f.Name == prop.Name); if (file != null) { attachment.Data = file.Data; if (string.IsNullOrEmpty(attachment.ContentType)) { attachment.ContentType = file.ContentType; } if (string.IsNullOrEmpty(attachment.FileName)) { attachment.FileName = file.FileName; } } return(attachment); }).ToArray(); // Convert the 'envelope' from a JSON string into a strongly typed object var envelope = JsonConvert.DeserializeObject <InboundEmailEnvelope>(parser.GetParameterValue("envelope", "{}")); // Convert the 'from' from a string into an email address var rawFrom = GetEncodedValue("from", charsets, encodedParsers, string.Empty); var from = MailAddressParser.ParseEmailAddress(rawFrom); // Convert the 'to' from a string into an array of email addresses var rawTo = GetEncodedValue("to", charsets, encodedParsers, string.Empty); var to = MailAddressParser.ParseEmailAddresses(rawTo); // Convert the 'cc' from a string into an array of email addresses var rawCc = GetEncodedValue("cc", charsets, encodedParsers, string.Empty); var cc = MailAddressParser.ParseEmailAddresses(rawCc); // Arrange the InboundEmail var inboundEmail = new InboundEmail { Attachments = attachments, Charsets = charsets, Dkim = GetEncodedValue("dkim", charsets, encodedParsers, null), Envelope = envelope, From = from, Headers = headers, Html = GetEncodedValue("html", charsets, encodedParsers, null), SenderIp = GetEncodedValue("sender_ip", charsets, encodedParsers, null), SpamReport = GetEncodedValue("spam_report", charsets, encodedParsers, null), SpamScore = GetEncodedValue("spam_score", charsets, encodedParsers, null), Spf = GetEncodedValue("SPF", charsets, encodedParsers, null), Subject = GetEncodedValue("subject", charsets, encodedParsers, null), Text = GetEncodedValue("text", charsets, encodedParsers, null), To = to, Cc = cc, RawEmail = rawEmail }; return(inboundEmail); }
/// <summary> /// Parses the inbound email webhook. /// </summary> /// <param name="stream">The stream.</param> /// <returns>The <see cref="InboundEmail"/></returns> public InboundEmail ParseInboundEmailWebhook(Stream stream) { // Parse the multipart content received from SendGrid var parser = new MultipartFormDataParser(stream); // Convert the 'headers' from a string into array of KeyValuePair var rawHeaders = parser .GetParameterValue("headers", string.Empty) .Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); var headers = rawHeaders .Select(header => { var splitHeader = header.Split(new[] { ": " }, StringSplitOptions.RemoveEmptyEntries); var key = splitHeader[0]; var value = splitHeader.Length >= 2 ? splitHeader[1] : null; return(new KeyValuePair <string, string>(key, value)); }).ToArray(); // Conbine the 'attachment-info' and Files into a single array or Attachments var attachmentInfoAsJObject = JObject.Parse(parser.GetParameterValue("attachment-info", "{}")); var attachments = attachmentInfoAsJObject .Properties() .Select(prop => { var attachment = prop.Value.ToObject <InboundEmailAttachment>(); attachment.Id = prop.Name; var file = parser.Files.FirstOrDefault(f => f.Name == prop.Name); if (file != null) { attachment.ContentType = file.ContentType; attachment.Data = file.Data; } return(attachment); }).ToArray(); // Convert the 'charset' from a string into array of KeyValuePair var charsetsAsJObject = JObject.Parse(parser.GetParameterValue("charsets", "{}")); var charsets = charsetsAsJObject .Properties() .Select(prop => { var key = prop.Name; var value = Encoding.GetEncoding(prop.Value.ToString()); return(new KeyValuePair <string, Encoding>(key, value)); }).ToArray(); // Convert the 'envelope' from a JSON string into a strongly typed object var envelope = JsonConvert.DeserializeObject <InboundEmailEnvelope>(parser.GetParameterValue("envelope", "{}")); // Convert the 'from' from a string into a strongly typed object var rawFrom = parser.GetParameterValue("from", string.Empty); var piecesFrom = rawFrom.Split(new[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries); var from = new MailAddress(piecesFrom[1], piecesFrom[0].Replace("\"", string.Empty).Trim()); // Convert the 'to' from a string into a strongly typed object var rawTo = parser.GetParameterValue("to", string.Empty); var piecesTo = rawFrom.Split(new[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries); var to = new MailAddress(piecesFrom[1], piecesFrom[0].Replace("\"", string.Empty).Trim()); // Arrange the InboundEmail var inboundEmail = new InboundEmail { Attachments = attachments, Charsets = charsets, Dkim = parser.GetParameterValue("dkim", null), Envelope = envelope, From = from, Headers = headers, Html = parser.GetParameterValue("html", null), SenderIp = parser.GetParameterValue("sender_ip", null), SpamReport = parser.GetParameterValue("spam_report", null), SpamScore = parser.GetParameterValue("spam_score", null), Spf = parser.GetParameterValue("SPF", null), Subject = parser.GetParameterValue("subject", null), To = to }; return(inboundEmail); }
private static async Task <string> ForwardEmail(InboundEmail mail, double spamScore, ILogger log) { // To, from emails string toAddress = GetEnvironmentVariable("SmtpToEmail"); string toName = GetEnvironmentVariable("SmtpToName"); MailAddress toEmail = new MailAddress(toAddress, toName); string fromAddress = GetEnvironmentVariable("SmtpFromEmail"); string fromName = GetEnvironmentVariable("SmtpFromName"); MailAddress fromEmail = new MailAddress(fromAddress, fromName); // Create StrongGrid mail client string apiKey = GetEnvironmentVariable("SENDGRID_API"); var client = new Client(apiKey); // Add spam report if (!string.IsNullOrEmpty(mail.SpamReport) && spamScore >= 2.5) { if (!string.IsNullOrEmpty(mail.Html)) { mail.Html = mail.SpamReport + "<br>---<br>" + mail.Html; } mail.Text = mail.SpamReport + "\n---\n" + mail.Text; } // Add message details if (!string.IsNullOrEmpty(mail.Html)) { mail.Html += "<br>---<br>"; mail.Html += $"Original From: \"{mail.From.Name}\" <{mail.From.Email}>"; mail.Html += "<br>"; mail.Html += $"Original To: \"{mail.To.FirstOrDefault()?.Email}\" <{mail.To.FirstOrDefault()?.Email}>"; } mail.Text += "\n---\n"; mail.Text += $"Original From: \"{mail.From.Name}\" <{mail.From.Email}>\n"; mail.Text += $"Original To: \"{mail.To.FirstOrDefault()?.Email}\" <{mail.To.FirstOrDefault()?.Email}>"; // Add attachments List <Attachment> attachmentList = new List <Attachment>(); foreach (var attach in mail.Attachments) { log.LogInformation($"{attach.FileName}\n{attach.Data}"); attachmentList.Add(Attachment.FromStream(attach.Data, attach.FileName, attach.ContentType, attach.ContentId)); } // Send mail if (attachmentList.Count > 0) { var attachments = attachmentList.ToArray(); return(await client.Mail.SendToSingleRecipientAsync( toEmail, fromEmail, mail.Subject, mail.Html, mail.Text, replyTo : mail.From, attachments : attachments ).ConfigureAwait(false)); } else { return(await client.Mail.SendToSingleRecipientAsync( toEmail, fromEmail, mail.Subject, mail.Html, mail.Text, replyTo : mail.From ).ConfigureAwait(false)); } }
/// <summary> /// Parses the inbound email webhook. /// </summary> /// <param name="stream">The stream.</param> /// <returns>The <see cref="InboundEmail"/>.</returns> public InboundEmail ParseInboundEmailWebhook(Stream stream) { // Parse the multipart content received from SendGrid var parser = new MultipartFormDataParser(stream, Encoding.UTF8); // Convert the 'headers' from a string into array of KeyValuePair var rawHeaders = parser .GetParameterValue("headers", string.Empty) .Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); var headers = rawHeaders .Select(header => { var splitHeader = header.Split(new[] { ": " }, StringSplitOptions.RemoveEmptyEntries); var key = splitHeader[0]; var value = splitHeader.Length >= 2 ? splitHeader[1] : null; return(new KeyValuePair <string, string>(key, value)); }).ToArray(); // Combine the 'attachment-info' and Files into an array of Attachments var attachmentInfoAsJObject = JObject.Parse(parser.GetParameterValue("attachment-info", "{}")); var attachments = attachmentInfoAsJObject .Properties() .Select(prop => { var attachment = prop.Value.ToObject <InboundEmailAttachment>(); attachment.Id = prop.Name; var file = parser.Files.FirstOrDefault(f => f.Name == prop.Name); if (file != null) { attachment.ContentType = file.ContentType; attachment.Data = file.Data; } return(attachment); }).ToArray(); // Convert the 'envelope' from a JSON string into a strongly typed object var envelope = JsonConvert.DeserializeObject <InboundEmailEnvelope>(parser.GetParameterValue("envelope", "{}")); // Convert the 'charset' from a string into array of KeyValuePair var charsetsAsJObject = JObject.Parse(parser.GetParameterValue("charsets", "{}")); var charsets = charsetsAsJObject .Properties() .Select(prop => { var key = prop.Name; var value = Encoding.GetEncoding(prop.Value.ToString()); return(new KeyValuePair <string, Encoding>(key, value)); }).ToArray(); // Create a dictionary of parsers, one parser for each desired encoding. // This is necessary because MultipartFormDataParser can only handle one // encoding and SendGrid can use different encodings for parameters such // as "from", "to", "text" and "html". var encodedParsers = charsets .Where(c => c.Value != Encoding.UTF8) .Select(c => c.Value) .Distinct() .Select(encoding => { stream.Position = 0; return(new { Encoding = encoding, Parser = new MultipartFormDataParser(stream, encoding) }); }) .Union(new[] { new { Encoding = Encoding.UTF8, Parser = parser } }) .ToDictionary(ep => ep.Encoding, ep => ep.Parser); // Convert the 'from' from a string into an email address var rawFrom = GetEncodedValue("from", charsets, encodedParsers, string.Empty); var from = ParseEmailAddress(rawFrom); // Convert the 'to' from a string into an array of email addresses var rawTo = GetEncodedValue("to", charsets, encodedParsers, string.Empty); var to = ParseEmailAddresses(rawTo); // Convert the 'cc' from a string into an array of email addresses var rawCc = GetEncodedValue("cc", charsets, encodedParsers, string.Empty); var cc = ParseEmailAddresses(rawCc); // Arrange the InboundEmail var inboundEmail = new InboundEmail { Attachments = attachments, Charsets = charsets, Dkim = GetEncodedValue("dkim", charsets, encodedParsers, null), Envelope = envelope, From = from, Headers = headers, Html = GetEncodedValue("html", charsets, encodedParsers, null), SenderIp = GetEncodedValue("sender_ip", charsets, encodedParsers, null), SpamReport = GetEncodedValue("spam_report", charsets, encodedParsers, null), SpamScore = GetEncodedValue("spam_score", charsets, encodedParsers, null), Spf = GetEncodedValue("SPF", charsets, encodedParsers, null), Subject = GetEncodedValue("subject", charsets, encodedParsers, null), Text = GetEncodedValue("text", charsets, encodedParsers, null), To = to, Cc = cc }; return(inboundEmail); }
public InboundEmailAdapter( InboundEmail arg0 ) { field0 = arg0; }
public InboundEmailResult handleInboundEmail(InboundEmail inboundEmail, InboundEnvelope inboundEnvelope) { throw new global::System.NotImplementedException("InboundEmailHandler.HandleInboundEmail"); }