The Ruby email gem: receive, read and send mail from Ruby.
Receive email in Ruby without a mail server or an inbound relay. Create an address, wait for the next message, read its text, HTML and attachments, and reply in the thread. Mail is stored encrypted and opened by your Ruby process, with no dependencies beyond the standard library.
mailcycle on RubyGems · Ruby 3.1 or later · Apache 2.0 · Free tier, no card
Receive and send email in Ruby.
Sign in, create an address, wait for a message and answer it. That is the whole loop, and it is the same loop whether the mail is a sign-up code, a customer or a receipt.
- 1Install mailcycle and set MAILCYCLE_PHRASE to your account's recovery phrase.
- 2Create an address with mc.addresses.create. It receives mail straight away.
- 3Wait for the next message with mc.messages.wait_for, or take it from a webhook.
- 4Reply with mc.messages.send, threaded under the original.
The whole email API, from Ruby.
Everything the Mailcycle console can do is in the gem: addresses, inbound mail, sending, webhooks, events, API keys and devices.
Create email addresses from Ruby
mc.addresses.create mints a new address on a shared domain, or on your own domain from Scale, and it receives mail at once. Give it a prefix and a label sealed on your machine.
Receive email and wait for it
mc.messages.wait_for listens on the event stream and returns the next matching message, filtered by sender or subject, opened and ready to read. Without a stream it checks every five seconds.
Read and parse incoming email
mc.messages.all and .attachment return the sender, subject, plain text, the original HTML, a safe HTML with remote images and trackers removed, and every attachment as bytes.
Send email and reply in the thread
mc.messages.send sends from an address your account owns, with up to ten files. Pass the message you are answering and the threading headers are filled in.
Inbound email webhooks
Register a URL and every message.received event is POSTed to it, signed with HMAC-SHA256 and retried. Mailcycle.verify_webhook_signature checks the signature in one line.
A live event stream
mc.events.stream carries the same events over a WebSocket the moment they happen, and reconnects after a drop. Events carry ids, never content.
Test email verification in RSpec, Minitest and Capybara.
Create an address in a before block, fill your sign-up form with Capybara, then call wait_for and read the code from message.text. A timeout raises Mailcycle::ApiError with code "timeout", so the spec fails with a reason instead of hanging.
- A real address on a real domain, so the mail goes through the same path your users' does.
- One call blocks until the message lands, filtered by subject or sender, with a timeout you set.
- Text, HTML and attachments come back parsed, so pulling out a code or a link is a regular expression.
- Mail received from the moment you start waiting counts, even if it lands before the stream is up.
Handle incoming email in Rails, Sinatra and Hanami.
Rather than polling, let the mail come to you. A webhook POSTs each event to your URL the moment it happens, signed so you can prove it came from Mailcycle, and retried if your server is down.
Events carry ids, never content. Fetch the message by id and it is opened in your code, exactly as it would be otherwise. Webhooks are on Operator and above.
Instead of the mail gem and Action Mailbox.
Action Mailer and the mail gem send through an SMTP server you configure. Action Mailbox receives, but only through an ingress: a relay from Postfix or Exim, or an inbound service that forwards to your app.
Here an address is one call, there is no ingress to configure, and mail arrives on a webhook or through wait_for. Each message comes back parsed: sender, subject, text, safe_html with remote content removed, and attachments as binary strings.
It is not a bulk sender. If you need newsletters or high volumes of transactional mail, use a sending service for that; Mailcycle is for addresses your code owns and the mail that comes back to them.
Mail is opened in your Ruby code, not on our servers.
Each address has a key pair derived from your recovery phrase. Incoming mail is sealed to its public key before anything is written down, and the gem derives the private key on your machine to open it.
- Signing in proves you hold the key by answering a challenge, so the phrase never crosses the wire.
- Bodies, attachments, address labels and API key names are all sealed. The server stores ciphertext.
- Mail sealed by one SDK opens in every other, and in the app, because they share one published format.
- The gem is checked against Mailcycle's published test vectors, including the cases that must be refused.
- Because the server cannot read mail, there is no server-side search. Search runs where the mail is opened.
What developers build with the Ruby SDK.
It runs in Rails apps, Sidekiq jobs, Rake tasks and scripts: anywhere Ruby code needs an email address of its own.
End-to-end tests for sign-up and login
Verification emails, one-time passcodes, magic links, password resets and invitations, checked by a real test in RSpec, Minitest and Capybara.
A support or orders inbox your code answers
Give an address to a queue, read what customers send, and reply from the address they wrote to, threaded under their message.
Receipts, invoices and alerts as data
Point suppliers, monitoring and other services at an address and pull the text and attachments straight into your own records.
An address per customer, job or device
Mint addresses on demand and keep each stream of mail separate, with its own label, and delete one when the job is done.
Building an AI agent? It can have an inbox too, through the Mailcycle MCP server, without writing any Ruby at all.
Ruby SDK at a glance.
Maintained by Mailcycle, the team that runs the API.
| Package | mailcycle |
|---|---|
| Registry | RubyGems |
| Install with | gem, or bundle add mailcycle |
| Needs | Ruby 3.1 or later |
| Also | No dependencies beyond Ruby's own standard library. |
| Licence | Apache 2.0, free to use in your own applications |
| API | JSON over HTTPS at api.mailcycle.email |
| Guide | The Ruby guide in the docs |
What each plan unlocks. Free receives mail. A signed-in session sends from Personal up. API keys and webhooks start at Operator, and sending from an API key at Scale. See pricing.
Ruby email SDK questions.
The same API in every language you use.
Nine SDKs share one encryption format, so a message created by one opens in all the others.