/* * Copyright (c) 2021, Kyle Pereira * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace IMAP { template using Promise = Core::Promise; class Client { AK_MAKE_NONCOPYABLE(Client); friend class Parser; public: static ErrorOr> connect_tls(StringView host, u16 port); static ErrorOr> connect_plaintext(StringView host, u16 port); Client(Client&&); RefPtr> connection_promise() { return m_connect_pending; } RefPtr>> send_command(Command&&); RefPtr>> send_simple_command(CommandType); ErrorOr send_raw(StringView data); RefPtr>> login(StringView username, StringView password); RefPtr>> list(StringView reference_name, StringView mailbox_name); RefPtr>> lsub(StringView reference_name, StringView mailbox_name); RefPtr>> select(StringView string); RefPtr>> examine(StringView string); RefPtr>> search(Optional charset, Vector&& search_keys, bool uid); RefPtr>> fetch(FetchCommand request, bool uid); RefPtr>> store(StoreMethod, Sequence, bool silent, Vector const& flags, bool uid); RefPtr>> copy(Sequence sequence_set, StringView name, bool uid); RefPtr>> create_mailbox(StringView name); RefPtr>> delete_mailbox(StringView name); RefPtr>> subscribe(StringView mailbox); RefPtr>> unsubscribe(StringView mailbox); RefPtr>> rename(StringView from, StringView to); RefPtr>> authenticate(StringView method); RefPtr>> idle(); RefPtr>> finish_idle(); RefPtr>> status(StringView mailbox, Vector const& types); RefPtr>> append(StringView mailbox, Message&& message, Optional> flags = {}, Optional date_time = {}); bool is_open(); void close(); Function unrequested_response_callback; private: Client(StringView host, u16 port, NonnullOwnPtr); void setup_callbacks(); ErrorOr on_ready_to_receive(); ErrorOr on_tls_ready_to_receive(); ErrorOr handle_parsed_response(ParseStatus&& parse_status); ErrorOr send_next_command(); StringView m_host; u16 m_port; NonnullOwnPtr m_socket; RefPtr> m_connect_pending {}; int m_current_command = 1; // Sent but response not received Vector>>> m_pending_promises; // Not yet sent Vector m_command_queue {}; ByteBuffer m_buffer; Parser m_parser {}; bool m_expecting_response { false }; }; }