/// <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(); } } }
/// <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> /// 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> /// 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> /// 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> /// 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.Port, _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> /// 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> /// Default constructor. Only used for deserialization purposes. /// </summary> public IMAPClient() { _config = null; _imap = new IMAP(); _folders = new IMAPFolderCollection(); }