我有一個 Web 應用程式,它應該在注冊時向用戶發送驗證電子郵件。我正在使用位于根目錄下的檔案夾(EmailTemplate)中的電子郵件模板,如下所示。

問題是當我在 Google Cloud Platform 上部署版本時,我在注冊時收到此錯誤

這些模板在 localhost 除錯測驗中運行良好,但在云測驗中卻不行。
.csproj 檔案
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UserSecretsId>removed intentionally</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<None Include="app.yaml" CopyToOutputDirectory="Always" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Repos\**" />
<Content Remove="Repos\**" />
<EmbeddedResource Remove="Repos\**" />
<None Remove="Repos\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.21" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.21" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.21">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="3.1.15" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.5" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.5" />
</ItemGroup>
</Project>
使用模板的電子郵件服務
public class EmailService : IEmailService
{
private const string templatePath = @"EmailTemplate/{0}.html";
private readonly SMTPConfigModel _smtpConfig;
public EmailService(IOptions<SMTPConfigModel> smtpConfig)
{
_smtpConfig = smtpConfig.Value;
}
public async Task SendTestEmail(EmailDataModel testEmailModel)
{
testEmailModel.Subject = FillPlaceholders("Hello {{UserName}} this test subject", testEmailModel.PlaceHolders);
testEmailModel.Body = FillPlaceholders(EmailBodyTemplateGetter("TestEmail"), testEmailModel.PlaceHolders);
await SendEmail(testEmailModel);
}
public async Task SendVerificationEmail(EmailDataModel emailVerifyModel)
{
emailVerifyModel.Subject = FillPlaceholders("Please verify your email", emailVerifyModel.PlaceHolders);
emailVerifyModel.Body = FillPlaceholders(EmailBodyTemplateGetter("EmailVerification"), emailVerifyModel.PlaceHolders);
await SendEmail(emailVerifyModel);
}
private async Task SendEmail(EmailDataModel email)
{
MailMessage mail = new MailMessage
{
Subject = email.Subject,
Body = email.Body,
From = new MailAddress(_smtpConfig.SenderAddress, _smtpConfig.SenderDisplayName),
IsBodyHtml = _smtpConfig.IsBodyHTML
};
foreach (var item in email.ToEmails)
mail.To.Add(item);
NetworkCredential networkCredential = new NetworkCredential(_smtpConfig.UserName, _smtpConfig.Password);
SmtpClient smtpClient = new SmtpClient
{
Host = _smtpConfig.Host,
Port = _smtpConfig.Port,
EnableSsl = _smtpConfig.EnableSSL,
UseDefaultCredentials = _smtpConfig.UseDefaultCredentials,
Credentials = networkCredential
};
mail.BodyEncoding = Encoding.Default;
await smtpClient.SendMailAsync(mail);
}
private string EmailBodyTemplateGetter(string templateName)
{
=========> string filepath = string.Format(templatePath, templateName); <==========
var body = File.ReadAllText(filepath);
return body;
}
private string FillPlaceholders(string text, List<KeyValuePair<string, string>> keyValuePairs)
{
if (!string.IsNullOrEmpty(text) && keyValuePairs != null)
foreach (var placeholder in keyValuePairs)
if (text.Contains(placeholder.Key))
text = text.Replace(placeholder.Key, placeholder.Value);
return text;
}
}
Register.cs 類中的呼叫方法
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new PtUser { UserName = Input.Email, Email = Input.Email, FirstName = Input.FirstName, LastName = Input.LastName };
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);
EmailDataModel emailDataModel = new EmailDataModel()
{
ToEmails = new List<string>() { Input.Email },
PlaceHolders = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("{{UserName}}", user.FirstName),
new KeyValuePair<string, string>("{{Link}}", callbackUrl)
}
};
=======> await _emailService.SendVerificationEmail(emailDataModel); <============
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
uj5u.com熱心網友回復:
根據asp.net core 3.1靜態檔案可通過相對于 Web 根目錄的路徑訪問。wwwroot因此,在生產環境中無法訪問外部的任何檔案。在這種情況下,您必須將EmailTemplate檔案夾移動到內部,wwwroot如下圖所示:

然后
Startup.Configure你必須添加這個中間件的參考app.UseStaticFiles();while you would browse the directory you have to modify code like this way注意:在這種情況下,您的路徑應該是這樣
wwwroot/EmailTemplate/EmailTemplate.html的,您的代碼應該是這樣的:private const string templatePath = @"wwwroot/EmailTemplate/{0}.html";
希望上述步驟能相應地指導您。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/430887.html
標籤:html asp.net-mvc asp.net 核心 谷歌云平台 html-电子邮件
