Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use MVCMailer without breaking my service layer?

I am looking into using MVcMailer to make nicer emails.

However one thing that I am unsure is how to organize the code. I currently have 2 projects. One for mvc and one for my repos and service layers.

my 2nd project has no knowledge of MVC and I would like to keep it that way.

I am thinking that my smtp code would go into a service layer or wrapper and then I would call it up from other service layers when I need to send emails out.

So where does the MVC mailer fit in? Do I generate the body in the controller then pass it to a serivce layer that passes it to my smtp class?

like image 420
chobo2 Avatar asked Mar 27 '11 23:03

chobo2


1 Answers

My solution was to build interfaces in the service layer that my services could then use to get a mail message, while the implementation that creates the message continues to reside in the web layer.

The interfaces are in the service layer:

public interface IMailMessage
{
    void Send();
    void SendAsync();
}

public interface IUserMailer
{
    IMailMessage Welcome(WelcomeMailModel model);
}

The implementations are then in the web (MVC) project:

public class MailMessage : MvcMailMessage, IMailMessage
{

}

public class UserMailer : MailerBase, IUserMailer
{
    public UserMailer()
    {
        MasterName = "_Layout";
    }

    public IMailMessage Welcome(WelcomeMailModel model)
    {
        var mailMessage = new MailMessage();
        mailMessage.SetRecipients(model.To);
        mailMessage.Subject = "Welcome";

        ViewData = new System.Web.Mvc.ViewDataDictionary(model);
        PopulateBody(mailMessage, "Welcome");

        return mailMessage;
    }
}

Finally in the service layer, the mailer interface is a dependency of the service:

public class UserCreationService : IUserCreationService
{
    private readonly IUserRepository _repository;
    private readonly IUserMailer _userMailer;

    public UserCreationService(IUserRepository repository, IUserMailer userMailer)
    {
        _repository = repository;
        _userMailer = userMailer;
    }

    public void CreateNewUser(string name, string email, string password)
    {
        // Create the user's account
        _repository.Add(new User { Name = name, Email = email, Password = password });
        _repository.SaveChanges();

        // Now send a welcome email to the user
        _userMailer.Welcome(new WelcomeMailModel { Name = name, To = email }).Send();
    }
}

When it's wired up in dependency injection, a Web.UserMailer object is used for the Services.IUserMail parameter to construct the UserCreationService object.

I've tried to keep the example simple so that it is easy to follow, but once you have a reference to an IMailMessage in the service layer, you can send it to your SMTP code instead of just calling Send() as I do. For your purposes, you may need to flesh out the IMailMessage interface more in order to access other parts of the MvcMailMessage class.

like image 195
Soldarnal Avatar answered Oct 15 '22 14:10

Soldarnal