Search code examples
c#.net-corehangfire

Sending emails using Hangfire on asp.net core 2.1


I have set up Hangfire correctly. I am able to run the following code from postman:

 [HttpPost("appointments/new")]
 public async Task<IActionResult> SendMailMinutely()
 {
     RecurringJob.AddOrUpdate(() => Console.WriteLine("Recurring!") Cron.Minutely);
     await Task.CompletedTask;
     return Ok();
 }

When I hit this API point, this works fine. What I would like to do is to run my email controller using the same code above. My modified SchedulersController code is:

[Route("/api/[controller]")]
public class SchedulersController : Controller
{
    private readonly MailsController mail;
    public SchedulersController(MailsController mail)
    {
        this.mail = mail;
    }

    [HttpPost("appointments/new")]
    public async Task<IActionResult> SendMailMinutely()
    {
        RecurringJob.AddOrUpdate(() => mail.SendMail(), Cron.Minutely);
        await Task.CompletedTask;
        return Ok();
    }
}

And My MailsController is:

[HttpPost("appointments/new")]
public async Task<IActionResult> SendMail()
 {
    var message = new MimeMessage ();
    message.From.Add (new MailboxAddress ("Test", "test@test.com"));
    message.To.Add (new MailboxAddress ("Testing", "test@test123.com"));
    message.Subject = "How you doin'?";

    message.Body = new TextPart ("plain") {
        Text = @"Hey Chandler,
                I just wanted to let you know that Monica and I were going to go play some paintball, you in?
                -- Joey"
    };

     using (var client = new SmtpClient ()) {
     client.ServerCertificateValidationCallback = (s,c,h,e) => true;

    client.Connect ("smtp.test.edu", 25, false);

    await client.SendAsync (message);
            client.Disconnect (true);
        }


        return Ok();
    }

The error message I receive is:

An unhandled exception has occurred while executing the request. System.InvalidOperationException: Unable to resolve service for type 'Restore.API.Controllers.MailsController' while attempting to activate 'Restore.API.Controllers.SchedulersController'

How can I use my MailsController so that I can schedule emails to send using Hangfire? Any help will be greatly appreciated.


Solution

  • The proper way to do this is to move your mail sending logic into a separate service.

    // We need an interface so we can test your code from unit tests without actually emailing people
    public interface IEmailService
    {
        async Task SendMail();
    }
    
    public EmailService : IEmailService
    {
        public async Task SendMail()
        {
            // Perform the email sending here
        }
    }
    
    [Route("/api/[controller]")]
    public class SchedulersController : Controller
    {
        [HttpPost("appointments/new")]
        public IActionResult SendMailMinutely()
        {
            RecurringJob.AddOrUpdate<IEmailService>(service => service.SendMail(), Cron.Minutely);
            return Ok();
        }
    }
    

    You'll need to make sure you've configured Hangfire for IoC as described in their documentation, so that it can resolve an IEmailService.