An error System.ObjectDisposedException
with message Cannot access a closed Stream
is being thrown when attempting to attach and send an System.IO.MemoryStream
EmailAttachment
to an EmailMessage
. The attachment is being generated using HtmlRenderer.PdfSharp. The attaching and sending is being done within a using statement.
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 = "[email protected]";
em.Recipients = "[email protected]";
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);
}
If I do the following instead, it is successful the error does not occur as long as I do not attempt to ms.Dispose()
within the try
block:
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 = "[email protected]";
em.Recipients = "[email protected]";
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();
}
The concern with the 2nd approach is that the MemoryStream
is not being explicitly disposed. Is the MemoryStream
inherently being disposed with this approach? If put ms.Dispose();
after this entire block the same Cannot access a closed Stream
occurs. Is this a memory leak waiting to happen? How can I dispose the MemoryStream
without closing the stream to allow the email message to send the attachment?
Is this an issue with needing to somehow wait for SendEmail()
to actually execute it's functionality?
Thank you for any help you can provide.
I was able to come to a solution using the following code. It really may have been more of a Kentico CMS issue regarding the sendImmediately
argument of SendMail()
. By setting that to false
(default), I was able to attach the stream as an EmailAttachment
without the System.ObjectDisposedException
error all within using
statement.
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 = "[email protected]";
em.Recipients = "[email protected]";
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);
}