0

Hi I created an app in asp.net which requires user authentication. I've activated the 'Email confirmation' option. This worked fine with a local db, but once on azure, doesn't work. the code for the email confirmation is as follows:

public Task SendAsync(IdentityMessage message)
        {
            
            return Task.Factory.StartNew(() =>
            {
            sendMail(message);
        });

    }

    
    void sendMail(IdentityMessage message)
    {
        #region formatter
       
        string html =  message.Body;
      

      
        #endregion

        MailMessage msg = new MailMessage();
        msg.From = new MailAddress(ConfigurationManager.AppSettings["Email"].ToString());
        msg.To.Add(new MailAddress(message.Destination));
        msg.Subject = message.Subject;
      
        msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));

        SmtpClient smtpClient = new SmtpClient("smtp-mail.outlook.com", Convert.ToInt32(587));
        System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["Email"].ToString(), ConfigurationManager.AppSettings["Password"].ToString());
        smtpClient.Credentials = credentials;
        smtpClient.EnableSsl = true;
        smtpClient.Send(msg);
    }

}

I tried sendgrid, but it didn't seem to work, so I used outlook.

This is the code for the Register part :

   public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {                   
            string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account");                 

                ViewBag.Message = "Check your email and confirm your account. You must confirm your email " + "before you can log in.";

                return View("Info");

                              }
            else 
            { return View("Error"); }

            AddErrors(result);
        }

and finally the code for the last part

private async Task<string> SendEmailConfirmationTokenAsync(string userID, string subject)
        {
            string code = await UserManager.GenerateEmailConfirmationTokenAsync(userID);
            var callbackUrl = Url.Action("ConfirmEmail", "Account",
               new { userId = userID, code = code }, protocol: Request.Url.Scheme);
            await UserManager.SendEmailAsync(userID, subject,
               "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

            return callbackUrl;
        }
MFogger
  • 1
  • 1
  • Oh, the connection string is fine as the registered data is inserted into the Database, but the confirmation token remains false as there is no email sent to confirm it. if I write to it from my local app, it works fine too. – MFogger Jul 14 '20 at 20:39
  • Presuming UserManager.SendEmailAsync calls SendAsync can you include some of that code? This is where I would use app insights to trigger a custom event to write to the log to track there in the process it is getting. If the email is not being sent then probably either there is an error, its delayed, or the code is being skipped. – Ron Jul 14 '20 at 20:53
  • @Ron, I think that seems to be the problem - the UserManager.SendEmailAsync doesn't call the SendAsync() method. But that is the way MS have it in their documentation. Not sure if I am missing something. I have followed the microsoft documentation: [link]https://learn.microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity#email-confirmation but I get an error on this bit :- // Create a Web transport for sending email. var transportWeb = new Web(credentials); Any help is appreciated. Thank you – MFogger Jul 18 '20 at 17:16
  • is the email for the user valid. sorry I have to ask because I want to make sure its not like there username@on.microsoft.com or something like that. That method will fail silently if the email is not valid or is not confirmed. You might try var result = await UserManager.SendEmailAsync(userID, subject, "Please confirm your account by clicking here"); Then you could test if it actually succeded or not. Might even have maybe error message in it. – Ron Jul 18 '20 at 21:24
  • No worries, yes it is valid. it is one of my accounts. It all worked perfectly when I was testing it on my local system, but doesn't now that I have published it on azure. I can still run the app locally and it works even though the db is on azure - I changed the connection string. I went back to trying to set up the sendgrid method, but still no joy. I don't understand how the UserManager.SendMailAsync() and SendAsync() methods are linked. Thanks for your help. – MFogger Jul 19 '20 at 15:03
  • Have you tried setting the smtp info in the web.config. It is possible that something with your local setup allows that to work, but not in Azure. https://stackoverflow.com/questions/19233108/how-to-configure-smtp-settings-in-web-config/42056991 I would also still try the var result = await UserManager.SendEmailAsync(userID, subject, "Please confirm your account by clicking here"); The result looks to contain some information that might be helpful. We are currently presuming its having an issue sending what if its not finding the userid. – Ron Jul 19 '20 at 16:38
  • @Ron Finally got iy working . will post the code below: – MFogger Jul 25 '20 at 11:42

2 Answers2

0

When your code runs in Azure it may not have access to Outlook, this could explain why emails are not being sent.

SendGrid is a recommended method for sending emails from the Azure function, web job, or any app. There is a good explaination of how to use SendGrid here: https://blog.mailtrap.io/azure-send-email/#What_do_I_need_to_send_emails_from_Azure

Shiraz Bhaiji
  • 64,065
  • 34
  • 143
  • 252
0

Finally got it working. Actually it worked previously when I tried it, but the confirmation went to my spam folder... Doh.

    public async Task SendAsync(IdentityMessage message)
    {
        // Plug in your email service here to send an email.

         var apiKey = ConfigurationManager.AppSettings["SendGridAPI"];
                   var client = new SendGridClient(apiKey);
        var from = new EmailAddress("your email address", "your name");
        var subject = message.Subject;
        var to = new EmailAddress(message.Destination);
        var plainTextContent = message.Body;
        var htmlContent = message.Body;
        var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
        var response = await client.SendEmailAsync(msg);


    }
MFogger
  • 1
  • 1