Deleting mailitems from Outlook public folders - c#

There are about 15 particular public folders out of several public folders from which I am deleting mailitems which are greater than 15 days old. Each public folder has around 1000+ mailitems. Every week it's the same quantity of items. Currently I am getting the default public folder and looping each of the sub-folders and deleting the mails.
Microsoft.Office.Interop.Outlook.Folder tempInbox = tempApp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olPublicFoldersAllPublicFolders) as Microsoft.Office.Interop.Outlook.Folder;
**SOME Code***
foreach (Microsoft.Office.Interop.Outlook.Folder subfolder1 in subfolder.Folders)
{
if ((check those 14 subfolder names )& (subfolder1.Folders.Count > 0))
{
CheckCountries(subfolder1, sw);
}
}
CheckCountries(subfolder1, sw) -> Here I am comparing and deleting the mail items.
//Deletion part of code below
foreach (object todel in delItem)
{
DateTime d1 = DateTime.Now;
Microsoft.Office.Interop.Outlook.MailItem mailitmType = todel as Microsoft.Office.Interop.Outlook.MailItem;
if (mailitmType is Microsoft.Office.Interop.Outlook.MailItem)
{
if ((mailitmType.IsConflict != true) & (mailitmType.MessageClass.Contains("IPM.Note.SMIME") == false))
{
DateTime d2 = mailitmType.ReceivedTime;
if ((d1 - d2).TotalDays > iDays)
{
sw.WriteLine("Deleting Mail with Subject line as = \"" + mailitmType.Subject + "\" and Received time = " + mailitmType.ReceivedTime);
mailitmType.Delete();
iCnt = iCnt + 1;
} //mailitmType.Save();
}
}
}
I want to improve on the following areas -
It takes almost 5-7 hours to execute this as it reads through all the
mailitems (if there are 2000 of which only 1000 are > 15 days) in each
of the 15 folders and compares the age of the mail and then deletes.
Some of the folders fails due to access issue. So I need to add an id at the start of the code which has access to all of these public folders and can be used to delete. Currently it takes the default id that is running the executable.

Never loop through all item in a folder - use Items.Find/FindNext of Items.Restrict with a query on ReceivedTime property being less than some value.

Related

Accessing the elements of an array

I have a task to create a program to read from a file and check which employees have worked together for longer. I have already created the code to read from a file and store the data in an array. You can check it below:
string path;
do
{
Console.Write("Please enter the path of the file: ");
path = Console.ReadLine();
if (!File.Exists(path))
{
Console.WriteLine("The path is not correct.");
}
} while (!File.Exists(path));
string[] lines = File.ReadAllLines(path);
foreach (string line in lines) //just to check if the program can read from a file
{
Console.WriteLine(line);
}
Console.WriteLine();
for (int i = 0; i < lines.Length; i++)
{
string[] values = lines[i].ToString().Split(',');
foreach (string el in values) //just to check if the value are stored inside the array
{
Console.Write(el + " ");
}
}
Console.ReadLine();
This code gives this result:
Please enter the path of the file: C:\Users\...
143, 12, 2013-11-01, 2014-01-05
145, 10, 2009/01/01, 2011/04/27
140, 10, 2009.03.01, 2011.04.27
111, 10, 2009.03.01, NULL
143 12 2013-11-01 2014-01-05
145 10 2009/01/01 2011/04/27
140 10 2009.03.01 2011.04.27
111 10 2009.03.01 NULL
(the columns represent: employerID, projectID, DateFrom and DateTo respectively). Now I need to create a code that calculates the time that 2 employees have worked on the same project (using project id and the dates to calculate the period of work together). I need some help to understand how I can do that. Thank you!
This could be a good start:
Create a class EmployeeWorkPeriod with the 4 fields
Parse values into data types like int and DateTime (and DateTime?).
Once you have these object you can start writing you program logic.

Edit specific word in specific line

I know this has been asked a few times, but I'm need a fast way to do this in files with different size (small and large files).
I need to edit scale factor in sat(txt) file. This is a first number in third line:
700 104 1 0 16 Autodesk AutoCAD 19 ASM 221.0.0.1871 NT 24 Tue
Aug 16 09:02:14 2016
1000 9.9999999999999995e-007 1e-010
I suggest extracting a method and Linq:
private static String MyEditLine(string value) {
var items = value.Split(new char[] { ' ' }, 2);
items[0] = "2000"; // let's change 1000 into 2000
return string.Join(" ", items);
}
...
var target = File
.ReadLines(#"C:\MyFile.txt")
.Select((line, index) => index != 2
? line
: MyEditLine(line))
.ToList();
File.WriteAllLines(#"C:\MyFile.txt", target);
assume you read your file and get a String[] called file and the number, you want to modify, is represented as float.
Than you can use the following code to first extract the line, you want. After this you get the number through float.TryParse(..)
int lineWithParam = 3;
String[] splittedLine = (file[lineWithParam-1]).Split(new char[] { ' ' }, 2);
if(splittedLine.Length == 2)
{
float fact = 0.0f;
String newFact = splittedLine[0];
// or how ever you want to modify your factor
if(float.TryParse(splittedLine[0], out fact))
{
newFact = "" + (fact * 12.3f);
}
file[lineWithParam-1] = newFact + " " + splittedLine[1];
}
Here an executable example: https://dotnetfiddle.net/NVgETo
after this you can write the String[] file back to the real file.
Note: this will not modify the file, if in the given line the first parameter isn't a valid float!

How to avoid running the same loop multiple times?

Here is a big problem for me, because I can't get out of the loop. I got in listDataReport.Count only 1. But in the foreach from beginDate (example: 10/01/2010) to endDate (today), my file writes as times as date are going through from the beginning to the end.
What I want is only one write for the specific date in listDataReport
listDataReport = blReports.GetDataClientes(beginDate, endDate);
string dateSelected = string.Empty;
while (beginDate < endDate)
{
foreach (var item in listDataReport)
{
FileCreated.WriteLog(item.NmbrCliLeg + "|" + item.NmbCliProf + "|" + item.Namsur + "|" + item.Mail, false);
dateSelected= item.DateUp;
}
beginDate = beginDate.AddDays(1);
}
log.WriteLog("Clients up date: " + dateSelected + ":" + listDataReport.Count);
It repeats as many days are between beginDate- endDate. And if i only get one Client on listDataReportthat happens.
As you can see there's FileCreated.WriteLogcreates a .txt which writes the data client here's the problem. In log.WriteLog which creates a .log file there's no problem in that. I'll show what I got from both files.
In log:
---***--- Execution Initiated: 27/03/2015 09:44:40 a.m.
27/03/2015 09:44:50 a.m. - Clients up date 03/19/2015: 1
===***=== Execution Ended: 03/27/2015 09:44:50 a.m.
But now in .txt file (Datefile03272015.txt) :
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
0123456789|7976967|NAME SURNAME|somemail#mail.com
All the job runs each day and creates a .txt file each day. It doesn't matter the .log file here.
Use the keyword break to break out of a loop:
https://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx
int[] list = [1, 2, 3, 4, 5, 6, 7, 8];
foreach(int item in list)
{
Console.WriteLine(item);
if (item == 5)
break;
}
Output:
1
2
3
4
5

How do i make a main group directory name for each directories ?

I have this code:
foreach (var map in maps)
{
// This starts a new group
var downloadDirectory = Path.Combine(BaseDirectory, htmlFiles[groupId++]);
BackgroundWorkerConfiguration.urlsDirectories.Add(downloadDirectory);
}
BaseDirectory in this is: d:\test\ImagesDirectories
htmlFiles is a List contain 35 indexs each index a directory name
froypId is int.
For example in the first index in htmlFiles i see: Sat24_Africa0
In index 1 i see : Sat24_Africa1
In index i see: Sat24_Africa2
.
.
In index 5 i see: Sat24_Asia0
In index 6 i see: Sat24_Asia1
.
.
.
.
And so on 35 directories.
In the end the List urlsDirectories that is List look like:
In index 0 i see: d:\test\ImagesDirectories\Sat24_Africa0
In index 1 i see: d:\test\ImagesDirectories\Sat24_Africa1
In index 2 i see: d:\test\ImagesDirectories\Sat24_Africa2
.
.
.
In index 33 i see: d:\test\ImagesDirectories\Sat24_South_america3
In the end i loop over this List urlsDirectories and create all the 35 directories.
for (int i = 0; i < BackgroundWorkerConfiguration.urlsDirectories.Count; i++)
{
if (!Directory.Exists(Path.Combine(imagesDirectory, BackgroundWorkerConfiguration.urlsDirectories[i])))
{
Directory.CreateDirectory(Path.Combine(imagesDirectory, BackgroundWorkerConfiguration.urlsDirectories[i]));
}
}
But instead creating 35 directories under the base directory i want that there will be a main directory first for Europe and then under Europe to have sub directories:
Africa, Asia, Europa, Middle East, North America, Oceania, South America
And under each directory for example Africa to have the directories: Africa0 Africa1 Africa2....
So it should be like this:
D:\test\ImagesDirectories\Europe\Africa\Africa0
D:\test\ImagesDirectories\Europe\Africa\Africa1
D:\test\ImagesDirectories\Europe\Africa\Africa2
D:\test\ImagesDirectories\Europe\Africa\Africa3
D:\test\ImagesDirectories\Europe\Africa\Africa4
D:\test\ImagesDirectories\Europe\Asia\Asia0
D:\test\ImagesDirectories\Europe\Asia\Asia1
D:\test\ImagesDirectories\Europe\Asia\Asia2
D:\test\ImagesDirectories\Europe\Asia\Asia3
D:\test\ImagesDirectories\Europe\Asia\Asia4
And so on. Now i have all the names in the directories in the urlsDirectories but how do i parse them and how do i make the groups of directories ?
This is for real what i see in the BaseDirectory variable:
C:\Users\bout0_000\AppData\Local\WeatherMaps\WeatherMaps\ImagesDirectory
Then this is what i see in real in htmlFiles in index0:
Sat24_Africa0
And this is what i see now in real in urlsDirectories in index0:
C:\Users\bout0_000\AppData\Local\WeatherMaps\WeatherMaps\ImagesDirectory\Sat24_Africa0
How can i make the changes ?
You can try this:
foreach (var map in maps)
{
// This starts a new group
var count = "Sat24_".Length;
var leafDirectory = htmlFiles[groupId++].Remove(0, count); // e.g. "Africa0"
var continent = Regex.Match(leafDirectory, #"[A-Za-z_]+").Value; // e.g. "Africa"
var downloadDirectory = Path.Combine(BaseDirectory, "Europe", continent, leafDirectory);
BackgroundWorkerConfiguration.urlsDirectories.Add(downloadDirectory);
}

C# - Calculate Total Statistics from Multiple Files

This is a similar question I asked earlier, except different in the fact that I am taking multiple files and calculating the total sums off of those files. I have it to the point where I am reading all the files from a specific directory, but for some reason its not grouping correctly.
Here is the code that I have:
public void CalculateMonthlyStatistics(string monthlyFiles)
{
string monthlyFileName = monthlyFiles + ".log";
var statistics = File.ReadLines(monthlyFileName)
.GroupBy(items => items[0])
.Select(g =>
new
{
Division = g.Key,
ZipFiles = g.Sum(i => Convert.ToInt32(i[1])),
Conversions = g.Sum(i => Convert.ToInt32(i[2])),
ReturnedFiles = g.Sum(i => Convert.ToInt32(i[3])),
TotalEmails = g.Sum(i => Convert.ToInt32(i[4]))
});
statistics
.ToList()
.ForEach(d => Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}",
d.Division,
d.ZipFiles,
d.Conversions,
d.ReturnedFiles,
d.TotalEmails));
Console.Read();
//.ForEach(d => Log.Open(tempFileName.TrimEnd(charsToTrim), d.Division, d.ZipFiles, d.Conversions, d.ReturnedFiles, d.TotalEmails));
}
}
}
The log files that I am putting into it look like the following:
Division Zip Files Conversions Returned Files Total E-Mails
Corporate 0 5 0 5
Energy 0 1 0 5
Global Operations 0 3 0 3
Oil & Gas 1 5 0 5
Capital 5 18 0 12
So what I am trying to do, is group by "Corporate", "Energy", etc. Then calculate the totals for ALL of the files being read, to create a Monthly Statistics file. I am getting totals currently, however I think its got something to do with the header that I am passing in, and I am not sure how to tell it to skip that line.
Thanks in advance
EDIT
Here is my processor, which originally reads the directory, etc.
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
foreach (string monthlyFileNames in Directory.GetFiles(path))
{
string monthlyFiles = path + #"\" + Path.GetFileNameWithoutExtension(monthlyFileNames);
new MonthlyReader().CalculateMonthlyStatistics(monthlyFiles);
}
}
The processor finds the proper directory to search through in order to get the files from. It uses the current date, and finds last month.
Skipping the header is straightforward:
File.ReadLines(monthlyFileName).Skip(1).<rest of your chain>
However, it seems as though you're reading one file at a time, when you want to be reading all files then calculating the statistics?
How about first:
public IEnumerable<String> ReadLinesInDirectory(string path)
{
return Directory.EnumerateFiles(path)
.SelectMany(f =>
File.ReadLines(f)
.AsEnumerable()
.Skip(1));
}
And replace ReadLines with that (ensuring you're pointing to the right path etc).
OK here's the full explanation, but I think you may need to study C# some more. First, define the ReadLinesInDirectory function I wrote above.
Then replace ProcessMonthlyLogFiles with this instead:
public void ProcessMonthlyLogFiles()
{
DateTime currentTime = DateTime.Now;
int month = currentTime.Month - 1;
int year = currentTime.Year;
string path = Path.GetDirectoryName(Settings.DailyPath + year + #"\" + month + #"\");
CalculateMonthlyStatistics(path);
}
And in CalculateMonthlyStatistics have the first three lines (before the GroupBy) as follows:
public void CalculateMonthlyStatistics(string path)
{
var statistics = ReadLinesInDirectory(path)
// .GroupBy etc...

Categories

Resources