I am using this tutorial to register a user with email confirmation, but I can't find the emailservice class.
http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset
I am using MVC 5 with Identity 2.2.
Thanks but i already find the solution
I have created the class emailservice and them
Selected the email from usermanager, like this
userManager.EmailService = new EmailService();
As far as I know, there is no such .net class as EmailService Typically you use the SmtpClient class to send emails:
SmtpClient client = new SmtpClient("server.address.com");
MailAddress from = new MailAddress(fromAddress, fromName);
MailMessage msg = new MailMessage();
msg.From = from;
foreach(string addr in to)
msg.To.Add(addr);
msg.Body = content;
msg.Subject = subject;
client.Send(msg);
I had the same question, and used the following solution. First, create a new folder in your project called services, and create a new class with the following code from the tutorial:
namespace YourProject.Services
{
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
await configSendGridasync(message);
}
// Use NuGet to install SendGrid (Basic C# client lib)
private async Task configSendGridasync(IdentityMessage message)
{
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new System.Net.Mail.MailAddress("no-reply#your-domain.com", "Customer Service");
myMessage.Subject = message.Subject;
myMessage.Text = message.Body;
myMessage.Html = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["SendGridUsername"],
ConfigurationManager.AppSettings["SendGridPassword"]
);
// Create a Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
if (transportWeb != null)
{
await transportWeb.DeliverAsync(myMessage);
}
else
{
Trace.TraceError("Failed to create Web transport.");
await Task.FromResult(0);
}
}
}
}
Then, what I did was set the EmailService property of the UserManager object in my controller to a new instance of the EmailService class (scroll all the way to the right to see it, sorry for that):
namespace YourProject.Controllers
{
public class UserManagementController : Controller
{
private UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())){EmailService = new Services.EmailService()};
// GET: UserManagement
Then, when you call
UserManager.SendEmailAsync(user.Id, subject, body);
It will send the email using your SendGrid accound as configured in the EmailService class above.
Related
I am using ASP.NET MVC5 with Identity 2, theres a file called IdentityConfig.cs which has EmailSerive that I have implemented like this:
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
using (var client = new SmtpClient())
{
using (var mailMessage = new MailMessage("info#mydomain.com", message.Destination, message.Subject, message.Body))
{
mailMessage.IsBodyHtml = true;
await client.SendMailAsync(mailMessage);
}
}
}
}
With this setup, I am able to send user emails by calling this method on UserManager:
await UserManager.SendEmailAsync(user.Id, emailSubject, emailBody);
So far so good, but Id want the email to be sent from different senders depending on the subject. For instance, account registration/reset password will have sender account#mydomain.com, information inquiry emails will have sender info#mydomain.com, sales/order placement should have sender sales#mydomain.com.
Unfortunately, the method SendEmailAsync has no way to set the sender, and I have no idea how to achieve this in the EmailService either. Can anyone help with this problem? Is there a way to add an extension method to UserManager or EmailSerivce so I can optionally specify a different sender?
If I am in your place I would put all my emails in the web.config file and access it in a private method in the EmailService class that returns relevant email based on the subject and then call this method at the place of email parameter. e.g:
public async Task SendAsync(IdentityMessage message)
{
using (var client = new SmtpClient())
{
//calling getEmail() instead of email
using (var mailMessage = new MailMessage(getEmail(message.Subject),
message.Destination, message.Subject, message.Body))
{
mailMessage.IsBodyHtml = true;
await client.SendMailAsync(mailMessage);
}
}
}
private string getEmail(string subject)
{
var emails = ConfigurationManager.AppSettings["Emails"];
string[] emailAddresses = emails.Split(',');
//your logic here
return email;
}
In ASP.NET, you configure email for Identity in IdentityConfig.cs in the App_Start folder, as per my own answer here.
ASP.NET Core Identity is now a library. And does not include this IdentityConfig.cs file by default. So how can I configure email sending, say, for Registration confirmation?
As per https://medium.com/#MisterKevin_js/enabling-email-verification-in-asp-net-core-identity-ui-2-1-b87f028a97e0
ASP.NET Core 2 relies a lot on dependency injection.
Identity Library's RegisterModel (as well as the other email-dependant models) has the following field:
private readonly IEmailSender _emailSender;
All you have to do is use Startup.cs ConfigureServices method to inject an IEmailSender implemented by yourself:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<IEmailSender, EmailSender>();
}
You may define this EmailSender class inside a folder named Services in your project:
And a possible implementation would be:
using Microsoft.AspNetCore.Identity.UI.Services;
using System.Net;
using System.Net.Mail;
using System.Threading.Tasks;
namespace YourProject.Services
{
public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
SmtpClient client = new SmtpClient
{
Port = 587,
Host = "smtp.gmail.com", //or another email sender provider
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential("your email sender", "password")
};
return client.SendMailAsync("your email sender", email, subject, htmlMessage);
}
}
}
You could refer the following steps to send email using SMTP:
Create a EmailSender class, and contains the following method:
public interface IMyEmailSender
{
void SendEmail(string email, string subject, string HtmlMessage);
}
public class MyEmailSender : IMyEmailSender
{
public IConfiguration Configuration { get; }
public MyEmailSender(IConfiguration configuration)
{
Configuration = configuration;
}
public void SendEmail(string email, string subject, string HtmlMessage)
{
using (MailMessage mm = new MailMessage(Configuration["NetMail:sender"], email))
{
mm.Subject = subject;
string body = HtmlMessage;
mm.Body = body;
mm.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = Configuration["NetMail:smtpHost"];
smtp.EnableSsl = true;
NetworkCredential NetworkCred = new NetworkCredential(Configuration["NetMail:sender"], Configuration["NetMail:senderpassword"]);
smtp.UseDefaultCredentials = false;
smtp.Credentials = NetworkCred;
smtp.Port = 587;
smtp.Send(mm);
}
}
}
Store the SMTP configuration information in the appsettings.json
"NetMail": {
"smtpHost": "smtp.live.com",
"sender": "sender email",
"senderpassword": "Password"
},
Register the EmailSernder in the ConfigureServices method in Startup.cs file.
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddTransient<IMyEmailSender, MyEmailSender>();
In the Register.cs file, after creating user, you could use UserManager to get the EmailConfirmationToken, and get the callbackurl, then, call the SendEmail() method to send email.
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
_myEmailSender.SendEmail(Input.Email, "Confirm your Email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
After that, you will receive a email like this:
After clicking the link, it will redirect to the Confirm Email page, then, check the database, the EmailConfirmed was changed to True .
Reference: Account confirmation and password recovery in ASP.NET Core
I am following this article: https://learn.microsoft.com/en-us/aspnet/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity
But still not able to enable account confirmation email sending using asp.net MVC. It's showing
type or namespace web could not be found
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
return configSendGridasync(message);
}
private Task configSendGridasync(IdentityMessage message)
{
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new MailAddress("xxxx#.com", "ABC");
myMessage.Subject = message.Subject;
myMessage.PlainTextContent = message.Body;
myMessage.HtmlContent = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["mailAccount"],
ConfigurationManager.AppSettings["mailPassword"]
);
// Create a Web transport for sending email.
var transportWeb = new System.Web(credentials);
// Send the email.
if (transportWeb != null)
{
return transportWeb.DeliverAsync(myMessage);
}
else
{
return Task.FromResult(0);
}
}
}
I've successfully created custom email service provider for UserManager by extending IIdentityMessageService:
public class ExchangeEmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
using (var client = new SmtpClient())
{
client.Host = "mail.example.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(#"noreply", "P#ssw0rd");
var from = new MailAddress("no-reply#example.com");
var to = new MailAddress(message.Destination);
var mailMessage = new MailMessage(from, to)
{
Subject = message.Subject,
Body = message.Body,
IsBodyHtml = true
};
await client.SendMailAsync(mailMessage);
}
}
}
Inside UserManager's Create I'm creating new instance of my service and assigning it to EmailService:
userManager.EmailService = new ExchangeEmailService();
This all works fine, but I have requirement to send emails from different email addresses, based on place this is called from, unfortunately UserManager.SendEmailAsync isn't allowing me to pass anything except userId, subject and body.
Ideally I'd like to be able to specify email address when calling SendEmailAcync or enum value.
I've searched in UserManager source and I thought about creating custom SendEmailAsync implementation, but I'd have to change multiple places - IIdentityMessageService, UserManager.
I know I can create new interface and build my email sending class on it, but I'd like to keep changes to minimum.
What I'd like to get:
I'd like to have enum containing names of mailboxes:
public enum Mailboxes
{
Noreply = 0,
Service = 1,
Contact = 2
}
and be able to call SendEmailAsync with that additional parameter:
await UserManager.SendEmailAsync(user.Id, "Account created", "Nice email content.", Mailboxes.Noreply );
I'm aware that I can set different title and use same email address, but this is requirement I got.
How can I do that?
A hack would be to create a model to store what you want sent to the service
public class MessageBody {
public string Body { get; set; }
public MailBoxes Source { get; set; }
}
and then serialize it (JSON maybe) as the body parameter of the SendEmailAsync method call.
var message = new MessageBody {
Body = "Nice email content.",
Source = Mailboxes.Noreply
};
var body = JsonConvert.SerializeObject(message);
await UserManager.SendEmailAsync(user.Id, "Account created", body);
The service would then deserialize the model, construct the email with the custom info and then send the email.
public class ExchangeEmailService : IIdentityMessageService {
readonly IMailBoxProvider provider;
public ExchangeEmailService(IMailBoxProvider provider) {
this.provider = provider;
}
public async Task SendAsync(IdentityMessage message) {
using (var client = new SmtpClient()) {
client.Host = "mail.example.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(#"noreply", "P#ssw0rd");
//Get the body and from address
var fromEmailAddress = "default-email#example.com";
var body = message.Body;
try {
var msg = JsonConvert.DeserializeObject<MessageBody>(body);
if(msg != null) {
body = msg.Body;
fromEmailAddress = provider.GetMailbox(msg.Source);
}
} catch { }
var from = new MailAddress(fromEmailAddress);
var to = new MailAddress(message.Destination);
var mailMessage = new MailMessage(from, to)
{
Subject = message.Subject,
Body = body,
IsBodyHtml = true
};
await client.SendMailAsync(mailMessage);
}
}
}
And just make sure to assigning it to UserManager.EmailService:
userManager.EmailService = new ExchangeEmailService(new MailBoxProvider());
I have a mailer for Google as shown below, how can i adapt this for other mail systems? Is there a better way of doing this? also how can i change the name of where the mail is from(the sender).
All help would be much appreciated, and thank you in advance
MailMessage message = new MailMessage();
message.From = new MailAddress(MailAddresds);
message.Subject = messagesubject;
message.Body = messagebody;
message.To.Add(messageto);
SmtpClient client = new SmtpClient();
client.Credentials = new NetworkCredential(userName, password);
client.Host = "smtp.gmail.com";
client.Port = 587;
client.EnableSsl = true;
client.Send(message);
Just example:
public class MailMessage
{
public string From{get;set;}
public string To{get;set;}
public string Body{get;set;}
public string Subject{get;set;}
....
//other common properties you may need
}
//interface
public interface IMailService
{
Send(MailMessage m);
}
concrete implementations:
public class GoogleMail : IMailService
{
public Send(Message msg)
{
//google mail specific code
}
}
public class YahooMail : IMailService
{
public Send(Message msg)
{
//yahoo mail specific code
}
}
.... Hotmail,...
somewhere in the code create a collection of supported mail services
var mailservices = new List<IMailService>();
mailservices.Add(new GoogleMail ());
mailservice.Add(new YahooMail ());
after, during the program run, pick the appropriate service to proceed user request.
simple example:
using System.Web.Mail;
MailMessage objMessage = new MailMessage();
objMessage.From = "from";
objMessage.To = "to";
objMessage.Subject = "subject";
objMessage.BodyFormat = MailFormat.Text;
objMessage.Body = "body";
SmtpMail.SmtpServer = "SmtpServer";
SmtpMail.Send(objMessage);