Пример #1
0
        /// <summary>
        /// Open a mailbox and make it current or enable write mode. 
        /// </summary>
        /// <param name="mbox">
        /// Reference to the mailbox the is to be opened. 
        /// </param>
        /// <param name="readOnly">
        /// A value of <c>false</c> (re-)opens the mailbox in write mode. 
        /// </param>
        /// <returns>
        /// On success <c>true</c> is returned.
        /// </returns>        
        /// <remarks>
        /// The mailbox reference must be valid for this function to succeed. See
        /// <see cref="OpenMailbox(bool)"/> for a simple way to reopen the current
        /// mailbox.
        /// </remarks>
        public bool MailboxOpen(MBoxRef mbox, bool readOnly)
        {
            if(!mbox.IsValid) return false;

            // we want to use the current mailbox ...
            if(mbox.Name == application.MailboxName)
            {   if(!readOnly && application.MailboxIsReadonly)
                {   if(!ZIMapAdmin.Confirm("Current mailbox '{0}' is readonly. Change mode",
                                           mbox.Name)) return false;
                    MonitorInfo("Setting write mode for current mailbox");
                }
            }
            else
                data.Clear(Info.Headers);

            // (re-)open the mailbox
            data.UpdateCurrent(MBoxRef.Nothing);
            if(!mbox.Open(application, readOnly)) return false;
            data.UpdateCurrent(mbox);
            return true;
        }
Пример #2
0
        /// <summary>
        /// Delete a mailbox from the server and update the cached information.
        /// </summary>
        /// <param name="mbox">
        /// A <see cref="MBoxRef"/>
        /// </param>
        /// <returns>
        /// A <see cref="System.Boolean"/>
        /// </returns>
        public bool MailboxDelete(MBoxRef mbox)
        {
            if(!mbox.IsValid) return false;
            using(ZIMapCommand.Delete cmd = new ZIMapCommand.Delete(factory))
            {   if(cmd == null) return false;
                if(mbox.Name == data.Current.Name) MailboxClose();

                // TODO: MailboxDelete must update QuotaRoot
                MailboxAdminRigths(mbox.Name, mbox.ExtraRights, "all", false);
                cmd.Queue(mbox.Name);
                if(!cmd.CheckSuccess(string.Format(
                       ":Failed to delete '{0}': {1}",
                       mbox.Name, cmd.Result.Message))) return false;
                MonitorInfo("Mailbox deleted: {0}", mbox.Name);
                data.FolderDelete(mbox);
            }
            return true;
        }
Пример #3
0
        // =============================================================================
        // Mailbox Export
        // =============================================================================
        /// <summary>
        /// Export mail from a single mailbox.
        /// </summary>
        /// <param name="mbox">
        /// A reference to the mailbox.
        /// </param>
        /// <param name="quoted">
        /// If <c>true</c> export using "From" quoting instead of "Content-Length" headers.
        /// </param>
        /// <param name="uids">
        /// A list of uids to be exported or <c>null</c>
        /// </param>
        /// <param name="mailTotal">
        /// Can specify a total number of mails when multiple mailboxes are going to be
        /// exported.
        /// </param>
        /// <param name="mailCounter">
        /// Incremented for each exported mail.
        /// </param>
        /// <returns>
        /// <c>true</c> on success.
        /// </returns>
        public bool MailboxExport(MBoxRef mbox, bool quoted, 
                                  uint[] uids, uint mailTotal, ref uint mailCounter)
        {
            if(!mbox.IsValid) return false;

            uint ucnt = (uids == null) ? mbox.Messages : (uint)uids.Length;
            if(ucnt > mailTotal) mailTotal = ucnt;
            string mailbox = mbox.Name;

            // get rid of INBOX and prefix personal mailboxes with the account name
            uint rnsi;
            string fullname = server.FriendlyName(mailbox, out rnsi);
            string prefix = server[rnsi].Prefix;
            if(prefix != "" && fullname.StartsWith(prefix))     // strip the ns prefix
                fullname = fullname.Substring(prefix.Length);

            // create the output file
            if (!application.ExportMailbox(fullname, rnsi)) return false;
            if(ucnt == 0) {
                MonitorInfo("Mailbox exported: {0} [no mails]", fullname.PadRight(32));
                return true;
            }

            // open the IMAP mailbox
            if(data.Current.Name != mailbox)
            {   ZIMapCommand.Examine exa = new ZIMapCommand.Examine(factory);
                exa.Queue(mailbox);
                if(!exa.CheckSuccess(":Cannot open Mailbox: " + mailbox))
                    return false;
            }

            // loop over mail items
            ZIMapCommand.Fetch.Item item = new ZIMapCommand.Fetch.Item();
            byte[] head = null;
            byte[] body = null;
            ZIMapCommand.Generic current = null;
            ZIMapFactory.Bulk bulk = factory.CreateBulk("FETCH", 4, uids != null);
            ZIMapMessage msg = new ZIMapMessage();
            uint ucur = 0;                      // current item/UID
            uint uerr = 0;                      // error counter
            uint urun = 0;                      // mail counter
            uint urdy = 0;
            string key = (uids == null) ? "item" : "UID";
            while(urdy < ucnt)
            {   // step 1: queue request and check for response ...
                bool done = bulk.NextCommand(ref current);
                ZIMapCommand.Fetch cmd = (ZIMapCommand.Fetch)current;

                // step 2: check server reply for error ...
                if(done)
                {   ucur = (uids == null) ? ++urdy : uids[urdy++];
                    if (cmd.Items == null || cmd.Items.Length != 1)
                    {   MonitorError(!cmd.CheckSuccess() ?
                            "Cannot fetch mail ({0}={1}): {2}" :
                            "Mail not existing ({0}={1})", key, ucur, cmd.Result.Message);
                        done = false; uerr++;
                    }
                }

                // step 3: process data sent by server ...
                if(done)
                {   item = cmd.Items[0];
                    head = item.Literal(0);
                    body = item.Literal(1);
                    if (head == null)
                    {   MonitorError("Mail data incomplete ({0}={1})", key, ucur);
                        done = false; uerr++;
                    }
                    if(body == null) body = new byte[0];        // message without body
                }
                if(done)
                {   msg.Parse(head, true);

                    // use the server's INTERNALDATE if we got it...
                    DateTime date;
                    string sdat;
                    if (ZIMapFactory.FindInParts(item.Parts, "INTERNALDATE", out sdat))
                        date = ZIMapConverter.DecodeIMapTime(sdat, true);
                    else
                        date = msg.DateBinary;

                    // finally write mail data to file ...
                    string flags = (item.Flags == null) ? null : string.Join(" ", item.Flags);
                    if (!application.Export.WriteMail(msg.From, date, flags, head, body, quoted))
                    {   MonitorError("Mail could not be written ({0}={1})", key, ucur);
                        uerr++;
                    }
                    progress.Update(mailCounter++, mailTotal);
                }

                // step 4: create a new request
                if(urun < ucnt)
                {   ucur = (uids == null) ? ++urun : uids[urun++];
                    cmd.Reset();
                    cmd.Queue(ucur, "FLAGS INTERNALDATE BODY.PEEK[HEADER] BODY.PEEK[TEXT]");
                }
            }
            bulk.Dispose();
            MonitorInfo("Mailbox exported: {0} [{1,4} mails]", fullname.PadRight(32), urun);
            return (uerr == 0);
        }
Пример #4
0
        public bool CommandCopy(uint[] items, bool useUID, MBoxRef mbox)
        {
            if(!mbox.IsValid || items == null || items.Length < 1) return false;
            progress.Update(0);

            // make sure that our current mailbox is open ...
            if(!data.Current.Open(application, true))
                return false;                           // could not reopen

            string dest = mbox.Name;
            if(dest == data.Current.Name)               // content changes
                data.Clear(Info.Headers);
            data.Clear(Info.Details);                   // message count changes

            using(ZIMapCommand.Copy cmd = new ZIMapCommand.Copy(factory))
            {   if(cmd == null) return false;
                cmd.UidCommand = useUID;
                cmd.Queue(items, dest);
                progress.Update(30);
                bool bok = cmd.CheckSuccess(":");
                progress.Done();
                return bok;
            }
        }
Пример #5
0
        public bool FoldersExtras(bool wantRights, bool wantQuota)
        {
            data.UpdateExtras(wantRights, wantQuota);
            if(!application.EnableRights) wantRights = false;
            if(!application.EnableQuota)  wantQuota  = false;
            if(!wantRights && !wantQuota) return true;
            MBoxRef boxes = data.Folders;
            uint ucnt = boxes.Count;
            if(ucnt == 0) return true;

            // progress report setup ...
            uint upro = ucnt;
            if(wantRights && wantQuota) upro += ucnt;
            progress.Update(0);
            MBoxRef mout = new MBoxRef(boxes.Array);

            // get rights ...
            uint ures = 0; boxes.Reset();
            if(wantRights)
                using(ZIMapFactory.Bulk rights = factory.CreateBulk("MyRights", 3, false))
                {   ZIMapCommand.Generic current = null;
                    while(ures < ucnt)
                    {   if(rights.NextCommand(ref current))
                        {   mout.Next((uint)current.UserData);
                            mout.ExtraRights = ((ZIMapCommand.MyRights)current).Rights;
                            current.Reset(); ures++;
                            progress.Update(ures, upro);
                        }
                        if(boxes.Next())
                        {   if(boxes.ExtraRights != null) ures++;
                            else
                            {   ((ZIMapCommand.MyRights)current).Queue(boxes.Name);
                                current.UserData = boxes.Index;
                            }
                        }
                    }
                }

            // get quota info ...
            ures = 0; boxes.Reset();
            if(wantQuota)
                using(ZIMapFactory.Bulk rights = factory.CreateBulk("GetQuotaRoot", 3, false))
                {   ZIMapCommand.Generic current = null;
                    while(ures < ucnt)
                    {   if(rights.NextCommand(ref current))
                        {   ZIMapApplication.QuotaInfo info;
                            application.QuotaInfos((ZIMapCommand.GetQuotaRoot)current, out info);
                            mout.Next((uint)current.UserData);
                            mout.ExtraSetQuota(info);               // also save on failure
                            current.Reset(); ures++;
                            progress.Update(ures, upro);
                        }
                        if(boxes.Next())
                        {   if(boxes.ExtraQuotaRoot != null) ures++;
                            else
                            {   ((ZIMapCommand.GetQuotaRoot)current).Queue(boxes.Name);
                                current.UserData = boxes.Index;
                            }
                        }
                    }
                }
            return true;
        }
Пример #6
0
 public new void UpdateCurrent(MBoxRef current)
 {
     base.UpdateCurrent(current);
 }
Пример #7
0
        // =============================================================================
        // Commands: Flags, Copy, Expunge
        // =============================================================================
        public bool CommandACL(MBoxRef mailbox, bool bRecurse, string user, string rights)
        {
            if(!mailbox.IsValid) return false;
            progress.Update(0);

            using(ZIMapCommand acl = (ZIMapCommand)application.Factory.CreateByName(
                                       (rights == null) ? "DeleteACL" : "SetACL"))
            {   CacheData.MBoxRef ubox = mailbox;
                if(string.IsNullOrEmpty(user)) user = application.User;
                uint ucnt = 0;
                if(bRecurse)                            // get count for progress report
                {   ubox = CacheData.MBoxRef.Nothing;
                    while(mailbox.Recurse(ref ubox, application.Server)) ucnt++;
                }

                uint urun = 0;
                while(bRecurse ? mailbox.Recurse(ref ubox, application.Server) : (urun == 0))
                {   string name = ubox.Name;
                    if(rights == null) ((ZIMapCommand.DeleteACL)acl).Queue(name, user);
                    else               ((ZIMapCommand.SetACL)acl).Queue(name, user, rights);
                    ubox.ExtraRights = null;
                    if(ucnt > 0) progress.Update(urun, ucnt);
                    else         progress.Update(30);
                    if(!acl.CheckSuccess(":Cannot change rights for: " + user)) return false;
                    acl.Reset(); urun++;
                }
            }
            return true;
        }
Пример #8
0
 protected void UpdateFolders(MBoxRef boxes, bool details)
 {
     this.boxes = boxes;
     SetInfo(Info.Details, details);
     info |= Info.Folders;
     boxesTime = Second();
 }
Пример #9
0
 protected void UpdateUsers(MBoxRef users, bool others)
 {
     this.users = users;
     SetInfo(Info.Others, others);
     SetInfo(Info.Shared, !others);
     usersTime = Second();
 }
Пример #10
0
 protected void UpdateCurrent(MBoxRef current)
 {
     this.current = current;
 }
Пример #11
0
 /// <summary>Remove one entry from the array of cached folders.</summary>
 public bool FolderDelete(MBoxRef mbox)
 {
     if(boxes.IsNothing) return false;
     return boxes.Delete(mbox);
 }
Пример #12
0
            /// <summary>
            /// Clear cached data.
            /// </summary>
            /// <remarks>
            /// The method does not clear or close the current mailbox.
            /// </remarks>
            public bool Clear(Info what)
            {
                //if((what & (Info.Quota | Info.Rights)) != 0)
                //    what |= (Info.Details | Info.Quota | Info.Rights);

                if((what & Info.Details) != 0) info &= ~Info.Details;
                if((what & Info.Quota)   != 0) info &= ~Info.Quota;
                if((what & Info.Rights)  != 0) info &= ~Info.Rights;

                if((what & Info.Folders) != 0)
                {   boxes = MBoxRef.Nothing; boxesTime = 0;
                    info &= ~(Info.Folders | Info.Details | Info.Quota | Info.Rights);
                }
                if((what & (Info.Others | Info.Shared)) != 0)
                {   users = MBoxRef.Nothing; usersTime = 0;
                    info &= ~(Info.Others | Info.Shared);
                }
                if((what & Info.Headers) != 0)
                {   headers = MailRef.Nothing; headersTime = 0;
                    info &= ~(Info.Headers);
                }
                return false;
            }
Пример #13
0
            /// <summary>Iterator to enumerate a mailbox and it's descendents.</summary>
            /// <param name="position">
            /// Set on return, must initially be <see cref="MBoxRef.Nothing"/>.
            /// </param>
            /// <param name="server">
            /// Used for namespace support <see cref="ZIMapServer.FriendlyName"/>.
            /// </param>
            /// <returns>On success <c>true</c> is returned.</returns>
            /// <remarks>
            /// The returned <paramref name="position"/> should be used to access the
            /// data.<para/>
            /// <example><code lang="C#">
            /// uint udel = 0;
            /// CacheData.MBoxRef root = ...;
            /// CacheData.MBoxRef position = CacheData.MBoxRef.Nothing;
            /// while(umbx.Recurse(ref positioin, Server))
            /// {    if(position.Messages > 0) udel++
            /// }
            /// </code></example> 
            /// </remarks>
            public bool Recurse(ref MBoxRef position, ZIMapServer server)
            {
                if(!IsValid) return false;
                if(!position.IsValid)                       // start the iteration
                {   position = this;
                    return true;
                }

                // get the friendly root name and append a hierarchie delimiter
                uint rnsi;
                string root = boxes[index].Name;
                root = server.FriendlyName(root, out rnsi);
                root += server[rnsi].Delimiter;

                // now scan the list of mailboxes ...
                while(position.Next())
                {   if(position.index == index) continue;   // Reset() called?
                    uint cnsi;
                    string name = server.FriendlyName(position.Name, out cnsi);
                    if(rnsi == cnsi && name.StartsWith(root)) return true;
                }
                position = MBoxRef.Nothing;
                return false;
            }
Пример #14
0
 /// <summary>Remove one entry from the array.</summary>
 public bool Delete(MBoxRef mbox)
 {
     if(boxes == null || !mbox.IsValid) return false;
     uint index = mbox.Index;
     if(!object.ReferenceEquals(boxes, mbox.boxes)) index = Search(mbox.Name);
     if(length == 0 || index >= length) return false;
     ZIMapApplication.MailBox[] dest = new ZIMapApplication.MailBox[--length];
     if(index > 0) System.Array.Copy(boxes, dest, index);
     int tail = (int)(length - index);
     if(tail > 0) System.Array.Copy(boxes, index+1, dest, index, tail);
     boxes = dest;
     return true;
 }