{"id":13636995,"url":"https://github.com/duesee/imap-codec","last_synced_at":"2025-04-05T09:16:54.782Z","repository":{"id":37084115,"uuid":"251266368","full_name":"duesee/imap-codec","owner":"duesee","description":"Rock-solid and complete codec for IMAP","archived":false,"fork":false,"pushed_at":"2025-03-10T02:06:34.000Z","size":2238,"stargazers_count":39,"open_issues_count":44,"forks_count":13,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-05T01:18:24.206Z","etag":null,"topics":["client-side","codec","email","imap","networking","parser","parsing-library","proto","protocol","rust","server-side"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/duesee.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["duesee"]}},"created_at":"2020-03-30T10:01:24.000Z","updated_at":"2025-03-07T17:21:33.000Z","dependencies_parsed_at":"2023-02-15T19:01:09.796Z","dependency_job_id":"a7f531a5-144f-4554-8827-ab8a7cb14ef7","html_url":"https://github.com/duesee/imap-codec","commit_stats":{"total_commits":597,"total_committers":7,"mean_commits":85.28571428571429,"dds":"0.49581239530988275","last_synced_commit":"8009edec59b0536f07f096435144900719f0bc12"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duesee%2Fimap-codec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duesee%2Fimap-codec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duesee%2Fimap-codec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duesee%2Fimap-codec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duesee","download_url":"https://codeload.github.com/duesee/imap-codec/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247312062,"owners_count":20918344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client-side","codec","email","imap","networking","parser","parsing-library","proto","protocol","rust","server-side"],"created_at":"2024-08-02T00:01:09.086Z","updated_at":"2025-04-05T09:16:54.744Z","avatar_url":"https://github.com/duesee.png","language":"Rust","funding_links":["https://github.com/sponsors/duesee"],"categories":["Libraries"],"sub_categories":["Email"],"readme":"[![Build \u0026 Test](https://github.com/duesee/imap-codec/actions/workflows/main.yml/badge.svg)](https://github.com/duesee/imap-codec/actions/workflows/main.yml)\n[![Audit](https://github.com/duesee/imap-codec/actions/workflows/audit.yml/badge.svg)](https://github.com/duesee/imap-codec/actions/workflows/audit.yml)\n[![Coverage](https://coveralls.io/repos/github/duesee/imap-codec/badge.svg?branch=main)](https://coveralls.io/github/duesee/imap-codec?branch=main)\n[![Documentation](https://docs.rs/imap-codec/badge.svg)](https://docs.rs/imap-codec)\n\n# imap-{codec,types}\n\nThis workspace contains [`imap-codec`] and [`imap-types`], two [rock-solid] and [well-documented] crates to build [IMAP4rev1] clients and servers.\n`imap-codec` provides parsing and serialization, and is based on `imap-types`.\n`imap-types` provides misuse-resistant types, constructors, and general support for IMAP implementations.\nThe crates live here together, but `imap-types` is a perfectly fine standalone crate.\n\nIf you are looking for a slightly more high-level library supporting your client or server implementation, take a look at [`imap-next`].\n\nLet's talk on [Matrix]!\n\n## Features\n\n* Complete [formal syntax] of IMAP4rev1 is implemented. Furthermore, several IMAP [extensions] are supported.\n* Correctness and misuse-resistance are enforced on the type level. It's not possible to construct a message that violates the IMAP specification.\n* Messages automatically use the most efficient representation. For example, atoms are preferred over quoted strings, and quoted strings are preferred over literals. It's equally easy to manually choose a representation.\n* Parsing works in streaming mode. `Incomplete` is returned when there is insufficient data to make a final decision. No message will be truncated.\n* Parsing is zero-copy by default. Allocation is avoided during parsing, but all messages can explicitly be converted into more flexible owned variants.\n* Fuzzing and property-based tests exercise the library. The library is fuzz-tested never to produce a message it can't parse itself.\n\n## Usage\n\n```rust\nuse imap_codec::{decode::Decoder, encode::Encoder, CommandCodec};\n\nfn main() {\n    let input = b\"ABCD UID FETCH 1,2:* (BODY.PEEK[1.2.3.4.MIME]\u003c42.1337\u003e)\\r\\n\";\n\n    let codec = CommandCodec::new();\n    let (remainder, cmd) = codec.decode(input).unwrap();\n    println!(\"# Parsed\\n\\n{:#?}\\n\\n\", cmd);\n\n    let buffer = codec.encode(\u0026cmd).dump();\n\n    // Note: IMAP4rev1 may produce messages that are not valid UTF-8.\n    println!(\"# Serialized\\n\\n{:?}\", std::str::from_utf8(\u0026buffer));\n}\n```\n\n## Examples\n\n### Simple parsing\n\nTry one of the `parse_*` examples, e.g., ...\n\n```sh\n$ cargo run --example=parse_command\n```\n\n... to parse some IMAP messages.\n\n### Robust parsing\n\nReal-world implementations need to handle invalid messages.\nThus, `imap-codec` provides a `Fragmentizer` (see `fragmentizer*` examples) for \"two-stage parsing\".\n\nThe idea is to detect message boundaries (consuming raw lines and literals) first, and to apply an IMAP message parser\nsecond.\nIf the message parser errors out, we can safely discard the erroneous message w/o affecting other messages because we\nknow the message boundaries.\n\nYou can try this out by running ...\n\n```sh\n$ cargo run --example=fragmentizer_server\n```\n\n... and connecting via ...\n\n```sh\n$ netcat -C 127.0.0.1 12345\n```\n\n### Parsed and serialized IMAP4rev1 connection\n\nThe following output was generated by reading the trace from [RFC 3501 section 8](https://tools.ietf.org/html/rfc3501#section-8), printing the input (first line), `Debug`-printing the parsed object (second line), and printing the serialized output (third line).\n\n```rust,compile_fail\n// * OK IMAP4rev1 Service Ready\nStatus(Ok { tag: None, code: None, text: Text(\"IMAP4rev1 Service Ready\") })\n// * OK IMAP4rev1 Service Ready\n\n// a001 login mrc secret\nCommand { tag: Tag(\"a001\"), body: Login { username: Atom(AtomExt(\"mrc\")), password: /* REDACTED */ } }\n// a001 LOGIN mrc secret\n\n// a001 OK LOGIN completed\nStatus(Ok { tag: Some(Tag(\"a001\")), code: None, text: Text(\"LOGIN completed\") })\n// a001 OK LOGIN completed\n\n// a002 select inbox\nCommand { tag: Tag(\"a002\"), body: Select { mailbox: Inbox } }\n// a002 SELECT INBOX\n\n// * 18 EXISTS\nData(Exists(18))\n// * 18 EXISTS\n\n// * FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\nData(Flags([Answered, Flagged, Deleted, Seen, Draft]))\n// * FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\n\n// * 2 RECENT\nData(Recent(2))\n// * 2 RECENT\n\n// * OK [UNSEEN 17] Message 17 is the first unseen message\nStatus(Ok { tag: None, code: Some(Unseen(17)), text: Text(\"Message 17 is the first unseen message\") })\n// * OK [UNSEEN 17] Message 17 is the first unseen message\n\n// * OK [UIDVALIDITY 3857529045] UIDs valid\nStatus(Ok { tag: None, code: Some(UidValidity(3857529045)), text: Text(\"UIDs valid\") })\n// * OK [UIDVALIDITY 3857529045] UIDs valid\n\n// a002 OK [READ-WRITE] SELECT completed\nStatus(Ok { tag: Some(Tag(\"a002\")), code: Some(ReadWrite), text: Text(\"SELECT completed\") })\n// a002 OK [READ-WRITE] SELECT completed\n\n// a003 fetch 12 full\nCommand { tag: Tag(\"a003\"), body: Fetch { sequence_set: SequenceSet([Single(Value(12))]+), macro_or_item_names: Macro(Full), uid: false } }\n// a003 FETCH 12 FULL\n\n// * 12 FETCH (FLAGS (\\Seen) INTERNALDATE \"17-Jul-1996 02:44:25 -0700\" RFC822.SIZE 4286 ENVELOPE (\"Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\" \"IMAP4rev1 WG mtg summary and minutes\" ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((NIL NIL \"imap\" \"cac.washington.edu\")) ((NIL NIL \"minutes\" \"CNRI.Reston.VA.US\")(\"John Klensin\" NIL \"KLENSIN\" \"MIT.EDU\")) NIL NIL \"\u003cB27397-0100000@cac.washington.edu\u003e\") BODY (\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL \"7BIT\" 3028 92))\nData(Fetch { seq: 12, items: [Flags([Flag(Seen)]), InternalDate(1996-07-17T02:44:25-07:00), Rfc822Size(4286), Envelope(Envelope { date: NString(Some(Quoted(Quoted(\"Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\")))), subject: NString(Some(Quoted(Quoted(\"IMAP4rev1 WG mtg summary and minutes\")))), from: [Address { name: NString(Some(Quoted(Quoted(\"Terry Gray\")))), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"gray\")))), host: NString(Some(Quoted(Quoted(\"cac.washington.edu\")))) }], sender: [Address { name: NString(Some(Quoted(Quoted(\"Terry Gray\")))), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"gray\")))), host: NString(Some(Quoted(Quoted(\"cac.washington.edu\")))) }], reply_to: [Address { name: NString(Some(Quoted(Quoted(\"Terry Gray\")))), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"gray\")))), host: NString(Some(Quoted(Quoted(\"cac.washington.edu\")))) }], to: [Address { name: NString(None), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"imap\")))), host: NString(Some(Quoted(Quoted(\"cac.washington.edu\")))) }], cc: [Address { name: NString(None), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"minutes\")))), host: NString(Some(Quoted(Quoted(\"CNRI.Reston.VA.US\")))) }, Address { name: NString(Some(Quoted(Quoted(\"John Klensin\")))), adl: NString(None), mailbox: NString(Some(Quoted(Quoted(\"KLENSIN\")))), host: NString(Some(Quoted(Quoted(\"MIT.EDU\")))) }], bcc: [], in_reply_to: NString(None), message_id: NString(Some(Quoted(Quoted(\"\u003cB27397-0100000@cac.washington.edu\u003e\")))) }), Body(Single { body: Body { basic: BasicFields { parameter_list: [(Quoted(Quoted(\"CHARSET\")), Quoted(Quoted(\"US-ASCII\")))], id: NString(None), description: NString(None), content_transfer_encoding: Quoted(Quoted(\"7BIT\")), size: 3028 }, specific: Text { subtype: Quoted(Quoted(\"PLAIN\")), number_of_lines: 92 } }, extension_data: None })]+ })\n// * 12 FETCH (FLAGS (\\Seen) INTERNALDATE \"17-Jul-1996 02:44:25 -0700\" RFC822.SIZE 4286 ENVELOPE (\"Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\" \"IMAP4rev1 WG mtg summary and minutes\" ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((NIL NIL \"imap\" \"cac.washington.edu\")) ((NIL NIL \"minutes\" \"CNRI.Reston.VA.US\")(\"John Klensin\" NIL \"KLENSIN\" \"MIT.EDU\")) NIL NIL \"\u003cB27397-0100000@cac.washington.edu\u003e\") BODY (\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL \"7BIT\" 3028 92))\n\n// a003 OK FETCH completed\nStatus(Ok { tag: Some(Tag(\"a003\")), code: None, text: Text(\"FETCH completed\") })\n// a003 OK FETCH completed\n\n// a004 fetch 12 body[header]\nCommand { tag: Tag(\"a004\"), body: Fetch { sequence_set: SequenceSet([Single(Value(12))]+), macro_or_item_names: MessageDataItemNames([BodyExt { section: Some(Header(None)), partial: None, peek: false }]), uid: false } }\n// a004 FETCH 12 BODY[HEADER]\n\n// * 12 FETCH (BODY[HEADER] {342}\n// Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\n// From: Terry Gray \u003cgray@cac.washington.edu\u003e\n// Subject: IMAP4rev1 WG mtg summary and minutes\n// To: imap@cac.washington.edu\n// cc: minutes@CNRI.Reston.VA.US, John Klensin \u003cKLENSIN@MIT.EDU\u003e\n// Message-Id: \u003cB27397-0100000@cac.washington.edu\u003e\n// MIME-Version: 1.0\n// Content-Type: TEXT/PLAIN; CHARSET=US-ASCII\n// \n// )\nData(Fetch { seq: 12, items: [BodyExt { section: Some(Header(None)), origin: None, data: NString(Some(Literal(Literal { data: b\"Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\\r\\nFrom: Terry Gray \u003cgray@cac.washington.edu\u003e\\r\\nSubject: IMAP4rev1 WG mtg summary and minutes\\r\\nTo: imap@cac.washington.edu\\r\\ncc: minutes@CNRI.Reston.VA.US, John Klensin \u003cKLENSIN@MIT.EDU\u003e\\r\\nMessage-Id: \u003cB27397-0100000@cac.washington.edu\u003e\\r\\nMIME-Version: 1.0\\r\\nContent-Type: TEXT/PLAIN; CHARSET=US-ASCII\\r\\n\\r\\n\" }))) }]+ })\n// * 12 FETCH (BODY[HEADER] {342}\n// Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\n// From: Terry Gray \u003cgray@cac.washington.edu\u003e\n// Subject: IMAP4rev1 WG mtg summary and minutes\n// To: imap@cac.washington.edu\n// cc: minutes@CNRI.Reston.VA.US, John Klensin \u003cKLENSIN@MIT.EDU\u003e\n// Message-Id: \u003cB27397-0100000@cac.washington.edu\u003e\n// MIME-Version: 1.0\n// Content-Type: TEXT/PLAIN; CHARSET=US-ASCII\n// \n// )\n\n// a004 OK FETCH completed\nStatus(Ok { tag: Some(Tag(\"a004\")), code: None, text: Text(\"FETCH completed\") })\n// a004 OK FETCH completed\n\n// a005 store 12 +flags \\deleted\nCommand { tag: Tag(\"a005\"), body: Store { sequence_set: SequenceSet([Single(Value(12))]+), kind: Add, response: Answer, flags: [Deleted], uid: false } }\n// a005 STORE 12 +FLAGS (\\Deleted)\n\n// * 12 FETCH (FLAGS (\\Seen \\Deleted))\nData(Fetch { seq: 12, items: [Flags([Flag(Seen), Flag(Deleted)])]+ })\n// * 12 FETCH (FLAGS (\\Seen \\Deleted))\n\n// a005 OK +FLAGS completed\nStatus(Ok { tag: Some(Tag(\"a005\")), code: None, text: Text(\"+FLAGS completed\") })\n// a005 OK +FLAGS completed\n\n// a006 logout\nCommand { tag: Tag(\"a006\"), body: Logout }\n// a006 LOGOUT\n\n// * BYE IMAP4rev1 server terminating connection\nStatus(Bye { code: None, text: Text(\"IMAP4rev1 server terminating connection\") })\n// * BYE IMAP4rev1 server terminating connection\n\n// a006 OK LOGOUT completed\nStatus(Ok { tag: Some(Tag(\"a006\")), code: None, text: Text(\"LOGOUT completed\") })\n// a006 OK LOGOUT completed\n```\n\n# FAQ\n\n\u003cdetails\u003e\n\u003csummary\u003eHow does \u003ccode\u003eimap-codec\u003c/code\u003e compare to \u003ccode\u003eimap-proto\u003c/code\u003e?\u003c/summary\u003e\n\n`imap-codec` provides low-level parsing and serialization support for IMAP4rev1, similar to [`imap-proto`].\nThe most significant differences are\nserver support,\nthe split into `imap-codec` and `imap-types`,\nmisuse resistance (affecting API design),\nand (real-world) test coverage.\n\nNo matter if implementing a client- or a server, you need the full set of IMAP type definitions.\nWhen you send a command with a specific [`Tag`], you expect a command completion response with the same [`Tag`].\nThus, commands and responses must work well together (and are best provided by a single crate).\nAs far as I know, `imap-proto` doesn't provide types that would be reusable in a generic server implementation.\n`imap-types` provides type definitions for client- and server implementations.\n\nAs a client developer, you will never parse commands or serialize responses.\nAs a server developer, you will never serialize commands or parse responses.\nThus, you only need \"half of\" the set of parsers and serializers.\nAs far as I know, `imap-proto` provides the \"client half\" only.\n`imap-codec` provides both the \"client half\" and the \"server half\".\n\nSeparating types and codecs increases cohesion and (hopefully) paves the way for IMAP crates that operate at higher levels.\nHowever, the maintenance cost of two crates, `imap-types` and `imap-codec`, could be higher than for `imap-proto`.\n\nGenerally, `imap-codec` has a more extensive API surface than `imap-proto` and could be [more challenging to use].\nIn return, it guarantees that you always construct valid messages and aims to make IMAP usable even for people with less IMAP experience.\nFor example, `imap-codec` has [build-in support for IMAP literals] and ensures to always use [a correct representation for strings].\n\n`imap-codec` has a high test coverage and is fuzz-tested to ensure properties such as invertibility, misuse-resistance, etc.\nYou should be unable to crash the library or generate messages that can't be parsed.\nHowever, \"interoperability can not be tested in a vacuum\" [^1].\n`imap-proto` already succeeded in production as it is (transitively) used in [`imap`], [`async-imap`], and [Delta Chat].\nIt could solve more real-world quirks, provide more IMAP extensions that matter in practice, or generally have a more mature interoperability story.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eHave you considered contributing to \u003ccode\u003eimap-proto\u003c/code\u003e?\u003c/summary\u003e\n\nI created `imap-codec` because I needed [server-side support](https://github.com/Email-Analysis-Toolkit/fake-mail-server).\nThe intention was to eventually merge `imap-codec` into `imap-proto` as soon as it's \"ready\".\nI even did a bit of [preparation work](https://github.com/djc/tokio-imap/graphs/contributors).\nHowever, the different types (and philosophy, maybe), made merging non-trivial.\nBoth projects can learn from each other and align on their goals.\nStill, joining forces would require a fair amount of work from everyone, and I wonder if we are willing (and have the resources) to start such an endeavor.\n\u003c/details\u003e\n\n# License\n\nThis crate is dual-licensed under Apache 2.0 and MIT terms.\n\n# Thanks\n\nThanks to the [NLnet Foundation](https://nlnet.nl/) for supporting imap-codec through their [NGI Assure](https://nlnet.nl/assure/) program!\n\n\u003cdiv align=\"right\"\u003e\n    \u003cimg height=\"100px\" src=\"https://user-images.githubusercontent.com/8997731/215262095-ab12d43a-ca8a-4d44-b79b-7e99ab91ca01.png\"/\u003e\n    \u003cimg height=\"100px\" src=\"https://user-images.githubusercontent.com/8997731/221422192-60d28ed4-10bb-441e-957d-93af58166707.png\"/\u003e\n    \u003cimg height=\"100px\" src=\"https://user-images.githubusercontent.com/8997731/215262235-0db02da9-7c6c-498e-a3d2-7ea7901637bf.png\"/\u003e\n\u003c/div\u003e\n\n[rock-solid]: https://github.com/duesee/imap-codec/tree/main/imap-codec/fuzz\n[well-documented]: https://docs.rs/imap-codec/latest/imap_codec/\n[Matrix]: https://matrix.to/#/#imap-codec:matrix.org\n[IMAP4rev1]: https://tools.ietf.org/html/rfc3501\n[formal syntax]: https://tools.ietf.org/html/rfc3501#section-9\n[extensions]: https://docs.rs/imap-codec/latest/imap_codec/#features\n[cargo fuzz]: https://github.com/rust-fuzz/cargo-fuzz\n[parse_command]: https://github.com/duesee/imap-codec/blob/main/examples/parse_command.rs\n\n[`imap-codec`]: imap-codec\n[`imap-types`]: imap-types\n[`imap-next`]: https://github.com/duesee/imap-next\n[`imap`]: https://github.com/jonhoo/rust-imap\n[`imap-proto`]: https://crates.io/crates/imap-proto\n[`async-imap`]: https://github.com/async-email/async-imap\n[Delta Chat]: https://delta.chat\n\n[core types]: https://docs.rs/imap-types/latest/imap_types/core/index.html\n[`Command`]: https://docs.rs/imap-types/latest/imap_types/command/struct.Command.html\n[`Response`]: https://docs.rs/imap-types/latest/imap_types/response/enum.Response.html\n[`Tag`]: https://docs.rs/imap-types/latest/imap_types/core/struct.Tag.html\n[`BodyStructure`]: https://docs.rs/imap-types/latest/imap_types/body/enum.BodyStructure.html\n[more challenging to use]: https://github.com/duesee/imap-codec/tree/main/imap-types#examples\n[a correct representation for strings]: https://github.com/duesee/imap-codec/tree/main/imap-types#examples\n[build-in support for IMAP literals]: https://docs.rs/imap-codec/latest/imap_codec/encode/struct.Encoded.html\n[IMAP servers with imap-codec]: https://github.com/Email-Analysis-Toolkit/fake-mail-server\n[^1]: https://datatracker.ietf.org/doc/html/rfc2683\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduesee%2Fimap-codec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduesee%2Fimap-codec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduesee%2Fimap-codec/lists"}