Tuesday, February 26, 2008

Sending an Activation Email with ASP.NET 2.0

Many sites as you've seen send out an email that contains a link to activate your account after you've filled out all requested information. This is primarily seen on Web Forum sites and other sites that require a membership. I'm going to show a quick example of how to do this using ASP.NET and sending the email via Gmail or some other SMTP server such as your hosting company's smtp server. It is assumed that you have already configured your ASPNETDB with Membership and Roles. This is just a basic email activation you can expand upon it and add other features you might want.

Start by dropping a standard CreateUserWizard Control on a page. I've dropped the control on a page called Default.aspx. You can format it later with any of the available Format templates Microsoft has provided or customize it using CSS if you like.

Below is the code-behind for the Default.aspx page. This code essentially grabs the Username, Password, and Email address that was entered through the CreateUserWizard Control puts the information into a StringBuilder object along with a link to the Activate.aspx page. The UserID is a Guid value that is appended to the Activate URL as a query string.

Using a conditional you can select to send the emails via your Hosting Companies SMTP server, a local SMTP server, or a Gmail account.

#define Gmail
#define SMTP

using System;
using System.Data;
using System.Configuration;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{

protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
StringBuilder bodyMsg = new StringBuilder();
TextBox username = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("UserName");
TextBox password = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Password");
TextBox email = (TextBox)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("Email");

CreateUserWizard cuw = (CreateUserWizard)sender;
MembershipUser user = Membership.GetUser(cuw.UserName);
Guid userID = (Guid)user.ProviderUserKey;

bodyMsg.Append("Thank you for creating your account.\n\nPlease follow this link to activate: ");
bodyMsg.Append("<br /><br /><a href=http://yourserver/SendEmailConfirmationSample/Activate.aspx?ID=" + userID.ToString() + ">Activate Your Account</a>");
bodyMsg.Append("<br />");
bodyMsg.Append("<br />");
bodyMsg.AppendFormat("UserName: {0}", username.Text);
bodyMsg.Append("<br />");
bodyMsg.AppendFormat("Password: {0}", password.Text);
bodyMsg.Append("<br />");
bodyMsg.AppendFormat("Registered Email: {0}", email.Text);

#if SMTP
// Sending email via local or web hosts smtp server.
NetworkCredential loginInfo = new NetworkCredential("yourusername", "yourpassword");
MailMessage msg = new MailMessage();
msg.From = new MailAddress("youremailaddress");
msg.To.Add(new MailAddress(CreateUserWizard1.Email));
msg.Subject = "Account Information";
msg.Body = bodyMsg.ToString();
msg.IsBodyHtml = true;

SmtpClient client = new SmtpClient("smtpserver", 25);
client.Credentials = loginInfo;
client.Send(msg);
#endif

#if Gmail
// Sending email via Gmail.
NetworkCredential loginInfo = new NetworkCredential("yourUsername@gmail.com", "yourGmailPassword");
MailMessage msg = new MailMessage();
msg.From = new MailAddress("yourUsername@gmail.com");
msg.To.Add(new MailAddress(CreateUserWizard1.Email));
msg.Subject = "Account Information";
msg.Body = bodyMsg.ToString();
msg.IsBodyHtml = true;

SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = loginInfo;
client.Send(msg);
#endif

Response.Redirect("~/thankyoupage.aspx");
}
}


Signing Up For A New Account.



The Confirmation email that is sent.



Here you can see the email that I received in my Gmail Inbox.



Here are the contents of the email that was sent.



The Activate.aspx page's code behind gets the ID that was passed in the query string and uses it to link the user to the account that was created, as well as adds the user to the Power Users Role in ASPNETDB. The page then displays the Username, Date the account was created, and the Status of the user's account.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Activate.aspx.cs" Inherits="Activate" %>



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">



<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>Activation Page</title>

</head>

<body>

<form id="form1" runat="server">

<br />

<asp:Table ID="Table1" runat="server" CellPadding="1" CellSpacing="0" GridLines="Both" BorderStyle="Groove" BackColor="BlanchedAlmond" Caption="Account Information">

<asp:TableRow runat="server">

<asp:TableCell HorizontalAlign="Right" runat="server">Username:</asp:TableCell>

<asp:TableCell HorizontalAlign="Left" runat="server"><asp:Label ID="ActiviationNameLabel" runat="server" Style="position: static"></asp:Label></asp:TableCell>

</asp:TableRow>

<asp:TableRow runat="server">

<asp:TableCell HorizontalAlign="Right" runat="server">Account Created:</asp:TableCell>

<asp:TableCell HorizontalAlign="Left" runat="server"><asp:Label ID="ActivationCreationDateLabel" runat="server" Style="position: static"></asp:Label></asp:TableCell>

</asp:TableRow>

<asp:TableRow runat="server">

<asp:TableCell HorizontalAlign="Right" runat="server">Account Status:</asp:TableCell>

<asp:TableCell HorizontalAlign="Left" runat="server"><asp:Label ID="ActivationStatusLabel" runat="server" style="position: static"></asp:Label></asp:TableCell>

</asp:TableRow>

</asp:Table>

</form>

</body>

</html>


using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;



public partial class Activate : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

if (!Page.IsPostBack)

{

string userID = Request.QueryString["ID"];

Guid gd = new Guid(userID);

MembershipUser user = Membership.GetUser(gd);

user.IsApproved = true;

Roles.AddUserToRole(user.ToString(), "Power Users");

Membership.UpdateUser(user);



ActiviationNameLabel.Text = user.UserName;

ActivationCreationDateLabel.Text = user.CreationDate.ToShortDateString();

if (user.IsApproved)

{

ActivationStatusLabel.Text = "Active";

}

else

{

ActivationStatusLabel.Text = "Pending";

}

}

}

}

Here are the final Account Details from the Activate.aspx screen.

24 comments:

Anonymous said...

Thanks man, this article rocks !

Anonymous said...

How would I do this with .Net 1.1?

Lance Spence said...

Sorry, I don't do any development with .Net v1.1. I'm sure that it is a bit more involved; however, due to not having the 2.0 Membership Providers available as well as a few namespace changes.

Here are a couple of links that might be helpful to you.

http://www.developer.com/net/asp/article.php/3096831

http://www.codeproject.com/KB/IP/mailtemplates.aspx

Anonymous said...

nice one...
can you tell me how to fix a particular time to this activation link....

William Bonner said...

Great post - thanks.

You don't happen to have a VB version of your code do you?

My c# is pretty weak but I'm going to try and convert it.

I am also curious if the new MailDefinition properties in the asp.net 3.5 createuserwizrd eliminates a few steps.

William Bonner said...

Great post - thanks.

You don't happen to have a VB version of your code do you?

My c# is pretty weak but I'm going to try and convert it.

I am also curious if the new MailDefinition properties in the asp.net 3.5 createuserwizrd eliminates a few steps.

Lance Spence said...

No I haven't provided a VB.NET version because C# is my primary language. It should be pretty straight forward to convert; however, you can speed the conversion process by using the Telerik Code Converter.

http://converter.telerik.com

What steps are you referring to?

Unknown said...

hi friends,
I got this error from your code plz ..send correct code... thanks 4 yr help....




An error occurred during the execution of the SQL file 'InstallCommon.sql'. The SQL error number is 1802 and the SqlException message is: CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
Cannot create file 'C:\DOCUMENTS AND SETTINGS\USER\DESKTOP\SDFS\APP_DATA\ASPNETDB_TMP.MDF' because it already exists. Change the file path or the file name, and retry the operation.
Creating the ASPNETDB_fb1b540ba5104411af07dc85cd2c3906 database...

Lance Spence said...

This error is not being generated by my code. You have a problem as the error states with the creation of 'ASPNETDB_TMP.MDF' because it already exists.

Please refer to the following link on how to resolve this.

http://social.msdn.microsoft.com/forums/en-US/sqlsetupandupgrade/thread/4549a8b4-0fdf-49d8-9e1c-e4bc0cf1e5ad/

mithun said...

thanks man

mithun said...

thanks man

someone164 said...

that was very helpful

thank you

Phuket Z z z z said...

Thanks you, It's great post

Anonymous said...

Thanks for Good article.

i have a question.
have this way enough security.because user knows his/her id's ?

thanks Again.

Lance Spence said...

Not sure I'm following you. Where are you referring to that the user knows his/her ID?

Anonymous said...

the user see his id in querystring that send in addressbar.

Lance Spence said...

The user's ID is a GUID, so there is little if anything that they can do with it. I think it would take a really determined hacker some effort to try to do some thing malicious just having the GUID alone.

Eran Smith said...
This comment has been removed by the author.
Anonymous said...

I need default.aspx page code
bacause i am getting to create default page

rgrgdfgd said...

Pls Send me the Default.page xccode because I am getting error in default.aspx page
I need Urgent

Anonymous said...

hi Friednds,
I got
Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'. this error at this line
MembershipUser user = Membership.GetUser(UserName);
i don't how to resolve this please tell me how to do this. i have search many hours but didn't get correct solution.

thanks

Unknown said...

how configured your ASPNETDB with Membership and Roles with this project?
plz help me?

Lance Spence said...

You will need to run aspnet_regsql from the Visual Studio command prompt.

Please refer to the following link for more information.

http://www.4guysfromrolla.com/articles/040506-1.aspx

Saurabh said...

How can we do this implementation without using create user wizard??
I am trying to use textbox