|
Hi All,
My requirement is... Generate a file, send that file as attachment using SMTP client and then delete the generated file.
I have generated the file fine.
I have implemented SMTP client usage fine.
first attempt error - file in use when trying to delete after sending email...
message.Attachments.Add(new System.Net.Mail.Attachment("FILEPATH"));
smtp.Send(message);
...OK, so SEND is for some reason still using the file. I have just removed another load of almost posted text as I have figured out the answer. Which is basically...
Collection<Stream> streams = new Collection<Stream>();
foreach(string filename in filenames)
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(filename);
Stream stream = new MemoryStream(File.ReadAllBytes(filename));
message.Attachments.Add(new System.Net.Mail.Attachment(stream, fileInfo.Name, null));
streams.Add(stream);
}
smtp.Send(message);
foreach(Stream stream in streams)
stream.Close();
So I have solved my problem, but have still posted as may be useful for others but also, does anybody know why adding an attachment via a file path keeps the file locked after sending?
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
WQithout seeing the code you used to create the file, it's diificult, but yes.
When you created the file, did you close and dispose the file before you tried to send it? If not, and it just went out of scope, then the file is in use until the garbage collector disposes of it. That could be next Tuesday...
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
The generated file is handled correctly. Hence the clean up code (deleting the generated file) works when I use a stream to add an attachment (as in my second code sample).
The only time the clean up fails is if I use my first code sample - if I comment the sole line of smtp.Send then the clean up does not fail. for some reason the Send function is still using the file. I cannot even manually delete the file after the failed clean up for the same reason. Only when I kill the program (which is a windows service) does the file become free again
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
After a bit more playing the answer to send using a file path is as follows...
using (System.Net.Mail.Attachment attachment = new System.Net.Mail.Attachment(filename))
{
message.Attachments.Add(attachment);
}
smtp.Send(message);
...I guess I was holding a handle on an System.Net.Mail.Attachment instance in my first code sample (somehow!). Though I would have liked to think this would not have keep a file open anyway!
this however does not work...
using(Stream stream = new MemoryStream(File.ReadAllBytes(filename)))
{
message.Attachments.Add(stream, "myfile", null);
}
smtp.Send(message);
...because the Send() call is out of scope of the stream. Why this doesn't work but the above does I do not know.
EDIT: Actually I forgot to recompile - neither work (which I would suspect not to)
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
Why are you opening the file? Didn't you read my response to your (whoops it wasn't yours, sorry) the earlier post?
modified on Monday, December 6, 2010 10:37 AM
|
|
|
|
|
PIEBALDconsult wrote: Why are you opening the file? Didn't you read my response to your earlier post?
I am not opening the file. What in my posts gave you that idea?
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
new MemoryStream(File.ReadAllBytes(filename));
|
|
|
|
|
File.ReadAllBytes() closes the file after creating a byte[] - this is not the issue
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
It is to me -- I send large XML and EDI files.
Oh, and PDFs generated by Crystal. ::shudder::
|
|
|
|
|
So then you mean the issue is loading file in memory? I agree with that, its not ideal but I am working with relatively small files and they should stay that way
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
You don't want your code crash the email server if you can help it. (Been there, done that. )
I prefer a more general solution whenever I can find one. I don't follow YAGNI -- I always stop to think, "How can this come back to bite me on the backside? I can't foresee all possible problems, but what steps can I take now to alleviate the future problems that I can foresee?"
Also, its easier to allow for very large files today than it will be in a few months.
And if the files are very small, why attach them? Why not use them as the message text?
On the other hand... why not avoid the files entirely? Generate the "file" in memory, store it in the database, read it from there, attach it, and then delete the record. Maybe have the delete postponed until after a database backup.
|
|
|
|
|
PIEBALDconsult wrote: You don't want your code crash the email server if you can help it.
If file sizes start to get to large for emailing then we will prevent sending by email and force users to use the FTP option.
PIEBALDconsult wrote: I don't follow YAGNI
I agree with regards to potential problems down the line. But I am not going to waste time implementing functionality that is not needed.
PIEBALDconsult wrote: And if the files are very small, why attach them? Why not use them as the message text?
They are data exports. XML files, MDB files - not very usable as just email body content
PIEBALDconsult wrote: On the other hand... why not avoid the files entirely?
Because one of the file types if MDB then a file must be created on disk
PIEBALDconsult wrote: Generate the "file" in memory, store it in the database, read it from there, attach it, and then delete the record
Why would I want to create a file in memory, store in DB and then read it straight back into memory?
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
musefan wrote: Why would I want to create a file in memory, store in DB and then read it straight back into memory?
Separation of responsibilities: one (or several) process(es) creates, another sends. Maybe another archives. Who knows?
|
|
|
|
|
PIEBALDconsult wrote: Separation of responsibilities: one (or several) process(es) creates, another sends. Maybe another archives. Who knows?
In some requirements, yes maybe so. But mine is much more just 'Create and Send' - its wasted effort to split the process
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
I'll check back in a year.
|
|
|
|
|
don't forget now... maybe I will come crawling before then
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
musefan wrote: maybe I will come crawling before then
I don't think so... I'm sure you'll be able to handle it on your own.
|
|
|
|
|
I had the same experience; my guess is the attachment files remain locked by the mail system until it is done sending them. Your code is not to blame for any of that. Solutions would be to create:
- an attachment from the file contents;
- an attachment form a stream, as you did;
- a copy of the file (leaving even more garbage on the file system).
|
|
|
|
|
Or don't delete the file -- archive it at a later date. You never know when you may need a paper trail to CYA. Or to resend for some reason.
|
|
|
|
|
Files are created purely for sending to users. There is no need for keeping the file - besides generated files could end up frequent and many so want to keep the file system tidy
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
musefan wrote: Files are created purely for sending to users
Aren't they all?
musefan wrote: There is no need for keeping the file
"There will be." -- Murphy
musefan wrote: keep the file system tidy
Create them in a directory specifically for them.
|
|
|
|
|
PIEBALDconsult wrote: Aren't they all?
No, I have many files on my computer that are not required to go anywhere. In my service the files being sent are exports of data at regular intervals
PIEBALDconsult wrote: "There will be." -- Murphy
If I ever need to keep them, then I will start keeping them. But I don't now and cannot think of what they would be useful for
PIEBALDconsult wrote: Create them in a directory specifically for them.
That's still a folder full of files I don't need or want. Plus they are already generated in a nice file structure to keep them unique
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
musefan wrote: I will start keeping them
I see no reason not to keep them now. Do you need plausible deniability?
musefan wrote: I don't now and cannot think of what they would be useful for
Mostly as a paper trail and for resending when someone's system crashes and is rebuilt. But also in case sometime down the road someone asks about comparing current numbers with numbers from a year earlier -- it happens, and if you aren't already archiving (and perhaps summarizing) data, all you have are files, reports, extracts... or maybe you don't.
Don't throw anything away.
|
|
|
|
|
If I need to resend I can generate the files again. These files are just data exports from a database, there is no lost data by deleting the files as they already will exist in the DB which itself will be backed up and archived.
These files are for users and they can do whatever they wish to with them. It is there data to control.. and to look after. We are not providing a file storage system for them.
Like I have already said if it wasn't for an MDB file being generated I probably woudln't even let them out of memory. In that instance would you be telling my to dump my RAM and keep copies of that 'just incase' - if requirements changes, then they change, and it can be handled then
You also said to plan for the future - but what if we look at this from the flip side. What if these generated files becomes thousands a day, even a TB of data a day (bit extreme, but you never know) - now the question will be 'what good reason is there to keep the files?'
Life goes very fast. Tomorrow, today is already yesterday.
|
|
|
|
|
musefan wrote: a TB of data a day
::gibbering:: Well... maybe a very pro-active archive regimen and compression?
|
|
|
|