System.ObjectDisposedException在使用SMTPCLIENT发送电子邮件时(Fluent-Email)

发布于 2025-02-01 00:26:49 字数 3545 浏览 2 评论 0原文

当我尝试使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不气馁 2025-02-08 00:26:49

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 of FluentEmail.Smtp.SendMailEx.SendMailExImplAsync.

After overridding the other dependencies in the DI extension, it worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文