/// <summary> /// Alternate Constructor /// </summary> /// <param name="name"></param> /// <param name="parent"></param> public IMAPFolder(string name, string parent) { _subFolders = new IMAPFolderCollection(); _parentFolder = null; _folderName = name; _parentFolderName = parent; _folderPath = String.Empty; _messages = new IMAPMessageCollection(); _quota = new IMAPFolderQuota(); }
/// <summary> /// New method for processing folder list /// </summary> /// <param name="rootFolder"></param> /// <returns></returns> public IMAPFolderCollection ProcessFolders(string rootFolder) { IMAPFolderCollection folders = new IMAPFolderCollection(); List<IMAPFolder> subFolders = new List<IMAPFolder>(); _rawFolderList.Clear(); string cmd = "LIST {0} \"*\"\r\n"; if (String.IsNullOrEmpty(rootFolder)) rootFolder = "\"\""; ArrayList result = new ArrayList(); SendAndReceive(String.Format(cmd, rootFolder), ref result); foreach (string s in result) { if (s.StartsWith("*")) { int idx = s.IndexOf("\""); char dirDivider = s[idx + 1]; int idx2 = s.IndexOf(" ", idx + 2); string folderString = s.Substring(idx2 + 1).Replace("\"",""); string[] folderParts = folderString.Split(new char[] { dirDivider }); StringBuilder folderPath = new StringBuilder(); for (int i = 0; i < folderParts.Length; i++) { if (i > 0 && i < folderParts.Length) folderPath.Append(dirDivider); folderPath.Append(folderParts[i]); IMAPFolder f = new IMAPFolder(); f.FolderName = folderParts[i]; f.FolderPath = folderPath.ToString(); f.Selectable = !s.ToLower().Contains("\\noselect"); if (i > 0) { // if this is greater than 0 then we must have already processed its parent folder. find it // in the list foreach (IMAPFolder pf in folders) { if (pf.FolderName.Equals(folderParts[i - 1])) { f.ParentFolder = pf; bool subAdded = false; foreach (IMAPFolder testfolder in pf.SubFolders) { if (testfolder.FolderPath.Equals(f.FolderPath)) subAdded = true; } if (!subAdded) { pf.SubFolders.Add(f); subFolders.Add(f); } //subFolders.Add(f); break; } } } bool alreadyAdded = false; foreach (IMAPFolder test in folders) { if (test.FolderPath.Equals(f.FolderPath)) alreadyAdded = true; } if (!alreadyAdded) { folders.Add(f); _rawFolderList.Add(f); } } } } List<IMAPFolder> tmp1 = new List<IMAPFolder>(); foreach (IMAPFolder f in folders) if (f.ParentFolder != null) tmp1.Add(f); foreach (IMAPFolder f in tmp1) folders.Remove(f); return folders; }
/// <summary> /// Default constructor. Only used for deserialization purposes. /// </summary> public IMAPClient() { _config = null; _imap = new IMAP(); _folders = new IMAPFolderCollection(); }
/// <summary> /// Helper method for recursively adding all folders from the source folder structure into the flat list /// </summary> /// <param name="currentFolder"></param> /// <param name="master"></param> private void FolderRecurser(IMAPFolder currentFolder, ref IMAPFolderCollection master) { if (currentFolder.SubFolders.Count > 0) { foreach (IMAPFolder f in currentFolder.SubFolders) { master.Add(f); FolderRecurser(f, ref master); } } }
/// <summary> /// Takes the multi-level folder structure and flattens it into a single list of all folders /// </summary> /// <param name="list"></param> /// <returns></returns> private IMAPFolderCollection FlattenFolderList(IMAPFolderCollection list) { IMAPFolderCollection newList = new IMAPFolderCollection(); foreach (IMAPFolder f in list) { FolderRecurser(f, ref newList); newList.Add(f); } return newList; }
/// <summary> /// Synchronizes the local cache with the server /// </summary> public void SyncCache() { if (this.OfflineMode) return; if (!this.UsingCache) return; // to synchronize the cache without having to download everything all over again, // we first get the folder list from the server. We then look at each folder in the server list // and see if it already exists in the client list. if it does not, we add it and pull // the message UIDs for it. // then we check the client list and see if all of those folders are still on the server // if not, the folder on the client side is removed, all with all of its messages // keep track of newly added folders so their contents can be downloaded. // next we iterate through all the existing folders and check for any new messages. // this is accomplished by simply calling the GetMessageIDs method on the folder. this will // update the folder with any UIDs that dont already exist. // the messages content will be loaded automatically when it is serialized. Log(IMAPBase.LogTypeEnum.INFO, "Synching Cache..."); IMAPFolderCollection serverFolderList = _imap.RawFolderList; IMAPFolderCollection clientFolderList = FlattenFolderList(_folders); IMAPFolderCollection newFolderList = new IMAPFolderCollection(); IMAPFolderCollection oldFolderList = new IMAPFolderCollection(); foreach (IMAPFolder f in serverFolderList) { bool found = false; foreach (IMAPFolder cf in clientFolderList) { if (cf.FolderPath.Equals(f.FolderPath)) found = true; } if (!found) { newFolderList.Add(f); } } foreach (IMAPFolder f in clientFolderList) { bool found = false; foreach (IMAPFolder sf in serverFolderList) { if (sf.FolderPath.Equals(f.FolderPath)) found = true; } if (!found) { oldFolderList.Add(f); } } if (oldFolderList.Count > 0) { Log(IMAPBase.LogTypeEnum.INFO, String.Format("{0} old folders found", newFolderList.Count)); foreach (IMAPFolder f in oldFolderList) { IMAPFolder temp = null; FindFolder(f.FolderPath, ref _folders, ref temp); if (temp != null) { if (temp.ParentFolder == null) { _folders.Remove(temp); } else { temp.ParentFolder.SubFolders.Remove(temp); } } } } if (newFolderList.Count > 0) { Log(IMAPBase.LogTypeEnum.INFO, String.Format("{0} new folders found", newFolderList.Count)); // now we need to put these new folders into the proper locations in the tree. foreach (IMAPFolder f in newFolderList) { f.GetMessageIDs(false); foreach (IMAPFolder sf in serverFolderList) { if (sf.FolderName.Equals(f.ParentFolderName)) { f.ParentFolder = sf; break; } } // if the new folder has no parent assigned to it then we just add it to the root folders if (f.ParentFolderName == String.Empty) { _folders.Add(f); } else { // otherwise we just loop through the flat list we created // and find the folder that is the parent of the current new folder // we then add the new folder to the sub folders of its parent foreach (IMAPFolder cf in clientFolderList) { if (cf.FolderPath.Equals(f.ParentFolder.FolderPath)) { cf.SubFolders.Add(f); f.ParentFolder = cf; break; } } } } } foreach (IMAPFolder f in clientFolderList) { // this will get the UIDs of any new messages that have been added to the folder on the server f.GetMessageIDs(false); } UpdateCache(false); Log(IMAPBase.LogTypeEnum.INFO, "Cache Synchronization Complete"); }
/// <summary> /// Login using currently specified connection settings. Called automatically if AutoLogon is true. /// </summary> public void Logon() { if (this.LoggedOn || this._config == null) return; if (!_imap.Login(_config.Host, _config.UserName, _config.Password, _config.UseSSL)) { if (!UsingCache) { Log(IMAPBase.LogTypeEnum.ERROR, "Cannot connect to server and no cache is available. System cannot proceed. Quiting..."); throw new IMAPException(IMAPException.IMAPErrorEnum.IMAP_ERR_CONNECT); } OfflineMode = true; Log(IMAPBase.LogTypeEnum.WARN, "Login Failed. Switching to Offline Mode"); return; } Log(IMAPBase.LogTypeEnum.INFO, "Login Successful"); if (!UsingCache) { XmlDocument doc = new XmlDocument(); _folders.Clear(); _folders = _imap.ProcessFolders(_config.DefaultFolderName); foreach (IMAPFolder f in _folders) { f.SetClient(this); if (_config.AutoGetMsgID) f.GetMessageIDs(false); } } }
/// <summary> /// Loads the specified local cache into the object model /// </summary> public void LoadCache() { Log(IMAPBase.LogTypeEnum.INFO, "Loading Local Cache..."); //try //{ Stream s = File.Open(_config.CacheFile, FileMode.Open); IMAPClient c = new IMAPClient(); switch (_config.Format) { case CacheFormat.XML: { XmlSerializer xml = new XmlSerializer(typeof(IMAPClient)); c = (IMAPClient)xml.Deserialize(s); break; } case CacheFormat.Binary: { BinaryFormatter b = new BinaryFormatter(); c = (IMAPClient)b.Deserialize(s); break; } } this._folders = c.Folders; foreach (IMAPFolder f in _folders) { f.SetClient(this); f.SetParent(null); } s.Close(); //} //catch (Exception e) //{ // throw e; //} Log(IMAPBase.LogTypeEnum.INFO, String.Format("Cache loaded ({0} messages found, in {1} folders)", this.TotalMessages, this.FolderCount)); }
/// <summary> /// Searches the entire tree structure of the provided folder collection looking for a folder with /// the specified path. if it finds the folder, it is stored in the foundFolder parameter /// </summary> /// <param name="path"></param> /// <param name="sourceList"></param> /// <param name="foundFolder"></param> public void FindFolder(string path, ref IMAPFolderCollection sourceList, ref IMAPFolder foundFolder) { if (sourceList.Count == 0) return; foreach (IMAPFolder f in sourceList) { if (f.FolderPath.Equals(path)) { foundFolder = f; return; } IMAPFolderCollection fc = f.SubFolders; FindFolder(path, ref fc, ref foundFolder); } }
/// <summary> /// Main constructor. /// </summary> /// <param name="config">The configuration instance to use for this client</param> /// <param name="logger">Custom logger to use with this client. Use null for default logger.</param> public IMAPClient(IMAPConfig config, IMAPLogger logger, int maxWorkers) { _config = config; _imap = new IMAP(); _logger = logger ?? new IMAPLogger(config); //_imap.InfoLogged += Log; _imap.Logger = _logger; _folders = new IMAPFolderCollection(); Log(IMAPBase.LogTypeEnum.IMAP, "------------------------------------------------------"); Log(IMAPBase.LogTypeEnum.INFO, "InterIMAP Client Initialized"); if (config.CacheFile != String.Empty) { this.UsingCache = true; Log(IMAPBase.LogTypeEnum.INFO, String.Format("Using Local Cache File: {0}", config.CacheFile)); } if (config.AutoLogon) Logon(); if (UsingCache) { FileInfo finfo = new FileInfo(config.CacheFile); if (finfo.Exists) { // this config has a cache file specified. Load the cache into the object model LoadCache(); if (!OfflineMode && config.AutoSyncCache) SyncCache(); } else { _folders.Clear(); _folders = _imap.ProcessFolders(_config.DefaultFolderName); //IMAPFolderCollection tempFolders = _imap.ProcessFolders(_config.DefaultFolderName); foreach (IMAPFolder f in _folders) { f.SetClient(this); if (_config.AutoGetMsgID) f.GetMessageIDs(false); } BuildNewCache(); } } }