I need to be able to send textual data stored in a database in multiple row format as txt file attachments in an email. Think Notes added to something by different people at different times.
As of right now the email sends and there are some text files generated like test0.txt and test1.txt but they're empty. I'm flushing the streamwriter so to me it seems like the file should have text in it. I can't close the stream writer before I send the email because then I get an error saying cannot read from closed stream. I'm storing both the memorystream and streamwriter in containers so they shouldn't get disposed of or cleaned up until the very end. I wonder if the email object gets lost or for some reason can't access the streams stored in the containers?
I've looked at some similar questions on SO but they don't seem to work.
This person is using byte[] so only memory stream no streamwriter
This person disposes of their streamwriter before sending email which errors out for me
Instead of trying to do this in memory should I just be writing temp files and then including those as attachments? It seems slow to write to disk just so that I can then read from disk to attach the attachment.
var companyEmail = new MailAddress("address@company.com", "Person Name");
email.To.Add(companyEmail);
email.From = new System.Net.Mail.MailAddress("donotreply@company.com", "doesn't matter");
email.Subject = "subject";
email.Body = "body";
email.IsBodyHtml = true;
var nonAttCounter = 0;
var nonAttStreamHolder = new List<MemoryStream>();
var nonAttWriterHolder = new List<StreamWriter>();
//churn through the attachments and see if any of them are checked in the form
foreach (DataRow datarow in claim.attachments.Rows)
{
string cbFormName = "ctl00$MainBody$att" + datarow["attNum"].ToString();//name of checkbox controls on page and in form.
var includedInForm = rForm[cbFormName];
//see if the attachment was selected as one to include.ie the attNum is in the posted form.
if (includedInForm != null)
{
string origData = datarow["origData"].ToString();
string[] fIDs = origData.Split(',');
foreach (var item in fIDs)
{
//not all attachments are real attachments with files...cause why would attachments be attachments.
int fid;
bool isInt = int.TryParse(item, out fid);
if (isInt)
{
var tempDS = new datastore(ref fid);
var tempData = tempDS.blobData;
email.Attachments.Add(new Attachment(tempData, tempDS.fileNameWithExt));
}
else
{
//grab all the textual data from the database for this "attachment" and write it to a memory stream and upload to the email
nonAttStreamHolder.Add(new MemoryStream());
nonAttWriterHolder.Add(new StreamWriter(nonAttStreamHolder[nonAttCounter]));
nonAttWriterHolder[nonAttCounter].WriteLine("This is a test.");
nonAttWriterHolder[nonAttCounter].WriteLine("Why this no work?!");
nonAttWriterHolder[nonAttCounter].Flush();
//nonAttWriterHolder[nonAttCounter].Close();
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
System.Net.Mail.Attachment tempFile = new System.Net.Mail.Attachment(nonAttStreamHolder[nonAttCounter], ct);
tempFile.ContentDisposition.FileName = "test" + nonAttCounter + ".txt";
email.Attachments.Add(tempFile);
nonAttCounter++;
}
}
}
}
Global_Utilities.SharedFunctions.emailQuickSend(email);
foreach (var writer in nonAttWriterHolder)
{ writer.Close(); }
foreach (var stream in nonAttStreamHolder)
{ stream.Close(); }
You can simply take your string(s) and encode them as byte[]
, then use the techniques outlined in attach multiple files to an email programticaly without writing to disk. Here's some simple code to get you started:
var myString = "This is a test.";
var myBytes = System.Text.Encoding.UTF8.GetBytes(myString);
Now myBytes
is an array of byte
s. Note that you'll likely want to specify the encoding of the attachment, via the TransferEncoding
property.