Exemple #1
0
        protected override bool IssueStartTlsCommand(string host)
        {
            var command = new ImapCommand(CommandStrings.StartTls);

            Send(command);
            return(Receive().IsOk);
        }
Exemple #2
0
        /// <summary>
        ///   This method is blocking.
        ///   The IDLE command may be used with any IMAP4 server implementation
        ///   that returns "IDLE" as one of the supported capabilities to the
        ///   CAPABILITY command.  If the server does not advertise the IDLE
        ///   capability, the client MUST NOT use the IDLE command and must poll
        ///   for mailbox updates.
        ///   http://tools.ietf.org/html/rfc2177
        /// </summary>
        public void StartIdle()
        {
            if (!ServerCapability.IsIdleSupported)
            {
                const string message = "Server does not support the idle command. Please check Capability.CanIdle before calling Idle.";
                throw new InvalidOperationException(message);
            }

            var command = new ImapCommand("IDLE");

            SendAndReceive(command);
            IsIdling = true;

            while (true)
            {
                // Need to set response timeout to 29 minutes, because the server will kick us after 30  if we do not re apply for IDLE.
                ResponseTimeout = TimeSpan.FromMinutes(29);
                var reader = new ImapResponseReader(this);
                try {
                    ReceiveIdleStatusUpdates(reader);
                }
                catch (TimeoutException) {
                    StopIdleAsync();
                }

                if (reader.IsCompleted)
                {
                    break;
                }
            }

            IsIdling = false;
        }
Exemple #3
0
        private bool ApplyStore(int[] messageIds, StoreFlagData flagData)
        {
            var storeResult = Context
                              .EntityProvider
                              .MailProvider
                              .StoreFlags(messageIds, flagData.Flags, flagData.Operation);

            if (!storeResult)
            {
                return(false);
            }

            foreach (var messageId in messageIds)
            {
                if (!flagData.IsSilent)
                {
                    var cmd       = new ImapCommand($"xx UID FETCH {messageId} (FLAGS)");
                    var uidResult = new ImapUidStateController().Run(Context, cmd);
                    if (!uidResult)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private bool AuthenticatePlain(NetworkCredential credentials)
        {
            var capabilities = _client.ServerCapability;
            var username     = credentials.UserName;
            var password     = credentials.Password;

            var auth        = username + "\0" + username + "\0" + password;
            var encodedAuth = Base64Encoder.Encode(auth);

            if (capabilities.IsInitialClientResponseSupported)
            {
                var text    = string.Format("AUTHENTICATE PLAIN {0}", encodedAuth);
                var command = new ImapCommand(text);
                return(_client.SendAndReceive(command).IsOk);
            }

            var authCommand = new ImapCommand("AUTHENTICATE PLAIN");
            var response    = _client.SendAndReceive(authCommand);

            if (response.IsContinuation)
            {
                var command = new BlankImapCommand(encodedAuth);
                _client.Send(command);
                return(_client.Receive().IsOk);
            }

            return(false);
        }
        private bool AuthenticateCramMd5(NetworkCredential credentials)
        {
            var command  = new ImapCommand("AUTHENTICATE CRAM-MD5");
            var response = _client.SendAndReceive(command);

            // don't trim the last plus !!
            var base64    = response.CurrentLine.TrimStart(Characters.Plus).Trim();
            var challenge = Base64Encoder.Decode(base64, Encoding.UTF8);

            var username = credentials.UserName;
            var password = credentials.Password;

            var hash = CramMd5Hasher.ComputeHash(password, challenge);

            var authentication = username + " " + hash;
            var authCommand    = new BlankImapCommand(Base64Encoder.Encode(authentication));

            var reader = _client.SendAndReceive(authCommand);

            while (!reader.IsCompleted)
            {
                reader = _client.Receive(false);
            }
            return(reader.IsOk);
        }
        protected override bool RunInternal(ImapCommand cmd)
        {
            // <sequnce set> mbox
            // NO - Wrong name
            Context.CommandProvider.Write("* " + cmd.Args + "\r\n");
            var match = Regex.Match(cmd.Args, "(?<sq>[^ ]+) (?<mbox>[^ ]+)$");

            if (!match.Success || !match.Groups["mbox"].Success || !match.Groups["sq"].Success ||
                string.IsNullOrWhiteSpace(match.Groups["mbox"].Value))
            {
                Context.CommandProvider.Write($"{cmd.Tag} BAD\r\n");
                return(true);
            }

            var mailbox     = match.Groups["mbox"].Value;
            var sqString    = match.Groups["sq"].Value;
            var isUid       = Context.States.Any(s => s.State == ImapState.Uid);
            var idType      = isUid ? MessageIdType.Uid : MessageIdType.Id;
            var sequenceSet = ImapCommon.GetMessageSequenceSet(sqString);
            var uids        = ImapCommon.ExtractRealMessageIds(Context, sequenceSet, idType);

            if (!Context.EntityProvider.DirectoryProvider.Copy(mailbox, uids.ToArray()))
            {
                Context.CommandProvider.Write($"{cmd.Tag} NO\r\n");
                return(true);
            }

            if (!isUid)
            {
                Context.CommandProvider.Write($"{cmd.Tag} OK COPY\r\n");
            }
            return(true);
        }
Exemple #7
0
        protected override void FetchCapabilities()
        {
            var command = new ImapCommand(CommandStrings.Capability);
            var reader  = SendAndReceive(command);

            ServerCapability = reader.ReadCapabilities();
        }
Exemple #8
0
        public void HandleSession(CancellationToken cancellationToken)
        {
            ImapCommand.Send(this, "*", "OK IMAP4rev1 Service Ready");

            string command = string.Empty;

            try
            {
                while (!String.IsNullOrEmpty(command = ReadLine()))
                {
                    var cmd = _parser.Parse(command);

                    if (cmd != null)
                    {
                        cmd.Execute(this, command.Split(null));
                    }
                    else
                    {
                        GenericCommand.Execute(this, "BAD", "Bad Command", command.Split(null));
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error");
            }

            this.Dispose();
        }
 public bool IsCommandValid(ImapCommand command)
 {
     switch (command)
     {
         default:
             return false;
     }
 }
 public bool IsCommandValid(ImapCommand command)
 {
     switch (command)
     {
     default:
         return(false);
     }
 }
Exemple #11
0
        private ImapResponseReader StoreInternal(SequenceSet set, string value, StoreProcedures procedure, string commandString)
        {
            var prefix  = procedure == StoreProcedures.Add ? "+" : "-";
            var isUid   = set.IsUid ? "UID " : string.Empty;
            var text    = string.Format("{0}STORE {1} {2}{3} ({4})", isUid, set, prefix, commandString, value);
            var command = new ImapCommand(text);

            return(SendAndReceive(command, false));
        }
        private void PreencheEmails(Usuario_Imap usuario_imap, string pasta, ref List <Email> emails)
        {
            Imap imap = usuario_imap.Imap;

            using (ImapConnect connection = new ImapConnect(imap.Host, imap.Porta, imap.SSL))
            {
                ImapCommand      command        = new ImapCommand(connection);
                ImapAuthenticate authentication = new ImapAuthenticate(connection, usuario_imap.Email, usuario_imap.Password);
                ImapMailbox      mailbox;

                connection.Open();
                authentication.Login();
                mailbox = command.Select(pasta);

                mailbox = command.Fetch(mailbox);
                foreach (ImapMailboxMessage m in mailbox.Messages.Reverse <ImapMailboxMessage>())
                {
                    string destinatarios = string.Empty;
                    Email  email         = new Email();

                    m.To.ToList().ForEach(a => destinatarios += a.Address + "; ");
                    email.Remetente    = m.From.Address;
                    email.Destinatario = destinatarios.Trim();
                    email.Assunto      = m.Subject;
                    email.Data_Envio   = m.Sent.ToString("dd/MM/yyyy");
                    email.Usuario_Imap = usuario_imap;

                    ImapMailboxMessage msg = command.FetchBodyStructure(m);
                    if (m.HasText)
                    {
                        msg            = command.FetchBodyPart(m, m.Text);
                        email.Mensagem = msg.BodyParts[m.Text].Data;
                    }
                    if (m.HasHTML)
                    {
                        msg = command.FetchBodyPart(m, m.HTML);
                        string   html     = msg.BodyParts[m.HTML].Data;
                        Encoding encoding = msg.BodyParts[m.HTML].Encoding;

                        if (msg.BodyParts[m.HTML].ContentEncoding == BodyPartEncoding.BASE64)
                        {
                            email.Mensagem = html.DecodeBase64(encoding);
                        }
                        else
                        {
                            email.Mensagem = html.ToUTF8(encoding);
                        }
                    }

                    emails.Add(email);
                }

                authentication.Logout();
                connection.Close();
            }
        }
Exemple #13
0
        /// <summary>
        ///   The FETCH command retrieves data associated with a message in the
        ///   mailbox.  The data items to be fetched can be either a single atom
        ///   or a parenthesized list.
        ///   http://tools.ietf.org/html/rfc3501#section-6.4.5
        /// </summary>
        /// <param name = "set">The list of ids of the messages to fetch.</param>
        /// <param name = "query">The query, consisting of message parts to fetch.</param>
        public FetchImapResponse Fetch(SequenceSet set, string query)
        {
            var text     = string.Format("FETCH {0} {1}", set, query);
            var command  = new ImapCommand(text);
            var reader   = SendAndReceive(command);
            var response = new FetchImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #14
0
        /// <summary>
        ///   The LOGOUT command informs the server that the client is done with the connection.
        ///   http://tools.ietf.org/html/rfc3501#section-6.1.3
        /// </summary>
        public ImapResponse Logout()
        {
            var command = new ImapCommand("LOGOUT");
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #15
0
        /// <summary>
        ///   The NOOP command always succeeds.  It does nothing.
        ///   http://tools.ietf.org/html/rfc3501#section-6.1.2
        /// </summary>
        public ImapResponse Noop()
        {
            var command = new ImapCommand("NOOP");
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #16
0
        /// <summary>
        ///   The EXPUNGE command permanently removes all messages that have the
        ///   \Deleted flag set from the currently selected mailbox.  Before returning
        ///   an OK to the client, an untagged EXPUNGE response is sent for each message that is removed.
        /// </summary>
        public ExpungeImapResponse Expunge()
        {
            var text    = string.Format("EXPUNGE");
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ExpungeImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #17
0
        /// <summary>
        ///   The CHECK command requests a checkpoint of the currently selected
        ///   mailbox.  A checkpoint refers to any implementation-dependent
        ///   housekeeping associated with the mailbox (e.g., resolving the
        ///   server's in-memory state of the mailbox with the state on its
        ///   disk) that is not normally executed as part of each command.  A
        ///   checkpoint MAY take a non-instantaneous amount of real time to
        ///   complete.  If a server implementation has no such housekeeping
        ///   considerations, CHECK is equivalent to NOOP.
        ///   http://tools.ietf.org/html/rfc2060#section-6.4.1
        /// </summary>
        public ImapResponse Check()
        {
            var text    = string.Format("CHECK");
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #18
0
        /// <summary>
        ///   The SEARCH command searches the mailbox for messages that match
        ///   the given searching criteria.  Searching criteria consist of one
        ///   or more search keys.
        /// </summary>
        /// <param name = "query">The query command that will be sent to the server.</param>
        /// <param name = "isUidSearch">Sets whether the search shall return uids instead of sequence numbers.</param>
        /// <returns>The sequence numbers or uids of those messages matching the given criteria.</returns>
        public SearchImapResponse Search(string query, bool isUidSearch = false)
        {
            var uid      = isUidSearch ? "UID " : string.Empty;
            var text     = string.Format("{0}SEARCH {1}", uid, query);
            var command  = new ImapCommand(text);
            var reader   = SendAndReceive(command);
            var response = new SearchImapResponse();

            response.Parse(reader);
            return(response);
        }
        protected override bool RunInternal(ImapCommand cmd)
        {
            var mailbox = cmd.Args.Trim();

            if (!Context.EntityProvider.CreateDirectory(mailbox))
            {
                Context.CommandProvider.Write($"{cmd.Tag} BAD CREATE\r\n");
            }

            Context.CommandProvider.Write($"{cmd.Tag} OK CREATE\r\n");
            return(true);
        }
        private bool AuthenticateLogin(NetworkCredential credentials)
        {
            var text    = string.Format("LOGIN {0} {1}", credentials.UserName, credentials.Password);
            var command = new ImapCommand(text);
            var reader  = _client.SendAndReceive(command);

            while (!reader.IsCompleted)
            {
                reader = _client.Receive(false);
            }
            return(reader.IsOk);
        }
Exemple #21
0
        protected override bool RunInternal(ImapCommand cmd)
        {
            var mailbox = cmd.Args.Trim();

            if (Context.SubscribedMailboxes.Contains(mailbox))
            {
                Context.CommandProvider.Write($"{cmd.Tag} NO\r\n");
            }
            Context.SubscribedMailboxes.Add(mailbox);
            Context.CommandProvider.Write($"{cmd.Tag} OK SUBSCRIBE completed\r\n");
            return(true);
        }
Exemple #22
0
        public override object Execute(Expression expression)
        {
            // reduce expressions to constants where possible
            expression = Evaluator.PartialEval(expression);

            var crawler          = new ExpressionCrawler();
            var searchExpression = crawler.FindSearchLambda(expression);
            var fetchExpression  = crawler.FindFetchLamda(expression);

            // the search string sequence
            string sequence;

            var searchTranslationResult = new ImapQueryTranslator().Translate(searchExpression);

            var isSearchRequired = searchTranslationResult.ValidateSearchNecessity();

            if (isSearchRequired)
            {
                var searchCommand = new ImapCommand(searchTranslationResult.SearchCommand);
                var response      = _client.SendAndReceive(searchCommand);

                var success = TryExtractIds(response, out sequence);
                if (!success)
                {
                    // no messages match the search criteria therefor we don't need to fetch anything
                    // we return an empty list
                    return(Activator.CreateInstance(typeof(List <>).MakeGenericType(fetchExpression.ReturnType), null));
                }
            }
            else
            {
                sequence = searchTranslationResult.ConvertCommandToSequence();
            }


            // There are no id's if no message matches the search criterias.
            var fetchTranslator = new ImapFetchQueryTranslator {
                IsUid = searchTranslationResult.IsUid, UsePeek = _client.UsePeek
            };

            ResponseProcessor processor;
            var fetchString   = fetchTranslator.Translate(fetchExpression, sequence, out processor);
            var fetchCommand  = new ImapCommand(fetchString);
            var fetchResponse = _client.SendAndReceive(fetchCommand);

            return(Activator.CreateInstance(
                       typeof(ImapQueryResponseReader <>).MakeGenericType(new[] { fetchExpression.ReturnType }),
                       BindingFlags.Instance | BindingFlags.Public,
                       null,
                       new object[] { fetchResponse, processor },
                       CultureInfo.CurrentCulture));
        }
Exemple #23
0
        /// <summary>
        ///   The CREATE command creates a mailbox with the given name.
        ///   http://tools.ietf.org/html/rfc3501#section-6.3.3
        /// </summary>
        /// <param name = "mailboxName">The name of the mailbox to create.</param>
        public ImapResponse Create(string mailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(mailboxName);

            var text    = string.Format("CREATE \"{0}\"", name);
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #24
0
        /// <summary>
        ///   The COPY command copies the specified message(s) to the end of the specified destination mailbox.
        ///   http://tools.ietf.org/html/rfc3501#section-6.4.7
        /// </summary>
        public ImapResponse Copy(SequenceSet set, string destinationMailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(destinationMailboxName);

            var text    = string.Format("COPY {0} \"{1}\"", set, name);
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #25
0
        public bool Run(IImapContext context, ImapCommand cmd)
        {
            Context = context;
            context.AddState(new ImapStateItem
            {
                State   = State,
                Command = cmd.Command,
                Tag     = cmd.Tag,
                Args    = cmd.Args
            });
            var result = RunInternal(cmd);

            context.TryPopState(out var state);
            return(result);
        }
        protected override bool RunInternal(ImapCommand cmd)
        {
            var mailbox = cmd.Args.Trim();

            if (!Context.EntityProvider.DeleteDirectory(mailbox))
            {
                Context.CommandProvider.Write($"{cmd.Tag} BAD\r\n");
                return(true);
            }

            // \noselect delele - BAD
            // nonexist delete - BAD
            Context.CommandProvider.Write($"{cmd.Tag} OK DELETE\r\n");
            return(true);
        }
Exemple #27
0
        protected override bool RunInternal(ImapCommand cmd)
        {
            var match = Regex.Match(cmd.Args,
                                    @"^[""]{0,1}(?<refname>[^""]*)[""]{0,1} [""]{0,1}(?<box>[^""]*)[""]{0,1}");

            if (!match.Success)
            {
                Context.CommandProvider.Write($"{cmd.Tag} BAD\r\n");
                return(true);
            }

            var refname     = match.Groups["refname"].Value;
            var boxWildcard = match.Groups["box"].Value;

            var path      = refname.Split('/');
            var mailboxes = (Context.EntityProvider.GetAllDirectories() ?? new Dictionary <int, string>())
                            .Values
                            .Select(p => p.Split('/'))
                            .ToList();

            var refResultBoxes = mailboxes
                                 .Where(m => m.Take(path.Length).SequenceEqual(path))
                                 .ToList();

            if (string.IsNullOrWhiteSpace(refname))
            {
                refResultBoxes = mailboxes.ToList();
            }

            var boxRegex = boxWildcard
                           .Replace("*", @".*")
                           .Replace("%", @"[^/]*")
                           .Insert(0, "^");

            var resultBoxes = refResultBoxes
                              .Select(path => string.Join("/", path))
                              .Where(p => Regex.IsMatch(p, boxRegex))
                              .ToList();

            foreach (var mailbox in resultBoxes)
            {
                Context.CommandProvider.Write($"* LIST (\\Noinferiors) \"/\" {mailbox}\r\n");
            }

            Context.CommandProvider.Write($"{cmd.Tag} OK LIST\r\n");

            return(true);
        }
Exemple #28
0
        /// <summary>
        ///   The LSUB command returns a subset of names from the set of names that the user has declared as being "active" or "subscribed".
        ///   http://tools.ietf.org/html/rfc3501#section-6.3.9
        /// </summary>
        /// <param name = "referenceName">The reference name.</param>
        /// <param name = "wildcardedMailboxName">The mailbox name with possible wildcards.</param>
        public ListImapResponse LSub(string referenceName, string wildcardedMailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            referenceName         = MailboxNameEncoder.Encode(referenceName);
            wildcardedMailboxName = MailboxNameEncoder.Encode(wildcardedMailboxName);

            var text    = string.Format("LSUB \"{0}\" \"{1}\"", referenceName, wildcardedMailboxName);
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ListImapResponse();

            response.Parse(reader);
            return(response);
        }
        protected override Command ParseCommandLine(string line)
        {
            ImapCommand c = new ImapCommand();
            c.Raw = line;

            string[] command = line.Split(' ');

            string tag = command[0];
            string cmd = command[1].ToUpperInvariant();

            c.Arguments = new List<string>(command.Skip(2));
            c.RawArguments = string.Join(" ", c.Arguments);

            c.Tag = tag;
            c.Code = cmd;

            return c;
        }
        protected override bool RunInternal(ImapCommand cmd)
        {
            /*
             *    Arguments:  none
             *
             * Responses:  untagged responses: EXPUNGE
             *
             * Result:     OK - expunge completed
             * NO - expunge failure: can't expunge (e.g., permission
             *      denied)
             * BAD - command unknown or arguments invalid
             *
             * The EXPUNGE command permanently removes all messages that have the
             * \Deleted flag set from the currently selected mailbox.  Before
             * returning an OK to the client, an untagged EXPUNGE response is
             * sent for each message that is removed.
             *
             * Example:    C: A202 EXPUNGE
             * S: * 3 EXPUNGE
             * S: * 3 EXPUNGE
             * S: * 5 EXPUNGE
             * S: * 8 EXPUNGE
             * S: A202 OK EXPUNGE completed
             *
             * Note: In this example, messages 3, 4, 7, and 11 had the
             * \Deleted flag set.  See the description of the EXPUNGE
             * response for further explanation.
             */

            var expunged = Context.EntityProvider.Expunge();

            if (expunged == null)
            {
                Context.CommandProvider.Write($"{cmd.Tag} NO EXPUNGE\r\n");
                return(true);
            }

            foreach (var id in expunged)
            {
                Context.CommandProvider.Write($"* {id} EXPUNGE\r\n");
            }
            Context.CommandProvider.Write($"{cmd.Tag} OK EXPUNGE completed\r\n");
            return(true);
        }
        public override object Execute(Expression expression)
        {
            // reduce expressions to constants where possible
            expression = Evaluator.PartialEval(expression);

            var crawler = new ExpressionCrawler();
            var searchExpression = crawler.FindSearchLambda(expression);
            var fetchExpression = crawler.FindFetchLamda(expression);

            // the search string sequence
            string sequence;

            var searchTranslationResult = new ImapQueryTranslator().Translate(searchExpression);

            var isSearchRequired = searchTranslationResult.ValidateSearchNecessity();
            if (isSearchRequired) {
                var searchCommand = new ImapCommand(searchTranslationResult.SearchCommand);
                var response = _client.SendAndReceive(searchCommand);

                var success = TryExtractIds(response, out sequence);
                if (!success) {
                    // no messages match the search criteria therefor we don't need to fetch anything
                    // we return an empty list
                    return Activator.CreateInstance(typeof (List<>).MakeGenericType(fetchExpression.ReturnType), null);
                }
            } else {
                sequence = searchTranslationResult.ConvertCommandToSequence();
            }

            // There are no id's if no message matches the search criterias.
            var fetchTranslator = new ImapFetchQueryTranslator {IsUid = searchTranslationResult.IsUid, UsePeek = _client.UsePeek};

            ResponseProcessor processor;
            var fetchString = fetchTranslator.Translate(fetchExpression, sequence, out processor);
            var fetchCommand = new ImapCommand(fetchString);
            var fetchResponse = _client.SendAndReceive(fetchCommand);

            return Activator.CreateInstance(
                typeof (ImapQueryResponseReader<>).MakeGenericType(new[] {fetchExpression.ReturnType}),
                BindingFlags.Instance | BindingFlags.Public,
                null,
                new object[] {fetchResponse, processor},
                CultureInfo.CurrentCulture);
        }
Exemple #32
0
        /// <summary>
        ///   The RENAME command changes the name of a mailbox.  A tagged OK
        ///   response is returned only if the mailbox has been renamed.  It is
        ///   an error to attempt to rename from a mailbox name that does not
        ///   exist or to a mailbox name that already exists.  Any error in
        ///   renaming will return a tagged NO response.
        /// </summary>
        /// <param name = "sourceName">The fullname of the mailbox to rename.</param>
        /// <param name = "targetName">The new name for the mailbox.</param>
        /// <returns>Returns the server response.</returns>
        public ImapResponse Rename(string sourceName, string targetName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var source = MailboxNameEncoder.Encode(sourceName);

            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var target = MailboxNameEncoder.Encode(targetName);

            var text    = string.Format("RENAME \"{0}\" \"{1}\"", source, target);
            var command = new ImapCommand(text);
            var reader  = SendAndReceive(command);

            var response = new ImapResponse();

            response.Parse(reader);
            return(response);
        }
Exemple #33
0
        protected override Command ParseCommandLine(string line)
        {
            ImapCommand c = new ImapCommand();

            c.Raw = line;

            string[] command = line.Split(' ');

            string tag = command[0];
            string cmd = command[1].ToUpperInvariant();

            c.Arguments    = new List <string>(command.Skip(2));
            c.RawArguments = string.Join(" ", c.Arguments);

            c.Tag  = tag;
            c.Code = cmd;

            return(c);
        }
 protected override bool IssueStartTlsCommand(string host)
 {
     var command = new ImapCommand(CommandStrings.StartTls);
     Send(command);
     return Receive().IsOk;
 }
        /// <summary>
        ///   The CLOSE command permanently removes all messages that have the 
        ///   \Deleted flag set from the currently selected mailbox, and returns to the authenticated state from the selected state.
        /// </summary>
        /// <param name = "mailboxName">The targeted mailboxName.</param>
        public ImapResponse Close(string mailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(mailboxName);

            var text = string.Format("CLOSE {0}", name);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);

            if (response.IsOk) {
                SelectedMailbox = string.Empty;
            }

            return response;
        }
 private ImapResponseReader StoreInternal(SequenceSet set, string value, StoreProcedures procedure, string commandString)
 {
     var prefix = procedure == StoreProcedures.Add ? "+" : "-";
     var isUid = set.IsUid ? "UID " : string.Empty;
     var text = string.Format("{0}STORE {1} {2}{3} ({4})", isUid, set, prefix, commandString, value);
     var command = new ImapCommand(text);
     return SendAndReceive(command, false);
 }
        /// <summary>
        ///   The NOOP command always succeeds.  It does nothing.
        ///   http://tools.ietf.org/html/rfc3501#section-6.1.2
        /// </summary>
        public ImapResponse Noop()
        {
            var command = new ImapCommand("NOOP");
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
        /// <summary>
        ///   The COPY command copies the specified message(s) to the end of the specified destination mailbox.
        ///   http://tools.ietf.org/html/rfc3501#section-6.4.7
        /// </summary>
        public ImapResponse Copy(SequenceSet set, string destinationMailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(destinationMailboxName);

            var text = string.Format("COPY {0} \"{1}\"", set, name);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
 private bool AuthenticateLogin(NetworkCredential credentials)
 {
     var text = string.Format("LOGIN {0} {1}", credentials.UserName, credentials.Password);
     var command = new ImapCommand(text);
     var reader = _client.SendAndReceive(command);
     while (!reader.IsCompleted) {
         reader = _client.Receive(false);
     }
     return reader.IsOk;
 }
 /// <summary>
 ///   Authenticates the client to the server using the XOAUTH mechanism.
 /// </summary>
 /// <param name = "key">The XOAUTH authetication key.</param>
 /// <returns>Returns true on success, false otherwise.</returns>
 public bool AuthenticateXOAuth(string key)
 {
     if (_client.ServerCapability.IsInitialClientResponseSupported) {
         var text = string.Format("AUTHENTICATE XOAUTH {0}", key);
         var command = new ImapCommand(text);
         return _client.SendAndReceive(command).IsOk;
     } else {
         var text = string.Format("AUTHENTICATE XOAUTH");
         var command = new ImapCommand(text);
         var reader = _client.SendAndReceive(command);
         if (reader.IsContinuation) {
             var auth = new BlankImapCommand(key);
             return _client.SendAndReceive(auth).IsOk;
         }
         return false;
     }
 }
        /// <summary>
        ///   This method is blocking.
        ///   The IDLE command may be used with any IMAP4 server implementation
        ///   that returns "IDLE" as one of the supported capabilities to the
        ///   CAPABILITY command.  If the server does not advertise the IDLE
        ///   capability, the client MUST NOT use the IDLE command and must poll
        ///   for mailbox updates.
        ///   http://tools.ietf.org/html/rfc2177
        /// </summary>
        public void StartIdle()
        {
            if (!ServerCapability.IsIdleSupported) {
                const string message = "Server does not support the idle command. Please check Capability.CanIdle before calling Idle.";
                throw new InvalidOperationException(message);
            }

            var command = new ImapCommand("IDLE");
            SendAndReceive(command);
            IsIdling = true;

            while (true) {
                // Need to set response timeout to 29 minutes, because the server will kick us after 30  if we do not re apply for IDLE.
                ResponseTimeout = TimeSpan.FromMinutes(29);
                var reader = new ImapResponseReader(this);
                try {
                    ReceiveIdleStatusUpdates(reader);
                }
                catch (TimeoutException) {
                    StopIdleAsync();
                }

                if (reader.IsCompleted) {
                    break;
                }
            }

            IsIdling = false;
        }
        /// <summary>
        ///   The UNSUBSCRIBE command removes the specified mailbox name from
        ///   the server's set of "active" or "subscribed" mailboxes as returned
        ///   by the LSUB command.
        ///   http://tools.ietf.org/html/rfc3501#section-6.3.7
        /// </summary>
        /// <param name = "mailboxName">The name of the mailbox to subscribe to.</param>
        public ImapResponse Unsubscribe(string mailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(mailboxName);

            var text = string.Format("UNSUBSCRIBE \"{0}\"", name);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
 /// <summary>
 ///   Sends a command to the server and returns a reader capable of receiving line by line.
 /// </summary>
 /// <param name = "command">The command to issue.</param>
 /// <param name = "processStatusUpdatesAutomatically">This param defines whether received status updates will be processed automatically.</param>
 /// <returns>Returns a response reader.</returns>
 public ImapResponseReader SendAndReceive(ImapCommand command, bool processStatusUpdatesAutomatically = true)
 {
     Send(command);
     return Receive(processStatusUpdatesAutomatically);
 }
 /// <summary>
 ///   Sends a command to the server.
 /// </summary>
 /// <param name = "command">The command to issue.</param>
 public void SendAsync(ImapCommand command)
 {
     var commandString = command.ToString();
     WriteLineAsync(commandString);
 }
        /// <summary>
        ///   The SELECT command selects a mailbox so that messages in the mailbox can be accessed.
        ///   http://tools.ietf.org/html/rfc3501#section-6.3.1
        /// </summary>
        /// <param name = "mailboxName">The name of the mailbox to select.</param>
        public SelectExamineImapResponse Select(string mailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var name = MailboxNameEncoder.Encode(mailboxName);

            var text = string.Format("SELECT \"{0}\"", name);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command, false);

            var response = new SelectExamineImapResponse(mailboxName);
            response.Parse(reader);

            if (response.IsOk) {
                SelectedMailbox = mailboxName;
            }

            return response;
        }
 /// <summary>
 ///   The SEARCH command searches the mailbox for messages that match
 ///   the given searching criteria.  Searching criteria consist of one
 ///   or more search keys.
 /// </summary>
 /// <param name = "query">The query command that will be sent to the server.</param>
 /// <param name = "isUidSearch">Sets whether the search shall return uids instead of sequence numbers.</param>
 /// <returns>The sequence numbers or uids of those messages matching the given criteria.</returns>
 public SearchImapResponse Search(string query, bool isUidSearch = false)
 {
     var uid = isUidSearch ? "UID " : string.Empty;
     var text = string.Format("{0}SEARCH {1}", uid, query);
     var command = new ImapCommand(text);
     var reader = SendAndReceive(command);
     var response = new SearchImapResponse();
     response.Parse(reader);
     return response;
 }
        /// <summary>
        ///   The RENAME command changes the name of a mailbox.  A tagged OK
        ///   response is returned only if the mailbox has been renamed.  It is
        ///   an error to attempt to rename from a mailbox name that does not
        ///   exist or to a mailbox name that already exists.  Any error in
        ///   renaming will return a tagged NO response.
        /// </summary>
        /// <param name = "sourceName">The fullname of the mailbox to rename.</param>
        /// <param name = "targetName">The new name for the mailbox.</param>
        /// <returns>Returns the server response.</returns>
        public ImapResponse Rename(string sourceName, string targetName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var source = MailboxNameEncoder.Encode(sourceName);

            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            var target = MailboxNameEncoder.Encode(targetName);

            var text = string.Format("RENAME \"{0}\" \"{1}\"", source, target);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
 protected override void FetchCapabilities()
 {
     var command = new ImapCommand(CommandStrings.Capability);
     var reader = SendAndReceive(command);
     ServerCapability = reader.ReadCapabilities();
 }
        /// <summary>
        ///   The LOGOUT command informs the server that the client is done with the connection.
        ///   http://tools.ietf.org/html/rfc3501#section-6.1.3
        /// </summary>
        public ImapResponse Logout()
        {
            var command = new ImapCommand("LOGOUT");
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
        private bool AuthenticatePlain(NetworkCredential credentials)
        {
            var capabilities = _client.ServerCapability;
            var username = credentials.UserName;
            var password = credentials.Password;

            var auth = username + "\0" + username + "\0" + password;
            var encodedAuth = Base64Encoder.Encode(auth);

            if (capabilities.IsInitialClientResponseSupported) {
                var text = string.Format("AUTHENTICATE PLAIN {0}", encodedAuth);
                var command = new ImapCommand(text);
                return _client.SendAndReceive(command).IsOk;
            }

            var authCommand = new ImapCommand("AUTHENTICATE PLAIN");
            var response = _client.SendAndReceive(authCommand);
            if (response.IsContinuation) {
                var command = new BlankImapCommand(encodedAuth);
                _client.Send(command);
                return _client.Receive().IsOk;
            }

            return false;
        }
        /// <summary>
        ///   The FETCH command retrieves data associated with a message in the
        ///   mailbox.  The data items to be fetched can be either a single atom
        ///   or a parenthesized list.
        ///   http://tools.ietf.org/html/rfc3501#section-6.4.5
        /// </summary>
        /// <param name = "set">The list of ids of the messages to fetch.</param>
        /// <param name = "query">The query, consisting of message parts to fetch.</param>
        public FetchImapResponse Fetch(SequenceSet set, string query)
        {
            var text = string.Format("FETCH {0} {1}", set, query);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);
            var response = new FetchImapResponse();

            response.Parse(reader);
            return response;
        }
        private bool AuthenticateCramMd5(NetworkCredential credentials)
        {
            var command = new ImapCommand("AUTHENTICATE CRAM-MD5");
            var response = _client.SendAndReceive(command);

            // don't trim the last plus !!
            var base64 = response.CurrentLine.TrimStart(Characters.Plus).Trim();
            var challenge = Base64Encoder.Decode(base64, Encoding.UTF8);

            var username = credentials.UserName;
            var password = credentials.Password;

            var hash = CramMd5Hasher.ComputeHash(password, challenge);

            var authentication = username + " " + hash;
            var authCommand = new BlankImapCommand(Base64Encoder.Encode(authentication));

            var reader = _client.SendAndReceive(authCommand);
            while (!reader.IsCompleted) {
                reader = _client.Receive(false);
            }
            return reader.IsOk;
        }
        /// <summary>
        ///   The EXPUNGE command permanently removes all messages that have the 
        ///   \Deleted flag set from the currently selected mailbox.  Before returning 
        ///   an OK to the client, an untagged EXPUNGE response is sent for each message that is removed.
        /// </summary>
        public ExpungeImapResponse Expunge()
        {
            var text = string.Format("EXPUNGE");
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ExpungeImapResponse();
            response.Parse(reader);
            return response;
        }
        /// <summary>
        ///   The CHECK command requests a checkpoint of the currently selected
        ///   mailbox.  A checkpoint refers to any implementation-dependent
        ///   housekeeping associated with the mailbox (e.g., resolving the
        ///   server's in-memory state of the mailbox with the state on its
        ///   disk) that is not normally executed as part of each command.  A
        ///   checkpoint MAY take a non-instantaneous amount of real time to
        ///   complete.  If a server implementation has no such housekeeping
        ///   considerations, CHECK is equivalent to NOOP.
        ///   http://tools.ietf.org/html/rfc2060#section-6.4.1
        /// </summary>
        public ImapResponse Check()
        {
            var text = string.Format("CHECK");
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ImapResponse();
            response.Parse(reader);
            return response;
        }
        /// <summary>
        ///   The LSUB command returns a subset of names from the set of names that the user has declared as being "active" or "subscribed".
        ///   http://tools.ietf.org/html/rfc3501#section-6.3.9
        /// </summary>
        /// <param name = "referenceName">The reference name.</param>
        /// <param name = "wildcardedMailboxName">The mailbox name with possible wildcards.</param>
        public ListImapResponse LSub(string referenceName, string wildcardedMailboxName)
        {
            // we need to convert non ASCII names according to IMAP specs.
            // http://tools.ietf.org/html/rfc2060#section-5.1.3
            referenceName = MailboxNameEncoder.Encode(referenceName);
            wildcardedMailboxName = MailboxNameEncoder.Encode(wildcardedMailboxName);

            var text = string.Format("LSUB \"{0}\" \"{1}\"", referenceName, wildcardedMailboxName);
            var command = new ImapCommand(text);
            var reader = SendAndReceive(command);

            var response = new ListImapResponse();
            response.Parse(reader);
            return response;
        }