예제 #1
0
        public ImapMailbox Add(ImapMailbox mailbox)
        {
            mailbox.AttachToSession(session);

              mailboxes[mailbox.Name] = mailbox;

              return mailbox;
        }
예제 #2
0
        private static async Task ProcessChallengeAsync(ImapEnvelope envelope, ImapMailbox mailbox)
        {
            var bytes = await mailbox.FetchMessageBodyAsync(envelope.Uid);

            var message = new MailMessageReader(bytes);

            var token     = string.Empty;
            var nonce     = string.Empty;
            var publicKey = string.Empty;

            const string pattern = @"\s|\t|\n|\r";

            var xHeaders = message.Headers.UnknownHeaders;

            for (var i = 0; i < xHeaders.Keys.Count; i++)
            {
                var key = xHeaders.Keys[i];

                var values = xHeaders.GetValues(i);
                if (values == null)
                {
                    throw new NullReferenceException(Resources.ChallengeCorruptException);
                }

                if (string.Compare(key, ParanoiaHeaderKeys.Token, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    token = values.FirstOrDefault() ?? string.Empty;
                    token = Regex.Replace(token, pattern, string.Empty);
                    continue;
                }

                if (string.Compare(key, ParanoiaHeaderKeys.Nonce, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    nonce = values.FirstOrDefault() ?? string.Empty;
                    nonce = Regex.Replace(nonce, pattern, string.Empty);
                    continue;
                }

                if (string.Compare(key, ParanoiaHeaderKeys.PublicKey, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    publicKey = values.FirstOrDefault() ?? string.Empty;
                    publicKey = Regex.Replace(publicKey, pattern, string.Empty);
                }
            }

            if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(publicKey))
            {
                throw new InvalidDataException(Resources.ChallengeCorruptException);
            }


            var data = App.Context.KeyContainer.DecryptWithPrivateKey(
                Convert.FromBase64String(token),
                Convert.FromBase64String(publicKey),
                Convert.FromBase64String(nonce));

            await RespondToChallengeAsync(Encoding.UTF8.GetString(data));
        }
예제 #3
0
 internal async Task <List <ImapMailboxInfo> > ListSubscribedMailboxesAsync(string pattern = "")
 {
     using (var connection = new ImapConnection {
         Security = ImapSecurity
     }) {
         connection.RemoteCertificateValidationFailed += (sender, e) => e.IsCanceled = false;
         using (var auth = await connection.ConnectAsync(ImapHost, ImapPort)) {
             using (var session = await auth.LoginAsync(ImapUsername, ImapPassword)) {
                 var wildcard = string.IsNullOrEmpty(pattern) ? "%" : pattern;
                 return(await session.LSubAsync("", ImapMailbox.EncodeName(wildcard)));
             }
         }
     }
 }
예제 #4
0
        public bool ExistChildrenOf(ImapMailbox mailbox)
        {
            if (mailbox.Flags.Has(ImapMailboxFlag.HasChildren))
            return true;

              if (string.IsNullOrEmpty(mailbox.HierarchyDelimiter))
            // mailbox has no hierarchy
            return false;

              var inferiorNamePrefix = mailbox.Name + mailbox.HierarchyDelimiter;

              foreach (var mailboxName in mailboxes.Keys) {
            if (mailboxName.StartsWith(inferiorNamePrefix, StringComparison.Ordinal))
              return true;
              }

              return false;
        }
예제 #5
0
        private async Task <IEnumerable <MailMessageModel> > SyncNonChallengesAsync(ImapMailbox mailbox, long uid)
        {
            var criteria = string.Format("{0}:* NOT HEADER \"{1}\" \"{2}\"", uid, ParanoiaHeaderKeys.Type, MailType.Challenge);
            var uids     = await mailbox.SearchAsync(criteria);

            if (!uids.Any())
            {
                return(new MailMessageModel[0]);
            }

            FetchedEnvelopeCount = 0;
            TotalEnvelopeCount   = uids.Count;

            mailbox.EnvelopeFetched += OnEnvelopeFetched;
            var envelopes = (await mailbox.FetchEnvelopesAsync(uids)).ToArray();

            if (envelopes.Length == 0)
            {
                return(new MailMessageModel[0]);
            }
            mailbox.EnvelopeFetched -= OnEnvelopeFetched;

            if (envelopes.Length == 1 && envelopes.First().Uid == uid)
            {
                return(new MailMessageModel[0]);
            }

            var messages = new List <MailMessageModel>();

            foreach (var envelope in envelopes)
            {
                try {
                    var message = envelope.ToMailMessage(MailType.Message);
                    messages.Add(message);
                } catch (Exception ex) {
                    Logger.Error(ex);
                }
            }
            return(messages);
        }
예제 #6
0
        private void TransitStateTo(ImapSessionState newState)
        {
            if (newState == state)
            return;

              switch (newState) {
            case ImapSessionState.NotConnected:
              authority = null;
              selectedMailbox = null;
              if (mailboxManager != null) {
            mailboxManager.DetachFromSession();
            mailboxManager = null;
              }
              TraceInfo("now in non-connected state");
              break;

            case ImapSessionState.NotAuthenticated:
              UpdateAuthority(null, null);
              if (state == ImapSessionState.Selected || state == ImapSessionState.Authenticated) {
            mailboxManager.DetachFromSession();
            mailboxManager = null;
            TraceInfo("logged out");
              }
              TraceInfo("now in non-authenticated state");
              break;

            case ImapSessionState.Authenticated:
              TraceInfo("now in authenticated state");
              if (state == ImapSessionState.NotAuthenticated || state == ImapSessionState.NotConnected) {
            mailboxManager = new ImapMailboxManager(this);
            TraceInfo("logged in");
              }
              break;

            case ImapSessionState.Selected:
              TraceInfo("now in selected state (selected '{0}')", selectedMailbox.Name);
              break;
              }

              state = newState;
        }
        /// <summary>sends extended LIST command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult ListExtended(string mailboxNamePattern,
                                          ImapListSelectionOptions selectionOptions,
                                          ImapListReturnOptions returnOptions,
                                          out ImapMailbox[] mailboxes)
        {
            if (selectionOptions == null)
            throw new ArgumentNullException("selectionOptions");
              if (returnOptions == null)
            throw new ArgumentNullException("returnOptions");

              return ListExtendedInternalNoRefName(mailboxNamePattern, null, selectionOptions, returnOptions, out mailboxes);
        }
 /// <summary>sends extended LIST command</summary>
 /// <remarks>valid in authenticated state</remarks>
 public ImapCommandResult ListExtended(string mailboxNamePattern,
                                   out ImapMailbox[] mailboxes)
 {
     return ListExtendedInternalNoRefName(mailboxNamePattern, null, null, null, out mailboxes);
 }
        /// <summary>sends RENAME command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult Rename(ImapMailbox existingMailbox, string newMailboxName)
        {
            ValidateMailboxRelationship(existingMailbox);

              ImapMailbox discard;

              return Rename(existingMailbox.Name, newMailboxName, out discard);
        }
        /// <summary>sends GETMETADATA command</summary>
        /// <remarks>
        /// valid in authenticated/selected state.
        /// this method will fail if server does not support METADATA extension.
        /// </remarks>
        public ImapCommandResult GetMetadata(ImapMailbox mailbox, string[] entrySpecifiers, ImapGetMetadataOptions options, out ImapMetadata[] metadata)
        {
            if (options == null)
            throw new ArgumentNullException("options");

              ValidateMailboxRelationship(mailbox);

              return GetMetadataInternal(mailbox.Name, false, entrySpecifiers, options, out metadata);
        }
        /// <summary>sends SETMETADATA command</summary>
        /// <remarks>
        /// valid in authenticated/selected state.
        /// this method will fail if server does not support METADATA extension.
        /// </remarks>
        public ImapCommandResult SetMetadata(ImapMailbox mailbox, params ImapMetadata[] metadata)
        {
            ValidateMailboxRelationship(mailbox);

              return SetMetadataInternal(mailbox.Name, false, metadata);
        }
        /// <summary>sends RLSUB command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult RLsub(string referenceName, string mailboxName, out ImapMailbox[] mailboxes)
        {
            if (mailboxName == null)
            throw new ArgumentNullException("mailboxName");

              return RLsubInternal(referenceName, new ImapMailboxNameString(mailboxName), out mailboxes);
        }
예제 #13
0
        public ImapMailbox Rename(ImapMailbox existingMailbox, string newMailboxName)
        {
            mailboxes.Remove(existingMailbox.Name);
              existingMailbox.Name = newMailboxName;
              mailboxes[existingMailbox.Name] = existingMailbox;

              return existingMailbox;
        }
        /// <summary>sends RLIST command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult RList(string mailboxName, out ImapMailbox[] mailboxes)
        {
            if (mailboxName == null)
            throw new ArgumentNullException("mailboxName");

              return RListInternal(string.Empty, new ImapMailboxNameString(mailboxName), out mailboxes);
        }
 /// <summary>sends RLSUB command</summary>
 /// <remarks>
 /// valid in authenticated state
 /// This method sends LIST command with an empty reference name and a wildcard "*" as mailbox name
 /// </remarks>
 public ImapCommandResult RLsub(out ImapMailbox[] mailboxes)
 {
     return RLsubInternal(string.Empty, "*", out mailboxes);
 }
 /// <summary>sends APPEND command</summary>
 /// <remarks>
 /// valid in authenticated state.
 /// this method tries to automatically create the mailbox when server sent [TRYCREATE] response code.
 /// the out parameter <paramref name="appendedUids"/> will be set if the server supports UIDPLUS extension and returns [APPENDUID] responce code, otherwise null.
 /// </remarks>
 public ImapCommandResult Append(IImapAppendMessage message, string mailboxName, out ImapAppendedUidSet appendedUids, out ImapMailbox createdMailbox)
 {
     return AppendInternal(new[] {message}, false, mailboxName, out appendedUids, out createdMailbox);
 }
        /// <summary>sends RENAME command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult Rename(string existingMailboxName, string newMailboxName, out ImapMailbox renamedMailbox)
        {
            RejectNonAuthenticatedState();

              RejectInvalidMailboxNameArgument(existingMailboxName);
              RejectInvalidMailboxNameArgument(newMailboxName);

              if (ImapMailbox.NameEquals(existingMailboxName, newMailboxName))
            throw new ArgumentException("An existing mailbox name and a new mailbox name are same.", "newMailboxName");

              /*
               * 6.3.5. RENAME Command
               *       It is
               *       an error to attempt to rename from a mailbox name that does not
               *       exist or to a mailbox name that already exists.
               */
              var existingRenameToMailbox = mailboxManager.GetExist(newMailboxName);

              if (ImapMailbox.IsNameInbox(newMailboxName) ||
              (existingRenameToMailbox != null && !existingRenameToMailbox.Flags.Has(ImapMailboxFlag.NonExistent)))
            throw new ImapProtocolViolationException(string.Format("It is an error to attempt to rename to a mailbox name that already exists. (newMailboxName: '{0}')", newMailboxName));

              renamedMailbox = null;

              using (var t = new RenameTransaction(connection)) {
            /*
             * RFC 4466 - Collected Extensions to IMAP4 ABNF
             * http://tools.ietf.org/html/rfc4466
             *
             *    rename          = "RENAME" SP mailbox SP mailbox
             *                      [rename-params]
             *                      ;; Use of INBOX as a destination gives
             *                      ;; a NO error, unless rename-params
             *                      ;; is not empty.
             *    rename-params     = SP "(" rename-param *( SP rename-param) ")"
             *    rename-param      = rename-param-name [SP rename-param-value]
             *    rename-param-name = tagged-ext-label
             *    rename-param-value= tagged-ext-val
             *                      ;; This non-terminal shows recommended syntax
             *                      ;; for future extensions.
             */
            t.RequestArguments["existing mailbox name"] = new ImapMailboxNameString(existingMailboxName);
            t.RequestArguments["new mailbox name"] = new ImapMailboxNameString(newMailboxName);

            // rename-params
            //t.RequestArguments["rename parameters"] = new ImapParenthesizedString();

            if (ProcessTransaction(t).Succeeded)
              renamedMailbox = mailboxManager.Rename(existingMailboxName, newMailboxName);
            else
              ProcessMailboxRefferalResponse(t.Result.TaggedStatusResponse);

            return t.Result;
              }
        }
        /// <summary>sends RENAME command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult Rename(ImapMailbox existingMailbox, string newMailboxName, out ImapMailbox renamedMailbox)
        {
            ValidateMailboxRelationship(existingMailbox);

              return Rename(existingMailbox.Name, newMailboxName, out renamedMailbox);
        }
예제 #19
0
        private void ValidateMailboxRelationship(ImapMailbox mailbox)
        {
            if (mailbox == null)
            throw new ArgumentNullException("mailbox");

              if (mailbox.Session != this)
            throw new ArgumentException("mailbox is not attached to current session", "mailbox");
        }
예제 #20
0
        public ImapMailbox Rename(string existingMailboxName, string newMailboxName)
        {
            var mailbox = GetExist(existingMailboxName);

              if (mailbox == null) {
            var newMailbox = new ImapMailbox(newMailboxName);

            Add(newMailbox);

            return newMailbox;
              }

              if (mailbox.IsInbox) {
            /*
             * 6.3.5. RENAME Command
             *       Renaming INBOX is permitted, and has special behavior.  It moves
             *       all messages in INBOX to a new mailbox with the given name,
             *       leaving INBOX empty.  If the server implementation supports
             *       inferior hierarchical names of INBOX, these are unaffected by a
             *       rename of INBOX.
             */
            Add(new ImapMailbox(ImapMailbox.Inbox));

            return Rename(mailbox, newMailboxName);
              }
              else {
            if (!string.IsNullOrEmpty(mailbox.HierarchyDelimiter)) {
              /*
               * 6.3.5. RENAME Command
               *       If the name has inferior hierarchical names, then the inferior
               *       hierarchical names MUST also be renamed.  For example, a rename of
               *       "foo" to "zap" will rename "foo/bar" (assuming "/" is the
               *       hierarchy delimiter character) to "zap/bar".
               */
              var existingNamePrefix = mailbox.Name + mailbox.HierarchyDelimiter;
              var newNamePrefix = newMailboxName + mailbox.HierarchyDelimiter;

              var inferiorNames = new List<string>();

              foreach (var mailboxName in mailboxes.Keys) {
            if (mailboxName.StartsWith(existingNamePrefix, StringComparison.Ordinal))
              inferiorNames.Add(mailboxName);
              }

              foreach (var inferiorName in inferiorNames) {
            var inferior = mailboxes[inferiorName];

            Rename(inferior, newNamePrefix + inferior.Name.Substring(existingNamePrefix.Length));
              }
            }

            return Rename(mailbox, newMailboxName);
              }
        }
        /// <remarks>
        /// valid in authenticated/selected state.
        /// this method will fail if server does not support METADATA extension.
        /// </remarks>
        public ImapCommandResult GetMetadata(ImapMailbox mailbox, string[] entrySpecifiers, out ImapMetadata[] metadata)
        {
            ValidateMailboxRelationship(mailbox);

              return GetMetadataInternal(mailbox.Name, false, entrySpecifiers, null, out metadata);
        }
        /// <summary>sends extended LIST command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult ListExtended(string referenceName,
                                          string[] mailboxNamePatterns,
                                          ImapListSelectionOptions selectionOptions,
                                          ImapListReturnOptions returnOptions,
                                          out ImapMailbox[] mailboxes)
        {
            if (referenceName == null)
            throw new ArgumentNullException("referenceName");
              if (mailboxNamePatterns == null)
            throw new ArgumentNullException("mailboxNamePatterns");
              else if (mailboxNamePatterns.Length == 0)
            throw new ArgumentException("must be non-empty array", "mailboxNamePatterns");
              if (selectionOptions == null)
            throw new ArgumentNullException("selectionOptions");
              if (returnOptions == null)
            throw new ArgumentNullException("returnOptions");

              return ListExtendedInternal(referenceName, mailboxNamePatterns, selectionOptions, returnOptions, out mailboxes);
        }
        /// <summary>sends GETQUOTAROOT command</summary>
        /// <remarks>valid in authenticated/selected state (undocumented)</remarks>
        public ImapCommandResult GetQuotaRoot(ImapMailbox mailbox, out IDictionary<string, ImapQuota[]> quotaRoots)
        {
            ValidateMailboxRelationship(mailbox);

              return GetQuotaRoot(mailbox.Name, out quotaRoots);
        }
예제 #24
0
 internal ImapOpenedMailboxInfo(ImapClient client, ImapMailbox mailbox)
     : base(client, mailbox)
 {
 }
        /// <summary>sends SETMETADATA command and sets NIL value to remove entries</summary>
        /// <remarks>
        /// valid in authenticated/selected state.
        /// this method will fail if server does not support METADATA extension.
        /// </remarks>
        public ImapCommandResult SetMetadata(ImapMailbox mailbox, params string[] entrySpecifiers)
        {
            ValidateMailboxRelationship(mailbox);

              return SetMetadataInternal(mailbox.Name, false, Array.ConvertAll<string, ImapMetadata>(entrySpecifiers, ImapMetadata.CreateNil));
        }
예제 #26
0
 public WaitForMessageArrivalContext(int pollingInterval,
                               ImapMailbox mailbox,
                               ImapMessageFetchAttributeOptions fetchOptions)
 {
     this.PollingInterval = pollingInterval;
     this.Mailbox = mailbox;
     this.CurrentMessageCount = mailbox.ExistsMessage;
     this.FetchOptions = fetchOptions;
 }
예제 #27
0
        private static async Task <IEnumerable <MailMessageModel> > SyncChallengesAsync(ImapMailbox mailbox, long uid)
        {
            var criteria = string.Format("{0}:* HEADER \"{1}\" \"{2}\"", uid, ParanoiaHeaderKeys.Type, MailType.Challenge);
            var uids     = await mailbox.SearchAsync(criteria);

            if (!uids.Any())
            {
                return(new MailMessageModel[0]);
            }

            var envelopes = (await mailbox.FetchEnvelopesAsync(uids)).ToArray();

            if (envelopes.Length == 0)
            {
                return(new MailMessageModel[0]);
            }

            if (envelopes.Length == 1 && envelopes.First().Uid == uid)
            {
                return(new MailMessageModel[0]);
            }

            var now = DateTime.Now;

            foreach (var envelope in envelopes.Where(x => x.InternalDate.HasValue &&
                                                     now.Subtract(x.InternalDate.Value) < TimeSpan.FromHours(1)))
            {
                try {
                    await ProcessChallengeAsync(envelope, mailbox);
                } catch (Exception ex) {
                    Logger.Error(ex);
                }
            }

            var messages = new List <MailMessageModel>();

            foreach (var envelope in envelopes)
            {
                try {
                    var message = envelope.ToMailMessage(MailType.Challenge);
                    messages.Add(message);
                } catch (Exception ex) {
                    Logger.Error(ex);
                }
            }
            return(messages);
        }
        /// <summary>sends LSUB command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult Lsub(ImapMailbox mailbox)
        {
            ValidateMailboxRelationship(mailbox);

              ImapMailbox[] discard;

              return LsubInternal(string.Empty, new ImapMailboxNameString(mailbox.Name), out discard);
        }
예제 #29
0
 public ExamineTransaction(ImapConnection connection, ImapMailbox selectingMailbox, ImapCapability selectParametersCapabilityRequirement)
     : base(connection, selectingMailbox, selectParametersCapabilityRequirement)
 {
 }
예제 #30
0
 internal IEnumerable<ImapMailboxInfo> GetMailboxes(ImapMailbox mailbox,
                                                ImapMailboxListOptions options)
 {
     return GetMailboxes(mailbox.Name,
                   mailbox.HierarchyDelimiter,
                   true,
                   mailbox.Flags.Has(ImapMailboxFlag.NoInferiors), // ignore HasNoChildren
                   options);
 }
예제 #31
0
 public WaitForMessageArrivalAsyncResult(int pollingInterval,
                                   ImapMailbox mailbox,
                                   ImapMessageFetchAttributeOptions fetchOptions,
                                   WaitForMessageArrivalProc proc,
                                   object asyncState,
                                   AsyncCallback asyncCallback)
     : base(pollingInterval, mailbox, fetchOptions)
 {
     this.proc = proc;
     this.AsyncState = asyncState;
     this.asyncCallback = asyncCallback;
 }
예제 #32
0
 protected SelectTransactionBase(ImapConnection connection, ImapMailbox selectingMailbox, ImapCapability selectParametersCapabilityRequirement)
     : base(connection)
 {
     this.selectingMailbox = selectingMailbox;
       this.selectParametersCapabilityRequirement = selectParametersCapabilityRequirement;
 }
예제 #33
0
 internal ImapMailboxInfo(ImapClient client, ImapMailbox mailbox)
 {
     this.client = client;
       this.mailbox = mailbox;
 }
        /// <summary>sends extended LIST command</summary>
        /// <remarks>valid in authenticated state</remarks>
        public ImapCommandResult ListExtended(ImapListReturnOptions returnOptions,
                                          out ImapMailbox[] mailboxes,
                                          string mailboxNamePattern,
                                          params string[] mailboxNamePatterns)
        {
            if (returnOptions == null)
            throw new ArgumentNullException("returnOptions");

              return ListExtendedInternalNoRefName(mailboxNamePattern, mailboxNamePatterns, null, returnOptions, out mailboxes);
        }