public bool Validate() { ImapClient imapClient = new ImapClient(Account); Error = string.Empty; int tryCount = 2; if (imapClient.Connect(tryCount)) { imapClient.Disconnect(); } else { Error = imapClient.Error; return false; } SmtpClient smtpClient = new SmtpClient(Account); if (smtpClient.Connect()) { smtpClient.Disconnect(); } else { Error = smtpClient.Error; return false; } return true; }
// Updates the mailbox tree in the specified account with ones from the server. // Also updates the database to reflect the change. private void BeginSyncMailboxList(Account account) { Task.Factory.StartNew(() => { List<Mailbox> localMailboxes = DatabaseManager.GetMailboxes(account.AccountName); ImapClient imapClient = new ImapClient(account); if (imapClient.Connect()) { List<Mailbox> serverMailboxes = imapClient.ListMailboxes(); var comparer = new CompareMailbox(); var localNotServer = localMailboxes.Except(serverMailboxes, comparer).ToList(); var serverNotLocal = serverMailboxes.Except(localMailboxes, comparer).ToList(); if (localNotServer.Count > 0 || serverNotLocal.Count > 0) { account.Mailboxes.Clear(); account.Mailboxes.AddRange(serverMailboxes); if (localNotServer.Count > 0) { DatabaseManager.DeleteMailboxes(localNotServer); } if (serverNotLocal.Count > 0) { DatabaseManager.InsertMailboxes(serverNotLocal); } } imapClient.Disconnect(); } while (!Common.Globals.BootStrapperLoaded) { // We don't want to fire this event before the subscribers are ready. // There must be a better way to handle these sort of things. Thread.Sleep(50); } GlobalEventAggregator.Instance.GetEvent<MailboxListSyncFinishedEvent>().Publish(account); }); }
private void SyncExistingMessageHeaders(Account account, string mailboxName, ImapClient imapClientOnSelectedStatus, int firstUid, int lastUid) { Trace.WriteLine("SyncExistingMessageHeaders: Mailbox(" + mailboxName + "), UIDs(" + firstUid + ", " + lastUid + ")"); // Decrement this at every exit point. openSyncOps.AddOrUpdate(account.AccountName, 1, (k, v) => v + 1); // Delete all messages that have been deleted from server. List <int> serverUids = new List <int>(); bool searchSuccess = imapClientOnSelectedStatus.SearchUids("ALL", serverUids); if (searchSuccess) { List <string> keysToDelete = new List <string>(); foreach (KeyValuePair <string, Message> entry in MessagesDico) { Message msg = entry.Value; if (msg.AccountName == account.AccountName && msg.MailboxPath == mailboxName && !serverUids.Contains(msg.Uid)) { keysToDelete.Add(entry.Key); } } List <Message> msgsDeleted = new List <Message>(); foreach (string key in keysToDelete) { Message msg = MessagesDico[key]; MessagesDico.Remove(key); OnMessageRemoved(msg); msgsDeleted.Add(msg); } DatabaseManager.DeleteMessages(msgsDeleted); } // Now synchronize the remaining messages. int messagesCount = lastUid - firstUid + 1; int downloadChunk = this.downloadChunkSize; int startUid = lastUid - downloadChunk + 1; int endUid = lastUid; while (endUid >= firstUid) { int abort = 0; if (abortLatches.TryGetValue(account.AccountName, out abort) && abort == 1) { Trace.WriteLine("Aborting sync..."); openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); return; } if (startUid < firstUid) { startUid = firstUid; } List <Message> serverMsgs = imapClientOnSelectedStatus.FetchHeaders(startUid, endUid - startUid + 1, true); if (serverMsgs.Count > 0) { List <Message> messagesAdded = new List <Message>(); foreach (Message serverMsg in serverMsgs) { Message localMsg; if (MessagesDico.TryGetValue(serverMsg.UniqueKeyString, out localMsg)) { // A local copy exists. Update its flags. if (localMsg.FlagString != serverMsg.FlagString) { localMsg.FlagString = serverMsg.FlagString; OnMessageModified(localMsg); } } else { MessagesDico.Add(serverMsg.UniqueKeyString, serverMsg); OnMessageAdded(serverMsg); messagesAdded.Add(serverMsg); } } DatabaseManager.StoreMessages(messagesAdded); } endUid = startUid - 1; startUid = endUid - downloadChunk + 1; } openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); }
private void SetMessage(Message newMessage) { if (Message != null) { Message.PropertyChanged -= HandleModelPropertyChanged; } Message = newMessage; Message.PropertyChanged += HandleModelPropertyChanged; Date = ImapParser.ParseDate(Message.DateString); if (string.IsNullOrEmpty(Message.Body)) { DownloadMessageBodyAsync(); } else { // Loading a message whose body has already been downloaded. TextBody = MimeUtility.GetTextBody(Message.Body); HtmlBody = MimeUtility.GetHtmlBody(Message.Body); ProcessedHtmlBody = ProcessHtmlBody(HtmlBody); LoadAttachments(Message.Body); if (!Message.IsSeen) { // Set the \Seen flag. Message.IsSeen = true; DatabaseManager.Update(Message); Task.Run(() => { ImapClient imap = new ImapClient(notification.SelectedAccount); if (imap.Connect()) { // Not readonly because we need to set the \Seen flag. bool readOnly = false; if (imap.SelectMailbox(notification.SelectedMailbox.DirectoryPath, readOnly)) { imap.SetFlag(ImapClient.FlagAction.Add, Message.Uid, "\\Seen"); } imap.Disconnect(); } }); } } }
private async void DownloadMessageBodyAsync() { Loading = true; string msgBody = string.Empty; await Task.Run(() => { ImapClient imap = new ImapClient(notification.SelectedAccount); if (imap.Connect()) { // Not readonly because we need to set the \Seen flag. bool readOnly = false; if (imap.SelectMailbox(notification.SelectedMailbox.DirectoryPath, readOnly)) { msgBody = imap.FetchBody(Message.Uid); } imap.Disconnect(); if (!Message.IsSeen) { Message.IsSeen = true; // The server should automatically set the \Seen flag when BODY is fetched. // We shouldn't have to send command for this. } } }); if (msgBody != string.Empty) { Message.Body = msgBody; } // Store the Body and IsSeen flag to the database. DatabaseManager.Update(Message); Loading = false; }
private void BeginMonitor(Account account, string mailboxName) { Trace.WriteLine("BeginMonitor " + account.AccountName); ImapClient imapClient = new ImapClient(account); if (!imapClient.Connect()) { Debug.WriteLine(imapClient.Error); return; } imapClient.NewMessageAtServer += HandleNewMessageAtServer; imapClient.MessageDeletedAtServer += HandleMessageDeletedAtServer; imapClient.MessageSeenAtServer += HandleMessageSeenAtServer; imapClient.MessageUnseenAtServer += HandleMessageUnseenAtServer; imapClient.BeginMonitor(mailboxName); }
public void DeleteMessages(List<Message> messages) { // Delete from memory. foreach (Message msg in messages) { MessagesDico.Remove(msg.UniqueKeyString); OnMessageRemoved(msg); } // Delete from database. DatabaseManager.DeleteMessages(messages); // Delete from server. Task.Run(() => { while (messages.Count > 0) { Account account = AccountManager.Instance.GetAccountByName(messages[0].AccountName); List<Message> accountMessages = new List<Message>(); for (int i = messages.Count - 1; i >= 0; --i) { Message msg = messages[i]; if (msg.AccountName == account.AccountName) { accountMessages.Add(msg); messages.RemoveAt(i); } } ImapClient imapClient = new ImapClient(account); if (imapClient.Connect()) { imapClient.DeleteMessages(accountMessages); imapClient.Disconnect(); } } }); }
private void SyncExistingMessageHeaders(Account account, string mailboxName, ImapClient imapClientOnSelectedStatus, int firstUid, int lastUid) { Trace.WriteLine("SyncExistingMessageHeaders: Mailbox(" + mailboxName + "), UIDs(" + firstUid + ", " + lastUid + ")"); // Decrement this at every exit point. openSyncOps.AddOrUpdate(account.AccountName, 1, (k, v) => v + 1); // Delete all messages that have been deleted from server. List<int> serverUids = new List<int>(); bool searchSuccess = imapClientOnSelectedStatus.SearchUids("ALL", serverUids); if (searchSuccess) { List<string> keysToDelete = new List<string>(); foreach (KeyValuePair<string, Message> entry in MessagesDico) { Message msg = entry.Value; if (msg.AccountName == account.AccountName && msg.MailboxPath == mailboxName && !serverUids.Contains(msg.Uid)) { keysToDelete.Add(entry.Key); } } List<Message> msgsDeleted = new List<Message>(); foreach (string key in keysToDelete) { Message msg = MessagesDico[key]; MessagesDico.Remove(key); OnMessageRemoved(msg); msgsDeleted.Add(msg); } DatabaseManager.DeleteMessages(msgsDeleted); } // Now synchronize the remaining messages. int messagesCount = lastUid - firstUid + 1; int downloadChunk = this.downloadChunkSize; int startUid = lastUid - downloadChunk + 1; int endUid = lastUid; while (endUid >= firstUid) { int abort = 0; if (abortLatches.TryGetValue(account.AccountName, out abort) && abort == 1) { Trace.WriteLine("Aborting sync..."); openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); return; } if (startUid < firstUid) { startUid = firstUid; } List<Message> serverMsgs = imapClientOnSelectedStatus.FetchHeaders(startUid, endUid - startUid + 1, true); if (serverMsgs.Count > 0) { List<Message> messagesAdded = new List<Message>(); foreach (Message serverMsg in serverMsgs) { Message localMsg; if (MessagesDico.TryGetValue(serverMsg.UniqueKeyString, out localMsg)) { // A local copy exists. Update its flags. if (localMsg.FlagString != serverMsg.FlagString) { localMsg.FlagString = serverMsg.FlagString; OnMessageModified(localMsg); } } else { MessagesDico.Add(serverMsg.UniqueKeyString, serverMsg); OnMessageAdded(serverMsg); messagesAdded.Add(serverMsg); } } DatabaseManager.StoreMessages(messagesAdded); } endUid = startUid - 1; startUid = endUid - downloadChunk + 1; } openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); }
private void SyncNewMessageHeaders(Account account, string mailboxName, ImapClient imapClientOnSelectedStatus, int firstUid, int lastUid) { Trace.WriteLine("SyncNewMessageHeaders: Mailbox(" + mailboxName + "), UIDs(" + firstUid + ", " + lastUid + ")"); // Decrement this at every exit point. openSyncOps.AddOrUpdate(account.AccountName, 1, (k, v) => v + 1); int messagesCount = lastUid - firstUid + 1; int downloadChunk = this.downloadChunkSize; int startUid = lastUid - downloadChunk + 1; int endUid = lastUid; while (endUid >= firstUid) { int abort = 0; if (abortLatches.TryGetValue(account.AccountName, out abort) && abort == 1) { Trace.WriteLine("Aborting sync..."); openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); return; } if (startUid < firstUid) { startUid = firstUid; } List<Message> msgs = imapClientOnSelectedStatus.FetchHeaders(startUid, endUid - startUid + 1, true); if (msgs.Count > 0) { foreach (Message msg in msgs) { if (!MessagesDico.ContainsKey(msg.UniqueKeyString)) { MessagesDico.Add(msg.UniqueKeyString, msg); OnMessageAdded(msg); } } DatabaseManager.StoreMessages(msgs); } endUid = startUid - 1; startUid = endUid - downloadChunk + 1; } openSyncOps.AddOrUpdate(account.AccountName, 0, (k, v) => v - 1); }
private void SyncMessage(Account account, string mailboxName) { int abort = 0; if (abortLatches.TryGetValue(account.AccountName, out abort) && abort == 1) { // Abort sync. return; } ImapClient imapClient = new ImapClient(account); if (!imapClient.Connect()) { Trace.WriteLine(imapClient.Error); return; } ExamineResult status; bool readOnly = true; if (!imapClient.SelectMailbox(mailboxName, readOnly, out status)) { Debug.WriteLine("MessageManager.SyncMessage(): Unable to select mailbox " + mailboxName + ".\n" + imapClient.Error); imapClient.Disconnect(); return; } int localLargestUid = DatabaseManager.GetMaxUid(account.AccountName, mailboxName); // Download the recent message headers that have never been downloaded yet. int serverLargestUid = status.UidNext - 1; if (serverLargestUid > localLargestUid) { SyncNewMessageHeaders(account, mailboxName, imapClient, localLargestUid + 1, serverLargestUid); } // Sync changes to the existing message headers (flags, etc.). if (localLargestUid > 0) { SyncExistingMessageHeaders(account, mailboxName, imapClient, 1, localLargestUid); } imapClient.Disconnect(); }