locked
How to activate Confirm email in Asp.Net identity RRS feed

  • Question

  • User-218090889 posted

    I want to activate confirm email and reset password in my asp.net Identity vs2015 template. I did the following

    !) I put the below code on App_Start/IdentityConfig.cs

     public class SMTP : IIdentityMessageService
        {
            public Task SendAsync(IdentityMessage message)
            {
                // Plug in your email service here to send an email.
                SmtpClient client = new SmtpClient("smtp.gmail.com");
                client.SendCompleted += (s, e) =>
                {
                    client.Dispose();
                };
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Credentials = new NetworkCredential("mymail@gmail.com", "myPassword");
    
                MailMessage mailMessage = new MailMessage("mymail@gmail.com", message.Destination);
                mailMessage.Subject = message.Subject;
                mailMessage.IsBodyHtml = true;
                mailMessage.Body = message.Body;
                return client.SendMailAsync(mailMessage);
                
            }
        }

    2) I un-commented the highlighted part of the code in Register.aspx.cs

     protected void CreateUser_Click(object sender, EventArgs e)
            {
               
                    
                        var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); // Normal ASP Register Code
                        var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();
                        var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };
                        IdentityResult result = manager.Create(user, Password.Text);
                        if (result.Succeeded)
                        {
                            // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                            string code = manager.GenerateEmailConfirmationToken(user.Id);
                            tring callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
                            manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
    
                            signInManager.SignIn(user, isPersistent: false, rememberBrowser: false);
    
                            
                            IdentityHelper.RedirectToReturnUrl("/pageA.aspx", Response); 
    
    
                        }
                        else
                        {
                            ErrorMessage.Text = result.Errors.FirstOrDefault();
                        }
                    }
                }

    3) I un-commented the highlighted part of the below code in Account/Forgot.aspx.cs

     protected void Forgot(object sender, EventArgs e)
            {
                if (IsValid)
                {
                    // Validate the user's email address
                    var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
                    ApplicationUser user = manager.FindByName(Email.Text);
                    if (user == null || !manager.IsEmailConfirmed(user.Id))
                    {
                        FailureText.Text = "The user either does not exist or is not confirmed.";
                        ErrorMessage.Visible = true;
                        return;
                    }
                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                    // Send email with the code and the redirect to reset password page
                    string code = manager.GeneratePasswordResetToken(user.Id);
                    string callbackUrl = IdentityHelper.GetResetPasswordRedirectUrl(code, Request);
                    manager.SendEmail(user.Id, "Reset Password", "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>.");
                    loginForm.Visible = false;
                    DisplayEmail.Visible = true;
                }
            }
        }

    From what I did I tried to run the code, I did registration it did not send confirmation email to user, and there was no error message.

    Please how may I resolve this.

    Monday, March 4, 2019 2:47 PM

Answers

  • User-893317190 posted

    Hi Enzyme,

    Although I don't know whether there is a better way to execute async method in webform, I found a way to execute the task.

    Below is my code.

     public partial class SendMailUsingIdentityMessageService : System.Web.UI.Page
        {
    
            IdentityMessage message;
            protected  void Page_Load(object sender, EventArgs e)
            {
    
                 // because the method couldn't pass parameter , so define it as a field
                message = new IdentityMessage() { Destination = "v-acxu@hotmail.com", Subject = "hello this is a test mail level two", Body = "please activate your email thank you" };
                RegisterAsyncTask(new PageAsyncTask(SendEmail));//register the method, and then it will execute
    
             
            }
    // define an async method to send email async private async Task SendEmail() { EmailService emailService = new EmailService(); await emailService.SendAsync(this.message); } }

    Please don't forget to change your page to async.

    <%@ Page  Async="true" Language="C#" AutoEventWireup="true" CodeBehind="SendMailUsingIdentityMessageService.aspx.cs" Inherits="WebFormCases2.csharpDemo.SendMailUsingIdentityMessageService" %>

    And my email service.

    public class EmailService : IIdentityMessageService
        {
            public  async Task SendAsync(IdentityMessage message)
            {
                // other code to set the email message
                using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                {
    
                    smtp.EnableSsl = true;
                    smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                    //to authenticate we set the username and password properites on the SmtpClient
                    smtp.Credentials = new NetworkCredential();
                 await smtp.SendMailAsync(mail);
                }
                
                
            }
        }

    For more information , please refer to

    https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

    Best regards,

    Ackerly Xu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 6, 2019 1:43 AM

All replies

  • User475983607 posted

    Try running your code through the Visual Studio debugger.  My best guess is the gmail configuration is incorrect as you are missing a the port and SSL is not enabled.  See gmail support for proper configuration.  Also visit your gmail account.  Often you'll see a security alert that needs your attention.

    https://stackoverflow.com/questions/704636/sending-email-through-gmail-smtp-server-with-c-sharp

    Monday, March 4, 2019 3:52 PM
  • User-218090889 posted

    mgebhard

    Try running your code through the Visual Studio debugger.  My best guess is the gmail configuration is incorrect as you are missing a the port and SSL is not enabled. 

    I tried fixing the port and enabled SSL,as below but it still can't send mail and no error message. what other method can I resolve this?

     // Plug in your email service here to send an email.
                SmtpClient client = new SmtpClient("smtp.gmail.com", Convert.ToInt32(587));
                client.SendCompleted += (s, e) =>
                {
                    client.Dispose();
                };
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Credentials = new NetworkCredential("mymail@gmail.com", "myPassword");
                client.EnableSsl = true;



    Monday, March 4, 2019 6:55 PM
  • User475983607 posted

    I tried fixing the port and enabled SSL,as below but it still can't send mail and no error message. what other method can I resolve this?

     // Plug in your email service here to send an email.
                SmtpClient client = new SmtpClient("smtp.gmail.com", Convert.ToInt32(587));
                client.SendCompleted += (s, e) =>
                {
                    client.Dispose();
                };
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.Credentials = new NetworkCredential("mymail@gmail.com", "myPassword");
                client.EnableSsl = true;

    This is a gmail support question. 

    Have you tried logging into your gmail account to check for any security messages form gmail?  Have you tried running your code through the Visual Studio debugger?  Is your code wrapped in an empty try...catch essentially hiding errors?

    I recommend creating a console app to send test SMTP messages.   Once get the test console working, then incorporate the working code into your web application.

    Monday, March 4, 2019 7:18 PM
  • User-218090889 posted

    I have tried most of your suggestions, below is my modification

    1) web,config file

     <system.net>
        <mailSettings>
          <smtp from="mymail@gmai.com">
            <network host="smtp.gmail.com" password="mypassword" port="587" userName="myusername"  enableSsl="true"/>
          </smtp>
        </mailSettings>
      </system.net>

    2) the App_Start/IdentityConfig

    public class EmailService : IIdentityMessageService
        {
            public Task SendAsync(IdentityMessage message)
            {
                
                SmtpClient client = new SmtpClient();
                client.SendCompleted += (s, e) =>
                {
                    client.Dispose();
                };
                
    
                return client.SendMailAsync("email from web.config",
                                            message.Destination,
                                            message.Subject,
                                            message.Body);
    
            }
        }

    with this it still not sent the mail, but I suspect I am not referencing the sendMail in Registration page and that of IdentityConfig properly, Can you help in that area?

    Below is my Registration code

    protected void CreateUser_Click(object sender, EventArgs e)
            {
               
                    
                        var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>(); // Normal ASP Register Code
                        var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();
                        var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text };
                        IdentityResult result = manager.Create(user, Password.Text);
                        if (result.Succeeded)
                        {
                            // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
                            string code = manager.GenerateEmailConfirmationToken(user.Id);
                            tring callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request);
                            manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>.");
    
                            signInManager.SignIn(user, isPersistent: false, rememberBrowser: false);
    
                            
                            IdentityHelper.RedirectToReturnUrl("/pageA.aspx", Response); 
    
    
                        }
                        else
                        {
                            ErrorMessage.Text = result.Errors.FirstOrDefault();
                        }
                    }
                }

    Tuesday, March 5, 2019 3:55 AM
  • User-893317190 posted

    Hi Enzyme,

    Have you set your method to async?

    Below is my method.

     public class EmailService : IIdentityMessageService
        {
            public async Task SendAsync(IdentityMessage message)
            {
                // Plug in your email service here to send an email.
    
                MailMessage mail = new MailMessage();
                //set the addresses
                mail.From = new MailAddress("v-acxu@hotmail.com");
                mail.To.Add(message.Destination);
                //set the content
                mail.Subject = message.Subject;
                mail.Body = message.Body;
                //send the message
                SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587);
                smtp.SendCompleted += (s, e) => {
                    smtp.Dispose();
                };
    
                smtp.EnableSsl = true;
                smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                //to authenticate we set the username and password properites on the SmtpClient
                smtp.Credentials = new NetworkCredential(...);
                await smtp.SendMailAsync(mail);
             
            }
        }

    My test

      public async Task<ActionResult> About()
            {
                EmailService emailService = new EmailService();
               
               await emailService.SendAsync(new IdentityMessage() { Destination = "v-acxu@hotmail.com", Subject = "this is my gmail", Body = "please activate your email" });
                
                ViewBag.Message = "Your application description page.";
                
                return View();
            }

    Best regards,

    Ackerly Xu

    Tuesday, March 5, 2019 7:50 AM
  • User-218090889 posted

     public async Task<ActionResult> About()
            {
                EmailService emailService = new EmailService();
               
               await emailService.SendAsync(new IdentityMessage() { Destination = "v-acxu@hotmail.com", Subject = "this is my gmail", Body = "please activate your email" });
                
                ViewBag.Message = "Your application description page.";
                
                return View();
            }

    You Test code is for MVC, but My code is web form.
    I want to reference the async  method as yours using my Registration code in my above post to affect the highlighted part of my code.

    Tuesday, March 5, 2019 12:20 PM
  • User475983607 posted

    For the second time...  Build a console application to test gmail.  This will allow you to test the SMTP configuration separately.   Once you get gmail working you can integrate the code into your application.  

    Tuesday, March 5, 2019 12:32 PM
  • User-218090889 posted

    Build a console application to test gmail.

    I ran a console application, I wan prompted to do some configuration setting before the worked.
    the below code is what I used

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net.Mail;
    using System.Net;
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Mail To");
            MailAddress to = new MailAddress(Console.ReadLine());
    
            Console.WriteLine("Mail From");
            MailAddress from = new MailAddress(Console.ReadLine());
    
            MailMessage mail = new MailMessage(from, to);
    
            Console.WriteLine("Subject");
            mail.Subject = Console.ReadLine();
    
            Console.WriteLine("Your Message");
            mail.Body = Console.ReadLine();
    
            SmtpClient smtp = new SmtpClient();
            smtp.Host = "smtp.gmail.com";
            smtp.Port = 587;
    
            smtp.Credentials = new NetworkCredential(
                "mymail@gmail.com", "mypassword");
            smtp.EnableSsl = true;
            Console.WriteLine("Sending email...");
            smtp.Send(mail);
        }
    }

    but the issue I am having is to be able to make the mail send from the Registration page as in my post above

    Tuesday, March 5, 2019 4:23 PM
  • User475983607 posted

    Enzyme

    mgebhard

    Build a console application to test gmail.

    I ran a console application, I wan prompted to do some configuration setting before the worked.
    the below code is what I used

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Net.Mail;
    using System.Net;
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Mail To");
            MailAddress to = new MailAddress(Console.ReadLine());
    
            Console.WriteLine("Mail From");
            MailAddress from = new MailAddress(Console.ReadLine());
    
            MailMessage mail = new MailMessage(from, to);
    
            Console.WriteLine("Subject");
            mail.Subject = Console.ReadLine();
    
            Console.WriteLine("Your Message");
            mail.Body = Console.ReadLine();
    
            SmtpClient smtp = new SmtpClient();
            smtp.Host = "smtp.gmail.com";
            smtp.Port = 587;
    
            smtp.Credentials = new NetworkCredential(
                "mymail@gmail.com", "mypassword");
            smtp.EnableSsl = true;
            Console.WriteLine("Sending email...");
            smtp.Send(mail);
        }
    }

    but the issue I am having is to be able to make the mail send from the Registration page as in my post above

    Confused... you confirmed the console application, shown above, successfully sends email?  You also went through the gmail security configuration to allow SMTP from your machine?

    If so, all you have to do is copy the known working code from the console application to the EmailService class.

    public class EmailService : IIdentityMessageService
    {

    Please see the docs.

    https://docs.microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

    The App_Start\IdentityConfig.cs file contains the ApplicationUserManagerEmailService and SmsService classes. The EmailService and SmsService classes each implement the IIdentityMessageService interface, so you have common methods in each class to configure email and SMS. 

            public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
            {
                var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
    
                //Custom password hasher
                //manager.PasswordHasher = new CustomPasswordHasher();
    
                // Configure validation logic for usernames
                manager.UserValidator = new UserValidator<ApplicationUser>(manager)
                {
                    AllowOnlyAlphanumericUserNames = false,
                    RequireUniqueEmail = true
                };
    
                // Configure validation logic for passwords
                manager.PasswordValidator = new PasswordValidator
                {
                    RequiredLength = 6,
                    RequireNonLetterOrDigit = true,
                    RequireDigit = true,
                    RequireLowercase = true,
                    RequireUppercase = true,
                };
    
                // Configure user lockout defaults
                manager.UserLockoutEnabledByDefault = true;
                manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
                manager.MaxFailedAccessAttemptsBeforeLockout = 5;
    
                // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
                // You can write your own provider and plug it in here.
                manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
                {
                    MessageFormat = "Your security code is {0}"
                });
                manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
                {
                    Subject = "Security Code",
                    BodyFormat = "Your security code is {0}"
                });
                manager.EmailService = new EmailService();
                manager.SmsService = new SmsService();
                var dataProtectionProvider = options.DataProtectionProvider;
                if (dataProtectionProvider != null)
                {
                    manager.UserTokenProvider = 
                        new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
                }
                return manager;
            }
        }

    If you are still having issue, set a breakpoint and debug.  

    Tuesday, March 5, 2019 5:08 PM
  • User-893317190 posted

    Hi Enzyme,

    Although I don't know whether there is a better way to execute async method in webform, I found a way to execute the task.

    Below is my code.

     public partial class SendMailUsingIdentityMessageService : System.Web.UI.Page
        {
    
            IdentityMessage message;
            protected  void Page_Load(object sender, EventArgs e)
            {
    
                 // because the method couldn't pass parameter , so define it as a field
                message = new IdentityMessage() { Destination = "v-acxu@hotmail.com", Subject = "hello this is a test mail level two", Body = "please activate your email thank you" };
                RegisterAsyncTask(new PageAsyncTask(SendEmail));//register the method, and then it will execute
    
             
            }
    // define an async method to send email async private async Task SendEmail() { EmailService emailService = new EmailService(); await emailService.SendAsync(this.message); } }

    Please don't forget to change your page to async.

    <%@ Page  Async="true" Language="C#" AutoEventWireup="true" CodeBehind="SendMailUsingIdentityMessageService.aspx.cs" Inherits="WebFormCases2.csharpDemo.SendMailUsingIdentityMessageService" %>

    And my email service.

    public class EmailService : IIdentityMessageService
        {
            public  async Task SendAsync(IdentityMessage message)
            {
                // other code to set the email message
                using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                {
    
                    smtp.EnableSsl = true;
                    smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                    //to authenticate we set the username and password properites on the SmtpClient
                    smtp.Credentials = new NetworkCredential();
                 await smtp.SendMailAsync(mail);
                }
                
                
            }
        }

    For more information , please refer to

    https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45

    Best regards,

    Ackerly Xu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 6, 2019 1:43 AM