private async void HandleQueue() { var active = queue.Join(mailboxes, queue => queue.Owner, mailboxes => mailboxes.Alias, (q, m) => new { queue = q, mailboxes = m }) .Where(q => q.queue.Status == Status.Waiting && !q.mailboxes.Busy) .OrderBy(q => q.queue.Size).ToList(); //List<Queue> active = queue.Where(q => !q.Owner.Busy && q.Status == Status.Waiting) // .OrderBy(q => q.Size).ToList(); if (active.Count == 0 || queuebusy) { return; } queuebusy = true; List <string> aliases = active.GroupBy(q => q.queue.Owner) .Select(g => g.First()) .Select(q => q.queue.Owner).ToList(); foreach (string alias in aliases) { //List<Queue> batch = active.Where(q => q.Alias == alias) // .GroupBy(q => q.Owner) // .Select(g => g.First()).ToList(); // TODO: combine duplicte messages, so they only download once. //while (tocktasks.Count >= config.Settings.MaxQueueThreads) while (tocktasks.Count >= 1) { await Task.Delay(1000); tocktasks.RemoveAll(t => t.Status == TaskStatus.RanToCompletion); } Queue q = queue.Where(a => a.Owner == alias).First(); Mailbox owner = mailboxes.Where(m => m.Alias == q.Owner).First(); tocktasks.Add(Task.Run(() => { ProcessQueuedMessages(owner); })); } queuebusy = false; }
private void ProcessQueuedMessages(Mailbox mailbox) { Server serverout = config.Servers.Find(s => s.Alias == mailbox.Outbound.Alias && s.Type == ServerType.SMTP); mailbox.Busy = true; WriteLog(string.Format("Precessing Queued Messages: {0}: {1}:{2}", serverout.Alias, mailbox.Alias, serverout.Domain, serverout.Port), LogLevel.Informational); using (SmtpClient outbound = new SmtpClient(serverout)) { outbound.MessageSent += onMessageSent; //TODO: outbound progress try { outbound.Connect(); } catch (Exception e) { WriteLog(String.Format("SMTP: Error connecting to {0} : {1}", mailbox.Outbound.Alias, e.Message), LogLevel.Error); return; } Server serverin = config.Servers.Find(s => s.Alias == mailbox.Inbound.Alias && s.Type == ServerType.POP3); using (var inbound = new Pop3Client(serverin, mailbox)) { inbound.ProgressChanged += onProgressChanged; try { inbound.Connect(); } catch (Exception e) { WriteLog(String.Format("POP3: Error connecting to {0} : {1}", mailbox.Inbound.Alias, e.Message), LogLevel.Error); return; } try { List <Queue> batch = queue.Where(q => q.Owner == mailbox.Alias).OrderBy(q => q.Size).ToList(); foreach (Queue q in batch) { TransferMessage(inbound, outbound, q); } } catch (Exception e) { WriteLog(String.Format("Error transfering from {0} : {1}", mailbox.Inbound.Alias, e.Message), LogLevel.Error); return; } if (inbound.IsConnected) { inbound.Disconnect(true); } if (inbound != null) { inbound.Dispose(); } } if (outbound.IsConnected) { outbound.Disconnect(true); } if (outbound != null) { outbound.Dispose(); } } mailbox.Busy = false; }
private void ProcessMailboxAsync(Mailbox mailbox) { Server server = config.Servers.Find(s => s.Alias == mailbox.Outbound.Alias && s.Type == ServerType.SMTP); using (SmtpClient outbound = new SmtpClient(server)) { outbound.MessageSent += onMessageSent; try { outbound.Connect(); } catch (Exception e) { WriteLog(String.Format("SMTP: Error connecting to {0} : {1}", mailbox.Outbound.Alias, e.Message), LogLevel.Error); return; } using (var inbound = new Pop3Client(config.Servers.Find(s => s.Alias == mailbox.Inbound.Alias && s.Type == ServerType.POP3), mailbox)) { try { inbound.Connect(); } catch (Exception e) { WriteLog(String.Format("POP3: Error connecting to {0} : {1}", mailbox.Inbound.Alias, e.Message), LogLevel.Error); return; } try { if (String.IsNullOrEmpty(mailbox.LastUID)) { WriteLog(string.Format("Skipping New Mailbox: {0} : {1} : {2} Mesages", mailbox.Alias, mailbox.Name, inbound.Count), LogLevel.Warning); if (inbound.Count > 0) { // We are going to skip ALL messages, because this is the first run on this mailbox! mailbox.LastUID = inbound.GetMessageUids().Last(); return; } else { // Return zero as last UID, because mailbox is empty. mailbox.LastUID = "0"; return; } } // Get a list of all new message UIDs IList <string> uids = inbound.GetNewMessageUids(mailbox.LastUID); //uids.Remove(mailbox.LastUID); if (uids.Count > 0) { WriteLog(string.Format("Processing Mailbox: {0} : {1} : {2} Mesages ({3} new)", mailbox.Alias, mailbox.Name, inbound.Count, uids.Count), LogLevel.Informational); } else { WriteLog(string.Format("Processing Mailbox: {0} : {1} : {2} Mesages ({3} new)", mailbox.Alias, mailbox.Name, inbound.Count, uids.Count), LogLevel.Verbose); } if (uids.Count() == 0) { return; } // Set LastUID to the last message in the mailbox. mailbox.LastUID = uids.Last(); foreach (string uid in uids) { int size = inbound.GetMessageSize(uid); Queue q = new Queue() { Uid = uid, Owner = mailbox.Alias, Size = size }; if (size > 2 * 1024 * 1024) // 2Mb { //TODO: Shorten size. // Queue the larger messages, so we can get the smaller ones faster. WriteLog(String.Format("Queued Message {0}:{1} (Size {2:N})", mailbox.Alias, uid, size), LogLevel.Verbose); queue.Add(q); } else { WriteLog(String.Format("Downloading Message {0}:{1} (Size {2:N})", mailbox.Alias, uid, size), LogLevel.Verbose); q.Status = Status.Downloading; queue.Add(q); TransferMessage(inbound, outbound, q); } } //TODO: Keep x days Thread.Sleep(1000); foreach (string uid in uids) { Queue q = queue.Find(c => c.Uid == uid); if (q != null) { if (q.Status == Status.Complete) { inbound.DeleteMessage(uid); } } } if (inbound.IsConnected) { inbound.Disconnect(true); } if (inbound != null) { inbound.Dispose(); } } catch (Exception e) { WriteLog(String.Format("Error downloading from {0} : {1}", mailbox.Inbound.Alias, e.Message), LogLevel.Error); return; } } if (outbound.IsConnected) { outbound.Disconnect(true); } if (outbound != null) { outbound.Dispose(); } } }
public Pop3Client(Server server, Mailbox mailbox) { Server = server; Mailbox = mailbox; }