I'm trying to zip an XML tree and use it as an email attachment. The sending of the email with an attachment succeeds, but the zip file created is always corrupt – it is not a valid zip file but does contain binary data.
The problem is recreated as follows, see specifically BuildAttachment()
:
static void Main(string[] args)
{
try
{
var report = new XElement("Report",
new XElement("Product",
new XElement("ID", "10000001"),
new XElement("Name", "abcdefghijklm"),
new XElement("Group", "nopqrstuvwxyz")
)
);
var mailMessage = BuildMessage(report);
EmailMessage(mailMessage);
Thread.Sleep(10000);
}
catch (Exception e) { Console.WriteLine(e.Message); }
}
static MailMessage BuildMessage(XElement report)
{
string from = "[email protected]";
string to = "[email protected]";
var message = new MailMessage(from, to, "Subject text", "Body text");
var attachment = BuildAttachment(report);
message.Attachments.Add(attachment);
return message;
}
static Attachment BuildAttachment(XElement report)
{
var inStream = new MemoryStream();
report.Save(inStream);
inStream.Position = 0;
var outStream = new MemoryStream();
var compress = new DeflateStream(outStream, CompressionMode.Compress);
inStream.CopyTo(compress);
outStream.Position = 0;
return new Attachment(outStream, "report.zip", "application/zip");
}
static void EmailMessage(MailMessage message)
{
var smtpClient = new SmtpClient("127.0.0.1");
smtpClient.SendCompleted += SendCompletedCallback;
smtpClient.SendAsync(message, null);
}
static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
Console.WriteLine(e.Error.ToString());
}
To put the problem in context: It’s part of a windows service application so I don’t want to create files on disk, and the email message also contains xslt-transformed alternate views of the xml tree so I don’t want a completely different solution.
Any suggestions why the zip file is corrupt?
I know this is an old question, but it turned up when I was searching for the same.
Here is my solution to add a compressed (zip) attachment using System.IO.Compression.ZipArchive (requires .NET 4.5 or higher) [based on the answer of acraig5075]:
byte[] report = GetSomeReportAsByteArray();
string fileName = "file.txt";
using (MemoryStream memoryStream = new MemoryStream())
{
using (ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Update))
{
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName);
using (StreamWriter streamWriter = new StreamWriter(zipArchiveEntry.Open()))
{
streamWriter.Write(Encoding.Default.GetString(report));
}
}
MemoryStream attachmentStream = new MemoryStream(memoryStream.ToArray());
Attachment attachment = new Attachment(attachmentStream, fileName + ".zip", MediaTypeNames.Application.Zip);
mail.Attachments.Add(attachment);
}