public void AttachmentsShouldBeCorrectlyParsed() { var parser = new SendgridEmailParser(); using (var form = Build(new Dictionary <string, object> { { "from", "from <*****@*****.**>" }, { "to", "no name <*****@*****.**>" }, { "subject", "subj" }, { "html", "other content" }, { "attachment-info", JsonConvert.SerializeObject(new { attachment1 = new { filename = "en.txt", type = "text/plain" }, attachment2 = new { filename = "img.jpg", type = "image/jpeg" } }) }, { "attachment1", new EmailAttachment { FileName = "en.txt", ContentType = "text/plain", Base64Data = "This is the actual content" } }, { "attachment2", new EmailAttachment { FileName = "img.jpg", ContentType = "image/jpeg", Base64Data = "large base64 payload" } } })) { var result = parser.Parse(form); result.From.Email.Should().Be("*****@*****.**"); result.To[0].Email.Should().Be("*****@*****.**"); result.Subject.Should().Be("subj"); result.Html.Should().Be("other content"); result.Attachments.Should().HaveCount(2); result.Attachments[0].ContentType.Should().Be("text/plain"); result.Attachments[0].FileName.Should().Be("en.txt"); result.Attachments[0].Base64Data.Should().Be(Convert.ToBase64String(Encoding.UTF8.GetBytes("This is the actual content"))); result.Attachments[1].ContentType.Should().Be("image/jpeg"); result.Attachments[1].FileName.Should().Be("img.jpg"); result.Attachments[1].Base64Data.Should().Be(Convert.ToBase64String(Encoding.UTF8.GetBytes("large base64 payload"))); } }
public void HtmlShouldBePreferredOverText() { var parser = new SendgridEmailParser(); const string actualContent = "Only this should be submitted"; var data = new Dictionary <string, object> { { "from", "from <*****@*****.**>" }, { "to", "no name <*****@*****.**>" }, { "subject", "subj" }, { "text", "other content" }, { "html", @"<html> <head> <meta http-equiv=""Content-Type"" content=""text/html; charset=iso-8859-1""> <style type=""text/css"" style=""display:none;""> P {margin-top:0;margin-bottom:0;} </style> </head> <body dir=""ltr""> <div style=""font-family:Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)"">" + actualContent + @"<br> </div> <div style=""font-family:Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)""> </div> <div style=""font-family:Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)""> <br> </div> <div id=""Signature""> <div id=""divtagdefaultwrapper"" style=""font-size:12pt; color:#000000; font-family:Calibri,Arial,Helvetica,sans-serif""> Regards, <div>Sender</div> </div> </div> </body> </html>" } }; using (var form = Build(data)) { var result = parser.Parse(form); result.From.Email.Should().Be("*****@*****.**"); result.To[0].Email.Should().Be("*****@*****.**"); result.Subject.Should().Be("subj"); result.Html.Should().Be((string)data["html"]); } }
public void ParsingDisplayNamesShouldWork() { var parser = new SendgridEmailParser(); using (var form = Build(new Dictionary <string, object> { { "from", "from <*****@*****.**>" }, { "to", "no name <*****@*****.**>" }, { "subject", "subj" }, { "html", "text" } })) { var result = parser.Parse(form); result.From.Email.Should().Be("*****@*****.**"); result.To[0].Email.Should().Be("*****@*****.**"); result.Subject.Should().Be("subj"); result.Html.Should().Be("text"); } }
public void TextShouldBeFallbackIfHtmlFails() { var parser = new SendgridEmailParser(); using (var form = Build(new Dictionary <string, object> { { "from", "from <*****@*****.**>" }, { "to", "no name <*****@*****.**>" }, { "subject", "subj" }, { "text", "other content" }, { "html", "" } })) { var result = parser.Parse(form); result.From.Email.Should().Be("*****@*****.**"); result.To[0].Email.Should().Be("*****@*****.**"); result.Subject.Should().Be("subj"); result.Html.Should().Be(""); result.Text.Should().Be("other content"); } }
public void AttachmentsShouldBeCorrectlyParsedFromActualPayload() { var parser = new SendgridEmailParser(); using (var form = new MemoryStream()) { var content = File.ReadAllText("Data/multipart.txt"); var writer = new StreamWriter(form); writer.Write(content); writer.Flush(); form.Position = 0; var result = parser.Parse(form); result.From.Email.Should().Be("*****@*****.**"); result.From.Name.Should().Be("Marc Stan"); result.To[0].Email.Should().Be("*****@*****.**"); result.To[0].Name.Should().Be("*****@*****.**"); result.Subject.Should().Be("Subject1"); result.Text.Should().Be("Content1"); result.Attachments.Should().HaveCount(1); result.Attachments[0].ContentType.Should().Be("text/plain"); result.Attachments[0].FileName.Should().Be("en.txt"); result.Attachments[0].Base64Data.Should().Be(Convert.ToBase64String(Encoding.UTF8.GetBytes("this is plaintext"))); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, Microsoft.Azure.WebJobs.ExecutionContext context, ILogger log, CancellationToken cancellationToken) { try { var config = LoadConfig(context.FunctionAppDirectory, log); var container = config["ArchiveContainerName"]; var target = config["RelayTargetEmail"]; if (string.IsNullOrEmpty(container) && string.IsNullOrEmpty(target)) { throw new NotSupportedException("Neither email target nor container name where set. Please set either ArchiveContainerName or RelayTargetEmail"); } Email email; using (var stream = new MemoryStream()) { // body can only be read once req.Body.CopyTo(stream); stream.Position = 0; var parser = new SendgridEmailParser(); email = parser.Parse(stream); } if (!string.IsNullOrEmpty(container)) { IPersister auditLogger = new BlobStoragePersister(config["AzureWebJobsStorage"], container); var d = DateTimeOffset.UtcNow; // one folder per day is fine for now var id = $"{d.ToString("yyyy-MM")}/{d.ToString("dd")}/{d.ToString("HH-mm-ss")}_{email.From.Email} - {email.Subject}"; await auditLogger.PersistAsync($"{id}.json", JsonConvert.SerializeObject(email, Formatting.Indented)); // save all attachments in subfolder await Task.WhenAll(email.Attachments.Select(a => auditLogger.PersistAsync($"{id} (Attachments)/{a.FileName}", Convert.FromBase64String(a.Base64Data)))); } if (!string.IsNullOrEmpty(target)) { var domain = config["Domain"]; var key = config["SendgridApiKey"]; if (!string.IsNullOrEmpty(target) && string.IsNullOrEmpty(domain)) { throw new NotSupportedException("Domain must be set as well when relay is used."); } if (!string.IsNullOrEmpty(target) && string.IsNullOrEmpty(key)) { throw new NotSupportedException("SendgridApiKey must be set as well when relay is used."); } var client = new SendGridClient(key); var subjectParser = new SubjectParser(config["Prefix"]); var relay = new RelayLogic(client, subjectParser, log, new[] { new OutlookWebSanitizer(subjectParser) } ); var sendAsDomain = "true".Equals(config["SendAsDomain"], StringComparison.OrdinalIgnoreCase); await relay.RelayAsync(email, target, domain, sendAsDomain, cancellationToken); } return(new OkResult()); } catch (Exception e) { log.LogCritical(e, "Failed to process request!"); return(new BadRequestResult()); } }