module/src/Invoke-SieveFilterCmdlet.cs
using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Linq; using System.Management.Automation; using System.Collections.Generic; [Cmdlet("Invoke", "SieveFilter")] public class InvokeSieveFilter : PSCmdlet { [Parameter(Mandatory = true)] public string SieveFile; [Parameter(Mandatory = true)] public string MaildirPath; Regex regex = new Regex("^To: (.*)$"); Regex innerRegex = new Regex("<(.*?)>$"); protected override void BeginProcessing() { var inboxPath = GetResolvedInboxPath(MaildirPath); var files = System.IO.Directory.EnumerateFiles(inboxPath); var filter = GetSieveFilter(SieveFile); foreach (var file in files) { var result = ReadFile(file); if (null != result) { string destination; filter.TryGetValue(result.Address, out destination); if (!string.IsNullOrEmpty(destination)) { MoveEmail(result, GetResolvedMailfolderPath(MaildirPath, destination)); } } } } private void MoveEmail(FileResult file, string destination) { string source = file.Path; string fileName = Path.GetFileName(source); string target = Path.Combine(destination, fileName); File.Move(source, target); WriteObject(string.Format("Move {0} to {1}", source, target)); } private Dictionary<string, string> GetSieveFilter(string sievePath) { var resolvedSievePath = GetResolvedPath(sievePath); var filter = new SieveFilter(resolvedSievePath); return filter.Parse(); } private string GetResolvedPath(string path) { string currentDirectory = Directory.GetCurrentDirectory(); try { Directory.SetCurrentDirectory(this.SessionState.Path.CurrentFileSystemLocation.Path); return Path.GetFullPath(path); } finally { Directory.SetCurrentDirectory(currentDirectory); } } private string GetResolvedMailfolderPath(string path, string mailFolder) { return Path.Combine(GetResolvedPath(path), "Maildir", "." + mailFolder, "cur"); } private string GetResolvedInboxPath(string path) { return Path.Combine(GetResolvedPath(path), "Maildir", "cur"); } private class FileResult { public string Path; public string Line; public string Address; } private FileResult ReadFile(string path) { using (var reader = new StreamReader(path, Encoding.UTF8, true, 1024)) { string line; while ((line = reader.ReadLine()) != null) { var match = regex.Match(line); if (match.Success) { var group = match.Groups[1].Value; return new FileResult() { Path = path, Line = match.Groups[0].Value, Address = InnerMatch(match.Groups[1].Value) }; } } } return null; } private string InnerMatch(string line) { var match = innerRegex.Match(line); if (match.Success) { return match.Groups[1].Value; } else { return line; } } } class SieveFilter { string path; Regex matchRegex = new Regex("^if header :contains \"to\" \"(.*)\"$"); Regex ruleRegex = new Regex("fileinto \"(.*)\";$"); public SieveFilter(string path) { this.path = path; } public Dictionary<string, string> Parse() { using (var reader = new StreamReader(path, Encoding.UTF8, true, 1024)) { Dictionary<string, string> result = new(); string line; string value = ""; while ((line = reader.ReadLine()) != null) { if (string.IsNullOrEmpty(value)) { var match = matchRegex.Match(line); if (match.Success) { var group = match.Groups[1].Value; value = match.Groups[1].Value; } } else { var match = ruleRegex.Match(line); if (match.Success) { result.Add(value, match.Groups[1].Value); value = ""; } } } return result; } } } |