The title pretty much says it. Is there a way of adding Email Confirmation to my application without using the send grid ? my Azure account won't let me use it, says it isnt available in my zone and i cant seem to find another solution .
-
What about using a self-hosted SMTP or another provider? For Identity you just have to implement the IIdentityMessageService and configure Identity to use it. An example is shown [in this thread](http://stackoverflow.com/questions/22797845/asp-net-identity-2-0-how-to-implement-iidentitymessageservice-to-do-async-smtp). – Horizon_Net Jan 24 '15 at 17:04
-
I have tried that, but this error always pops : The remote certificate is invalid according to the validation procedure – Pedro Costa Jan 24 '15 at 17:11
-
any tip for the error ? – Pedro Costa Jan 24 '15 at 17:29
-
Think that's because you don't have a valid certificate. Have a look at [this thread](http://stackoverflow.com/questions/777607/the-remote-certificate-is-invalid-according-to-the-validation-procedure-using) what you can do. Keep in mind that you shouldn't do that in production (as stated in the thread). – Horizon_Net Jan 24 '15 at 17:36
-
I looked at that already, but thats not a solution. Plus, it doesnt work anymore. How can i get a valid cartificate ? – Pedro Costa Jan 25 '15 at 15:28
1 Answers
I didn't use sendgrid neither in my website for the Email confirmation service. I See no point having it in small websites with low traffic.
I use gmail SMTP service instead and it's works perfectly:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Mail;
using System.Web;
namespace MyProject.MyClasses
{
public class GmailEmailService : SmtpClient
{
// Gmail user-name
public string UserName { get; set; }
public GmailEmailService():
base( ConfigurationManager.AppSettings["GmailHost"], Int32.Parse(ConfigurationManager.AppSettings["GmailPort"]) )
{
//Get values from web.config file:
this.UserName = ConfigurationManager.AppSettings["GmailUserName"];
this.EnableSsl = Boolean.Parse( ConfigurationManager.AppSettings["GmailSsl"] );
this.UseDefaultCredentials = false;
this.Credentials = new System.Net.NetworkCredential(this.UserName, ConfigurationManager.AppSettings["GmailPassword"]);
}
}
}
in the Web.Config file add the following:
<configSections>
<appSettings>
<!--Smptp Server (confirmations emails)-->
<add key="GmailUserName" value="[your user name]@gmail.com"/>
<add key="GmailPassword" value="[your password]"/>
<add key="GmailHost" value="smtp.gmail.com"/>
<add key="GmailPort" value="587"/>
<add key="GmailSsl" value="true"/>
</appSettings>
</configSections>
In App_Start\IdentityConfig.cs file change the SendAsync method to this code:
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
MailMessage email = new MailMessage(new MailAddress("noreply@myproject.com", "(do not reply)"),
new MailAddress(message.Destination));
email.Subject = message.Subject;
email.Body = message.Body;
email.IsBodyHtml = true;
using( var mailClient = new MyProject.MyClasses.GmailEmailService() )
{
//In order to use the original from email address, uncomment this line:
//email.From = new MailAddress(mailClient.UserName, "(do not reply)");
await mailClient.SendMailAsync(email);
}
}
}
note: you will also have to add this using to the IdentityConfig.cs file:
using System.Net.Mail;
The last thing is to update the following in your AccountController file to something like that:
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.UserName, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
//Comment the following line to prevent log in until the user is confirmed:
//await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Account confirmation");
// Uncomment to debug locally
// TempData["ViewBagLink"] = callbackUrl;
ViewBag.errorMessage = "Please confirm the email was sent to you.";
return View("ShowMsg");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
private async Task<string> SendEmailConfirmationTokenAsync(string userID, string subject)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link:
string code = await UserManager.GenerateEmailConfirmationTokenAsync(userID);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = userID, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(userID, subject, "Please confirm your account by <a href=\"" + callbackUrl + "\">clicking here</a>");
return callbackUrl;
}
and a possible view ShowMsg.cs file can be:
@{
ViewBag.Title = "Message";
}
<h1 class="text-danger">@ViewBag.Title</h1>
@{
if (String.IsNullOrEmpty(ViewBag.errorMessage))
{
<h3 class="text-danger">An error occurred while processing your request.</h3>
}
else
{
<h3 class="text-danger">@ViewBag.errorMessage</h3>
}
}
That's it!, It works for me.
p.s: you will have to allow the "less-secure-apps" option in your gmail account. follow that gmail link
I used the following articles to write that solution:
Create a secure ASP.NET MVC 5 web app with..
ASP-NET-MVC-Confirm-Registration-Email
stackoverflow-email-using-gmail-smtp-in-asp-net-mvc-application
adding-two-factor-authentication..