Zip a MemoryStream for an email attachment

acraig5075 picture acraig5075 · Jul 23, 2012 · Viewed 11.1k times · Source

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?

Answer

Niels R. picture Niels R. · Jan 3, 2014

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);
}