{"id":51645941,"url":"https://github.com/zerodrop-dev/zerodrop-ruby","last_synced_at":"2026-07-20T05:00:48.241Z","repository":{"id":371182683,"uuid":"1299624568","full_name":"zerodrop-dev/zerodrop-ruby","owner":"zerodrop-dev","description":"Ruby SDK for email verification in CI — OTPs and magic links auto-extracted. RSpec, Minitest, Capybara. No regex, no Docker.","archived":false,"fork":false,"pushed_at":"2026-07-13T21:39:00.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-17T02:26:50.577Z","etag":null,"topics":["capybara","email-testing","magic-link","otp","rails","rspec","ruby","testing-tools"],"latest_commit_sha":null,"homepage":"https://zerodrop.dev","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zerodrop-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-13T18:40:10.000Z","updated_at":"2026-07-16T06:58:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zerodrop-dev/zerodrop-ruby","commit_stats":null,"previous_names":["zerodrop-dev/zerodrop-ruby"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/zerodrop-dev/zerodrop-ruby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodrop-dev%2Fzerodrop-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodrop-dev%2Fzerodrop-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodrop-dev%2Fzerodrop-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodrop-dev%2Fzerodrop-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerodrop-dev","download_url":"https://codeload.github.com/zerodrop-dev/zerodrop-ruby/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodrop-dev%2Fzerodrop-ruby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35602805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-18T02:00:07.223Z","response_time":61,"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":["capybara","email-testing","magic-link","otp","rails","rspec","ruby","testing-tools"],"created_at":"2026-07-13T23:00:15.197Z","updated_at":"2026-07-20T05:00:48.223Z","avatar_url":"https://github.com/zerodrop-dev.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zerodrop\n\n[![Gem Version](https://badge.fury.io/rb/zerodrop.svg)](https://rubygems.org/gems/zerodrop)\n[![CI](https://github.com/zerodrop-dev/zerodrop-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/zerodrop-dev/zerodrop-ruby/actions/workflows/ci.yml)\n[![license](https://img.shields.io/github/license/zerodrop-dev/zerodrop-ruby.svg)](LICENSE)\n\nEmail verification infrastructure for CI pipelines.\n\nSend a verification email. Catch it at the edge. Get `email.otp` and `email.magic_link` back — auto-extracted, no regex, no Docker, no signup.\n\n```ruby\nemail = mail.wait_for_latest(inbox, timeout: 15)\n\nemail.otp        # =\u003e \"123456\" — auto-extracted\nemail.magic_link # =\u003e \"https://...\" — no regex needed\n```\n\n**[Documentation](https://docs.zerodrop.dev)** · [GitHub](https://github.com/zerodrop-dev) · [Status](https://zerodrop.instatus.com)\n\n## Install\n\n```bash\ngem install zerodrop\n```\n\nOr in your Gemfile:\n\n```ruby\ngem \"zerodrop\", group: :test\n```\n\nZero runtime dependencies. Ruby 3.0+.\n\n## Quick start\n\n```ruby\nrequire \"zerodrop\"\n\nmail = ZeroDrop::Client.new\ninbox = mail.generate_inbox\n# =\u003e \"swift-x7k29ab@zerodrop-sandbox.online\"\n\n# Trigger your app's email flow with the inbox address...\n\nemail = mail.wait_for_latest(inbox, timeout: 15)\n\nemail.subject    # =\u003e \"Verify your email\"\nemail.otp        # =\u003e \"123456\" — auto-extracted, no regex\nemail.magic_link # =\u003e \"https://...\" — auto-extracted\n```\n\n## RSpec + Capybara\n\n```ruby\nRSpec.describe \"Signup email verification\", type: :system do\n  let(:mail) { ZeroDrop::Client.new }\n\n  it \"verifies the account via emailed OTP\" do\n    inbox = mail.generate_inbox\n\n    visit \"/signup\"\n    fill_in \"Email\", with: inbox\n    fill_in \"Password\", with: \"TestPassword123!\"\n    click_button \"Create account\"\n\n    email = mail.wait_for_latest(inbox, timeout: 15)\n\n    expect(email.otp).not_to be_nil\n    fill_in \"Code\", with: email.otp\n    click_button \"Verify\"\n\n    expect(page).to have_current_path(\"/dashboard\")\n  end\nend\n```\n\n## Minitest\n\n```ruby\nrequire \"minitest/autorun\"\nrequire \"zerodrop\"\n\nclass SignupTest \u003c Minitest::Test\n  def test_email_verification\n    mail = ZeroDrop::Client.new\n    inbox = mail.generate_inbox\n\n    # Trigger signup with inbox...\n\n    email = mail.wait_for_latest(inbox, timeout: 15)\n\n    refute_nil email.otp\n    assert_match(/\\A\\d{6}\\z/, email.otp)\n  end\nend\n```\n\n## Email filtering\n\nFilter by sender, subject, body, or extracted fields:\n\n```ruby\nemail = mail.wait_for_latest(\n  inbox,\n  timeout: 15,\n  filter: ZeroDrop::Filter.new(\n    from: \"noreply@yourapp.com\",\n    subject: \"Verify\",\n    has_otp: true\n  )\n)\n```\n\nAll string filters are case-insensitive partial matches.\n\n## Magic link flows\n\n```ruby\nemail = mail.wait_for_latest(\n  inbox,\n  timeout: 15,\n  filter: ZeroDrop::Filter.new(has_magic_link: true)\n)\n\nvisit email.magic_link\nexpect(page).to have_current_path(\"/dashboard\")\n```\n\n## Parallel test runs\n\n`generate_inbox` runs locally — no network request, no collisions:\n\n```ruby\n# parallel_tests, flatware, turbo_tests — all safe\n# Each process gets isolated inboxes automatically\ninbox = mail.generate_inbox # unique every call\n```\n\n## Error handling\n\n```ruby\nbegin\n  email = mail.wait_for_latest(inbox, timeout: 15)\nrescue ZeroDrop::TimeoutError\n  # No email arrived — check your app is sending correctly\nrescue ZeroDrop::AuthError\n  # Invalid API key\nrescue ZeroDrop::NetworkError =\u003e e\n  # Transport failure — e.message includes status page link\nend\n```\n\n## Workspaces\n\n```ruby\nmail = ZeroDrop::Client.new(api_key: ENV[\"ZERODROP_API_KEY\"])\n```\n\n## Self-hosted\n\n```ruby\nmail = ZeroDrop::Client.new(base_url: \"https://your-instance.yourdomain.com\")\n```\n\n## API\n\n| Method | Description |\n|---|---|\n| `Client.new(api_key: nil, base_url: ...)` | Create a client. No args = free sandbox mode. |\n| `#generate_inbox` | Instant inbox address. No network request. |\n| `#fetch_latest(inbox, filter: nil)` | Latest matching email or nil. |\n| `#wait_for_latest(inbox, timeout: 10, poll_interval: 2, filter: nil)` | Block until email arrives. |\n\n## Free vs Workspace\n\n|  | Free | Workspace |\n|---|---|---|\n| Inbox generation | ✓ | ✓ |\n| OTP auto-extraction | ✓ | ✓ |\n| Magic link extraction | ✓ | ✓ |\n| Email filtering | ✓ | ✓ |\n| Email retention | 30 min | Extended |\n| Custom domains | ✗ | ✓ |\n\nGet a Workspace at [zerodrop.dev](https://zerodrop.dev)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodrop-dev%2Fzerodrop-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerodrop-dev%2Fzerodrop-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodrop-dev%2Fzerodrop-ruby/lists"}