我目前正在设置一个.net核心Web应用程序,并设置了MailKit来处理它的电子邮件发送。
我没有硬编码我的smtp密码,而是使用了用户密码选项。但是由于某些原因,每次我尝试检索密码时,它都会返回null。 错误:
处理请求时发生未处理的异常。 ArgumentNullException:值不能为null。 参数名称:密码 MessageServices.cs中的MoveNext,第56行
我想知道是否有人能看到我错过的东西!
这是我的MessageService.cs
public class AuthMessageSender : IEmailSender, ISmsSender
{
public IConfiguration Configuration { get; set; }
public AuthMessageSender()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public async Task SendEmailAsync(string email, string subject, string message, string fullName)
{
try
{
var _email = "info@*******.co.uk";
var _epass = Configuration["AdminPassword:Email"];
var _dispName = "Mark ****";
var myMessage = new MimeMessage();
var builder = new BodyBuilder();
myMessage.To.Add(new MailboxAddress(fullName ?? "User", email));
myMessage.From.Add(new MailboxAddress(_dispName, _email));
myMessage.Subject = subject;
builder.HtmlBody = message;
myMessage.Body = builder.ToMessageBody();
using (SmtpClient smtp = new SmtpClient())
{
bool UseSSL = true;
string Host = "just22.justhost.com";
int Port = 465;
await smtp.ConnectAsync(Host, Port, UseSSL).ConfigureAwait(true);
smtp.AuthenticationMechanisms.Remove("XOAUTH2");
smtp.Authenticate(_email, _epass); // Note: only needed if the SMTP server requires authentication
await smtp.SendAsync(myMessage).ConfigureAwait(false);
await smtp.DisconnectAsync(true).ConfigureAwait(false);
}
}
catch (Exception ex)
{
throw ex;
}
}
public Task SendSmsAsync(string number, string message)
{
// Plug in your SMS service here to send a text message.
return Task.FromResult(0);
}
这是我的Start.cs
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddDistributedMemoryCache();
services.AddSession();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public async void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory, IServiceProvider serviceProvider, ApplicationDbContext context)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseSession();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseFacebookAuthentication(new FacebookOptions()
{
AppId = Configuration["Authentication:Facebook:AppId"],
AppSecret = Configuration["Authentication:Facebook:AppSecret"]
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
await CreateRoles(context, serviceProvider);
}
private async Task CreateRoles(ApplicationDbContext context, IServiceProvider serviceProvider)
{
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
// Create a list of roles with both name and normalised name attributes
List<IdentityRole> roles = new List<IdentityRole>();
roles.Add(new IdentityRole { Name = "Admin", NormalizedName = "ADMIN" });
roles.Add(new IdentityRole { Name = "Member", NormalizedName = "MEMBER" });
roles.Add(new IdentityRole { Name = "Moderator", NormalizedName = "MODERATOR" });
// Check if the role already exists
foreach (var role in roles)
{
var roleExist = await RoleManager.RoleExistsAsync(role.Name);
if (!roleExist)
{ // Add it if it doesn't
context.Roles.Add(role);
context.SaveChanges();
}
}
var user = await userManager.FindByEmailAsync("mark****@gmail.com");
if (user != null)
{
var gotRoles = userManager.GetRolesAsync(user);
if (!gotRoles.Equals("Admin"))
{
await userManager.AddToRoleAsync(user, "Admin");
}
}
}
}
我已经检查过以确保它存在的秘密,以及Facebook身份验证机密,这似乎工作正常。
如果我对密码进行硬编码,则会发送电子邮件。当我设置断点时,我可以看到密码确实为空。我有点难过!
提前致谢。
答案 0 :(得分:1)
基于@Kritner和此链接提供的信息的新答案:Access to Configuration object from Startup class
首先,我创建了一个POCO,其中包含我应该看不见的所有SMTP属性,如下所示:
public class SmtpConfig
{
public string EmailDisplayName { get; set; }
public string SmtpPassworrd { get; set; }
public string SmtpUserEmail { get; set; }
public string SmtpHost { get; set; }
public int SmtpPort { get; set; }
}
然后在My Startup.cs中我将其添加到ConfigureServices:
services.Configure<SmtpConfig>(optionsSetup =>
{
//get from appsetings.json file
optionsSetup.SmtpPassworrd = Configuration["SMTP:Password"];
optionsSetup.SmtpUserEmail = Configuration["SMTP:Email"];
optionsSetup.SmtpHost = Configuration["SMTP:Host"];
optionsSetup.SmtpPort = Convert.ToInt32(Configuration["SMTP:Port"]);
});
最后我编辑了我的messageServices看起来像这样:
public class AuthMessageSender : IEmailSender, ISmsSender
{
private readonly IOptions<SmtpConfig> _smtpConfig;
public IConfiguration Configuration { get; set; }
public AuthMessageSender( IOptions<SmtpConfig> smtpConfig)
{
_smtpConfig = smtpConfig;
}
public async Task SendEmailAsync(string email, string subject, string message, string fullName)
{
try
{
var _email = _smtpConfig.Value.SmtpUserEmail;
string _epass = _smtpConfig.Value.SmtpPassworrd;
var _dispName = _smtpConfig.Value.EmailDisplayName;
var myMessage = new MimeMessage();
var builder = new BodyBuilder();
myMessage.To.Add(new MailboxAddress(fullName ?? "User", email));
myMessage.From.Add(new MailboxAddress(_dispName, _email));
myMessage.Subject = subject;
builder.HtmlBody = message;
myMessage.Body = builder.ToMessageBody();
using (SmtpClient smtp = new SmtpClient())
{
bool UseSSL = true;
string Host = _smtpConfig.Value.SmtpHost;
int Port = _smtpConfig.Value.SmtpPort;
await smtp.ConnectAsync(Host, Port, UseSSL).ConfigureAwait(true);
smtp.AuthenticationMechanisms.Remove("XOAUTH2");
smtp.Authenticate(_email, _epass); // Note: only needed if the SMTP server requires authentication
await smtp.SendAsync(myMessage).ConfigureAwait(true);
await smtp.DisconnectAsync(true).ConfigureAwait(true);
}
}
catch (Exception ex)
{
throw ex;
}
}