Подтверждение регистрации по Email

Последнее обновление: 1.11.2015

Как правило, большинство крупных сервисов при регистрации требуют ее подтверждения по email. Посмотрим, как сделать подобный механизм в ASP.NET MVC.

В ASP.NET MVC есть несколько моделей авторизации и аутентификации. В данном случае используем механизм авторизации AspNet Identity, так как он более сложен в плане понимания. При использовании других методов аутентификации/авторизации общая схема подтверждения регистрации по email будет аналогична.

Итак, создадим новый проект ASP.NET MVC 5 с типом аутентификации Individual User Accounts. Он по умолчанию содержит весь инструментарий для авторизации: модели, контроллер и представления. Перейдем в папку моделей и откроем файл IdentityModels.cs, который содержит модель ApplicationUser. Изменим эту модель на следующую:

public class ApplicationUser : IdentityUser
{
    public string Email { get; set; }
    public bool ConfirmedEmail { get; set; }
}

К стандартному определению модели мы добавили свойство для email и свойство для хранения значения, подтверждена ли регистрация. Соответственно нам надо изменить модель регистрации RegisterViewModel в файле AccountViewModels.cs, чтобы она принимала дополнительное поле для email:

public class RegisterViewModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

И также добавим поле для email в представление для регистрации Register.chtml:

<div class="form-group">
    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
    </div>
</div>

Теперь контроллер AccountController, который и производит основную работу. Во-первых, так как нам предстоит отправлять письма, подключим в него необходимое пространство имен:

using System.Net.Mail;

Теперь добавим в AccountController два новых действия и изменим следующим образом действие Register, обрабатывающее post-запросы:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName };
        user.Email = model.Email;
        user.ConfirmedEmail = false;
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
			// наш email с заголовком письма
            MailAddress from = new MailAddress("somemail@yandex.ru", "Web Registration");
            // кому отправляем
            MailAddress to = new MailAddress(user.Email);
            // создаем объект сообщения
            MailMessage m = new MailMessage(from, to);
            // тема письма
            m.Subject = "Email confirmation";
            // текст письма - включаем в него ссылку
            m.Body = string.Format("Для завершения регистрации перейдите по ссылке:" + 
							"<a href=\"{0}\" title=\"Подтвердить регистрацию\">{0}</a>",
                Url.Action("ConfirmEmail", "Account", new { Token = user.Id, Email = user.Email }, Request.Url.Scheme));
            m.IsBodyHtml = true;
            // адрес smtp-сервера, с которого мы и будем отправлять письмо
            SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.yandex.ru", 25);
            // логин и пароль
            smtp.Credentials = new System.Net.NetworkCredential("somemail@yandex.ru", "password");
            smtp.Send(m);
            return RedirectToAction("Confirm", "Account", new { Email = user.Email });
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}  

[AllowAnonymous]
public string Confirm(string Email)
{
    return "На почтовый адрес " + Email + " Вам высланы дальнейшие" +
            "инструкции по завершению регистрации";
} 

[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string Token, string Email)
{
    ApplicationUser user = this.UserManager.FindById(Token);
    if (user != null)
    {
        if (user.Email == Email)
        {
            user.ConfirmedEmail = true;
            await UserManager.UpdateAsync(user);
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home", new { ConfirmedEmail = user.Email });
        }
        else
        {
            return RedirectToAction("Confirm", "Account", new { Email = user.Email });
        }
    }
    else
    {
        return RedirectToAction("Confirm", "Account", new { Email = "" });
    }
}

По сравнению со стандартным определением метода Register здесь добавлена логика отправки письма стандартными механизмами .NET, которые находятся в пространстве имен System.Net.Mail. После отправки посетитель получает на свой адрес письмо с ссылкой, по которой ему надо пройти. Эта ссылка указывает на метод ConfirmEmail.

После перехода в методе ConfirmEmail обновляется данные пользователя в базе данных: для поля ConfirmedEmail устанавливается значение true, означающее, что пользователь подтвердил регистрацию.

Теперь надо также изменить метод Login, обрабатывющий post-запрос:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindAsync(model.UserName, model.Password);
        if (user != null)
        {
            if (user.ConfirmedEmail == true)
            {
                await SignInAsync(user, model.RememberMe); 
                return RedirectToLocal(returnUrl);
            }
            else
            {
                ModelState.AddModelError("", "Не подтвержден email.");
            }
		}
        else
        {
            ModelState.AddModelError("", "Неверный логин или пароль");
        }
    }
	return View(model);
}

Теперь при логине будет учитываться, подтвердил ли ранее пользователь свой email.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850