I need to send a lot of different forms to the mail. For example FeedBackForm
ContactsForm
. the only difference is that I create different mail.Subject
and mail.Body
.
I need to automate this action.
public class EmailService : IEmailService, ITransientService
{
private IConfiguration _configuration;
public EmailService(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task SendFormToAdminEmailAsync (FeedBackForm form)
{
var fromAddress = _configuration["EmailCredentials:Email"];
var fromPassword = _configuration["EmailCredentials:Password"];
var toAddress = new MailAddress("[email protected]");
var mail = new MailMessage(new MailAddress(fromAddress), toAddress);
mail.Subject = $"Need consultation {form.Name}";
mail.Body = $@"Name: {form.Name}
Email: {form.Email}
Phone: {form.PhoneNumber}
Link: {form.BotLink}";
using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
{
smtp.Credentials = new NetworkCredential("[email protected]", fromPassword);
smtp.EnableSsl = true;
await smtp.SendMailAsync(mail);
}
}
}
I tried this, in this method I accepted a generic type, and with the help of automapper I mapped what I needed, and specified the conditions in MappingConfig, but I don’t know if this is correct
The way I'd proceed would be to (if you don't already have it) create an interface for forms (FeedbackForm
, ContactForm
)
interface IFormData
{
// Don't know if you have some common ground on forms
// This may be an empty interface to mark types that can be worked with
// in later stages of this solution.
}
You can create an interface like:
interface IMailHydrator
{
void Hydrate(MailMessage message, IFormData form);
}
And than you create implementation like
class FeedBackFormHydrator : IMailHydrator
{
public void Hydrate(MailMessage message, IFormData form)
{
var cast = form as FeedBackForm;
if (cast == null)
{
throw new InvalidOperationException();
}
message.Subject = $"Need consultation {cast.Name}";
mail.Body = $@"Name: {cast.Name}
Email: {cast.Email}
Phone: {cast.PhoneNumber}
Link: {cast.BotLink}";
}
}
You register those hydrators in your DI as named/keyed registrations where the name/key is full name of form type. So something like:
this.AddSingleton<IMailHydrator, FeedBackFormHydrator>().Named(typeof(FeedBackForm).FullName);
You change your method to:
public async Task SendFormToAdminEmailAsync (IFormData form)
{
var fromAddress = _configuration["EmailCredentials:Email"];
var fromPassword = _configuration["EmailCredentials:Password"];
var toAddress = new MailAddress("[email protected]");
var mail = new MailMessage(new MailAddress(fromAddress), toAddress);
var hydrator = this.container.Resolve<IMailHydrator>(form.GetType().FullName);
hydrator.Hydrate(mail, form);
using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
{
smtp.Credentials = new NetworkCredential("[email protected]", fromPassword);
smtp.EnableSsl = true;
await smtp.SendMailAsync(mail);
}
}
There may be some tweaking depending on your DI container.