4

I am building an MVC 4 application starting with the default internet application. My goal is to send a confirmation email to users as they register to the website, i have managed to send the confirmation email but when i click on it the account is not being confirmed.

Note: I know the Register action is crowded, i will separate pieces to different files when i make it work.

*This is what i have done:*

Register Action

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
    {
        if (ModelState.IsValid)
        {
            try //CreateUserAndAccount
            {
                var token = WebSecurity.CreateUserAndAccount(model.UserName, model.Password, null, true);
                if (token != null)
                {
                    var hosturl =
                        System.Web.HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +
                        "/Account/ConfirmAccount?token=" + token;

                    var confirmationLink = string.Format("<a href=\"{0}\">Clink to confirm your registration</a>",
                                                         hosturl);




                    var message = new MailMessage("komengem@gmail.com", model.UserName)
                    {
                        Subject = "Please confirm your email",
                        Body = confirmationLink
                    };

                    var client = new SmtpClient();
                    client.EnableSsl = true;
                    client.Send(message);
                }

                TempData["message"] = string.Format(
                    "Thank you for registering. An email has been sent to {0}. " +
                    "Please check your email and use the enclosed link to finish registration.", model.UserName);
                return RedirectToAction("Index", "Home");
            }
            catch (MembershipCreateUserException e)
            {
                ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
            }
        }

ConfirmAcount Action

public ActionResult ConfirmAccount(string ID)
    {
        //return View("ConfirmAccount");
        var confirmationToken = Request["token"];
        if (!String.IsNullOrEmpty(confirmationToken))
        {
            var user = WebSecurity.CurrentUserName;
            WebSecurity.ConfirmAccount(confirmationToken);
            WebSecurity.Login(user, null);
            return View("Welcome");
        }

        TempData["message"] = string.Format(
                    "Your account was not confirmed, please try again or contact the website adminstrator.");
        return RedirectToAction("Index", "Home");            
    }

Also Tried

public ActionResult ConfirmAccount(string ID)
    {
        if (string.IsNullOrEmpty(ID) || (!Regex.IsMatch(ID,
                        @"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}")))
        {
            TempData["tempMessage"] =
                "The user account is not valid. Please try clicking the link in your email again.";
            return View();
        }
        MembershipUser user = Membership.GetUser(new Guid(ID));

        if (!user.IsApproved)
        {
            user.IsApproved = true;
            Membership.UpdateUser(user);
            FormsAuthentication.SetAuthCookie(user.UserName, false);
            return RedirectToAction("Login");
        }
        WebSecurity.Logout();
        TempData["tempMessage"] = "You have already confirmed your email address... please log in.";
        return RedirectToAction("Login");
    }      

Could anyone please show me how to make this work, or perhaps suggest a different way to make this work??

Komengem
  • 3,662
  • 7
  • 33
  • 57
  • 1
    What is the specified string? Is `model.UserName` in the form `someone@somewhere.com`? – Robert Harvey Jan 31 '13 at 19:07
  • You haven't set who the email is from, which may make a difference – levelnis Jan 31 '13 at 19:13
  • Well, it seems pretty clear that it's a problem with the `Webmail.Send()` call, and not anything else. I would focus on getting *that* to work. – Robert Harvey Jan 31 '13 at 19:36
  • @RobertHarvey So, should i assume that all my code is in its right place? This is my biggest worry – Komengem Jan 31 '13 at 19:40
  • You can't assume anything until you get the error fixed. – Robert Harvey Jan 31 '13 at 19:45
  • @levelnis see edit above, no development still throws an error. Error occurs at same code – Komengem Jan 31 '13 at 19:45
  • 1
    Maybe that's a stupid question, but have you set up a mail server on your local mashine? – Konrad Gadzina Jan 31 '13 at 20:01
  • @KonradGadzina the application is running on iis server on local machine, iis has SMTP E-mail and i have applied all the settings to the application configured there. – Komengem Jan 31 '13 at 20:55
  • @KonradGadzina yes, i used postal....I have marked answer below, follow the link to Kevin's blog but also read comments, i left a few there myself which could be vital to making it work over the network. – Komengem Feb 11 '13 at 05:20
  • @KomengeMwandila Great! I'll check it if needed for sure. Thanks for the comment, I would miss the solution otherwise. – Konrad Gadzina Feb 11 '13 at 09:10

3 Answers3

7

I encourage you to use Postal, which is a simple to use email-creation package. It's available as a nuget-package.

Also take a look at Kevin Junghans blogpost on the subject! Email confirmation

Frederik
  • 2,178
  • 4
  • 20
  • 20
1

I have done the following and it is working:

Create the token in the Register as :

string confirmationToken =
                        WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Email = model.Email }, true);

Then in the confirmation used the following:

public ActionResult RegisterConfirmation(string Id)
        {
            if (WebSecurity.ConfirmAccount(Id))
            {
                return RedirectToAction("ConfirmationSuccess");
            }
            return RedirectToAction("ConfirmationFailure");
        }
René Höhle
  • 26,716
  • 22
  • 73
  • 82
Hennie Nel
  • 11
  • 1
0

Error message from your edit sounds like your local machine is not listening neither on port 25 nor 587. I think you should check if the SMTP server is configured and running before doing anything with your code.

You can simply create 2 accounts on this local server and set them up in any email client and check if you're able to send emails between them. Second option is checking connection using telnet, but I have not tried it - http://www.petri.co.il/test_smtp_service.htm

If using mail server outside of your app was successfull and you still have errors, be sure that your WebMail.UserName and WebMail.Password are correct. If yes, try setting WebMail.From to one of local test email addresses that you're using in WebMail configuration, like test@localhost or test@127.0.0.1 (I had to use IP to pass email validation sometimes).

Konrad Gadzina
  • 3,407
  • 1
  • 18
  • 29
  • I just don't understand why port `25` isn't working on `localhost`. This is the only port i know which is meant to work for `Smpt E-mail` on local machine. I just think that something is up with my code. Anyways, i just received my `Pro ASP.NET MVC4 book` I will check if there is anything like that in there. – Komengem Feb 01 '13 at 01:38
  • @KomengeMwandila But have you checked if SMTP server is working on it's own like I suggested? Check it first, and if it's working move to checking your code. – Konrad Gadzina Feb 01 '13 at 14:35
  • I changed the port to my application port, now i am getting `The operation has timed out.` and all errors are happening at: `WebMail.Send` – Komengem Feb 01 '13 at 21:17
  • @KomengeMwandila You have a different error because there is a service running on your application's port - it's application's server and the operation has timed out because this service is not created to handle SMTP requests. Check if your SMTP server **is running** using one of the ways i posted. SMTP should be on port `25`. Error message `No connection could be made because the target machine actively refused it 127.0.0.1:PORT` means that there is no service listening on this port or the firewall is causing problems. But since it's your local development machine, fw should not be an issue. – Konrad Gadzina Feb 01 '13 at 21:43