System.ObjectDisposedException在使用SMTPCLIENT发送电子邮件时(Fluent-Email)
当我尝试使用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
> 瞬态, scoped ,作为 singleton ,但没有解决此问题的选项。
DI代码:
var smtpClient = new SmtpClient(smtpSenderOptions.Host, smtpSenderOptions.Port)
{
EnableSsl = smtpSenderOptions.EnableSsl
};
services.AddSingleton(instance => smtpClient);
用法(摘自Fluent-Email库( https://github.com/lukencode/lukencode/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);
I am getting a System.ObjectDisposedException
when i try to send an e-mail in a .NET core 6.0 project using the fluent-email library:
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)
I have tried to inject the smtpclient
transient, scoped and as a singleton but neither one of the options fixed this issue.
DI code:
var smtpClient = new SmtpClient(smtpSenderOptions.Host, smtpSenderOptions.Port)
{
EnableSsl = smtpSenderOptions.EnableSsl
};
services.AddSingleton(instance => smtpClient);
Usage (from the fluent-email library (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();
}
}
}
My code calling the library:
var response = await _fluentEmail
.Subject(emailContents.Subject)
.To(emailContents.To)
.Attach(attachments)
.UsingTemplate(template, emailContents)
.SendAsync(cancellationToken);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Fluent-Email提供的扩展名确实将这些类注射为Singleton和我确实使用了另一个生命周期,因此发生了这个问题。
因此,我也忘了使用
system.ObjectDisposedexception
使用Singleton的所有依赖项的依赖项注入容器配置,因为我正在使用自定义实现fluentemail.smtp.sendmail.sendmailmail.sendmailmailex.sendmailmaileximpleximpleximpleximplasync 。
在DI扩展中超越了其他依赖关系之后,它起作用了。
The extensions provided by fluent-email did inject these classes as singleton and I did use another lifetime and therefore this issue occured.
So I forgot to also override the dependency injection container configuration for all dependencies using the
System.ObjectDisposedException
to use singleton, since I was using a custom implementation ofFluentEmail.Smtp.SendMailEx.SendMailExImplAsync
.After overridding the other dependencies in the DI extension, it worked.