UserManager SendEmailAsync No Email Sent

I am using the following code to try to send an email asynchronously, but no email is sent and I am not sure what is being done incorrectly. I have also added the 2nd segment of code in the web.config for the emailing protocol.

SendEmailAsync code

await UserManager.SendEmailAsync(username.Id, "MTSS-B: Forgot Password", "Here is your new password. Please go back to the MTSS-B web tool and sign in. You will be prompted to create your own password.<br/><br/>" + tmpPass + "<br/><br/>MTSS-B Administrator");

Web.config code

<system.net>
<mailSettings>
  <smtp>
    <network host="smtp1.airws.org" userName="" password="" />
  </smtp>
</mailSettings>
</system.net>

****UPDATE****

I tested if an email could be sent with the usual method and an email was able to be sent using the following code.

MailMessage m = new MailMessage(new MailAddress(ConfigurationManager.AppSettings["SupportEmailAddr"]), new MailAddress(model.Email));
m.Subject = "MTSS-B: Forgot Password"; 
m.Body = string.Format("Here is your new password. Please go back to the MTSS-B web tool and sign in. You will be prompted to create your own password.<br/><br/>Password: " + tmpPass + "<br/><br/>MTSS-B Administrator"); 
m.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient("smtp2.airws.org"); 
smtp.Send(m);

Solution 1:

In your app you probably have a file called IdentityConfig.cs in the App_Start folder. That file probably has something like this towards the top:

public class EmailService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        // Plug in your email service here to send an email.
        return Task.FromResult(0);
    }
}

change it to:

public class EmailService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        SmtpClient client = new SmtpClient();
        return client.SendMailAsync(ConfigurationManager.AppSettings["SupportEmailAddr"], 
                                    message.Destination, 
                                    message.Subject, 
                                    message.Body);
    }
}

Customizing the send code to your liking.

Solution 2:

Joe's solution guided me a lot, thanks for that! Yet to contribute with it, you must include the following namespaces:

using System.Configuration;
using System.Net.Mail;

I´ve changed his solution a little, after a lot of trying i've reached some code that worked (it must still be refacored, but it doesn't change the idea), this is how my SendAsync method looks like:

public Task SendAsync(IdentityMessage message) {
    //SmtpClient client = new SmtpClient();
    //return client.SendMailAsync(ConfigurationManager.AppSettings["SupportEmailAddr"],
    //                            message.Destination,
    //                            message.Subject,
    //                            message.Body);

    SmtpClient client = new SmtpClient();
    client.Port = 587;
    client.Host = "smtp.gmail.com";
    client.EnableSsl = true;
    //client.Timeout = 10000;
    client.DeliveryMethod = SmtpDeliveryMethod.Network;
    client.UseDefaultCredentials = false;
    client.Credentials = new NetworkCredential("[email protected]", "mailPassword");

    return client.SendMailAsync("[email protected]", message.Destination, message.Subject, message.Body);
}

You can see Joe's solution commented in top, then, a lot of configurations are made to the SmtpClient (the timeout is commented due to some testing i've been making, you can uncomment it if it suits your needs).

After that, the mail is sent in an asyncronous way, notice that the sender (which Joe get's from an AppSettings variable) is the same specified in the credentials (you must create a gmail [or wathever mail service you want] account and use it's name and password to create the credentials).

That should do the trick! Bear in mind that gmail may complicate your life while trying to connect to your new mail account this way, to solve it, you must log in that account and go to your account configurations and activate "less secure applications acces" (or sth like that, i speak spanish so my traduction may not be that good...).

Edit 22/04/16: Seems this solution doesn't work properly while working behing a proxy, there should be a way to configure it. In my case i find it cheaper to disable the proxy and go on, but for those of you who can't afford that, expect to have this obstacle while implementing this.

Solution 3:

I think you are using Macrosoft ASP.NET Identity and SMTP email client server. Then your full configuration would be like below :

Web.config

<system.net>
<mailSettings>
  <smtp from="[email protected]">
    <network host="smtp.gmail.com" userName="xyz" defaultCredentials="false" password="xyz" port="587" enableSsl="true" />
  </smtp>
</mailSettings>
</system.net>

Create a class SmtpEmailService.cs

public class SmtpEmailService : IIdentityMessageService
{
    readonly ConcurrentQueue<SmtpClient> _clients = new ConcurrentQueue<SmtpClient>();

    public async Task SendAsync(IdentityMessage message)
    {
        var client = GetOrCreateSmtpClient();
        try
        {
            MailMessage mailMessage = new MailMessage();

            mailMessage.To.Add(new MailAddress(message.Destination));
            mailMessage.Subject = message.Subject;
            mailMessage.Body = message.Body;

            mailMessage.BodyEncoding = Encoding.UTF8;
            mailMessage.SubjectEncoding = Encoding.UTF8;
            mailMessage.IsBodyHtml = true;

            // there can only ever be one-1 concurrent call to SendMailAsync
            await client.SendMailAsync(mailMessage);
        }
        finally
        {
            _clients.Enqueue(client);
        }
    }


    private SmtpClient GetOrCreateSmtpClient()
    {
        SmtpClient client = null;
        if (_clients.TryDequeue(out client))
        {
            return client;
        }

        client = new SmtpClient();
        return client;
    }
}

IdentityConfig.cs

// Configure the application user manager used in this application. 
//UserManager is defined in ASP.NET Identity and is used by the application.
public class ApplicationUserManager : UserManager<User>
{
    public ApplicationUserManager(IUserStore<User> store, IIdentityMessageService emailService)
        : base(store)
    {
        this.EmailService = emailService;
    }

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<User>(context.Get<ApplicationDbContext>()), new SmtpEmailService());
        .
        .
        .
        .
        return manager;
    }
}

If you are using dependency injection(DI) then configure it. I am using UnityContainer (UnityConfig.cs) so my configuration is :

container.RegisterType<IIdentityMessageService, SmtpEmailService>();

Finally use it from your controller :

public async Task<IHttpActionResult> TestSmtpMail()
{
    var subject = "Your subject";
    var body = "Your email body it can be html also";
    var user = await UserManager.FindByEmailAsync("[email protected]");
    await UserManager.SendEmailAsync(user.Id, subject, body);
    return Ok();
}

You can get an error something like :

The SMTP server requires a secure connection or the client was not authenticated.

Then Allow less security apps & Allow gmail account making it possible for other apps to gain access

For more details and SendGrid client visit here