Search code examples
c#asp.net-corehtml-emailrazorengine

Sending Newsletter using template .Net Core


I have being tasked with setting up a way where an admin user can easily pick articles to send out to a list of subscribers. The below image is what i'm trying to create but my problem is how get the view sent in an email. I have it created as a static template and as a razor template. I tried to use RazorEngine and Razorlight but can't figure them out.

enter image description here

Alot of the questions i have seen on this only adds one item to a email. e.g here and here. I am using MailKit to send emails but for the life of me i cant figure how to get an email body like above. My code looks like this

   var mimeMessage = new MimeMessage();
            mimeMessage.From.Add(new MailboxAddress("email", "[email protected]"));
            foreach (var item in contacts)
            {
                mimeMessage.To.Add(new MailboxAddress(ToAdressTitle, string.Join(",", item.Email.ToString())));
            }
            mimeMessage.Subject = Subject;
            var builder = new BodyBuilder();
            foreach (var item in post)
            {
                // Set the plain-text version of the message text
                builder.TextBody = item.Intro;
                 var ContentId = MimeUtils.GenerateMessageId();
                // Set the html version of the message text
                builder.HtmlBody = string.Format(item.Intro,@"<img src=""cid:{0}"">", item.FeaturedImage);
                // Now we just need to set the message body and we're done
                mimeMessage.Body = builder.ToMessageBody();
            }

Can i get my desired layout like this?


Solution

  • After a long time searching i cam across this answer which enabled my to get the answer i was looking for. First i add this code to my constructor

     public class PostsController : Controller
    {
            private ICompositeViewEngine _viewEngine;
    
           public PostsController(ICompositeViewEngine viewEngine)
           {
               _viewEngine = viewEngine;
           }
    
     } 
    

    To render the view as a string i use this function

           private async Task<string> RenderViewToString(string viewName, object model)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = ControllerContext.ActionDescriptor.ActionName;
    
            ViewData.Model = model;
    
            using (var writer = new StringWriter())
            {
                ViewEngineResult viewResult =
                    _viewEngine.FindView(ControllerContext, viewName, false);
    
                ViewContext viewContext = new ViewContext(
                    ControllerContext,
                    viewResult.View,
                    ViewData,
                    TempData,
                    writer,
                    new HtmlHelperOptions()
                );
    
                await viewResult.View.RenderAsync(viewContext);
    
                return writer.GetStringBuilder().ToString();
            }
        }
    

    and i call it like this var renderedView = await RenderViewToString("NameOfView", Model); The model is the data i want to display.

    var mimeMessage = new MimeMessage();
            mimeMessage.From.Add(new MailboxAddress("email", "[email protected]"));
            foreach (var item in contacts)
            {
                mimeMessage.To.Add(new MailboxAddress(ToAdressTitle, string.Join(",", item.Email.ToString())));
            }
            mimeMessage.Subject = Subject;
            var builder = new BodyBuilder();                                             
                // Set the html version of the message text
                builder.HtmlBody = renderedView;
                // Now we just need to set the message body and we're done
                mimeMessage.Body = builder.ToMessageBody();
    

    This enables me to get the desired view.