@ -0,0 +1,23 @@ | |||||
using System.ComponentModel; | |||||
using System.ComponentModel.DataAnnotations; | |||||
namespace Sevomin.Models | |||||
{ | |||||
public class ChangePasswordViewModel | |||||
{ | |||||
[DisplayName("رمز عبور فعلی")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
[DataType(DataType.Password)] | |||||
public string Password { get; set; } | |||||
[DisplayName("رمز عبور جدید")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
[DataType(DataType.Password)] | |||||
public string NewPassword { get; set; } | |||||
[DisplayName("تایید رمز عبور")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
[DataType(DataType.Password)] | |||||
[Compare("NewPassword", ErrorMessage = "تایید رمز عبور با رمز عبور جدید مطابقت ندارد.")] | |||||
public string ConfirmPassword { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,11 @@ | |||||
using System.ComponentModel; | |||||
using System.ComponentModel.DataAnnotations; | |||||
namespace Sevomin.Models | |||||
{ | |||||
public class ForgotPasswordViewModel | |||||
{ | |||||
[DisplayName("ایمیل")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
public string Email { get; set; } | |||||
} | |||||
} |
@ -1,5 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.IO; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Net.Mail; | using System.Net.Mail; | ||||
using System.Text; | using System.Text; | ||||
@ -7,18 +8,67 @@ using System.Threading.Tasks; | |||||
namespace Sevomin.Models.Helpers | namespace Sevomin.Models.Helpers | ||||
{ | { | ||||
public enum EmailType | |||||
{ | |||||
EmailConfirmation, | |||||
PasswordReset, | |||||
NewPassword | |||||
} | |||||
public class SevominEmailer | public class SevominEmailer | ||||
{ | { | ||||
public Dictionary<string, string> Parameters { get; set; } | public Dictionary<string, string> Parameters { get; set; } | ||||
public EmailType EmailType { get; set; } | |||||
private string EmailFolderPath; | |||||
private string EmailConfirmationFilePath; | |||||
private string NewPasswordFilePath; | |||||
private string PasswordResetFilePath; | |||||
public SevominEmailer() | public SevominEmailer() | ||||
{ | { | ||||
EmailFolderPath = Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/app_data"), "emails"); | |||||
if (!Directory.Exists(EmailFolderPath)) | |||||
throw new ApplicationException("Emails folder does not exist in the right address."); | |||||
EmailConfirmationFilePath = Path.Combine(EmailFolderPath, "email-confirmation.html"); | |||||
NewPasswordFilePath = Path.Combine(EmailFolderPath, "new-password.html"); | |||||
PasswordResetFilePath = Path.Combine(EmailFolderPath, "password-reset.html"); | |||||
if(!File.Exists(EmailConfirmationFilePath)) | |||||
throw new ApplicationException("Email confirmation template does not exist in the right address."); | |||||
if (!File.Exists(NewPasswordFilePath)) | |||||
throw new ApplicationException("New password template does not exist in the right address."); | |||||
if (!File.Exists(PasswordResetFilePath)) | |||||
throw new ApplicationException("Password reset template does not exist in the right address."); | |||||
Parameters = new Dictionary<string, string>(); | |||||
} | |||||
public SevominEmailer(Dictionary<string, string> parameters, EmailType emailType) : this() | |||||
{ | |||||
Parameters = parameters; | |||||
EmailType = emailType; | |||||
} | } | ||||
public async void Send(string to, string subject, string template, bool isHtml) | |||||
public async Task SendAsync(string to, string subject, bool isHtml) | |||||
{ | { | ||||
SmtpClient client = new SmtpClient(); | SmtpClient client = new SmtpClient(); | ||||
MailMessage msg = new MailMessage(); | MailMessage msg = new MailMessage(); | ||||
string template; | |||||
switch (EmailType) | |||||
{ | |||||
case EmailType.EmailConfirmation: | |||||
template = | |||||
File.ReadAllText(EmailConfirmationFilePath, Encoding.UTF8); | |||||
break; | |||||
case EmailType.PasswordReset: | |||||
template = | |||||
File.ReadAllText(PasswordResetFilePath, Encoding.UTF8); | |||||
break; | |||||
case EmailType.NewPassword: | |||||
template = | |||||
File.ReadAllText(NewPasswordFilePath, Encoding.UTF8); | |||||
break; | |||||
default: | |||||
template = string.Empty; | |||||
break; | |||||
} | |||||
foreach (var address in to.Split(',')) | foreach (var address in to.Split(',')) | ||||
msg.To.Add(address); | msg.To.Add(address); | ||||
msg.From = new MailAddress("[email protected]", "سومین - مرکز کاریابی کنترل پروژه"); | msg.From = new MailAddress("[email protected]", "سومین - مرکز کاریابی کنترل پروژه"); | ||||
@ -28,14 +78,16 @@ namespace Sevomin.Models.Helpers | |||||
msg.IsBodyHtml = isHtml; | msg.IsBodyHtml = isHtml; | ||||
Func<string> getBody = () => | Func<string> getBody = () => | ||||
{ | { | ||||
foreach (var param in Parameters) | |||||
template = template.Replace(param.Key, param.Value); | |||||
foreach (var param in Parameters) | |||||
template = template.Replace(string.Format("[{0}]", param.Key), param.Value); | |||||
return template; | return template; | ||||
}; | }; | ||||
msg.Body = getBody(); | |||||
client.SendAsync(msg, null); | |||||
msg.Body = getBody(); | |||||
await Task.Run(() => | |||||
{ | |||||
client.Send(msg); | |||||
}); | |||||
} | } | ||||
} | } | ||||
} | |||||
} |
@ -0,0 +1,18 @@ | |||||
using System.ComponentModel; | |||||
using System.ComponentModel.DataAnnotations; | |||||
namespace Sevomin.Models | |||||
{ | |||||
public class ResetPasswordViewModel | |||||
{ | |||||
[DisplayName("رمز عبور")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
[DataType(DataType.Password)] | |||||
public string Password { get; set; } | |||||
[DisplayName("تایید رمز عبور")] | |||||
[Required(ErrorMessage = "ورود {0} الزامی است.")] | |||||
[DataType(DataType.Password)] | |||||
[Compare("Password", ErrorMessage = "تایید رمز عبور با رمز عبور اصلی مطابقت ندارد.")] | |||||
public string ConfirmPassword { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,51 @@ | |||||
@model Sevomin.Models.ChangePasswordViewModel | |||||
@{ | |||||
ViewBag.Title = "تغییر کلمه عبور"; | |||||
} | |||||
@Html.Partial("PostResult", ViewBag.Result as Sevomin.Models.PostResultViewModel) | |||||
<div class="page-header rtl"> | |||||
<h1>تغییر کلمه عبور</h1> | |||||
</div> | |||||
<div class="row rtl"> | |||||
<div class="col-md-12"> | |||||
@using (Html.BeginForm("ChangePassword", "Account", FormMethod.Post, new { role = "form" })) | |||||
{ | |||||
@Html.AntiForgeryToken() | |||||
<div class="form-horizontal"> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.Password, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.PasswordFor(model => model.Password, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.Password) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.NewPassword, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.PasswordFor(model => model.NewPassword, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.NewPassword) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.ConfirmPassword) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-12"> | |||||
<button type="submit" class="btn btn-default">ارسال رمز عبور</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
} | |||||
</div> | |||||
</div> |
@ -0,0 +1,34 @@ | |||||
@model Sevomin.Models.ForgotPasswordViewModel | |||||
@{ | |||||
ViewBag.Title = "بازنشانی رمز عبور"; | |||||
} | |||||
@Html.Partial("PostResult", ViewBag.Result as Sevomin.Models.PostResultViewModel) | |||||
<div class="page-header rtl"> | |||||
<h1>بازنشانی رمز عبور <small>برای بازنشانی رمز عبور خود، ایمیل خود را وارد کنید.</small></h1> | |||||
</div> | |||||
<div class="row rtl"> | |||||
<div class="col-md-12"> | |||||
@using (Html.BeginForm("Forgot", "Account", FormMethod.Post, new { role = "form" })) | |||||
{ | |||||
@Html.AntiForgeryToken() | |||||
<div class="form-horizontal"> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.Email, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.TextBoxFor(model => model.Email, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.Email) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-12"> | |||||
<button type="submit" class="btn btn-default">ارسال رمز عبور</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
} | |||||
</div> | |||||
</div> |
@ -0,0 +1,42 @@ | |||||
@model Sevomin.Models.ResetPasswordViewModel | |||||
@{ | |||||
ViewBag.Title = "بازنشانی رمز عبور"; | |||||
} | |||||
@Html.Partial("PostResult", ViewBag.Result as Sevomin.Models.PostResultViewModel) | |||||
<div class="page-header rtl"> | |||||
<h1>بازنشانی رمز عبور <small>رمز عبور جدید خود را وارد نمایید.</small></h1> | |||||
</div> | |||||
<div class="row rtl"> | |||||
<div class="col-md-12"> | |||||
@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { role = "form" })) | |||||
{ | |||||
@Html.AntiForgeryToken() | |||||
<div class="form-horizontal"> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.Password, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.PasswordFor(model => model.Password, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.Password) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-3 pull-right"> | |||||
@Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label" }) | |||||
</div> | |||||
<div class="col-md-9"> | |||||
@Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control ltr" }) | |||||
@Html.ValidationMessageFor(model => model.ConfirmPassword) | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div class="col-md-12"> | |||||
<button type="submit" class="btn btn-default">ارسال رمز عبور</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
} | |||||
</div> | |||||
</div> |
@ -1,3 +1,3 @@ | |||||
@if (Model != null && Model is Sevomin.Models.PostResultViewModel) { | @if (Model != null && Model is Sevomin.Models.PostResultViewModel) { | ||||
<div class="alert @(Model.Success ? "alert-success" : "alert-danger") rtl">@Model.Message</div> | |||||
<div class="alert @(Model.Success ? "alert-success" : "alert-danger") rtl">@MvcHtmlString.Create(Model.Message)</div> | |||||
} | } |