Question

I'm trying to send formatted emails in my MVC project. I had normal emails being sent perfectly with this method in my BaseService class, which all other services inherit from:

public void SendAsyncEmail(MailMessage message)
        {
            var client = new SmtpClient("smtp.gmail.com", 587)
            {
                Credentials = new NetworkCredential("cred", "password"),
                EnableSsl = true
            };
            client.SendCompleted += (s, e) =>
            {
                client.Dispose();
                message.Dispose();
            };
            ThreadPool.QueueUserWorkItem(o => client.SendAsync(message, Tuple.Create(client, message)));
        }

Now, instead of a text-only body, I need to transform every MailMessage.Body into an HTML page, ideally by using Razor templating. I found MVCMailer:

https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide

I installed it, scaffolded some templates, and added the following in my BaseService:

public virtual MvcMailMessage Welcome()
    {
        ViewBag.Name = "Test";
        return Populate(x =>
        {
            x.viewName = "Welcome";
            x.To.Add("sohan39@example.com");
        });
    }

But my service doesn't have an HTTPContext, so ViewBag isn't resolving (nor Populate).

What's the simplest way to get this working?

Was it helpful?

Solution

You're confusing Razor with MVC Views. Razor is just a templating language, it does not inherently have a concept of HttpContext, nor should it. The view receives HttpContext in a request cycle because it's a web request, but if you're using Razor outside of a request cycle, then you don't have that. The simplest solution, therefore, is to just not use ViewBag. Personally, I would say that advice should apply even if you do have HttpContext at your disposal, but that's beside the point.

I'm not overly familiar with MvcMailer; I use Postal myself. But, I believe the principal is basically the same. You pass a model or object into the mail rendering and then you have access to that data within your view. So, instead of using ViewBag, just pass the data directly. If MvcMailer doesn't have the ability to add arbitrary data into its view context (which I would find surprising), then try out Postal. With Postal, you create a subclass of Postal.Email with whatever data you like on it. It functions like a view model. Then you can strongly-type your view to this model and utilize it in your view with full intellisense support. If you need some info from the action, you just pass it into your model for the view: simple.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top