iTextSharp - Sending in-memory pdf in an email attachment

C#EmailPdfItextsharp

C# Problem Overview


I've asked a couple of questions here but am still having issues. I'd appreciate if you could tell me what I am doing wrong in my code. I run the code above from a ASP.Net page and get "Cannot Access a Closed Stream".

var doc = new Document();

MemoryStream memoryStream = new MemoryStream();

PdfWriter.GetInstance(doc, memoryStream);
doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));

doc.Close(); //if I remove this line the email attachment is sent but with 0 bytes 

MailMessage mm = new MailMessage("[email protected]", "[email protected]")
{
	Subject = "subject",
	IsBodyHtml = true,
	Body = "body"
};

mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));
SmtpClient smtp = new SmtpClient
{
	Host = "smtp.gmail.com",
	Port = 587,
	EnableSsl = true,
	Credentials = new NetworkCredential("[email protected]", "my_password")
};

smtp.Send(mm); //the "Cannot Access a Closed Stream" error is thrown here

Thanks!!!

EDIT:

Just to help somebody looking for the answer to this question, the code to send a pdf file attached to an email without having to physically create the file is below (thanks to Ichiban and Brianng):

var doc = new Document();
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));

writer.CloseStream = false;
doc.Close();
memoryStream.Position = 0;

MailMessage mm = new MailMessage("[email protected]", "[email protected]")
{
	Subject = "subject",
	IsBodyHtml = true,
	Body = "body"
};

mm.Attachments.Add(new Attachment(memoryStream, "filename.pdf"));
SmtpClient smtp = new SmtpClient
{
	Host = "smtp.gmail.com",
	Port = 587,
	EnableSsl = true,
	Credentials = new NetworkCredential("[email protected]", "password")

};

smtp.Send(mm);

C# Solutions


Solution 1 - C#

Have you tried:

PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

// Build pdf code...

writer.CloseStream = false;
doc.Close();

// Build email

memoryStream.Position = 0;
mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

If my memory serves me correctly, this solved a similar problem in a previous project.

See http://forums.asp.net/t/1093198.aspx

Solution 2 - C#

I tried the code posted by brianng and it worked. Just change the top of the code to this:

var doc = new Document();
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream); //capture the object
doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));
writer.CloseStream = false; //set the closestream property
doc.close(); //close the document without closing the underlying stream
memoryStream.Position = 0;

/* remainder of your code stays the same*/

Solution 3 - C#

Probably calling doc.Close() Disposes the underlying stream. Try removing doc.Close() and instead of that line set memoryStream.Position = 0;

Alternatively you can use a temp file:

var tempFilePath = Path.GetTempFileName();

try 
{	        
    var doc = new Document();

    PdfWriter.GetInstance(doc, File.OpenWrite(tempFilePath));
    doc.Open();
    doc.Add(new Paragraph("First Paragraph"));
    doc.Add(new Paragraph("Second Paragraph"));

    doc.Close();

    MailMessage mm = new MailMessage("[email protected]", "[email protected]")
    {
        Subject = "subject",
        IsBodyHtml = true,
        Body = "body"
    };

    mm.Attachments.Add(new Attachment(tempFilePath, "test.pdf"));
    SmtpClient smtp = new SmtpClient
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        Credentials = new NetworkCredential("[email protected]", "my_password")
    };

    smtp.Send(mm);
}
finally
{
    File.Delete(tempFilePath);
}

Solution 4 - C#

Can you flush the document or memory stream and then close it after you attach it?

Solution 5 - C#

I had the same problem and I used this post to solve it.In the code written by brianng

PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

// Build pdf code...

writer.CloseStream = false;
doc.Close();

// Build email

memoryStream.Position = 0;
mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

I think instead of writing

writer.CloseStream = false and memoryStream.Position = 0;

Just create a new Stream

MemoryStream m = new MemoryStream(memoryStream);

and then call

mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

Both work but I think it is better to create the new stream

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGus CavalcantiView Question on Stackoverflow
Solution 1 - C#brianngView Answer on Stackoverflow
Solution 2 - C#ichibanView Answer on Stackoverflow
Solution 3 - C#huseyintView Answer on Stackoverflow
Solution 4 - C#James ConigliaroView Answer on Stackoverflow
Solution 5 - C#Zein SleimanView Answer on Stackoverflow