【发布时间】:2022-06-13 14:18:09
【问题描述】:
当我尝试使用 fluent-email 库在 .NET core 6.0 项目中发送电子邮件时,我收到了 System.ObjectDisposedException:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Mail.SmtpClient'.
at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken)
at FluentEmail.Smtp.SendMailEx.SendMailExImplAsync(SmtpClient client, MailMessage message, CancellationToken token)
我曾尝试注入 smtpclient transient、scoped 并作为 singleton,但没有一个选项可以解决此问题。
DI 代码:
var smtpClient = new SmtpClient(smtpSenderOptions.Host, smtpSenderOptions.Port)
{
EnableSsl = smtpSenderOptions.EnableSsl
};
services.AddSingleton(instance => smtpClient);
用法(来自 fluent-email 库 (https://github.com/lukencode/FluentEmail)):
// Taken from https://stackoverflow.com/questions/28333396/smtpclient-sendmailasync-causes-deadlock-when-throwing-a-specific-exception/28445791#28445791
// SmtpClient causes deadlock when throwing exceptions. This fixes that.
public static class SendMailEx
{
public static Task SendMailExAsync(
this SmtpClient @this,
MailMessage message,
CancellationToken token = default(CancellationToken))
{
// use Task.Run to negate SynchronizationContext
return Task.Run(() => SendMailExImplAsync(@this, message, token));
}
private static async Task SendMailExImplAsync(
SmtpClient client,
MailMessage message,
CancellationToken token)
{
token.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<bool>();
SendCompletedEventHandler handler = null;
Action unsubscribe = () => client.SendCompleted -= handler;
handler = async (_, e) =>
{
unsubscribe();
// a hack to complete the handler asynchronously
await Task.Yield();
if (e.UserState != tcs)
tcs.TrySetException(new InvalidOperationException("Unexpected UserState"));
else if (e.Cancelled)
tcs.TrySetCanceled();
else if (e.Error != null)
tcs.TrySetException(e.Error);
else
tcs.TrySetResult(true);
};
client.SendCompleted += handler;
try
{
client.SendAsync(message, tcs);
using (token.Register(() =>
{
client.SendAsyncCancel();
}, useSynchronizationContext: false))
{
await tcs.Task;
}
}
finally
{
unsubscribe();
}
}
}
我的代码调用库:
var response = await _fluentEmail
.Subject(emailContents.Subject)
.To(emailContents.To)
.Attach(attachments)
.UsingTemplate(template, emailContents)
.SendAsync(cancellationToken);
【问题讨论】:
-
您需要包含如何使用它的代码。
-
由于大部分魔法都发生在 fluentemail 项目中,我想我可能对所有异步内容都做错了。
-
看起来您有两个客户。您还需要在每条消息之前为客户端调用构造函数。您不能重复使用客户端。
-
ASP.NET Core 不使用同步上下文,SMTPClient 不会死锁,不需要实现。
-
I have tried to inject the smtpclient transient, scoped and as a singleton but neither one of the options fixed this issue.=> 好吧,当然不是,你总是返回同一个实例,一旦处理它就不能再使用了。
标签: c# .net-core smtpclient