0

I am developing an ASP.NET Core 2 api and recently I've been trying to create a "password reset function" similar to most websites, by sending an email to the account in order to change the password.

So I've googled and wrote something that partially works. By partially I mean, it works as expected in localhost, but im hosting my application on Amazon Web Services (AWS) and for some reason when it's uploaded the email is never sent. By this i mean that the api returns an internal server error, and I'm not sure how i could debug something that just fails on host

I know there is Amazon SES but unfortunatly I can't use it, since my api is hosted in Brazil and Amazon SES is not avaiable in my region yet.

Does anyonne know what could be going wrong, or even how to debug it?

Here's the code I'm currently using to send emails

Base

public interface IEmailService
{
    HttpStatusCode SendEmail(string email, string subject, string body);
}

public class EmailService : IEmailService
{
    private readonly IConfiguration _config;
    public static NetworkCredential credential;
    public static SmtpClient client;


    public EmailService(IConfigurationRoot c)
    {
        _config = c;

        credential = new NetworkCredential()
        {
            UserName = _config["EmailSettings:Email"],
            Password = _config["EmailSettings:Password"]
        };

        client = new SmtpClient()
        {
            Credentials = credential,
            Host = _config["EmailSettings:Host"],
            Port = int.Parse(_config["EmailSettings:Port"]),
            EnableSsl = true

        };

    }


    public HttpStatusCode SendEmail(string email, string subject, string body)
    {
        using (client)
        {
            using (var message = new MailMessage())
            {
                message.To.Add(new MailAddress(email));
                message.From = new MailAddress(_config["EmailSettings:Email"]);
                message.Subject = subject;
                message.Body = body;
                message.IsBodyHtml = true;
                try
                {
                    client.Send(message);
                    return HttpStatusCode.OK;
                }
                catch
                {
                    return HttpStatusCode.InternalServerError;
                }
            }

        }
    }


    // Body builder, just
    public static string PasswordResetBody(string token)
    {
        StringBuilder body = new StringBuilder();
        body.AppendFormat("<h1>My title</h1>");
        body.AppendFormat("<br />");
        body.AppendFormat("<h3>Passw recovery</h3>");
        body.AppendFormat("<br />");
        body.AppendFormat("<p>Automated Msg.</p>");
        body.AppendFormat("<br />");
        body.AppendFormat("<p>Click below</p>");
        body.AppendFormat($"<a href=\"https://www.mywebsite.com/account/reset/{token}\">https://www.mywebsite.com/account/reset/{token}</a>");


        return body.ToString();
    }
}

On Controller

 public HttpStatusCode SendResetPassword(GetStringModel model)
    {
        ...

        var sentEmail = emailService.SendEmail(model.Data, "MySubject", EmailService.PasswordResetBody(guid.ToString()));
        return sentEmail;
    }

Exception

System.Net.Mail.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at
at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response)
at System.Net.Mail.MailCommand.Send(SmtpConnection conn, Byte[] command, MailAddress from, Boolean allowUnicode)
at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, Boolean allowUnicode, SmtpFailedRecipientException& exception)
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at Agrega.MySQL.Services.Database.Services.EmailService.SendEmail(String email, String subject, String body) in C:\Projects\PersonalProjects\Project.Core\Project\Project.MySQL\Services\Database\Services\EmailService.cs:line 55
at Agrega.MySQL.Services.Utilities.Authentication.AuthenticationUtility.SendResetPassword(GetStringModel model) in C:\Projects\PersonalProjects\Project.Core\Project\Project.MySQL\Services\Utilities\Authentication\AuthenticationUtility.cs:line 376
Lucas Arruda
  • 533
  • 1
  • 8
  • 15
  • What exactly do you mean with "do not send the email"? Errors? Exceptions? Lands in spam filter?! – Tseng Mar 31 '18 at 14:16
  • It returns InternalServerError. I'm not sure how could I debug something that only fails on host – Lucas Arruda Mar 31 '18 at 14:18
  • 1
    Typically in Cloud Scenarios, VMs and App hosting severs are deployed on a free server, hence the IP address is not always the same (such as it would be with virtual server hosting) and the IP ranges are often treated as dynamic range by filters and the mail may be treated as spam by the receiving mail server, so its recommneded to use a smartmail/mail relay offered by your service/cloud provider. Just because you are in Brazil doesn't mean you can't rent the mail service in a nearby region such as the US region – Tseng Mar 31 '18 at 14:19
  • Internal Service Error means, exception happened. Copy it here, indicates mostly whats the issue for the problem – Tseng Mar 31 '18 at 14:19
  • You should catch the exception and log it s0 – Chetan Mar 31 '18 at 14:21
  • @Tseng How should I get an Exception that happens on a production environment? I'll try to display it somewhere on the website and copy it here. Hold up – Lucas Arruda Mar 31 '18 at 14:22
  • Log files? If you host it in IIS its logged by default into the file specified in web.config. Otherwise the source you've defined in your application. Can't tell you, its your code you should know where you log it :) By default its logged to the console and IIS pipes it into the log file. Dunno where your current setup does that – Tseng Mar 31 '18 at 14:24
  • https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?tabs=aspnetcore2x – Tseng Mar 31 '18 at 14:24

1 Answers1

0

Thanks to logging, I googled up and found the answer on another stackoverflow question

Basically, it seems that because I was using Gmail, Google has a location security feature and it blocked the email request. When i trusted the device and accepted the activity it worked. I'm not sure, however, if this is the best way.

Tseng must be right, I will look into SES in another region, as i'm on AWS free tier so the machines and IP can change anytime. It's possible Google would block them again.

Lucas Arruda
  • 533
  • 1
  • 8
  • 15
  • 1
    I use Sendgrid API for managing emails for my projects, Extremely easy to implement and it gives you 40,0000 emails to send a month for free which should be loads for any small projects you are creating – Kevin Apr 01 '18 at 06:17
  • @Kevin Thanks. For further reference, I found out another service called ZohoMail. It gives 25 free emails with a custom domain (as long as you own it). All i had to do was change the host on my code. Guess i’ll try it. – Lucas Arruda Apr 01 '18 at 12:32