public async Task Given_base_view_is_full_path_Then_alternative_views_are_correctly_looked_up()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject
Views: Text, Html";
            var text  = @"Content-Type: text/plain

Hello, World!";
            var html  = @"Content-Type: text/html

<p>Hello, World!</p>";

            var email    = new Email("~/Views/Emails/Test.cshtml");
            var renderer = new Mock <IEmailViewRender>();

            renderer.Setup(r => r.RenderAsync(email, "~/Views/Emails/Test.Text.cshtml")).Returns(Task.FromResult(text));
            renderer.Setup(r => r.RenderAsync(email, "~/Views/Emails/Test.Html.cshtml")).Returns(Task.FromResult(html));

            var parser = new EmailParser(renderer.Object);

            using (var message = await parser.ParseAsync(input, email))
            {
                message.AlternateViews[0].ContentType.ShouldBe(new ContentType("text/plain; charset=utf-16"));
                var textContent = new StreamReader(message.AlternateViews[0].ContentStream).ReadToEnd();
                textContent.ShouldBe("Hello, World!");

                message.AlternateViews[1].ContentType.ShouldBe(new ContentType("text/html; charset=utf-16"));
                var htmlContent = new StreamReader(message.AlternateViews[1].ContentStream).ReadToEnd();
                htmlContent.ShouldBe("<p>Hello, World!</p>");
            }

            renderer.Verify();
        }
        public async Task Given_base_view_is_full_path_Then_alternative_views_are_correctly_looked_up()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject
Views: Text, Html";
            var text  = @"Content-Type: text/plain

Hello, World!";
            var html  = @"Content-Type: text/html

<p>Hello, World!</p>";

            var email    = new Email("~/Views/Emails/Test.cshtml");
            var renderer = new Mock <IEmailViewRender>();

            renderer.Setup(r => r.RenderAsync(email, "~/Views/Emails/Test.Text.cshtml")).Returns(Task.FromResult(text));
            renderer.Setup(r => r.RenderAsync(email, "~/Views/Emails/Test.Html.cshtml")).Returns(Task.FromResult(html));

            var parser  = new EmailParser(renderer.Object);
            var message = await parser.ParseAsync(input, email);

            message.TextBody.ShouldBe("Hello, World!");

            message.HtmlBody.ShouldBe("<p>Hello, World!</p>");

            renderer.Verify();
        }
        public async Task ContentType_determined_by_view_name_when_alternative_view_is_missing_Content_Type_header()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject
Views: Text, Html";
            var text  = @"
Hello, World!";
            var html  = @"
<p>Hello, World!</p>";

            var email    = new Email("Test");
            var renderer = new Mock <IEmailViewRender>();

            renderer.Setup(r => r.RenderAsync(email, "Test.Text")).Returns(Task.FromResult(text));
            renderer.Setup(r => r.RenderAsync(email, "Test.Html")).Returns(Task.FromResult(html));

            var parser  = new EmailParser(renderer.Object);
            var message = await parser.ParseAsync(input, email);

            message.TextBody.ShouldBe("text/plain");
            message.HtmlBody.MediaType.ShouldBe("text/html");

            renderer.Verify();
        }
        public async Task Alternative_views_are_added_to_MailMessage()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject
Views: Text, Html";
            var text  = @"Content-Type: text/plain

Hello, World!";
            var html  = @"Content-Type: text/html

<p>Hello, World!</p>";

            var email    = new Email("Test");
            var renderer = new Mock <IEmailViewRender>();

            renderer.Setup(r => r.RenderAsync(email, "Test.Text")).Returns(Task.FromResult(text));
            renderer.Setup(r => r.RenderAsync(email, "Test.Html")).Returns(Task.FromResult(html));

            var parser  = new EmailParser(renderer.Object);
            var message = await parser.ParseAsync(input, email);

            message.TextBody.ShouldBe("Hello, World!");

            message.HtmlBody.ShouldBe("<p>Hello, World!</p>");
            renderer.Verify();
        }
        public async Task Parse_creates_MailMessage_with_headers_and_body()
        {
            var input    = @"
To: [email protected]
From: [email protected]
CC: [email protected]
Bcc: [email protected]
Reply-To: [email protected]
Sender: [email protected]
Priority: high
X-Test: test
Subject: Test Subject

Hello, World!";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);

            using (var message = await parser.ParseAsync(input, new Email("Test")))
            {
                message.To[0].Address.ShouldBe("*****@*****.**");
                message.From.Address.ShouldBe("*****@*****.**");
                message.CC[0].Address.ShouldBe("*****@*****.**");
                message.Bcc[0].Address.ShouldBe("*****@*****.**");
                message.ReplyToList[0].Address.ShouldBe("*****@*****.**");
                message.Subject.ShouldBe("Test Subject");
                message.Sender.Address.ShouldBe("*****@*****.**");
                message.Priority.ShouldBe(MailPriority.High);
                message.Headers["X-Test"].ShouldBe("test");
                message.Body.ShouldBe("Hello, World!");
                message.IsBodyHtml.ShouldBeFalse();
            }
            renderer.Verify();
        }
        public async Task Parse_creates_MailMessage_with_headers_and_body()
        {
            var input    = @"
To: [email protected]
From: [email protected]
CC: [email protected]
Bcc: [email protected]
Reply-To: [email protected]
Sender: [email protected]
Priority: Urgent
X-Test: test
Subject: Test Subject

Hello, World!";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);
            var message  = await parser.ParseAsync(input, new Email("Test"));

            message.To[0].ToString().ShouldBe("*****@*****.**");
            message.From.ToString().ShouldBe("*****@*****.**");
            message.Cc[0].ToString().ShouldBe("*****@*****.**");
            message.Bcc[0].ToString().ShouldBe("*****@*****.**");
            message.ReplyTo[0].ToString().ShouldBe("*****@*****.**");
            message.Subject.ShouldBe("Test Subject");
            message.Sender.ToString().ShouldBe("*****@*****.**");
            message.Priority.ShouldBe(MessagePriority.Urgent);
            message.Headers["X-Test"].ShouldBe("test");
            message.TextBody.ShouldBe("Hello, World!");
            message.HtmlBody.ShouldBeNull();

            renderer.Verify();
        }
        public async Task Priority_header_can_be_set_automatically_from_MailPriorityEnum()
        {
            dynamic email = new Email("Test");

            email.Priority = MessagePriority.Urgent;
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var message = await parser.ParseAsync("body", (Email)email);

            message.Priority = MessagePriority.Urgent;
        }
        public async Task ReplyTo_header_can_be_set_automatically()
        {
            dynamic email = new Email("Test");

            email.ReplyTo = "*****@*****.**";
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var message = await parser.ParseAsync("body", (Email)email);

            message.ReplyTo[0].ToString().ShouldBe("*****@*****.**");
        }
        public async Task From_header_can_be_set_automatically_as_MailAddress()
        {
            dynamic email = new Email("Test");

            email.From = new MailboxAddress("*****@*****.**");
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var message = await parser.ParseAsync("body", (Email)email);

            message.From[0].ToString().ShouldBe("*****@*****.**");
        }
        public async Task Subject_header_can_be_set_automatically()
        {
            dynamic email = new Email("Test");

            email.Subject = "test";
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var message = await parser.ParseAsync("body", (Email)email);

            message.Subject.ShouldBe("test");
        }
        public async Task Priority_header_can_be_set_automatically()
        {
            dynamic email = new Email("Test");

            email.Priority = "high";
            var parser = new EmailParser(Mock.Of <IEmailViewRender>());

            using (var message = await parser.ParseAsync("body", (Email)email))
            {
                message.Priority = MailPriority.High;
            }
        }
        public async Task From_header_can_be_set_automatically()
        {
            dynamic email = new Email("Test");

            email.From = "*****@*****.**";
            var parser = new EmailParser(Mock.Of <IEmailViewRender>());

            using (var message = await parser.ParseAsync("body", (Email)email))
            {
                message.From.Address.ShouldBe("*****@*****.**");
            }
        }
        public async Task Email_address_can_include_display_name()
        {
            var input   = @"To: ""John Smith"" <*****@*****.**>
From: [email protected]
Subject: test

message";
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var email   = new Email("Test");
            var message = await parser.ParseAsync(input, email);

            message.To[0].ToString().ShouldBe("*****@*****.**");
            message.To[0].Name.ShouldBe("John Smith");
        }
        public async Task Can_detect_HTML_body()
        {
            var input    = @"
To: [email protected]
From: [email protected]
Subject: Test Subject

<p>Hello, World!</p>";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);
            var message  = await parser.ParseAsync(input, new Email("Test"));

            message.HtmlBody.ShouldBe("<p>Hello, World!</p>");
            message.TextBody.ShouldBeNull();
        }
        public async Task Parse_creates_email_addresses_with_display_name()
        {
            var input    = @"
To: John H Smith [email protected]
From: [email protected]
Subject: Test Subject

Hello, World!";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);
            var message  = await parser.ParseAsync(input, new Email("Test"));

            message.To[0].ToString().ShouldBe("*****@*****.**");
            message.To[0].ToString().ShouldBe("John H Smith");
            renderer.Verify();
        }
        public async Task Attachments_are_added_to_MailMessage()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject

Hello, World!";
            var email = new Email("Test");

            email.BodyBuilder.Attachments.Add("name", Array.Empty <byte>());
            var parser = new EmailParser(Mock.Of <IEmailViewRender>());

            var message = await parser.ParseAsync(input, email);

            message.Attachments.Count().ShouldBe(1);
        }
        public async Task Attachments_are_added_to_MailMessage()
        {
            var input = @"
To: [email protected]
From: [email protected]
Subject: Test Subject

Hello, World!";
            var email = new Email("Test");

            email.Attach(new Attachment(new MemoryStream(), "name"));
            var parser = new EmailParser(Mock.Of <IEmailViewRender>());

            var message = await parser.ParseAsync(input, email);

            message.Attachments.Count.ShouldBe(1);
        }
        public async Task Can_parse_empty_header_fields()
        {
            var input = @"To: [email protected]
From: [email protected]
CC: 
Bcc:
Reply-To:  
Subject: test

message";

            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var email   = new Email("Test");
            var message = await parser.ParseAsync(input, email);

            message.To.Count.ShouldBe(1);
            message.To[0].ToString().ShouldBe("*****@*****.**");
        }
        public async Task Do_not_implicitly_add_To_from_model_when_set_in_view()
        {
            var     input  = @"To: [email protected]
From: [email protected]
Subject: test

message";
            var     parser = new EmailParser(Mock.Of <IEmailViewRender>());
            dynamic email  = new Email("Test");

            email.To = "*****@*****.**";
            var message = await parser.ParseAsync(input, (Email)email);

            // Check for bug reported here: http://aboutcode.net/2010/11/17/going-postal-generating-email-with-aspnet-mvc-view-engines.html#comment-153486994
            // Should not add anything extra to the 'To' list.
            message.To.Count.ShouldBe(1);
            message.To[0].ToString().ShouldBe("*****@*****.**");
        }
        public async Task Can_parse_multiple_email_addresses_in_header()
        {
            var input    = @"
To: [email protected]
From: [email protected]
CC: [email protected], [email protected], [email protected]
Subject: Test Subject

Hello, World!";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);
            var message  = await parser.ParseAsync(input, new Email("Test"));

            message.Cc[0].ToString().ShouldBe("*****@*****.**");
            message.Cc[1].ToString().ShouldBe("*****@*****.**");
            message.Cc[2].ToString().ShouldBe("*****@*****.**");
            renderer.Verify();
        }
        public async Task Repeating_CC_adds_each_email_address_to_list()
        {
            var input    = @"
To: [email protected]
From: [email protected]
CC: [email protected]
CC: [email protected]
CC: [email protected]
Subject: Test Subject

Hello, World!";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);
            var message  = await parser.ParseAsync(input, new Email("Test"));

            message.Cc[0].ToString().ShouldBe("*****@*****.**");
            message.Cc[1].ToString().ShouldBe("*****@*****.**");
            message.Cc[2].ToString().ShouldBe("*****@*****.**");
        }
        public async Task Can_detect_HTML_body_with_leading_whitespace()
        {
            var input    = @"
To: [email protected]
From: [email protected]
Subject: Test Subject


<p>Hello, World!</p>";
            var renderer = new Mock <IEmailViewRender>();
            var parser   = new EmailParser(renderer.Object);

            using (var message = await parser.ParseAsync(input, new Email("Test")))
            {
                message.Body.ShouldBe("<p>Hello, World!</p>");
                message.IsBodyHtml.ShouldBeTrue();
            }
            renderer.Verify();
        }
        public async Task Can_parse_reply_to()
        {
            var input   = @"To: [email protected]
From: [email protected]
Reply-To: [email protected]
Subject: test

message";
            var parser  = new EmailParser(Mock.Of <IEmailViewRender>());
            var email   = new Email("Test");
            var message = await parser.ParseAsync(input, email);

            message.ReplyTo[0].ToString().ShouldBe("*****@*****.**");

            // Check for bug reported here: http://aboutcode.net/2010/11/17/going-postal-generating-email-with-aspnet-mvc-view-engines.html#comment-153486994
            // Should not add anything extra to the 'To' list.
            message.To.Count.ShouldBe(1);
            message.To[0].ToString().ShouldBe("*****@*****.**");
        }