0

I am new to ASP.NET and C# and this is my first big project.

Unable to send forgot password mail through ASP.NET and C#. Even, neither errors nor exceptions are displayed by Visual Studio.

These are my files:

Code Behind

   //Reset password event 
   protected void btnResetPassword_Click(object sender, EventArgs e)
    {
        string CS = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;

        using (SqlConnection con = new SqlConnection(CS))
        {
            con.Open();

            SqlCommand cmd = new SqlCommand("spResetPassword", con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter paramUsername = new SqlParameter("@UserName", txtUserName.Text);
            cmd.Parameters.Add(paramUsername);

            SqlDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read())
            {
                if (Convert.ToBoolean(rdr["ReturnCode"]))
                {
                    SendPasswordResetEmail(rdr["EmailID"].ToString(), txtUserName.Text, rdr["UniqueId"].ToString());
                    lblMessage.Text = "An email with instructions to reset your password is sent to your registered email";
                }
                else
                {
                    lblMessage.ForeColor = System.Drawing.Color.Red;
                    lblMessage.Text = "Username not found!";
                }
            }
        }
    }

Send Email to Recipient, an email template is been added inline code instead of a using AlternateView.

private void SendPasswordResetEmail(string ToEmail, string UserName, string UniqueId)
{
        try
        {  
            MailMessage mailMessage = new MailMessage("Email@gmail.com", ToEmail);
            StringBuilder sbEmailBody = new StringBuilder();
            sbEmailBody.Append("Dear " + UserName + ",<br/><br/>");
            sbEmailBody.Append("Please click on the following link to reset your password");
            sbEmailBody.Append("<br/>"); sbEmailBody.Append("http://localhost:64736/SmartE/Registration/ChangePassword.aspx?uid=" + UniqueId);
            sbEmailBody.Append("<br/><br/>");
            sbEmailBody.Append("<b>Smart Elector</b>");
            mailMessage.IsBodyHtml = true;
            mailMessage.Body = sbEmailBody.ToString();
            mailMessage.Subject = "Reset Your Password";
            SmtpClient smtpClient = new SmtpClient("smtp.gmail.com", 587);
            smtpClient.Credentials = new System.Net.NetworkCredential()
            {
                UserName = "Email@gmail.com",
                Password = "Password"
            };
            smtpClient.EnableSsl = true;
            smtpClient.Send(mailMessage);
        }
        catch(Exception ex)
        {
            lblMessage.Text= "Record Insert Exception: " + ex.Message;
        }
    }

Stored procedure:

There is no output parameter defined in this stored procedure, which returns the unique code to the invoker. instead, select query is used to return the same.

CREATE PROCEDURE Spresetpassword 
     @UserName NVARCHAR(100) 
AS 
BEGIN 
    DECLARE @UserID  INT, 
            @EmailID NVARCHAR(100); 

    SELECT 
        @UserID = userid, 
        @EmailID = emailid 
    FROM   
        globalusers 
    WHERE  
        username = @UserName; 

    IF (@UserID IS NOT NULL) 
    BEGIN 
        -- If username exists 
        DECLARE @GUID UNIQUEIDENTIFIER; 

        SET @GUID = NEWID(); 

        INSERT INTO tblresetpasswordrequests (id, userid, resetrequestdatetime)
        VALUES (@GUID, @UserID, GETDATE()) 

        SELECT 
            1 AS ReturnCode, 
            @GUID AS UniqueId, 
            @EmailID AS EmailID 
    END 
    ELSE 
    BEGIN 
        -- If username does not exist 
        SELECT 
            0 AS ReturnCode, 
            NULL AS UniqueId, 
            NULL AS EmailID 
    END 
END 
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • What happens when you step through your code with the debugger? – ProgrammingLlama Apr 06 '19 at 11:44
  • You are not seeing any errors because you are overwritting the text of an possible exception, thrown by `SendPasswordResetEmail`. After you call that method, you always overwrite the label's text with a successmessage. Your `SendPasswordResetEmail` should return a boolean value, denoting, whether the send was successful or not (for instance exception is thrown) and you should only set the successmessage if the returnvalue is true – derpirscher Apr 06 '19 at 12:41
  • Try setting a breakpoint into the `catch` block of `SendPasswordResetEmail`. I bet there is some sort of authorization exception thrown, because google is quite restrictive when using their smtp server. For details see the answers here https://stackoverflow.com/questions/32260/sending-email-in-net-through-gmail – derpirscher Apr 06 '19 at 12:44
  • 1
    And just a comment on the process itself: The usual pattern with password reset emails is not to tell the whether the entered email/username is known in the system because that may be a security issue. – derpirscher Apr 06 '19 at 13:04
  • You are right @derpirscher , exception is on 'smtpClient.Send(mailMessage);': Failure sending mail. System.Net.WebException: Unable to connect to the remote server -> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 74.125.130.108:587 at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) – Heena Sood Apr 06 '19 at 22:22

1 Answers1

0

Try this solution using membership,

 protected void btnResetPassword_Click(object sender, EventArgs e)
    {
MembershipUser mu = Membership.GetUser(txtResetUserName.Text.Trim());
            if (mu != null)
            {
                if (!mu.IsLockedOut)
                {
                    string resetPassword = Membership.GeneratePassword(8, 1);
                    mu.ChangePassword(mu.ResetPassword(), resetPassword);
                    ListDictionary replaceList = new ListDictionary();
                    replaceList.Add("<%UserName%>", "Name of the user");
                    replaceList.Add("<%NewCode%>", resetPassword);

                    Utility fetch = new Utility();
                    fetch.SendMail(mu.Email, string.Empty, "User account " + txtResetUserName.Text.Trim() + " password reset to: " + resetPassword, fetch.MailBodyTemplate(replaceList, "ResetEmailTemplate"), null);
               }
            }
}

Put the below code in an Utility class of your project.

  public void SendMail(string to, string cc, string subject, AlternateView body, string path)
    {
        MailMessage message = new MailMessage(AppSettings.Default.From, to);
        if (!String.IsNullOrEmpty(path)) message.Attachments.Add(new Attachment(path));
        if (!String.IsNullOrEmpty(cc)) message.CC.Add(cc);
        if (body != null)
        {
            message.AlternateViews.Add(body);
            message.IsBodyHtml = true;
        }
        message.Body = subject;
        message.Subject = subject;

        Thread bgThread = new Thread(new ParameterizedThreadStart(SendEmailInBackgroud));
        bgThread.IsBackground = true;
        bgThread.Start(message);
    }

Template based Email body

 public AlternateView MailBodyTemplate(ListDictionary replaceList, string fileName)
    {
        AlternateView plainView = null;

        string templatePath = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/MailTemplate/" + fileName + ".txt");
        if (File.Exists(templatePath))
        {
            string templateContent = File.ReadAllText(templatePath);
            foreach (DictionaryEntry item in replaceList)
            {
                if (item.Value != null)
                    templateContent = templateContent.Replace(item.Key.ToString(), item.Value.ToString());
                else
                    templateContent = templateContent.Replace(item.Key.ToString(), string.Empty);
            }
            plainView = AlternateView.CreateAlternateViewFromString(templateContent, null, MediaTypeNames.Text.Html);
        }
        return plainView;
    }

Your Email Template File As Follows, File Name: ResetEmailTemplate.txt

<!DOCTYPE html>
<html><head>
  <style>
    .ContentBody {
       color: #1331a0;
     }
  </style></head>
 <body class="ContentBody">
  <p>Dear <%UserName%>,</p>
  <p>New Password for your accout is:  <%NewCode%> </p>
 </body>
</html>
Pranesh Janarthanan
  • 1,134
  • 17
  • 26