Поток закрывается при добавлении в 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()" не создает собственную копию потока?
Ответы
Ответ 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();
}