Подтвердить что ты не робот

Поток закрывается при добавлении в MailMessage

Я использую следующий код для прикрепления файла к сообщению электронной почты.

msg = new MailMessage();

    using (strMem = new MemoryStream((byte[])attDr["filedata"]))
    {
        using (strWriter = new StreamWriter(strMem))
        {
            strWriter.Flush(); strMem.Position = 0;
            using (attachment = new Attachment(strMem, attDr["filename"].ToString()))
            {
                msg.Attachments.Add(attachment);
            }
        }
    }

...
...
msg.Send();  //Error: System.ObjectDisposedException: Cannot access a closed Stream.

Сообщение об ошибке://Ошибка: System.ObjectDisposedException: невозможно получить доступ к закрытому потоку

Я предполагаю, что оператор USING закрывает поток при выходе из блока. Но почему "Attacments.Add()" не создает собственную копию потока?

4b9b3361

Ответ 1

Метод Send() будет обращаться к вложениям, чтобы вставлять их в почтовое сообщение. Это происходит здесь, поток памяти был удален. Вам нужно переместить вызов Send() внутри операторов using, чтобы поток не удалялся до тех пор, пока сообщение не будет отправлено.

Упоминание о том, что использование здесь не требуется, потому что в потоке памяти нет неуправляемых ресурсов, которые должны быть удалены, всегда вызывает у меня проблемы в SO. Поэтому я не приму этого.

Ответ 2

Одно из решений, которое я нашел, когда я имел дело со сценарием, когда MailMessage создавался отдельно от отправки и потенциально с несколькими вложениями, заключался в использовании объектов списка объектов MemoryStream

// Tuple contains displayName and byte[] content for attachment in this case
List<Tuple<string,byte[]>> attachmentContent;
MailMessage email = BuildNativeEmail(requestObject, out attachmentContent);
List<MemoryStream> streams = new List<MemoryStream>();
foreach(Tuple<string,byte[]> attachment in attachmentContent)
{
    MemoryStream m = new MemoryStream(attachment.Item2);
    email.Attachments.Add(new System.Net.Mail.Attachment(m, attachment.Item1));
    streams.add(m);
}

// client represents a System.Net.Mail.SmtpClient object
client.Send(email);

foreach(MemoryStream stream in streams)
{
    stream.Dispose();
}

Ответ 3

Использование:

using (strMem = new MemoryStream((byte[])attDr["filedata"]))
{
    using (strWriter = new StreamWriter(strMem))
    {
        strWriter.Flush(); strMem.Position = 0;
        using (attachment = new Attachment(attDr["filename"].ToString()))
        {
            strMem.CopyTo(attachment.ContentStream);
            msg.Attachments.Add(attachment);
        }
    }
}

Ответ 4

Поместите использование в MailMessage, оно будет внутренне удалять потоки, составляющие вложения

using(var msg = new MailMessage())
{
    ...
    ...
    var attachment = new Attachment(strMem, filename,contentType);
    msg.Attachments.Add(attachment);
    ...
    ...             
    msg.Send();
}