2
votes

My project is hosted on Azure, and I would like to send an email every morning to users who have forgotten to complete certain tasks in my application.

I have my email built (sending using Postal). If I run the function itself, the emails send as expected.

I have configured the Azure scheduler to run an HTTPs action, get method, [https://www.example.com/Email/EmailReminder]. The scheduled job reporting as successful, but no emails are going out.

I haven't had to do this before, so I suspect I have a missing link between my function > scheduler job. I have searched for code samples on how to set this up, but I haven't found a solution yet. What is the scheduler expecting that I am not giving it?

public void EmailReminder()
{
     var remCheckOuts = // query code here                                
     into grouped
     select new Reminder
     {
          /// populate viewmodel 
     });    

    // send emails
    foreach (var i in remCheckOuts)
    {
                string Full = i.Full;
                string FirstName = i.FirstName;
                var CheckOutCt = i.CheckOutCt;                   

                dynamic email = new Email("emReminder");
                email.FromAdd = "[email protected]";
                email.To = "[email protected]";
                email.NPFirstName = NPFirstName;
                email.CheckOutCt = CheckOutCt;
                email.Send();
      } 
}
2
Have you properly configured the outbound SMTP port in your web.config as described here? Hint - Azure doesn't provide a pure SMTP server for you - you'll need a third-party like SendGrid, or you can spin up a VM if you want to roll your own.Matt Johnson-Pint
Yes - The emails send correctly if just access run the function above. However, the scheduler that I set up to access this page runs successfully, but nothing sends. I know I am missing something in my code that the scheduler is looking for. If it is creating a cron job from the above, I don't know how to do that....Daniela
How are you determining that the email did not go out? You said the job shows that it ran in the job history, and when you hit the link manually the email goes out. Perhaps there's an authentication issue? If so, perhaps these docs will help.Matt Johnson-Pint
I have myself setup as the recipient for testing, and the Azure site is showing the job running successfully. I will look into this authentication issue, perhaps that is the problem. For testing, I turned off any authentication requirements on my end, but perhaps I am missing something!Daniela
I was having an an authentication issue. My original script is sending now. Thank you.Daniela

2 Answers

6
votes

I think your best bet is a Webjob. I assume you already have a Web App, so if you add a Webjob that uses the Webjob SDK, you can create a function with the signature:

public class Functions
{
    public static void ProcessTimer([TimerTrigger("0 0 9 1/1 * ? *", RunOnStartup = true)]
    TimerInfo info)
    {
        var remCheckOuts = // query code here                                
     into grouped
     select new Reminder
     {
          /// populate viewmodel 
     });    

    // send emails
    foreach (var i in remCheckOuts)
    {
                string Full = i.Full;
                string FirstName = i.FirstName;
                var CheckOutCt = i.CheckOutCt;                   

                dynamic email = new Email("emReminder");
                email.FromAdd = "[email protected]";
                email.To = "[email protected]";
                email.NPFirstName = NPFirstName;
                email.CheckOutCt = CheckOutCt;
                email.Send();
      } 
    }
}

It uses the TimerTrigger to fire at a given time (defined by the CRON expression), it's much simpler than the HTTP POST approach (in which you would need to take the HTTP Timeout into consideration).

If you have trouble with CRON expressions, check CronMaker.

For email sending and following the WebJobs SDK samples, you could use the SendGrid extension paired with a Queue for decoupling, this way you can have multiple TimerTrigger functions (for example, Morning mails, Evening Mails for X purpose, Night emails for Y purpose, Monthly reports) and one function that sends all the mails:

public class MailNotification{
    public string From {get;set;}
    public string To {get;set;}
    public string Subject {get;set;}
    public string Body {get;set;}
}

public class Functions
{
    public static void MorningMail([TimerTrigger("0 0 9 1/1 * ? *", RunOnStartup = true)]
    TimerInfo info, [Queue]("mail") ICollector<MailNotification> mails)
    {
        var remCheckOuts = // query code here                                
     into grouped
     select new Reminder
     {
          /// populate viewmodel 
     });    

    // send emails
    foreach (var i in remCheckOuts)
    {
            mails.Add(new MailNotification(){
                To = "[email protected]",
                From = "[email protected]",
                Subject = "Whatever Subject you want",
                Body = "construct the body here"
            }); 

      } 
    }

    public static void EveningMail([TimerTrigger("0 0 18 1/1 * ? *", RunOnStartup = true)]
    TimerInfo info, [Queue]("mail") ICollector<MailNotification> mails)
    {
        var remCheckOuts = // query code here                                
     into grouped
     select new Reminder
     {
          /// populate viewmodel 
     });    

    // send emails
    foreach (var i in remCheckOuts)
    {
            mails.Add(new MailNotification(){
                To = "[email protected]",
                From = "[email protected]",
                Subject = "Whatever Subject you want",
                Body = "construct the body here"
            }); 

      } 
    }

    public static void SendMails([QueueTrigger(@"mails")] MailNotification order,
        [SendGrid(
            To = "{To}",
            From = "{From}",
            Subject = "{Subject}",
            Text = "{Body}")]
        SendGridMessage message)
    {
        ;
    }
}
1
votes

In regards to my question of why Azure Scheduler wasn't sending my emails, it was an issue with authentication that was solved in the Azure Portal.

Matias answer was also correct, and the direction I will move in in the future.