feat(inboxes): add support for the Inboxes API
Summary
Add the Inboxes API to the Ruby SDK. The PR covers the 26 routes under /inboxes. The names follow the Node SDK preview (resend.inboxes.*) and the nested modules of this SDK.
Resend::Inboxes:create,list,get,update,remove.gettakes an inbox ID or an email address.Resend::Inboxes::Agent:get,update.Resend::Inboxes::Labels:list,create,update,remove.Resend::Inboxes::Threads:list,search,get,update,remove. Array filters (folders,labels,from,to,cc,bcc) go out as one comma-separated value.Resend::Inboxes::Threads::Emails:list,get,reply,forward. Reply and forward acceptattachments.Resend::Inboxes::Drafts:list,create,get,update,remove,send. Create and update acceptattachments. On update,attachmentsreplaces every attachment on the draft, and[]removes them all.
Nested methods take one params hash with the path IDs (inbox_id, thread_id, email_id, label_id, draft_id). A missing path ID raises ArgumentError, as in Contacts::Segments. The other keys go to the API as they are, so nil clears a field where the API allows it.
Thread update accepts read, folder, add_label_ids and remove_label_ids. The API removed label_id, so the SDK does not document it.
Draft create, draft send, reply and forward take options: { idempotency_key: "..." }, the same way as Resend::Emails.send. The params hash then needs braces, as with Emails.send.
Reply, forward and draft send accept headers, a hash of string values, as on Resend::Emails.send. Draft send sends a body only when headers is set. In-Reply-To, References and Reply-To are reserved, and the API returns 422 for them.
The PR also adds examples/inboxes.rb and bumps the version to 1.18.0.
Depends on
- The spec PR resend/resend-openapi#125.
- monorepo #12396 (merged) for
add_label_idsandremove_label_idson thread update. - monorepo #12481 (merged) for draft attachments.
- monorepo #12509 (merged) for custom
headerson reply, forward and draft send. - monorepo #11768 (merged) for the
Idempotency-Keyheader on draft create, draft send, reply and forward. - monorepo #12152 for the attachment IDs of sent thread emails. The SDK passes the response through, so no code depends on it.
- The tone presets text merges after resend-monorepo #12580, #12634 and #12635 are deployed.
Verification
bundle install && bundle exec rubocop && bundle exec rake spec
Result: rubocop has no offenses. 466 examples, 0 failures.
End to end against https://api.resend.com with the shared test team, through the built code (bundle exec ruby -I lib e2e.rb). 39 calls, 0 failures.
- Inboxes: list, get by ID, get by email address (upper case), update and restore. Create returns the expected 403
You have reached the inbox limit of your plan. - Agent: get, update and restore.
- Labels: create with a lowercase color (returned as
#E93D82), list, update, remove. - Threads: search by subject token, search with
from,has_attachmentandstart_date, list withfoldersandread, list bylabels, get, updatereadandfolder, remove. - Thread labels:
add_label_idsadds the label,remove_label_idsremoves it, and the label still exists after. A body with the same ID in both arrays returns 422. - Thread emails: list, get, reply, reply with a base64 text attachment, forward to
delivered@resend.dev. - Drafts: create with one attachment, get and list show it, update replaces it with two, update with
[]empties it, send with one attachment. A second draft created and removed.
Idempotency: a draft created twice with one key gives one draft and idempotent-replayed: true. A draft sent twice with one key returns the same email id. The same key with a different body returns 409.
Headers: a reply with X-Ticket-Id goes to delivered@resend.dev. A draft sends with X-Ticket-Id. A reply with reply-to in headers returns 422.
examples/inboxes.rb also runs against the test inbox, with the inbox create and remove replaced by the existing inbox.
The e2e script removed every label, thread and draft it made. It is not in this PR.
Not in this PR
- Webhook event types. The Ruby SDK has no typed webhook events, and
Resend::Webhooks.verifyworks for theinbox.*events as it is. - Sender authentication fields. They are not on the API main branch.
- README and CHANGELOG entries. The changelog is written at release time.