ASP.NET 核心 - 发送电子邮件:请通过您的网络浏览器登录,然后重试

ASP.NET CORE - Send email: Please log in via your web browser and then try again

我正尝试在生产环境中发送一封带有用户注册验证 link 的邮件。

为此,我在 appsettings.json

中附上了发送邮件的 gmail 帐户的凭据

APPSETTINGS.JSON:

我的控制器发送邮件的动作如下:

   [HttpPost]
    public async Task<JsonResult> Register(AddUserViewModel model)
    {
        if (ModelState.IsValid)
        {
            User user = await _userHelper.AddUserAsync(model, imageId);

            if (user == null)
            {
                return Json("Email repeat");
            }

            string myToken = await _userHelper.GenerateEmailConfirmationTokenAsync(user);
            string tokenLink = Url.Action("ConfirmEmail", "Account", new
            {
                userid = user.Id,
                token = myToken
            }, protocol: HttpContext.Request.Scheme);

            Response response = _mailHelper.SendMail(model.Username, "App - Confirmación de cuenta", $"<h1>App - Confirmación de cuenta</h1>" +
                $"Para habilitar el usuario, " +
                $"por favor hacer clic en el siguiente enlace: </br></br><a href = \"{tokenLink}\">Confirmar Email</a>");

            if (response.IsSuccess)
            {
                return Json("Email send");
            }
          
            string message = response.Message;
            return Json(message);
           
        }

        return Json("Model invalid");
    }

returns一个Response的sendEmail方法如下:

 public Response SendMail(string to, string subject, string body)
        {
            try
            {
                string from = _configuration["Mail:From"];
                string smtp = _configuration["Mail:Smtp"];
                string port = _configuration["Mail:Port"];
                string password = _configuration["Mail:Password"];

                MimeMessage message = new MimeMessage();
                message.From.Add(new MailboxAddress(from));
                message.To.Add(new MailboxAddress(to));
                message.Subject = subject;
                BodyBuilder bodyBuilder = new BodyBuilder
                {
                    HtmlBody = body
                };
                message.Body = bodyBuilder.ToMessageBody();

                using (SmtpClient client = new SmtpClient())
                {
                    client.CheckCertificateRevocation = false;
                    client.Connect(smtp, int.Parse(port), false);                   
                    client.Authenticate(from, password);
                    client.Send(message);
                    client.Disconnect(true);
                }

                return new Response { IsSuccess = true };

            }
            catch (Exception ex)
            {
                return new Response
                {
                    IsSuccess = false,
                    Message = ex.Message,
                    Result = ex
                };
            }
        }

错误信息如下:

"534: 5.7.14 \u003Chttps://accounts.google.com/signin/continue?sarp=1\u0026scc=1\u0026plt=AKgnsbt\n5.7.14 GCim6bqtaJeANyyQ0NvegYJS8qnYbDSCz3M0IMvB-rgIFdr1rLrIl1wbt4DkimTvNMLDl\n5.7.14 8dSGZxGuAWmDwX6gPD1T_lJ3U1e0G8EEAu6Lgt3p5gk1yJpr85Pm2mBN9nO4G33Y\u003E\n5.7.14 Please log in via your web browser and then try again.\n5.7.14 Learn more at\n5.7.14 https://support.google.com/mail/answer/78754 t15sm12262168pjy.17 - gsmtp"

我发送正确吗? 我应该更改任何 gmail 设置吗?

在开发环境中发送没有问题,对我有什么帮助或建议吗?

不建议直接使用 Gmail、Outlook 和类似的提供商,因为它们执行的检查可能会像您在此处看到的那样破坏您的代码。

这可能会在没有事先通知的情况下发生。相信我,它会不时发生。

常见问题

Web-based OAuth 流程

大多数提供商(特别是 Gmail)现在根据最新的 OAuth/OpenID 规范执行 web-based 流程,以实现更安全的 authentication/authorization。

这是我的第一个猜测:Gmail 身份验证(基于浏览器)只是阻止您的登录尝试,因为它希望您使用浏览器而不是简单地提交您的凭据。

IAM 解决方案完成了很多后台工作来帮助保护用户,即所谓的风险评估。这可能需要及时将验证码和 MFA 挑战发送回用户,因此 API 不会真正起作用,这是他们关注浏览器而不是简单地获取正确凭据的另一个原因.

Bot 预防

电子邮件提供商(特别是 Gmail)非常擅长检测可能的机器人程序,这是我的第二个猜测:它检测到您的服务是机器人程序并暂时冻结您的帐户以“保护您”。

这可能适用于较低的环境(又名:您的机器 and/or 测试环境)而不适用于生产环境,因为服务器 bot 预防系统通常会从浏览器检查 IP 地址、用户代理(如果any), API 调用率,鉴权率等。

使用率限制

在进行此类集成时,另一个可能会阻碍您的因素是速率限制。通常,500 messages/month.


可能的解决方案

解决方法 - 仍在使用 Gmail

要解决此问题并继续使用 Gmail,方法如下: https://support.google.com/accounts/answer/185833?hl=en

它被称为 application password 并且是您在您的帐户上为允许登录的特定应用程序生成的不同密码。这将跳过 OAuth 和机器人验证(至少在大多数情况下)。

正确的long-term解决方案

修复此问题的唯一可靠方法是使用正确的电子邮件发送服务。诸如 Amazon Simple Email ServiceSendgrid 或其他一些东西。

那是因为它们是为 API 调用而创建的,不会妨碍您。您可以在那里 set-up 您自己的域,包括 SPFDKIM 密钥,这样您的收件人的电子邮件服务器就会将邮件识别为安全的,并且确实是来自您的(而不是随机垃圾邮件)。