4
\$\begingroup\$

In my project I need to send emails. Emails will have different credentials and senders. I'm thinking about "abstract factory", but will it be good solution?

public abstract class Mail
    {
        public string Body { get; protected set; }
        public string Subject { get; private set; }
        public string EmailTo { get; private set; }

        protected Mail(string subject, string emailTo)
        {
            this.Subject = subject;
            this.EmailTo = emailTo;
        }

        protected abstract void BuildBody();
    }
public class AccountMail : Mail
    {
        private string _firstName;
        private string _lastName;
        private string _email;
        private string _siteDomain;
        public AccountMail(string subject, string emailTo, string firstName, string lastName, string siteDomain, string email): base(subject, emailTo)
        {
            _firstName = firstName;
            _lastName = lastName;
            _email = email;
            _siteDomain = siteDomain;
            BuildBody();            
        }

        protected override sealed void BuildBody()
        {   
             StringBuilder bodyBuilder = new StringBuilder();
             base.Body = bodyBuilder.ToString();
        }  

That is abstract Mail and concrete Mail. Do I really need abstract MailSender and concrete MailSender for each email? This is quick solution, because I needed this functionality right now. It's working like this:

public abstract class MailSender
    {
        public abstract void SendMail(string subject, string emailTo, string firstName, string lastName);
    } 
public class AccountMailSender : MailSender
    {    
        public override void SendMail(string subject, string emailTo, string firstName, string lastName)
        {
            AccountMail mail = new AccountMail(subject, emailTo, firstName, lastName, "");
            Task.Factory.StartNew(() =>
            {
                MailMessage mailMessage = new MailMessage(ConfigSettings.EmailFrom, mail.EmailTo, mail.Subject, mail.Body);
                mailMessage.IsBodyHtml = true;
                SmtpClient client = new SmtpClient(ConfigSettings.EmailServer, ConfigSettings.EmailPort);
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.UseDefaultCredentials = false;
                client.Credentials = new System.Net.NetworkCredential(ConfigSettings.EmailUser, ConfigSettings.EmailPassword);

                try
                {
                    client.Send(mailMessage);
                }
                catch
                {

                }
            });

        }        
    }

I know that it's bad and that I need to refactor, but I also need your advice.

\$\endgroup\$
  • \$\begingroup\$ What are your test cases? Without having specific requirements it's difficult to implement anything. In the real world there are messages and there are services that send them. You build a message and pass it to a sending service. So I don't understand AccountMail at all. \$\endgroup\$ – kevin cline Jan 14 '16 at 2:18
3
\$\begingroup\$

Abstract base classes are only useful if you're inheriting functionality. So, what you've done with Mail is good, because all of your inheritors get their properties "for free". In contrast, there's no sense in your MailSender class. Inheritors get no functionality, but are forced to adhere to the contract you've decided on. That's what Interfaces are for.

What I actually don't like is that it's only possible to send an email to exactly one person with your classes. Very soon, you'll wish that you could send an email to a bunch of people at once. EmailTo should mimic the class that you're wrapping up and return a collection.

You're also missing any concept of From in your Mail class. I would expect an email message to know who it's coming from.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your comment. I was thinking about interface and I've added it and then... remove. Don't know why. So, as far as I understand you, I'll do something like that SendMail(ISendMail sendMail)? Am I right? \$\endgroup\$ – Alex Gurskiy Jan 13 '16 at 13:19
  • \$\begingroup\$ Yes that's correct. \$\endgroup\$ – RubberDuck Jan 13 '16 at 14:38
  • 1
    \$\begingroup\$ It's also generaly a good practice to dispose objects that implement IDisposable. In this case the MailMessage and the SmtpClient. \$\endgroup\$ – t3chb0t Jan 14 '16 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.