PdfGenerator EmailMessage EmailAttachment - Не удается получить доступ к закрытому потоку - PullRequest
0 голосов
/ 23 октября 2018

Ошибка System.ObjectDisposedException с сообщением Cannot access a closed Stream выдается при попытке присоединить и отправить System.IO.MemoryStream EmailAttachment на EmailMessage.Вложение создается с использованием HtmlRenderer.PdfSharp .Присоединение и отправка выполняются в операторе using.

using (MemoryStream ms = new MemoryStream())
{
    var pdf = PdfGenerator.GeneratePdf("<html><body>foo</body></html>", PdfSharp.PageSize.Letter);
    // 2nd argument is to NOT close stream
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    // SiteContext.CurrentSiteName argument is just a site name required for Kentico CMS
    // true argument is send immediately
    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);    
}

Если вместо этого я сделаю следующее, то это успешно, ошибка не произойдет, пока я не попытаюсь выполнить ms.Dispose() в пределах try блок:

MemoryStream ms = new MemoryStream();
try
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception)
{
    ms.Dispose();
}

Проблема, связанная со вторым подходом, заключается в том, что MemoryStream явно не утилизируется.Является ли MemoryStream изначально имеющим такой подход?Если поставить ms.Dispose(); после , то для всего этого блока происходит то же самое Cannot access a closed Stream.Это утечка памяти в ожидании?Как я могу утилизировать MemoryStream, не закрывая поток, чтобы позволить почтовому сообщению отправить вложение?

Это проблема с необходимостью как-то ждать, пока SendEmail() фактически выполнит свою функцию?

Спасибо за любую помощь, которую вы можете оказать.

Ответы [ 3 ]

0 голосов
/ 23 октября 2018

Я смог прийти к решению, используя следующий код.Возможно, это была скорее проблема Kentico CMS, связанная с аргументом sendImmediately о SendMail().Установив для него значение false (по умолчанию), я смог присоединить поток как EmailAttachment без ошибки System.ObjectDisposedException все в операторе using.

using (MemoryStream ms = new MemoryStream())
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment.";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    // default sendImmediately of false
    EmailSender.SendEmail(SiteContext.CurrentSiteName, em);
}
0 голосов
/ 24 октября 2018

Ну, вам просто нужно закрыть поток перед доступом к нему из Kentico, то есть:

using (MemoryStream ms = new MemoryStream())
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
    pdf.Save(ms, false);
}

А затем вы сделаете свою электронную часть:

0 голосов
/ 23 октября 2018
  1. Я не понимаю, почему вы хотите расположить ms в блоке try, обычно для очистки переменных вы используете блок finally, который всегда будет выполняться независимо от того, есть исключение или нет.

  2. Если вы используете улов (этот вид улова с Exception улавливает все исключения), вы не будете получать ошибки, потому что вы улавливаете их

Как выдолжен сделать это:

MemoryStream ms = new MemoryStream();
try
{
    var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
    pdf.Save(ms, false);

    EmailMessage em = new EmailMessage();
    em.EmailFormat = EmailFormatEnum.Html;
    em.From = "no-reply@foo.com";
    em.Recipients = "foo.bar@baz.net";
    em.Subject = "Attachment Name";
    em.Body = "There is an attachment";

    var attachment = new EmailAttachment(ms, "foo.pdf");
    em.Attachments.Add(attachment);

    EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
ms.Dispose();
}
...