I want to be able to improve the way I am sending these emails because it is currently not testable (via Mocking) and it is hard to maintain.
Main Sender (I also need an Async method on there but I have left it out):
public class MailSender
{
protected bool SendEmail(MailAddress toAddress, string subject, string body)
{
var fromAddress = new MailAddress(WebConfigurationManager.AppSettings["FromEmail"]);
var fromPassword = WebConfigurationManager.AppSettings["FromPassword"];
var smtpHost = WebConfigurationManager.AppSettings["SmtpHost"];
var smtpPort = WebConfigurationManager.AppSettings["SmtpPort"];
try
{
int port;
Int32.TryParse(smtpPort, out port);
var smtp = new SmtpClient
{
Host = smtpHost,
Port = port,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Bcc = { new MailAddress(WebConfigurationManager.AppSettings["FromEmail"]) },
Subject = subject,
Body = body,
IsBodyHtml = true
})
{
smtp.Send(message);
}
return true;
}
catch (Exception)
{
return false;
}
}
}
The calling methods that build up the email content and subject:
public bool SendEmailToCustomer(OrderDto order)
{
var subject = "A subject relating to this method";
var body =
File.ReadAllText(HttpContext.Current.Server.MapPath("/EmailTemplates/OrderAnswer.html"));
var orderStatus = order.OrderStatus;
body = body.Replace("#orderref#", order.OrderID.ToString());
body = body.Replace("#orderstatus#", EnumHelper<OrderStatus>.GetDisplayValue(orderStatus));
body = body.Replace("#questiontext#", order.Question);
body = body.Replace("#answertext#", order.Answer);
body = body.Replace("#Description#", order.OrderDescription);
body = body.Replace("#BackgroundColour#", order.BackgroundColour.ToString());
body = body.Replace("#DisplayText#", order.DisplayText);
body = body.Replace("#Name#", order.Name);
body = body.Replace("#HouseNumber#", order.HouseNumber);
body = body.Replace("#FirstLineAddress#", order.FirstLineAddress);
body = body.Replace("#SecondLineAddress#", order.SecondLineAddress);
body = body.Replace("#ThirdLineAddress#", string.IsNullOrWhiteSpace(order.ThirdLineAddress) ? string.Empty : order.ThirdLineAddress);
body = body.Replace("#City#", order.City);
body = body.Replace("#PostCode#", order.PostCode);
body = body.Replace("#ContactNumber#", order.ContactNumber);
body = body.Replace("#email#", order.Email);
if (SendEmail(new MailAddress(WebConfigurationManager.AppSettings["FromEmail"]), subject, body))
{
return true;
}
return false;
}
Now I have a few 'callers' like the method above (6 currently but could easily be more).
I have attempted to wrap interfaces around the Sender class and the callers but I'm just not progressing anywhere.
Anyone got any tips to lead me into the right direction?
OrderDto:
public class OrderDto
{
public int OrderID { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public DateTime? OrderDate { get; set; }
public string HouseNumber { get; set; }
public string FirstLineAddress { get; set; }
public string SecondLineAddress { get; set; }
public string ThirdLineAddress { get; set; }
public string City { get; set; }
public string PostCode { get; set; }
public string ContactNumber { get; set; }
public string OrderDescription { get; set; }
public Colour BackgroundColour { get; set; }
public string DisplayText { get; set; }
public OrderStatus OrderStatus { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
public decimal? Price { get; set; }
public bool CustomerPaid { get; set; }
}
OrderStatus:
public enum OrderStatus
{
[Display(Name = "Unknown")]
Unknown = 0,
[Display(Name = "New")]
New = 1,
[Display(Name = "Need More Information")]
NeedMoreInformation = 2,
[Display(Name = "Order Accepted")]
OrderAccepted = 3,
[Display(Name = "In Progress")]
InProgress = 4,
[Display(Name = "Completed")]
Completed = 5,
[Display(Name = "Shipped")]
Shipped = 6
}