/// <summary> /// Fetch Mail Header for a list of UIDs (or IDs). /// </summary> /// <param name="ids"> /// Depending on <see cref="EnableUidCommands"/> this is an array of UIDs /// (<c>true</c>) or IDs (<c>false</c>). /// </param> /// <param name="what"> /// A list of IMap items to be returned. If empty or null the default is: /// "<c>(UID FLAGS RFC822.SIZE BODY.PEEK[HEADER])</c>". /// </param> /// <returns> /// An array of mail headers (may be zero-sized) or <c>null</c> on error. /// </returns> /// <remarks> /// This method is used by <see cref="MailSearch(string, string, string[])"/>. /// It is recommended to set <see cref="EnableUidCommands"/> to <c>true</c>. /// </remarks> public MailInfo[] MailHeaders(uint[] ids, string what) { if(factory == null || ids == null) return null; if(ids.Length <= 0) return new MailInfo[0]; if(string.IsNullOrEmpty(what)) what = "UID FLAGS RFC822.SIZE BODY.PEEK[HEADER]"; ZIMapCommand.Fetch fetch = new ZIMapCommand.Fetch(factory); if(fetch == null) return null; progress.Update(0); fetch.UidCommand = enableUid; uint count = (uint)ids.Length; uint block = fetchBlock; ZIMapCommand.Fetch.Item[] part = null; MailInfo[] rval = null; if(count <= block) { fetch.Queue(ids, what); progress.Update(20); part = fetch.Items; if(part == null) { MonitorError("MailHeaders: FETCH failed: " + fetch.Result.Message); factory.DisposeCommands(null, false); return null; } rval = new MailInfo[part.Length]; for(uint irun=0; irun < part.Length; irun++) rval[irun] = new MailInfo(part[irun]); } else { List<MailInfo> items = new List<MailInfo>(); uint last = 0; uint offs = 0; uint[] sub = null; while(count > 0) { uint chunk = Math.Min(count, block); if(chunk != last) { sub = new uint[chunk]; last = chunk; } Array.Copy(ids, offs, sub, 0, chunk); progress.Update(offs, (uint)ids.Length); fetch.Queue(sub, what); part = fetch.Items; if(part == null) { MonitorError("MailHeaders: FETCH failed: " + fetch.Result.Message); factory.DisposeCommands(null, false); return null; } foreach(ZIMapCommand.Fetch.Item item in part) items.Add(new MailInfo(item)); fetch.Reset(); count -= chunk; offs += chunk; } rval = items.ToArray(); } factory.DisposeCommands(null, false); if(rval == null) rval = new MailInfo[0]; MonitorInfo("MailHeaders: Got " + rval.Length + " mails"); progress.Done(); return rval; }
public static bool ShowInfo(object what) { if(what == null) return false; // ----------------------------------------------------------------- // Server // ----------------------------------------------------------------- if(what is string) { ListOutput(0, " ", "Server Information for: " + App.ServerName); ListOutput(1, "Security ", App.Connection.TlsMode.ToString()); ListOutput(1, "Timeout ", App.Connection.TransportTimeout.ToString() + " [s]"); ListOutput(2, "Greeting ", App.Connection.ProtocolLayer.ServerGreeting); ListOutput(1, "Type ", App.Server.ServerType + " (Subtype: " + App.Server.ServerSubtype + ")"); ListOutput(1, "Admin ", App.Server.IsAdmin ? "yes" : "no"); ListOutput(2, "Capability", string.Join(" ", App.Factory.Capabilities)); ListOutput(1, "Rights ", App.EnableRights ? "enabled" : "disabled"); string sout = "disabled"; if(App.EnableQuota) sout = string.Format("enabled (STORAGE={0} MESSAGE={1})", App.Server.HasLimit("STORAGE") ? "yes" : "no", App.Server.HasLimit("MESSAGE") ? "yes" : "no"); ListOutput(1, "Quota ", sout); ListOutput(5, "Namespace ", "Personal=" + App.Server.NamespaceDataPersonal + "\n" + "Others =" + App.Server.NamespaceDataOther + "\n" + "Shared =" + App.Server.NamespaceDataShared + "\n" + "Search =" + App.Server.NamespaceDataSearch); return true; } // ----------------------------------------------------------------- // Application // ----------------------------------------------------------------- if(what == App) { ListOutput(0, " ", "Application Information"); ListOutput(1, "Runtime ", System.Environment.Version.ToString() + " (" + System.Environment.OSVersion.ToString() + ")" ); ListOutput(1, "Version ", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() #if DEBUG + " (DEBUG build)" #endif ); App.Export.Open(null, (char)0, false, false); string bfld = ZIMapExport.BaseFolder; ListOutput(2, "Path ", (bfld == "") ? "[not set]" : bfld); long mem1 = GC.GetTotalMemory(false) / 1024; Cache.Data.Clear(CacheData.Info.All); long mem2 = GC.GetTotalMemory(true) / 1024; ListOutput(5, "Memory ", string.Format("{0} kByte (minimum is {1} kByte)", mem1, mem2)); return true; } // ----------------------------------------------------------------- // Mailbox // ----------------------------------------------------------------- if(what is ZIMapApplication.MailBox) { ZIMapApplication.MailBox mbox = (ZIMapApplication.MailBox)what; ListOutput(0, " ", "Mailbox Information"); string msg = mbox.Name; if(mbox.Name == App.MailboxName) msg = string.Format("{0} (current {1})", msg, App.MailboxIsReadonly ? "Read-Only" : "Writable"); else msg += " (not current)"; ListOutput(1, "Mailbox ", msg); ListOutput(1, "Messages ", string.Format("{0} mails ({1} recent {2} unseen)", mbox.Messages, mbox.Recent, mbox.Unseen)); ListOutput(1, "Subscribed", mbox.Subscribed ? "yes" : "no"); ListOutput(2, "Flags ", string.Join(" ", mbox.Flags)); ListOutput(1, "Attributes", string.Join(" ", mbox.Attributes)); string qroot, storage, message; FormatQuota(mbox.Name, out storage, out message, out qroot); if(qroot == null) ListOutput(5, "Quota ", "-none-"); else { if(message != null) message = "\n" + message; if(storage != null) storage = "\n" + storage; ListOutput(5, "Quota ", "Quota Root : " + qroot + message + storage); } return true; } // ----------------------------------------------------------------- // Mail Item // ----------------------------------------------------------------- if(what is uint[]) { uint[] uarg = (uint[])what; ZIMapApplication.MailInfo[] mails = Cache.Data.Headers.Array(0); uint uuid = uarg[0]; uint urun; for(urun=0; urun < mails.Length; urun++) if(mails[urun].UID == uuid) break; if(urun >= mails.Length) { Error("UID not found: " + uuid); return false; } ZIMapApplication.MailInfo mail = mails[urun]; ZIMapMessage mesg = new ZIMapMessage(); if(!mesg.Parse(mail.Literal, false)) return false; ZIMapMessage.BodyInfo info = null; ZIMapCommand.Fetch cmd = new ZIMapCommand.Fetch(App.Factory); cmd.UidCommand = App.EnableUidCommands; if((uarg[1] & 2) != 0) cmd.Queue(uuid, "BODY BODY.PEEK[TEXT]"); else cmd.Queue(uuid, "BODY"); if(!cmd.CheckSuccess("Failed to get status")) return false; if((uarg[1] & 2) != 0) { if(cmd.Result.Literals == null || cmd.Result.Literals.Length < 1) { Info("Message has no body"); return true; } mesg.ParseBody(cmd.Result.Literals[0], 0); } string[] parts = cmd.Items[0].Parts; if(parts != null && parts.Length > 1 && parts[0] == "BODY") info = ZIMapMessage.ParseBodyInfo(parts[1]); uint utxt = ListOutput(0, " ", "Mail Information"); ListOutput(1, "Item ", string.Format("{0} (ID={1} UID={2})", urun+1, mail.Index, mail.UID)); ListOutput(1, "From ", mesg.From); ListOutput(1, "To ", mesg.To); ListOutput(1, "Subject ", mesg.Subject); ListOutput(1, "Date ", mesg.DateISO); ListOutput(1, "Size ", mail.Size.ToString()); ListOutput(2, "Flags ", string.Join(" ", mail.Flags)); if(info != null && info.Parts != null) for(int irun=0; irun < info.Parts.Length; irun++) { string text = info.Parts[irun].ToString(); int icol = text.IndexOf(':'); if(icol > 0) text = text.Substring(icol+2); ListOutput((uint)((irun == 0) ? 2 : 1), ("Part [" + info.Parts[irun].Level + "]").PadRight(10), text); } if((uarg[1] & 1) != 0) { List<string> llis = new List<string>(); //string[] names = item.FieldNames; for(int irun=0; irun < mesg.HeaderCount; irun++) { string[] lines = TextTool.TextIndent(mesg.FieldKey(irun).PadRight(15) + " " + mesg.FieldText(irun), 17, utxt); llis.AddRange(lines); } if(llis.Count == 0) ListOutput(5, "Headers ", "-none-"); if(llis.Count == 1) ListOutput(5, "Headers ", llis[0]); else for(int irun=0; irun < llis.Count; irun++) { if(irun == 0) ListOutput(2, "Headers ", llis[0]); else ListOutput(1, " ", llis[irun]); } } if(mesg.BodyCount > 0) { StringBuilder sb = new StringBuilder(); for(int irun=0; irun < mesg.BodyCount; irun++) sb.AppendLine(mesg.BodyLine(irun, null)); ListOutput(2, "Body Text ", sb.ToString()); } TextTool.Formatter.WriteLine( TextTool.DecoLine(TextTool.Decoration.Double, 0, utxt+12)); return true; } return false; }
public MailInfo[] MailHeaders(uint firstIndex, uint lastIndex, string what) { if(what == null || what == "") what = "UID FLAGS RFC822.SIZE BODY.PEEK[HEADER]"; if(lastIndex < firstIndex) return null; if(factory == null) return null; ZIMapCommand.Fetch fetch = new ZIMapCommand.Fetch(factory); if(fetch == null) return null; progress.Update(0); uint count = lastIndex - firstIndex; uint block = fetchBlock; uint progrcnt = 0; uint progrmax = count; List<MailInfo> items = null; ZIMapCommand.Fetch.Item[] part = null; while(count > 0) { uint chunk = count; // Math.Min(count, block); // bug on mono? if(chunk > block) chunk = block; fetch.Reset(); fetch.Queue(firstIndex, firstIndex+chunk-1, what); // semi logarithmic progress ... if(lastIndex == uint.MaxValue) { if(progrcnt < 32*16) progrcnt += 64; else if(progrcnt < 64*16) progrcnt += 16; else if(progrcnt < 99) progrcnt += 1; progress.Update(progrcnt / 16); } // exact progress ... else { progrcnt += block; progress.Update(progrcnt, progrmax); } part = fetch.Items; if(part == null) { if(fetch.CheckSuccess()) break; // server said: OK no more data if(fetch.Result.State == ZIMapProtocol.ReceiveState.Error && items != null) break; // server said: BAD no more data if(fetch.Result.State == ZIMapProtocol.ReceiveState.Failure) break; // server said: No no matching data MonitorError("MailHeaders: FETCH failed: " + fetch.Result.Message); factory.DisposeCommands(null, false); return null; } // only one chunk, directly return the array if(count == chunk && items == null) break; // multiple chunks, store items in a list if(items == null) items = new List<MailInfo>(); foreach(ZIMapCommand.Fetch.Item item in part) items.Add(new MailInfo(item)); count -= chunk; firstIndex += chunk; } factory.DisposeCommands(null, false); MailInfo[] rval = null; if (items != null) rval = items.ToArray(); else if(part == null) rval = new MailInfo[0]; progress.Done(); MonitorInfo("MailHeaders: Got " + rval.Length + " mails"); return rval; }