protected override bool IssueStartTlsCommand(string host) { var command = new ImapCommand(CommandStrings.StartTls); Send(command); return(Receive().IsOk); }
/// <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; }
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); }
protected override void FetchCapabilities() { var command = new ImapCommand(CommandStrings.Capability); var reader = SendAndReceive(command); ServerCapability = reader.ReadCapabilities(); }
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); } }
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(); } }
/// <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); }
/// <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); }
/// <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 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 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); }
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); }
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)); }
/// <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); }
/// <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); }
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); }
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); }
/// <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); }
/// <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 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> /// 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; }
/// <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; }