.Net Core 5.0用户注册触发MailboxAddress构造方法缺失异常
在基于.Net Core 5.0开发的项目中,执行用户注册操作时返回异常。初步排查怀疑问题由Netcore.MailKit导致,不排除AutoMapper侧存在配置问题,本次使用的是日常开发常用的成熟代码结构。运行时返回的具体异常如下:
MissingMethodException: Method not found: 'Void MimeKit.MailboxAddress..ctor(System.String)'
项目依赖版本
- Netcore.MailKit Version: 2.0.3
- Microsoft.AspNetcore.Http.Features version: 5.0.9
相关业务代码
用户注册方法
if (!ModelState.IsValid) { return View(userModel); } var user = _mapper.Map<User>(userModel); var result = await userManager.CreateAsync(user, userModel.Password); if (!result.Succeeded) { foreach (var error in result.Errors) { ModelState.TryAddModelError(error.Code, error.Description); } return View(userModel); } await userManager.AddToRoleAsync(user, "Customer"); var token = await userManager.GenerateEmailConfirmationTokenAsync(user); var confirmationLink = Url.Action(nameof(ConfirmEmail), "Account", new { token, email = user.Email }, Request.Scheme); var message = new Message(new string[] { user.Email }, "Confirmation email link", confirmationLink, null); await emailSender.SendEmailAsync(message); return RedirectToAction(nameof(SuccessRegister));
EmailSender类实现
public class EmailSender : IEmailSender { private readonly EmailConfiguration _emailConfig; public EmailSender(EmailConfiguration emailConfig) { _emailConfig = emailConfig; } public void SendEmail(Message message) { var emailMessage = CreateEmailMessage(message); Send(emailMessage); } public async Task SendEmailAsync(Message message) { var mailMessage = CreateEmailMessage(message); await SendAsync(mailMessage); } private MimeMessage CreateEmailMessage(Message message) { var emailMessage = new MimeMessage(); emailMessage.From.Add(new MailboxAddress(_emailConfig.From)); emailMessage.To.AddRange(message.To); emailMessage.Subject = message.Subject; var bodyBuilder = new BodyBuilder { HtmlBody = string.Format("<h2 style='color:red;'>{0}</h2>", message.Content) }; if (message.Attachments != null && message.Attachments.Any()) { byte[] fileBytes; foreach (var attachment in message.Attachments) { using (var ms = new MemoryStream()) { attachment.CopyTo(ms); fileBytes = ms.ToArray(); } bodyBuilder.Attachments.Add(attachment.FileName, fileBytes, ContentType.Parse(attachment.ContentType)); } } emailMessage.Body = bodyBuilder.ToMessageBody(); return emailMessage; } private void Send(MimeMessage mailMessage) { using (var client = new SmtpClient()) { try { client.Connect(_emailConfig.SmtpServer, _emailConfig.Port, true); client.AuthenticationMechanisms.Remove("XOAUTH2"); client.Authenticate(_emailConfig.UserName, _emailConfig.Password); client.Send(mailMessage); } catch { // 记录错误日志或抛出异常 throw; } finally { client.Disconnect(true); client.Dispose(); } } } private async Task SendAsync(MimeMessage mailMessage) { using (var client = new SmtpClient()) { try { await client.ConnectAsync(_emailConfig.SmtpServer, _emailConfig.Port, true); client.AuthenticationMechanisms.Remove("XOAUTH2"); await client.AuthenticateAsync(_emailConfig.UserName, _emailConfig.Password); await client.SendAsync(mailMessage); } catch { // 记录错误日志或抛出异常 throw; } finally { await client.DisconnectAsync(true); client.Dispose(); } } } }
Message类定义
public class Message { public List<MailboxAddress> To { get; set; } public string Subject { get; set; } public string Content { get; set; } public IFormFileCollection Attachments { get; set; } public Message(IEnumerable<string> to, string subject, string content, IFormFileCollection attachments) { To = new List<MailboxAddress>(); To.AddRange(to.Select(x => new MailboxAddress(x))); Subject = subject; Content = content; Attachments = attachments; } }
Startup服务注册代码
.AddEntityFrameworkStores<AppDbContext>() .AddDefaultTokenProviders() .AddErrorDescriber<TurkishIdentityErrorDescriber>(); var emailConfig = Configuration.GetSection("EmailConfiguration").Get<EmailConfiguration>(); services.AddSingleton(emailConfig); services.AddSingleton<Extension>(); services.AddScoped<IEmailSender, EmailSender>(); services.Configure<DataProtectionTokenProviderOptions>(opt => opt.TokenLifespan = TimeSpan.FromHours(2)); services.AddAutoMapper(typeof(Startup));
该异常与AutoMapper配置无关,属于典型的依赖版本不兼容问题。
Netcore.MailKit 2.0.3 依赖2.x版本的MimeKit,此版本中MailboxAddress提供了仅接收1个字符串参数(邮箱地址)的构造函数。但项目运行时实际加载的是3.0及以上版本的MimeKit——高版本MimeKit出于邮箱地址解析准确性考虑,移除了这个单参数构造函数,要求必须传入「显示名称」「邮箱地址」两个参数,因此运行时找不到匹配的构造方法,直接抛出MissingMethodException。
出现隐式加载高版本MimeKit的原因,一般是项目中其他NuGet包间接依赖了高版本MimeKit,NuGet还原时自动升级了依赖版本,覆盖了Netcore.MailKit要求的低版本依赖。
两种方案按需选择即可:
方案1:适配高版本MimeKit构造函数(推荐)
无需调整依赖版本,仅修改所有调用MailboxAddress单参数构造的位置,改为双参数形式即可,显示名称如果不需要可以传空字符串:
- 修改Message类构造函数中的地址转换逻辑:
// 原代码 To.AddRange(to.Select(x => new MailboxAddress(x))); // 修改后 To.AddRange(to.Select(x => new MailboxAddress("", x)));
- 修改EmailSender类中设置发件人的代码:
// 原代码 emailMessage.From.Add(new MailboxAddress(_emailConfig.From)); // 修改后 emailMessage.From.Add(new MailboxAddress("", _emailConfig.From));
修改完成后重新编译运行即可解决问题。
方案2:锁定MimeKit为兼容低版本
如果不想修改业务代码,可以在项目csproj文件中手动添加MimeKit的版本引用,强制使用和Netcore.MailKit 2.0.3兼容的2.x版本,添加如下配置:
<ItemGroup> <PackageReference Include="MimeKit" Version="2.15.0" /> </ItemGroup>
添加后重新执行NuGet包还原即可。
内容的提问来源于stack exchange,提问作者Ramazan Musluoğlu

