deleting a file in c# after sending email attachment - c#

I have the following code that basically attaches a file to an email message then after all attachments are attached and email is sent, i try to delete all files, however I get a file in use exception. I believe the error comes in this line
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
I tried using this code but I get an cannot sent email message
using Attachment data = new Attachment(file, MediaTypeNames.Application.Octet)){
//and the rest of the code in here.
}
foreach (KeyValuePair<string, string> kvp in reports) {
browser.GoTo(kvp.Value);
Thread.Sleep(1000);
System.IO.File.Move(#"C:\Reports\bidata.csv", #"C:\Reports\"+kvp.Key.ToString()+".csv");
string file = #"C:\Reports\" + kvp.Key.ToString() + ".csv";
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
mail.Attachments.Add(data);
}
smtpserver.Send(mail);
string[] files = Directory.GetFiles(#"C:\Reports");
foreach (string files1 in files)
{
File.Delete(files1);
}

In order to delete the files first you will have to dispose the attachment and mail objects and then delete the files

Dispose the smtpclient by putting it in a usings or calling dispose directly. That should free the file resource and allow you to nuke it.

Related

Fetching attachment from given .eml file and using that attachment to other mail

I am working on code in C#,but not going through on thing that is I have saved some .eml file on my disk now I am parsing each eml file and creating a new mail adding the eml file data to the new mail but I am unable to attach the attachments present in the .eml file to the new mail , can anybody please help?
I am using the follwing code but it shows the error ex = {"The process cannot access the file because it is being used by another process.\r\n":null}
foreach (CDO.IBodyPart attach in msg.Attachments)
{
i++;
string filenm = "C:\\mail_automation\\attachments\\xyz" + i +".eml";
if (File.Exists(filenm))
{
string fn = attach.FileName;
attach.SaveToFile("C:\\mail_automation\\attachments\\xyz" + i + ".eml");
Attachment data = new Attachment(filenm);
mailMessage.Attachments.Add(data);
}
else
{
File.Create(filenm);
string fn = attach.FileName;
attach.SaveToFile("C:\\mail_automation\\attachments\\xyz" + i + ".eml");
Attachment data = new Attachment(filenm);
mailMessage.Attachments.Add(data);
}
You have to extract the attachments and save them to disk first, then fetch it again into the new mail.
Code example here
MailMessage message = new MailMessage();
MemoryStream ms = new MemoryStream(); //store the mail into this ms 'memory stream'
ms.Position = 0;
message.Attachments.Add(new Attachment(ms, attachmentName));

How can I get File.Delete() to actually delete my file?

I generate a PDF file, save it on the server:
var bytes = ms.ToArray();
. . .
String fileFullpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), pdfFileName);
. . .
File.WriteAllBytes(fileFullpath, bytes);
...and then save it into a Sharepoint Document Library, and send it as an email attachment to the person who generated the file:
SavePDFToDocumentLibrary(fileFullpath);
String from = GetFromEmailID();
String to = GetUserEmail();
String subjLine = String.Format("The PDF file you generated ({0})", pdfFileName);
String body = String.Format("The Direct Pay PDF file you generated ({0}) is attached.", pdfFileName);
SendEmailWithAttachment(fileFullpath, from, to, subjLine, body);
// Now that it has been put in a Document Library and emailed, delete the file that was saved locally
File.Delete(fileFullpath);
...at which point, I no longer need the file I saved to disk on the server, and so, as shown in the last line above, attempt to delete it.
However, it doesn't work. The now-redundant file is still in the place where it was saved.
Why, and how can I get it to understand that "Delete" really means "delete"?
UPDATE
Here are the methods Scott wanted to see:
// This works; got it from Henry Zucchini's answer at http://stackoverflow.com/questions/468469/how-do-you-upload-a-file-to-a-document-library-in-sharepoint
private void SavePDFToDocumentLibrary(String fullpath)
{
String fileToUpload = fullpath;
String sharePointSite = siteUrl;
String documentLibraryName = "DirectPayPDFForms";
using (SPSite oSite = new SPSite(sharePointSite))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
if (!System.IO.File.Exists(fileToUpload))
throw new FileNotFoundException("File not found.", fileToUpload);
SPFolder doclib = oWeb.Folders[documentLibraryName];
// Prepare to upload
Boolean replaceExistingFiles = true;
String fileName = System.IO.Path.GetFileName(fileToUpload);
FileStream fileStream = File.OpenRead(fileToUpload);
// Upload document
SPFile spfile = doclib.Files.Add(fileName, fileStream, replaceExistingFiles);
// Commit
doclib.Update();
}
}
}
// This is adapted from https://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage(v=vs.90).aspx
public static void SendEmailWithAttachment(string fileToMail, String from, String to, String subj, String body)
{
String server = GetSMTPHostName(); //"468802-DEV-SPWF"; // change this to prod when go live, or programatically assign?
// Specify the file to be attached and sent.
string file = fileToMail;
// Create a message and set up the recipients.
MailMessage message = new MailMessage(
from,
to,
subj,
body);
// Create the file attachment for this e-mail message.
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
//Send the message.
SmtpClient client = new SmtpClient(server);
// Add credentials if the SMTP server requires them.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateMessageWithAttachment(): {0}", ex.ToString());
}
// Display the values in the ContentDisposition for the attachment.
// May not need/want this section
ContentDisposition cd = data.ContentDisposition;
Console.WriteLine("Content disposition");
Console.WriteLine(cd.ToString());
Console.WriteLine("File {0}", cd.FileName);
Console.WriteLine("Size {0}", cd.Size);
Console.WriteLine("Creation {0}", cd.CreationDate);
Console.WriteLine("Modification {0}", cd.ModificationDate);
Console.WriteLine("Read {0}", cd.ReadDate);
Console.WriteLine("Inline {0}", cd.Inline);
Console.WriteLine("Parameters: {0}", cd.Parameters.Count);
foreach (DictionaryEntry d in cd.Parameters)
{
Console.WriteLine("{0} = {1}", d.Key, d.Value);
}
// </ May not need/want this section
data.Dispose();
}
UPDATE 2
I see when stepping through it, after adding this test:
if (File.Exists(fileFullpath))
{
File.Delete(fileFullpath);
}
...that there is an exception after all, in the IOException catch block:
The process cannot access the file 'C:\Users\TEMP.SP.018\Desktop\DirectPayDynamic_2015Jul28_19_02_clayshan_0.pdf' because it is being used by another process.
So how is one of the other methods holding onto it? ISTM that SavePDFToDocumentLibrary() is safe, because it uses using blocks.
Is data.Dispose(); in SendEmailWithAttachment() not enough? Do I need to explicitly call close there, or what?
UPDATE 3
I added "message.Dispose();" just prior to "data.Dispose();" in SendEmailWithAttachment(), but it made no difference.
Try disposing the file stream used in SavePDFToDocumentLibrary like so:
using (FileStream fileStream = File.OpenRead(fileToUpload))
{
...
}

Access the email attachment

I am trying to access the file attachment in the email message and upload the attachment to a azure table storage as a blob.
using Microsoft.Exchange.WebServices.Data
public void SendEmail(EmailMessage emailMessage)
{Stream stream = null;
foreach (Attachment attachment in emailMessage.Attachments)
{
if (attachment is FileAttachment)
{
FileAttachment file = (FileAttachment)attachment;
file.Load(stream);
emailAttachment.UploadEmailAttachment(attachmentFileName, stream);// This will upload to the table storage
}
}
}
when I load the attachment I am getting a error saying "The request failed schema validation: The required attribute 'Id' is missing.".
Any idea regarding this
As I understand, all you are looking for a way to load the contents of the attachment into a stream which you can further upload as blob.
If that is the case, I would suggest you to write the contents of your file attachment into MemoryStream instead:
var stream = new System.IO.MemoryStream(fileAttachment.Content);
If you want to read the contents as string, you can do that as well:
var reader = new System.IO.StreamReader(stream, UTF8Encoding.UTF8);
var text = reader.ReadToEnd();
Hope this helps!

Save attach of attached mail

I'm using Mail.dll from limilabs to manage an IMAP folder.
There is one mail with an attachment that is an eml file, so a mail.
It has in turn one attached eml file that I need to extract.
So the email structure is as follows:
Email
|- Attachment: file.eml
|- Attachment file2.eml
This is my code:
IMail email = new MailBuilder().CreateFromEml(imap.GetMessageByUID(uid));
Console.WriteLine(email.Subject);
// save all attachments to disk
foreach(MimeData mime in email.Attachments)
{
if (uid == 1376)
{
System.IO.Directory.CreateDirectory(string.Format(#"c:\EMAIL\{0}", uid));
mime.Save(#"c:\EMAIL\" + uid + "\\" + mime.SafeFileName);
MimeData help;
if (mime.ContentType.ToString() == "message/rfc822")
{
//i need to cast this attach in a imail
}
}
}
How can I extract the inner-most eml file (file2.eml in the structure mentioned above)?
From this link, it looks like you should be able to do the following:
if (attachment.ContentType == ContentType.MessageRfc822)
{
string eml = ((MimeText)attachment).Text;
IMail attachedMessage = new MailBuilder().CreateFromEml(eml);
// process further
}
If you only need to extract all attachments from all inner messages, you can use IMail.ExtractAttachmentsFromInnerMessages method:
IMail email = new MailBuilder().CreateFromEml(imap.GetMessageByUID(uid));
ReadOnlyCollection<MimeData> attachments = mail.ExtractAttachmentsFromInnerMessages();
foreach (MimeData mime in attachments)
{
mime.Save(#"c:\" + mime.SafeFileName);
}

File is used by another process exception C#

I have created an application that generates excel files from information in a database. These files are saved on my HDD in a folder.
After that I attach the files and send them via mail. When I generate another batch of files I delete the old files and then create the new ones.
My problem is when I have generated one batch of files and then send them, and I want to generate another batch I cannot delete the one of the old files, because the mailing method is still holding on to one of the excel files.
Here is my code:
public void SendMailedFilesDKLol() {
string[] sentFiles=Directory.GetFiles(some_Folder);
if(sentFiles.Count()>0) {
System.Net.Mail.SmtpClient client=new System.Net.Mail.SmtpClient("ares");
System.Net.Mail.MailMessage msg=new System.Net.Mail.MailMessage();
msg.From=new MailAddress("system#lol.dk");
msg.To.Add(new MailAddress("lmy#lol.dk"));
msg.Subject="IBM PUDO";
msg.Body=
sentFiles.Count()+" attached file(s) has been sent to the customer(s) in question ";
msg.IsBodyHtml=true;
foreach(string file in sentFiles) {
Attachment attachment=new Attachment(file);
msg.Attachments.Add(attachment);
}
client.Send(msg);
}
}
I have tried to dispose the client element but that didn't help.
Can anyone help me with this?
Both System.Net.Mail.MailMessage & System.Net.Mail.SmtpClient are IDisposable classes. You can try the following,
using (System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient("ares"))
{
using (System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage())
{
msg.From = new MailAddress("system#lol.dk");
msg.To.Add(new MailAddress("lmy#lol.dk"));
msg.Subject = "IBM PUDO";
msg.Body = sentFiles.Count() + " attached file(s) has been sent to the customer(s) in question ";
msg.IsBodyHtml = true;
foreach (string file in sentFiles)
{
Attachment attachment = new Attachment(file);
msg.Attachments.Add(attachment);
}
client.Send(msg);
}
}
It sounds like you may not be closing your file stream when generating the excel files or you have them open in excel when trying to email them.
Please can you show your code for generating the excel files.
You need to dispose the Attachment objects.
Example using LINQ:
public void SendMailedFilesDKLol() {
string[] sentFiles=Directory.GetFiles(some_Folder);
if(sentFiles.Count()>0) {
System.Net.Mail.SmtpClient client=new System.Net.Mail.SmtpClient("ares");
System.Net.Mail.MailMessage msg=new System.Net.Mail.MailMessage();
msg.From=new MailAddress("system#lol.dk");
msg.To.Add(new MailAddress("lmy#lol.dk"));
msg.Subject="IBM PUDO";
msg.Body=
sentFiles.Count()+" attached file(s) has been sent to the customer(s) in question ";
msg.IsBodyHtml=true;
var attachments = sentFiles.Select(f => new Attachment(f)).ToList();
attachments.ForEach(a => msg.Attachments.Add(a));
client.Send(msg);
attachments.ForEach(a => a.Dispose());
}
}

Categories

Resources