C# Method Chaining for Email I have been looking into stuff like method chaining, Cascade-Lambda pattern etc.

I have created a class which seems to work fine. However, I just wanted to confirm if this is the best way and the right way to implement this.

For the cascade lambda pattern I was unable to use Action action as a parameter to the Send() method. I couldn't figure out how would I use it.

Any suggestions are welcome.

Here is the code:

public class MailManager
{
    MailMessage _mail { get; set; }
    SmtpClient _smtp { get; set; }

    public MailManager()
    {
        _mail = new MailMessage();
        _smtp = new SmtpClient();
    }

    public MailManager To(string address)
    {
        _mail.From = new MailAddress(address);
        return this;
    }

    public MailManager From(string address)
    {
        _mail.To.Add(new MailAddress(address));
        return this;
    }

    public MailManager Subject(string subject)
    {
        _mail.Subject = subject;
        return this;
    }

    public MailManager Body(string body)
    {
        _mail.Body = body;
        return this;
    }

    public MailManager IsBodyHtml(bool isBodyHtml = true)
    {
        _mail.IsBodyHtml = isBodyHtml;
        return this;
    }

    public MailManager AlternateViews(AlternateView alternateView)
    {
        _mail.AlternateViews.Add(alternateView);
        return this;
    }

    public MailManager Host(string host)
    {
        _smtp.Host = host; return this;
    }

    public MailManager Port(int port)
    {
        _smtp.Port = port; return this;
    }

    public MailManager Credentials(NetworkCredential credentials)
    {
        _smtp.Credentials = credentials; return this;
    }

    public MailManager EnableSsl(bool enableSsl = true)
    {
        _smtp.EnableSsl = enableSsl; return this;
    }        

    public void Send()
    {
        using (_smtp)
        {
            _smtp.Send(_mail);
        }
    }
}


This is how I use it:

mailManager.From(_emailSettings.Email)
           .To(item.Email)
           .Subject(string.Format(_emailSettings.Subject, item.Name)).AlternateViews(htmlView)
           .Body(body).IsBodyHtml()
           .Host(_emailSettings.Domain)
           .Port(_emailSettings.Port)
           .Credentials(new NetworkCredential(_emailSettings.Email, _emailSettings.Password))
           .EnableSsl()
           .Send();
As far as method chaining goes, this is neatly implemented.



You've swapped To and From, the method names are inverted. I assume that's just a typo.

public MailManager To(string address)
{
    _mail.From = new MailAddress(address);
    return this;
}

public MailManager From(string address)
{
    _mail.To.Add(new MailAddress(address));
    return this;
}




As it currently stands, I don't think method chaining is really needed here. Every method operates as a basic property setter, which can be handled by using public properties.

This is a matter of preference; but in C# I'd be more inclined to use public properties as opposed to methods.
In the past, all we had was fields and methods. When the tiniest amount of logic was needed to set a field value, we had to rely on methods. Properties were added as a compromise: they are used for setting field values, but you're able to add some minor logic (within reason).

Simple string values can be handled by basic properties:

public string Subject
{
    get { return _mail.Subject; }
    set { _mail.Subject = value; }
}


Note: This example directly sets the value of _mail.Subject. Personally, I'd prefer to not use _mail until the Send() was triggered (and store the values in properties until then), but that may be too subjective for a review.

Your current To() method somewhat conceals the fact that you can add more than one recipient. It doesn't suggest that you're adding to a list. Using a property, this is slightly easier to understand:

public List&lt;string&gt; To { get; set; }


You can cast these into the appropriate MailAddress object and add it to _mail inside the Send() method:

_mail.To.AddRange(this.To.Select(s =&gt; new MailAddress(s));


An example of how you'd use a property-based approach:

var mailManager = new MailManager() {
    From = _emailSettings.Email,
    To = new List&lt;string&gt;() { item.Email },
    Subject = string.Format(_emailSettings.Subject, item.Name),
    Body = body,
    IsBodyHtml = true,
    Host = _emailSettings.Domain,
    Port = _emailSettings.Port,
    Credentials =new NetworkCredential(_emailSettings.Email, _emailSettings.Password),
    EnableSsl = true
};

mailManager.Send(); 


Note: You can also inline everything, i.e; (new MailManager() { ... }).Send();.

Note: I set the property values in the property initializer. You're not required to do so, you can also just store the MailManager in a variable and set its properties when you want to at a later stage (but obviously before calling Send()).


  Should you avoid method chaining?
  No. You wanted to use it, and you used it in a good way. I'm just trying to offer you an alternative which requires less code to achieve the same result.  
  
  If you were implementing method chaining in a class where there is a lot of business logic involved when a method gets calls, then method chaining becomes the preferred approach.
  For the current MailManager class, I find that it doesn't have enough business logic to warrant method chaining just yet. But it's not particularly wrong to do so, just a bit more cumbersome (in my opinion).




Some minor nitpicks:


If you're going to use method chaining to simplify the syntax, it seems consistent to change the Credentials method to take two strings (email,password) instead of a NetworkCredential, or at least create two overloaded methods to allow for either option. Credentials(_emailSettings.Email, _emailSettings.Password) is nicer to read than Credentials(new NetworkCredential(_emailSettings.Email, _emailSettings.Password))
IsBodyHtml() Based on its name, this should be a method that returns a boolean, instead of setting a boolean. A better name would be SetBodyHtml()
AlternateViews(AlternateView alternateView) should really be called AddAlternateView(AlternateView alternateView)
Similarly, To really should be called AddRecipient, since calling the method adds a second value instead of overwriting the first value.


I chose AddRecipient instead of AddTo to avoid semantical confusion between "Add a To-recipient" and "Add this to that".

I would personally change EnableSsl(bool enableSsl = true), though I can see argument for why you used your version.


UseSsl(bool useSsl = true)
EnableSsl() and DisableSsl()