Skip to content

Repository files navigation

Ukdah

Turn raw email and mbox files into readable MIME messages, without a mail client.

Gem version CI status Ruby 3.1 or newer MIT license

Features · Installation · Quick start · Mailboxes and threads · Scope and safety


Ukdah is a dependency-free Ruby parser for RFC 5322 messages and MIME bodies. It exposes headers, decoded text, attachments, diagnostics, and conversation structure without connecting to IMAP, POP, or SMTP. The name comes from ι Cancri and the Arabic ʿuqdah, “knot.”

Features

  • Folded headers, encoded words, address groups, and RFC 2231 parameters
  • Multipart MIME trees with base64 and quoted-printable transfer decoding
  • Attachment and inline-part discovery, including cid: identifiers
  • Tolerant parsing with diagnostics for damaged messages
  • mbox splitting, Message-ID threading, and quote segmentation
  • Injectable charset decoder; no runtime dependencies

Installation

Add gem "ukdah" to your Gemfile and run bundle install, or install directly:

gem install ukdah

Requires Ruby 3.1 or newer.

Quick start

require "ukdah"

raw = "From: Ada <ada@example.com>\r\n" \
      "Subject: Hello\r\n" \
      "Content-Type: text/plain; charset=UTF-8\r\n\r\n" \
      "A short note."

message = Ukdah::Message.parse(raw)
puts message.from.first.email           # => ada@example.com
puts message.subject                    # => Hello
puts message.decoded(message.text_part) # => A short note.
puts message.diagnostics

message.attachments returns MIME parts with decoded transfer bodies. Treat their filenames as untrusted input; choose a safe destination name before writing one to disk.

Mailboxes and threads

messages = Ukdah::Mbox.each(File.binread("archive.mbox")).to_a
threads = Ukdah::Thread_.build(messages)

Mbox.each accepts bytes or an IO object and yields parsed messages. Thread_.build groups messages using Message-ID, References, and In-Reply-To.

Charset decoding

Pass a decoder when the application has its own charset strategy:

text = message.decoded(message.text_part, decoder: ->(bytes, charset) {
  bytes.force_encoding(charset || "UTF-8").encode("UTF-8", invalid: :replace, undef: :replace)
})

Without a custom decoder, Ukdah uses Ruby's Encoding support.

Scope and safety

Ukdah parses messages only; it does not fetch, send, or sanitize HTML mail. Sanitize message.html_part before display. For design rationale, see parsing-only scope and decoder injection.

Development

bundle install
bundle exec rake
gem build --strict ukdah.gemspec

License

MIT

About

Dependency-free pure Ruby RFC 5322 and MIME parser with mbox and threading support.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages