{"id":15616648,"url":"https://github.com/saibotsivad/jmap-fetch-test-email","last_synced_at":"2026-08-16T13:31:51.379Z","repository":{"id":57281161,"uuid":"371067051","full_name":"saibotsivad/jmap-fetch-test-email","owner":"saibotsivad","description":"Wait for and fetch a sent email over JMAP, e.g. for integration tests of tools that send emails.","archived":false,"fork":false,"pushed_at":"2022-10-04T16:57:58.000Z","size":15,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-08-13T19:35:31.217Z","etag":null,"topics":["email","jmap","testing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saibotsivad.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-26T14:39:25.000Z","updated_at":"2023-11-03T22:38:43.000Z","dependencies_parsed_at":"2022-09-19T21:18:38.896Z","dependency_job_id":null,"html_url":"https://github.com/saibotsivad/jmap-fetch-test-email","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/saibotsivad/jmap-fetch-test-email","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saibotsivad%2Fjmap-fetch-test-email","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saibotsivad%2Fjmap-fetch-test-email/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saibotsivad%2Fjmap-fetch-test-email/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saibotsivad%2Fjmap-fetch-test-email/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saibotsivad","download_url":"https://codeload.github.com/saibotsivad/jmap-fetch-test-email/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saibotsivad%2Fjmap-fetch-test-email/sbom","scorecard":{"id":795437,"data":{"date":"2025-08-11","repo":{"name":"github.com/saibotsivad/jmap-fetch-test-email","commit":"2bf2c377aefb170a6b589efcdb926105b5e8b1b0"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/6 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T08:48:38.144Z","repository_id":57281161,"created_at":"2025-08-23T08:48:38.144Z","updated_at":"2025-08-23T08:48:38.144Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36715911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-08-06T04:43:03.162Z","status":"online","status_checked_at":"2026-08-16T02:00:06.462Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["email","jmap","testing"],"created_at":"2024-10-03T07:20:28.974Z","updated_at":"2026-08-16T13:31:51.360Z","avatar_url":"https://github.com/saibotsivad.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JMAP: Fetch Test Email\n\nWait for and fetch a sent email over [JMAP](https://jmap.io/), e.g. for integration tests of email-sending tools.\n\n## Install\n\nThe usual way:\n\n```bash\nnpm install jmap-fetch-test-email\n```\n\n## Example\n\nIf you have an integration test where a user-login event sends an email, and you want to assert that the email arrived  and contained some property:\n\n```js\nimport assert from 'node:assert'\nimport { fetchEmail } from 'jmap-fetch-test-email'\n\nconst email = await fetchEmail({\n\tusername: 'you@site.com',\n\ttoken: 'battery-horse-staple',\n\thostname: 'api.fastmail.com',\n\tsubject: 'New login alert!'\n})\nassert.ok(email, 'the email was found')\n// assert other things about the email\n```\n\n## Searching\n\nYou'll probably need a bit more control on searching for the correct email, so there are a few options: `subject`, `body`, or `find`.\n\nNote that at least one of the three search options must be specified.\n\n### `subject`\n\nYou can specify a string for exact comparison:\n\n```js\nfetchEmail({\n\tusername: '...',\n\ttoken: '...',\n\thostname: '...',\n\tsubject: 'New login alert!'\n})\n```\n\nOr a regex for more complex searches:\n\n```js\nfetchEmail({\n\tusername: '...',\n\ttoken: '...',\n\thostname: '...',\n\tsubject: /^Order \\d+ is ready$/\n})\n```\n\n\u003e **Note:** if you modify `emailGetProperties` you must make sure it includes `subject` or an error will be thrown.\n\n### `body`\n\nSimilarly, you can search for a string in the HTML and plaintext body.\n\nYou can specify a string, which will use the `String.includes` method:\n\n```js\nfetchEmail({\n\tusername: '...',\n\ttoken: '...',\n\thostname: '...',\n\tbody: 'Login attempt from 192.168.1.1'\n})\n```\n\nOr specify a regex for more complex searches:\n\n```js\nfetchEmail({\n\tusername: '...',\n\ttoken: '...',\n\thostname: '...',\n\tbody: /^Login attempt from \\d{1-3}/\n})\n```\n\n\u003e **Note:** if you modify `emailGetProperties` you must make sure it includes `htmlBody` and `bodyValues` and ensure that you do not set `emailGetFetchHtmlBodyValues` to false (the default is `true`), or an error will be thrown.\n\n### `find`\n\nIf you need something more complex, you can specify a function which will be called on all retry attempts, and will contain the full list of fetched emails.\n\nSimply return the email, if you find it, and the function will complete.\n\nFor example, using [cheerio](https://github.com/cheeriojs/cheerio) to traverse the HTML:\n\n```js\nimport cheerio from 'cheerio'\n\nfetchEmail({\n\tusername: '...',\n\ttoken: '...',\n\thostname: '...',\n\tfind: emails =\u003e {\n\t\tconst email = emails.find(email =\u003e {\n\t\t\tconst $ = cheerio.load(email._html)\n\t\t\tconst ipAddress = $('.ip-address', '#login').text()\n\t\t\treturn ipAddress === '192.168.1.1'\n\t\t})\n\t\treturn email\n\t}\n})\n```\n\n\u003e **Note:** the property `_html` is not part of the JMAP specs, it is a convenience property added by this library so that you don't have to pull out the `bodyValues` manually yourself.\n\n### Options\n\nThe full list of options you can pass in.\n\n#### `username: String` *required*\n\nThe JMAP username, typically the email address.\n\n#### `token: String`\n\nThe JMAP token, used for `Bearer` authentication.\n\n#### `password: String`\n\nThe JMAP password, used for `Basic` authentication (this is uncommon).\n\n#### `hostname: String` *required*\n\nThe hostname of the JMAP server.\n\n#### `subject: (String|RegExp)`\n\nA string or regular expression used to find an email by matching to the email subject text.\n\n#### `body: (String|RegExp)`\n\nA string or regular expression used to find an email by matching to the email plaintext or HTML text--both are checked where available.\n\n#### `find: Function(Array\u003cObject\u003e)`\n\nA function used to find an email, it is passed the full list of emails after every retry fetch.\n\n#### `mailboxName: String` (default: `inbox`)\n\nThe mailbox name to look in for emails.\n\n#### `emailQueryLimit: Integer` (default: `5`)\n\nThe limit to specify when fetching emails from the JMAP server.\n\n#### `emailGetProperties: Array\u003cString\u003e` (default: *see below*)\n\nThe default properties that will be fetched are:\n\n- `id`\n- `subject`\n- `receivedAt`\n- `htmlBody`\n- `sender`\n- `bodyValues`\n\nIf you use the `subject` property to find your email, make sure this list includes `subject` or an error will be thrown.\n\nIf you use the `body` property to find your email, make sure this includes `htmlBody` and `bodyValues`, and ensure that you do not set `emailGetFetchHtmlBodyValues` to false (the default is `true`), or an error will be thrown.\n\n#### `emailGetFetchHtmlBodyValues: String` (default: `true`)\n\nIf you don't want to return the HTML body in the JMAP fetch request, you can set this to `false` to disable it.\n\n#### `maximumRetryCount: Integer` (default: `10`)\n\nThe maximum number of retries before giving up.\n\n#### `retryDelayMillis: Integer` (default: `3000`)\n\nThe number of milliseconds to wait between retries.\n\n## License\n\nPublished and released with love under the [Very Open License](http://veryopenlicense.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaibotsivad%2Fjmap-fetch-test-email","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaibotsivad%2Fjmap-fetch-test-email","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaibotsivad%2Fjmap-fetch-test-email/lists"}