Here is the sample code.
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);
writer.Write("Hello its my sample file");
writer.Flush();
writer.Dispose();
ms.Position = 0;
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
attach.ContentDisposition.FileName = "myFile.txt";
// I guess you know how to send email with an attachment
// after sending email
ms.Close();
Edit 1
You can specify other file types by System.Net.Mime.MimeTypeNames like System.Net.Mime.MediaTypeNames.Application.Pdf
Based on Mime Type you need to specify correct extension in FileName for instance "myFile.pdf"
A bit of a late entry - but hopefully still useful to someone out there:-
Here's a simplified snippet for sending an in-memory string as an email attachment (a CSV file in this particular case).
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream)) // using UTF-8 encoding by default
using (var mailClient = new SmtpClient("localhost", 25))
using (var message = new MailMessage("[email protected]", "[email protected]", "Just testing", "See attachment..."))
{
writer.WriteLine("Comma,Seperated,Values,...");
writer.Flush();
stream.Position = 0; // read from the start of what was written
message.Attachments.Add(new Attachment(stream, "filename.csv", "text/csv"));
mailClient.Send(message);
}
The StreamWriter and underlying stream should not be disposed until after the message has been sent (to avoid ObjectDisposedException: Cannot access a closed Stream
).
Since I couldn't find confirmation of this anywhere, I tested if disposing of the MailMessage and/or the Attachment object would dispose of the stream loaded into them as I expected would happen.
It does appear with the following test that when the MailMessage is disposed, all streams used to create attachments will also be disposed. So as long as you dispose your MailMessage the streams that went into creating it do not need handling beyond that.
MailMessage mail = new MailMessage();
//Create a MemoryStream from a file for this test
MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"C:\temp\test.gif"));
mail.Attachments.Add(new System.Net.Mail.Attachment(ms, "test.gif"));
if (mail.Attachments[0].ContentStream == ms) Console.WriteLine("Streams are referencing the same resource");
Console.WriteLine("Stream length: " + mail.Attachments[0].ContentStream.Length);
//Dispose the mail as you should after sending the email
mail.Dispose();
//--Or you can dispose the attachment itself
//mm.Attachments[0].Dispose();
Console.WriteLine("This will throw a 'Cannot access a closed Stream.' exception: " + ms.Length);
If you actually want to add a .pdf, I found it necessary to set the position of the memory stream to Zero.
var memStream = new MemoryStream(yourPdfByteArray);
memStream.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var reportAttachment = new Attachment(memStream, contentType);
reportAttachment.ContentDisposition.FileName = "yourFileName.pdf";
mailMessage.Attachments.Add(reportAttachment);
If all you're doing is attaching a string, you could do it in just 2 lines:
mail.Attachments.Add(Attachment.CreateAttachmentFromString("1,2,3", "text/csv");
mail.Attachments.Last().ContentDisposition.FileName = "filename.csv";
I wasn't able to get mine to work using our mail server with StreamWriter.
I think maybe because with StreamWriter you're missing a lot of file property information and maybe our server didn't like what was missing.
With Attachment.CreateAttachmentFromString() it created everything I needed and works great!
Otherwise, I'd suggest taking your file that is in memory and opening it using MemoryStream(byte[]), and skipping the StreamWriter all together.
I landed on this question because I needed to attach an Excel file I generate through code and is available as MemoryStream
. I could attach it to the mail message but it was sent as 64Bytes file instead of a ~6KB as it was meant. So, the solution that worked for me was this:
MailMessage mailMessage = new MailMessage();
Attachment attachment = new Attachment(myMemorySteam, new ContentType(MediaTypeNames.Application.Octet));
attachment.ContentDisposition.FileName = "myFile.xlsx";
attachment.ContentDisposition.Size = attachment.Length;
mailMessage.Attachments.Add(attachment);
Setting the value of attachment.ContentDisposition.Size
let me send messages with the correct size of attachment.
use OTHER OPEN memorystream:
example for lauch pdf and send pdf in MVC4 C# Controller
public void ToPdf(string uco, int idAudit)
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename= Document.pdf");
Response.Buffer = true;
Response.Clear();
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.OutputStream.Flush();
}
public ActionResult ToMail(string uco, string filter, int? page, int idAudit, int? full)
{
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
using (var stream = new MemoryStream(bytes))
using (var mailClient = new SmtpClient("**YOUR SERVER**", 25))
using (var message = new MailMessage("**SENDER**", "**RECEIVER**", "Just testing", "See attachment..."))
{
stream.Position = 0;
Attachment attach = new Attachment(stream, new System.Net.Mime.ContentType("application/pdf"));
attach.ContentDisposition.FileName = "test.pdf";
message.Attachments.Add(attach);
mailClient.Send(message);
}
ViewBag.errMsg = "Documento enviado.";
return Index(uco, filter, page, idAudit, full);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With