2

I am working on a project which is in ASP.NET Core.

In this project users have to confirm their mail before using their panel. I have written this part of code but there is a problem.

When I debug project and I get the confirmation link, copy it and paste it to browser, mail confirmation goes successful

but

when I send confirmation Url by email to user's mail and user clicks on it to redirect to my website confirmation fails.

I don't understand the issue because it's weird. I have hard coded some part to test it but nothing changed.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Register(RegisterViewModel model)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    if (model.ReferralCode != null)
                    {
                        var tmpUser = userManager.Users.FirstOrDefault(f => f.IntroductionCode == model.ReferralCode);
                        if(tmpUser == null)
                        {
                            return Json(new { result = "error", target = "register", message = $"No user found with this({model.ReferralCode}) referral code" });
                        }
                    }
                    var user = new ApplicationUser
                    {
                        Id = Guid.NewGuid().ToString(),
                        FullName = model.FullName,
                        Email = model.Email,
                        UserName = model.Email,
                        Balance = 0,
                        ReferralCode = model.ReferralCode,
                        IntroductionCode = new Random().RandomString(16),                        
                        IsVerified = false
                    };
                    var signUpResut = await userManager.CreateAsync(user, model.Password);
                    if (signUpResut == IdentityResult.Success)
                    {
                        var token = await userManager.GenerateEmailConfirmationTokenAsync(user);
                        var emailActivationUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, verifyToken = token });
                        new MailHelper(_logger).SendConfirmationEmail(user.FullName,user.Id, user.Email, token);
                        _logger.Log(LogLevel.Information, $"User {model.Email} Registered Successfully.");
                        return Json(new { result = "success", target = "register", message = "You have successfully registered. Check your mail to activate account." });
                    }                    
                    return Json(new { result = "error", target = "register", message = "Something went wrong in server side." });
                }
                return Json(new { result = "error", target = "register", message = "Something went wrong in server side." });
            }
            catch (Exception exc)
            {
                _logger.Log(LogLevel.Critical, $"Failed Registeration : {exc.Message}");
                return Json(new { result = "error", target = "register", message = "Something went wrong in server side." });
            }
        }

here is mail sender code

public bool SendConfirmationEmail(string name, string id, string email, string confirmationToken)
        {
            try
            {
                var mailMessage = new MimeMessage();
                mailMessage.From.Add(new MailboxAddress("***", "***"));
                mailMessage.To.Add(new MailboxAddress(name, email));
                mailMessage.Subject = "subject";
                var configurationUrl = $"https://localhost:44323/Account/ConfirmEmail?userId={id}&verifyToken={confirmationToken}";
                mailMessage.Body = MailBodyMaker($"<a href=\"{configurationUrl}\">Click here</a>", "Click here");

                using (var smtpClient = new SmtpClient())
                {
                    smtpClient.Connect("smtp.gmail.com", 465, true);
                    smtpClient.Authenticate("***", "****");
                    smtpClient.Send(mailMessage);
                    smtpClient.Disconnect(true);
                }
                return true;
            }
            catch(Exception exc)
            {
                _logger.Log(LogLevel.Critical, $"Email sending finished with exception ${exc.Message}");
                return false;
            }
        }

The confirmation link looks like below in debug mode

https://localhost:44323/Account/ConfirmEmail?userId=9bb1a751-813b-48d2-a44c-74fd32a2db9a&verifyToken=CfDJ8A%2FFQtr0XBRFinX98FbsJc5LpPXqjstNllYq%2Br7kr6BHFfA7lBINCCoviE0nqJ6EQc1sJ7RW87jNsaR3fEkEbKoOhemFE62GCrTfn9gEizWV99lZhMrLxJPzGm1u6j3x%2FARoBqVuCVpp34ki0OZM%2BEJi31hNbwyowZ4YwoOnKjMqAOdu2bVG46WfXZBRG9AiOaFNTy326ijQmaTVDNSBl8lQR4gBWkmmRAdkcdFfOasLHD24wyUjmqgkOM2yTJ19Dw%3D%3D

and it looks like below in email body

https://localhost:44323/Account/ConfirmEmail?userId=9bb1a751-813b-48d2-a44c-74fd32a2db9a&verifyToken=CfDJ8A/FQtr0XBRFinX98FbsJc5LpPXqjstNllYq+r7kr6BHFfA7lBINCCoviE0nqJ6EQc1sJ7RW87jNsaR3fEkEbKoOhemFE62GCrTfn9gEizWV99lZhMrLxJPzGm1u6j3x/ARoBqVuCVpp34ki0OZM+EJi31hNbwyowZ4YwoOnKjMqAOdu2bVG46WfXZBRG9AiOaFNTy326ijQmaTVDNSBl8lQR4gBWkmmRAdkcdFfOasLHD24wyUjmqgkOM2yTJ19Dw==

6
  • "confirmation fails" - how? Commented Oct 5, 2021 at 8:44
  • May be the link is somehow malformed in the email. Have you confirmed that both links (for the same confirmation) are identical? Commented Oct 5, 2021 at 8:45
  • when I use usermanager.ConfirmEmailAsync it fails Commented Oct 5, 2021 at 8:45
  • @phuzi I have test it and I have doubt about it. When I see url in debug mode it containes %3d char code but in email it converted to = Commented Oct 5, 2021 at 8:47
  • Could you edit your question to show us both links? Commented Oct 5, 2021 at 8:48

1 Answer 1

4

Certain characters must be escaped in url, and your verification token contains such characters, however you put it as is into your url here:

var configurationUrl = $"https://localhost:44323/Account/ConfirmEmail?userId={id}&verifyToken={confirmationToken}";

To escape them - use Uri.EscapeDataString:

var configurationUrl = $"https://localhost:44323/Account/ConfirmEmail?userId={Uri.EscapeDataString(id)}&verifyToken={Uri.EscapeDataString(confirmationToken)}";
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.