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");
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> Email()
        {
            var          parser       = new WebhookParser();
            InboundEmail inboundEmail = parser.ParseInboundEmailWebhook(Request.Body);
            await _messageSink.ProcessMessageAsync(CreateMessage(inboundEmail));

            return(Ok());
        }
Ejemplo n.º 3
0
        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");
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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
            });
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        /// <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);
        }
Ejemplo n.º 9
0
        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}\" &lt;{mail.From.Email}&gt;";
                mail.Html += "<br>";
                mail.Html += $"Original To: \"{mail.To.FirstOrDefault()?.Email}\" &lt;{mail.To.FirstOrDefault()?.Email}&gt;";
            }

            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));
            }
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
 public InboundEmailAdapter(
     InboundEmail arg0
     )
 {
     field0 = arg0;
 }
Ejemplo n.º 12
0
 public InboundEmailResult handleInboundEmail(InboundEmail inboundEmail, InboundEnvelope inboundEnvelope)
 {
     throw new global::System.NotImplementedException("InboundEmailHandler.HandleInboundEmail");
 }