Deleting files fails as held by and existing process - c#

I'm having issues with a bit of code that I am writing in C#.
I am sending a document using the MailMessage and SMTP components. I copy the files that I wish to send to a temp directory such as c:\temp, loop through the documents and attach them to the email.
The email sends fine, however when I try to delete the files from the temp directory, I get the following error:
The process can not access the file because it is being used by another process
I can't understand why this is happening. Below is the code that processes the documents
public void sendDocument(String email, string barcode, int requestid)
{
string tempDir = #"c:\temp";
//first we get the document information from the database.
Database db = new Database(dbServer, dbName, dbUser, dbPwd);
List<Document> documents = db.getDocumentByID(barcode);
int count = 0;
foreach (Document doc in documents)
{
string tempPath = tempDir + "\\" + doc.getBarcode() + ".pdf";
string sourcePath = doc.getMachineName() + "\\" + doc.getFilePath() + "\\" + doc.getFileName();
//we now copy the file from the source location to the new target location
try
{
//this copies the file to the folder
File.Copy(sourcePath, tempPath, false);
}
catch (IOException ioe)
{
count++;
//the file has failed to copy so we add a number to the file to make it unique and try
//to copy it again.
tempPath = tempDir + "\\" + doc.getBarcode() + "-" + count + ".pdf";
File.Copy(sourcePath, tempPath, false);
}
//we now need to update the filename in the to match the new location
doc.setFileName(doc.getBarcode() + ".pdf");
}
//we now email the document to the user.
this.sendEmail(documents, email, null);
updateSentDocuments(documents, email);
//now we update the request table/
db.updateRequestTable(requestid);
//now we clean up the documents from the temp folder.
foreach (Document doc in documents)
{
string path = #"c:\temp\" + doc.getFileName();
File.Delete(path);
}
}
I would of thought that the this.sendEmail() method would of sent the email before returning to the sendDocument method, as I think it is the smtp object that is causing the deletes to fail.
This is the sendEmail method:
public void sendEmail(List<Document> documents, String email, string division)
{
String SMTPServer = null;
String SMTPUser = null;
String SMTPPwd = null;
String sender = "";
String emailMessage = "";
//first we get all the app setting used to send the email to the users
Database db = new Database(dbServer, dbName, dbUser, dbPwd);
SMTPServer = db.getAppSetting("smtp_server");
SMTPUser = db.getAppSetting("smtp_user");
SMTPPwd = db.getAppSetting("smtp_password");
sender = db.getAppSetting("sender");
emailMessage = db.getAppSetting("bulkmail_message");
DateTime date = DateTime.Now;
MailMessage emailMsg = new MailMessage();
emailMsg.To.Add(email);
if (division == null)
{
emailMsg.Subject = "Document(s) Request - " + date.ToString("dd-MM-yyyy");
}
else
{
emailMsg.Subject = division + " Document Request - " + date.ToString("dd-MM-yyyy");
}
emailMsg.From = new MailAddress(sender);
emailMsg.Body = emailMessage;
bool hasAttachements = false;
foreach (Document doc in documents)
{
String filepath = #"c:\temp\" + doc.getFileName();
Attachment data = new Attachment(filepath);
emailMsg.Attachments.Add(data);
hasAttachements = true;
}
SmtpClient smtp = new SmtpClient(SMTPServer);
//we try and send the email and throw an exception if it all goes tits.
try
{
if (hasAttachements)
{
smtp.Send(emailMsg);
}
}
catch (Exception ex)
{
throw new Exception("EmailFailure");
}
}
How to I get around this problem with a process hogging the file I wish to delete.
I can delete the file(s) once the application finishes.

You're email message isn't being Disposed, try disposing it after you've sent it:
try
{
if (hasAttachements)
{
smtp.Send(emailMsg);
}
}
catch ...
finally
{
emailMsg.Dispose();
}

The first step is to figure out what process is holding onto the file in question. I would grab the SysInternals toolkit and use the handle.exe command to determine what process is holding onto the file.
Without knowing what process has the file open, there is no way to fix this problem.
Sysinternals Link: http://technet.microsoft.com/en-us/sysinternals/default.aspx

Here's a trick I just discoverred, which will hopefully be of use to other folk?
Before adding attachments to a message, create the attachment in a using wrapper. This ensures it gets disposed of correctly, allowing the file to be successfully deleted. I'm not sure if the send also needs to be in this loop; (when I tested, emails didn't get through at first, then half an hour later I got flooded, so decided to leave testing for a time when the network was a little calmer).
using (Attachment attachment = new Attachment(filename))
{
message.Attachments.Add(attachment);
client.SendAsync(message, string.Empty);
}
File.Delete(filename);
Works OK for me anyway :)
Good luck,
JB

Related

Wait until file exists

I've written a set of web services using Web Api 2. They eventually end up calling a CMD program that fires up a OpenEdge Progress client, passes a formatted XML string and then inserts records into a OpenEdge Progress database by calling a .p procedure (WebSpeed is not an option).
The .P file has a set of business logic to run against a Progress application. It subsequently generates an XML file on completion containing an < Error > node. If this node is empty - then it worked. If the file doesn't exist or the node contains text... it failed. I then read this XML file and pass the contents of the < Error > node back to the client in Web Api.
At the moment, there is a static delay of 10 seconds from calling the CMD/Progress applet, to attempting to read the XML file, to give the server time to run the .P file and create said XML file. This isn't great, though, and occasionally an error is returned to the client because it can't find the file, yet, the file was created 1 second after the response was returned because of abnormally high server loads. Alternatively, people are forced to wait 10 seconds when the response could have been handled in 2 seconds.
I need to come up with a way to "check until file exists" until a timeout period has elapsed. I've done some research and can't find anything suitable for a Web Api environment. Does anyone have any suggestions?
Code below - forgive me. I've very much been learning as I've been going along and am very new to this!
Controller
// the request date/time
DateTime requestDate = DateTime.Now;
// list of validation errors
List<string> ohValidation = new List<string>();
...
WebExtensions.callInsertProgram(xml, "JOBLOG");
ohValidation = XmlExtensions.ReadProgressXmlFileWithArray(job.logjob.placeref, requestDate, "joblogging");
CallInsertProgram
public static void callInsertProgram(string xml, string program)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = #"C:\Rubixx\runProgress.exe";
p.StartInfo.WorkingDirectory = #"C:\Rubixx";
// stop windows from appearing on the server
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// set the arguments for running. The program name and xml are passed in as arguments
// wrapped in escaping "\" to stop spaces from being treated as a separator
p.StartInfo.Arguments = "\"" + program + "," + xml + "\"";
p.Start();
}
}
catch (Exception e)
{
throw new OpenHousingException(e.Message.ToString());
}
}
ReadProgressXMLWithArray
public static List<string> ReadProgressXmlFileWithArray(string reference, DateTime requestDateTime, string folder)
{
// new empty list
List<string> output
= new List<string>();
// wait X seconds before doing anything
// to ensure the XML file has time to be created
Delay_Start(fileDelay);
//
string filename = fullFileName(jobno, folder, requestDateTime);
string filepath = getFullFilepath(filename, folder);
if (checkXmlFileExists(filepath))
{
// if so check for the existence of an error message
output = getXmlErrorArray(filepath);
}
else
{
// if no file is found - the call to Progress hasn't executed. So tell the end user.
throw new OpenHousingException("No OpenHousing file could be found");
}
return output;
}
Delay_Start
private static void Delay_Start(int Seconds)
{
DateTime StartTime;
DateTime EndTime;
StartTime = DateTime.Now;
EndTime = StartTime.AddSeconds(Seconds);
do
{ StartTime = DateTime.Now; } while (StartTime < EndTime);
}
FullFileName (needed because I can't be sure of XML filename until created. File Format is UniqueReference_DateTimeFileCreated.xml (xxxxxxxx_20160401-1100.xml) So, I have to wildcard search a folder with a unique reference).
public static string fullFileName(string jobNo, string folder, DateTime createdDate)
{
string fileName = string.Empty;
string folderPath = fileLocation + folder;
DirectoryInfo dir = new DirectoryInfo(folderPath);
FileInfo[] files = dir.GetFiles(jobNo + "*", SearchOption.TopDirectoryOnly).Where(f => f.CreationTimeUtc > createdDate || f.LastWriteTimeUtc > createdDate).ToArray() ;
foreach (var item in files)
{
fileName = item.Name;
}
if (string.IsNullOrEmpty(fileName))
throw new OpenHousingException("No OpenHousing file could be found");
return fileName;
}
GetFullFilePath (Can probably be consolidated into fullFileName)
private static string getFullFilepath(string filename, string folder)
{
return fileLocation + folder + #"\" + filename;
}
CheckXMLFileExists
private static bool checkXmlFileExists(string filepath)
{
bool fileExists = false;
if (File.Exists(filepath))
{
fileExists = true;
}
return fileExists;
}
GetXMLErrorArray
private static List<string> getXmlErrorArray(string filepath)
{
List<string> output
= new List<string>();
// read the text from XML file
using (TextReader txtReader = new StreamReader(filepath))
{
XmlSerializer xs
= new XmlSerializer(typeof(JobError));
// de-serialise the xml text
// to a strongly typed object
JobError result = (JobError)xs.Deserialize(txtReader);
// if the xml file contains an error - return it to the client
if (!string.IsNullOrEmpty(result.ErrorText))
output.Add(result.ErrorText);
//check for SoR errors that are created under a different node
if (result.LineError != null)
{
List<LineError> lineErrs = result.LineError.ToList();
foreach (LineError le in lineErrs)
{
output.Add(le.SorCode + ":" + le.Error);
}
}
}
return output;
}
OK - so I think I was overcomplicating the problem.
Instead of waiting for the file to exist, I added a line into my CallInsertProgram method as below (as suggested by RB...
public static void callInsertProgram(string xml, string program)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = #"C:\Rubixx\runProgress.exe";
p.StartInfo.WorkingDirectory = #"C:\Rubixx";
// stop windows from appearing on the server
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// set the arguments for running. The program name and xml are passed in as arguments
// wrapped in escaping "\" to stop spaces from being treated as a separator
p.StartInfo.Arguments = "\"" + program + "," + xml + "\"";
p.Start();
// ADDED
p.WaitForExit(60000);
}
}
catch (Exception e)
{
throw new OpenHousingException(e.Message.ToString());
}
}
This ensures that the Progress cmd applet is completed before moving onto the next line - at which point the XML will have been created (or not if it's failed). Initial testing is working well. Can anyone foresee any problems with this approach?

Having issues saving email attachment to directory

I am working on an application that crawls my email and sniffs out any emails with attachments. All attachment are being returned in the order they were received. Now I want to go a step further and would like to save any attachments in a local directory. I have been looking for documentation or examples but I have come up empty. I will show you a snippet of my code
This Function will get Email Attachments
public static List<IMessage> GetEmailAttachments()
{
OutlookServicesClient star_Mail_Box = Start_OutLook_Services();
try
{
var Email_Box = star_Mail_Box.Users["*****#dell.com"].Folders["Inbox"].Messages.Where(m => m.HasAttachments == true).Expand(m => m.Attachments).ExecuteAsync();
var messages = Email_Box.Result.CurrentPage;
foreach (var message in messages.OrderByDescending(m=> m.DateTimeReceived))
{
var attachments = message.Attachments.CurrentPage;
foreach (var attachment in attachments)
{
///This is where I will need to put my Logic.
}
}
}
catch (Exception ex)
{
Console.WriteLine("Not Able To Get This Mail Box" + ex.Message + "\n\nDetails : \n\n " + ex.InnerException);
Console.ReadLine();
}
return null; // returning null right now for testing
}
Ok so after looking at the attachment definition I figured I go through a byte array to achieve what I want. Here goes the Some code for my attachment loop.
foreach (FileAttachment attachment in attachments)
{
byte[] bytefiles = attachment.ContentBytes;
string path = #"C:\Top-Level\" + attachment.Name;
if (!string.IsNullOrEmpty(message.Subject))
{
path = #"C:\Top-Level\" + message.Subject + "." + attachment.ContentType;
}
File.WriteAllBytes(path, bytefiles);
}

Download files from SFTP with SSH.NET library

string host = #"ftphost";
string username = "user";
string password = "********";
string localFileName = System.IO.Path.GetFileName(#"localfilename");
string remoteDirectory = "/export/";
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
if (!file.Name.StartsWith("."))
{
string remoteFileName = file.Name;
if (file.LastWriteTime.Date == DateTime.Today)
Console.WriteLine(file.FullName);
File.OpenWrite(localFileName);
string sDir = #"localpath";
Stream file1 = File.OpenRead(remoteDirectory + file.Name);
sftp.DownloadFile(remoteDirectory, file1);
}
}
}
I am using SSH.NET (Renci.SshNet) library to work with an SFTP server. What I need to do is grab files from a specific folder on the SFTP server based on today's date. Then copy those files from the SFTP server to a local drive a server of mine.
Above is the code I have but it is not working. Sometimes it says file does not exist but sometimes the files I will be downloading will not be on my local servers but I need to download whatever files were uploaded to the remote folder for that day.
Can someone take a look and see what is wrong? I believe it has something to do with the stream portion. I have worked with FTP much besides uploading files which I took some previous code I had and thought I could reverse the process but that isn't working. The code I used is based off of this example.
A simple working code to download a file with SSH.NET library is:
using (Stream fileStream = File.Create(#"C:\target\local\path\file.zip"))
{
sftp.DownloadFile("/source/remote/path/file.zip", fileStream);
}
See also Downloading a directory using SSH.NET SFTP in C#.
To explain, why your code does not work:
The second parameter of SftpClient.DownloadFile is a stream to write a downloaded contents to.
You are passing in a read stream instead of a write stream. And moreover the path you are opening read stream with is a remote path, what cannot work with File class operating on local files only.
Just discard the File.OpenRead line and use a result of previous File.OpenWrite call instead (that you are not using at all now):
Stream file1 = File.OpenWrite(localFileName);
sftp.DownloadFile(file.FullName, file1);
Or even better, use File.Create to discard any previous contents that the local file may have.
I'm not sure if your localFileName is supposed to hold full path, or just file name. So you may need to add a path too, if necessary (combine localFileName with sDir?)
While the example works, its not the correct way to handle the streams...
You need to ensure the closing of the files/streams with the using clause..
Also, add try/catch to handle IO errors...
public void DownloadAll()
{
string host = #"sftp.domain.com";
string username = "myusername";
string password = "mypassword";
string remoteDirectory = "/RemotePath/";
string localDirectory = #"C:\LocalDriveFolder\Downloaded\";
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
string remoteFileName = file.Name;
if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today))
using (Stream file1 = File.Create(localDirectory + remoteFileName))
{
sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
}
}
}
}
My version of #Merak Marey's Code. I am checking if files exist already and different download directories for .txt and other files
static void DownloadAll()
{
string host = "xxx.xxx.xxx.xxx";
string username = "###";
string password = "123";string remoteDirectory = "/IN/";
string finalDir = "";
string localDirectory = #"C:\filesDN\";
string localDirectoryZip = #"C:\filesDN\ZIP\";
using (var sftp = new SftpClient(host, username, password))
{
Console.WriteLine("Connecting to " + host + " as " + username);
sftp.Connect();
Console.WriteLine("Connected!");
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
string remoteFileName = file.Name;
if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today)))
{
if (!file.Name.Contains(".TXT"))
{
finalDir = localDirectoryZip;
}
else
{
finalDir = localDirectory;
}
if (File.Exists(finalDir + file.Name))
{
Console.WriteLine("File " + file.Name + " Exists");
}else{
Console.WriteLine("Downloading file: " + file.Name);
using (Stream file1 = File.OpenWrite(finalDir + remoteFileName))
{
sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
}
}
}
}
Console.ReadLine();
}
Massimiliano's solution has one problem which will lead to files not being completely downloaded. The FileStream must be closed. This is especially a problem for encrypted files. They won't completely decrypt intermittently without closing the stream.
var files = sftp.ListDirectory(remoteVendorDirectory).Where(f => !f.IsDirectory);
foreach (var file in files)
{
var filename = $"{LocalDirectory}/{file.Name}";
if (!File.Exists(filename))
{
Console.WriteLine("Downloading " + file.FullName);
using (var localFile = File.OpenWrite(filename))
sftp.DownloadFile(file.FullName, localFile);
}
}
This solves the problem on my end.
var files = sftp.ListDirectory(remoteVendorDirectory).Where(f => !f.IsDirectory);
foreach (var file in files)
{
var filename = $"{LocalDirectory}/{file.Name}";
if (!File.Exists(filename))
{
Console.WriteLine("Downloading " + file.FullName);
using (var localFile = File.OpenWrite(filename))
sftp.DownloadFile(file.FullName, localFile);
}
}
Without you providing any specific error message, it's hard to give specific suggestions.
However, I was using the same example and was getting a permissions exception on File.OpenWrite - using the localFileName variable, because using Path.GetFile was pointing to a location that obviously would not have permissions for opening a file > C:\ProgramFiles\IIS(Express)\filename.doc
I found that using System.IO.Path.GetFileName is not correct, use System.IO.Path.GetFullPath instead, point to your file starting with "C:\..."
Also open your solution in FileExplorer and grant permissions to asp.net for the file or any folders holding the file. I was able to download my file at that point.

Best Way to implement Email generation in this scheduled console app

I have never programmatically generated and sent email notifications before. What I need to do is this, if this program fails to move files or encounters an exception to generate an email and (preferably) attach a Log.txt file to the email then send it. This app will be ran from an enterprise scheduler and ran 1/hour to manage the files and folders.
Here is the functional code that I currently have (no email implementation exists yet) I have commented in the locations that I would like to send an email
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
namespace FileOrganizer
{
class Program
{
//These are the folder to organize and delimeter that is in the filenames to split off a folder from
static string folder = ConfigurationManager.AppSettings["folder"]; //"C:\Users\MyUserName\Desktop\Organize Me"
static string delim = ConfigurationManager.AppSettings["delim"]; // delim = "__"
//location for the log.txt file
static string logPath = ConfigurationManager.AppSettings["logPath"]; //C:\Users\MyUserName\Desktop\Log.txt
//contact list from the app.config
static string emailTo = ConfigurationManager.AppSettings["notifyEmailAddress"]; //multiple email addresses delimited by a ; example = tom#domain.com;dick#differentDomain.com;harry#domain.com
//for the log.txt reporting
static int filesMoved = 0;
static int filesNOTmoved = 0;
static string fileNamesNOTmoved = "";
static int foldersCreated = 0;
static string message = "";
static string stackTrace = "";
//used for passing all the objects into the log method
static object[] details = new object[6];
static void Main(string[] args)
{
try
{
using (StreamWriter w = File.AppendText(logPath))
{
int total = organizeFolder(delim, folder);
details[0] = filesMoved;
details[1] = filesNOTmoved;
details[2] = fileNamesNOTmoved;
details[3] = foldersCreated;
details[4] = "No Errors Found";
details[5] = "No Errors Found";
Log(details, w);
if (filesNOTmoved > Convert.ToInt32(filesNOTmoved))
{
//generate email to notify of filesNames not moved (prefer to send Log.txt as attachment)
}
}
using (StreamReader r = File.OpenText(logPath))
{
DumpLog(r);
}
}
catch (Exception ex)
{
using (StreamWriter w = File.AppendText(logPath))
{
details[0] = filesMoved;
details[1] = filesNOTmoved;
details[2] = fileNamesNOTmoved;
details[3] = foldersCreated;
details[4] = ex.Message.ToString();
details[5] = ex.StackTrace.ToString();
Log(details, w);
}
//generate email to notify of Error and (prefer to send Log.txt as attachment)
using (StreamReader r = File.OpenText(logPath))
{
DumpLog(r);
}
}
}
/*Takes a folder and organizes it into folder by naming folder whatever
* is in front of the delimeter Example -->(folderName__fileName.txt would be moved
* to a new or existing folder named folderName. Final path for file would
* look like this folderName\folderName__fileName.txt)
*
* It will not move file if it already exists in the new location, instead
* it prompts user that they should rename file and run program again.*/
static int organizeFolder(string delimeter, string rootPath)
{
//counter for total files in Folder
int Count = 0;
int totalMoved = 0;
FileInfo[] fileNames;
DirectoryInfo di = new DirectoryInfo(rootPath);
//set all file names as a string from network directory into an array
fileNames = di.GetFiles("*.*");
Count = fileNames.Length;
//Count = 0;//just to test exception handling
//if no files exist in network folder throw error message.
if (Count == 0)
{
fileNamesNOTmoved = "No Files Were In Directory to Move.";
}
else //files exist in network folder
{
int delimIndex = 0;
string folderName;
for (int i = 0; i < Count; i++)
{
if (fileNames[i].ToString().Contains(delimeter))
{
delimIndex = fileNames[i].ToString().IndexOf(delimeter);
folderName = fileNames[i].ToString().Substring(0, delimIndex);
//if folder doesnt exist create it here.
folderCreation(rootPath, folderName);
if (!File.Exists(rootPath + #"\" + folderName + #"\" + fileNames[i].Name))
{
File.Move(rootPath + #"\" + fileNames[i].ToString(), rootPath + #"\" + folderName + #"\" + fileNames[i].Name);
filesMoved++;
}
else
{
if (fileNamesNOTmoved == "")
fileNamesNOTmoved += "| ";
fileNamesNOTmoved += fileNames[i].Name + " | ";
filesNOTmoved++;
}
totalMoved++;
}
}
}
return totalMoved;
}
//if folder does not exist this method will create it
private static void folderCreation(string strTempPath, string folderName)
{
strTempPath = strTempPath + #"\" + folderName;
if (!Directory.Exists(strTempPath))
{
//Create \folderName
Directory.CreateDirectory(strTempPath);
foldersCreated++;
}
}
//adds entries to the log.txt file
public static void Log(object[] details, TextWriter w)
{
w.Write("\r\nLog Entry : ");
w.WriteLine("{0} {1}", DateTime.Now.ToShortTimeString(), DateTime.Now.ToShortDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", "Files Moved = " + details[0].ToString());
w.WriteLine(" :{0}", "Folders Created = " + details[3].ToString());
w.WriteLine(" :{0}", "Files Not Moved = " + details[1].ToString());
w.WriteLine(" :{0}", "Files Names Not Moved = {" + details[2].ToString() + "}");
w.WriteLine(" :{0}", "Error Message = " + details[4].ToString());
w.WriteLine(" :{0}", "Error Stack Trace = " + details[5].ToString());
w.WriteLine("---------------------------------------------------------------------------------------");
}
public static void DumpLog(StreamReader r)
{
string line;
while ((line = r.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
}
Basically would like the email to say:
Subject: Data Management Error Notification
Body: This is an Auto-Generated email to notify you there
was an error attempting to clean up the Files in the Directory.
Please refer to Attached Log.txt File for more detailed information.
Attachment: Log.txt
As it turns out SMTP was the way to go and Due to restrictions on my local machine I could only access it from the Dev, Qua, & Prd Servers. Once tested as admin from any of those locations.. email sent perfectly!!!
using the App.Config to hold all my To's, Froms, and the SMTP Host info and passing HTML as a string object into the method, here is the method I used to send email.
public static void sendMail(string msg)
{
SmtpClient smtpClient = new SmtpClient();
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress(emailFrom);
smtpClient.Host = smtpHost;
message.From = fromAddress;
message.Subject = "Test Email";
message.IsBodyHtml = true;
message.Body = msg;
message.To.Add(emailTo);
message.Priority = MailPriority.High;
smtpClient.Send(message);
}

Permission error when accessing folder

I have created a web service to take all files found in a folder specified, eg C:/Incoming/20121018 and email them as attachments to an email address that I specify.
I can send a mail with one attachment successfully, but I thought I would pass several files via an array to be sent as attachments. The only problem is that when I try to read the folder containing the files, I get a Permission error, even though I have rights to that folder. Any idea on where I'm going wrong?
See my code below:
[WebMethod]
public string Sending_Email(string strEmailAddrFrom, string[] strEmailAddrTo, int intTotalEmailTo, string [] strAttachement)
{
DateTime LeadDate;
LeadDate = DateTime.Now.Date;
string Year = Convert.ToString(LeadDate.Year);
string Month = Convert.ToString(LeadDate.Month);
string Day = Convert.ToString(LeadDate.Day);
string[] arr1 = new string[150];
string Loc = "C:\\Incoming\\" + "" + Year + "" + Month + "" + Day + "";
StreamReader reader = File.OpenText(Loc);
string contents = reader.ReadToEnd();
reader.Close();
DirectoryInfo di = new DirectoryInfo(Loc);
FileInfo[] fileList = di.GetFiles(".*.");
int count = 0;
foreach (FileInfo fi in fileList)
{
arr1[count] = fi.Name;
}
EmailAlert NewMail = new EmailAlert();
return NewMail.EmailSent(strEmailAddrFrom, strEmailAddrTo, intTotalEmailTo, arr1);
}
your error lies here you are trying to open folder as stream which is not right way.
StreamReader reader = File.OpenText(Loc);
string contents = reader.ReadToEnd();
reader.Close();

Categories