AI 에이전트를 위한 이메일 인프라 SDK. 런타임 의존성 없음 — Ruby 표준 라이브러리(net/http·json)만 사용합니다. Rails 통합(railtie + initializer 생성기)을 포함합니다.
요구 Ruby: 3.0 이상.
gem install loftbox또는 Gemfile:
gem "loftbox"require "loftbox"
client = LoftBox::Client.new(api_key: "lb_live_xxx")
# 에이전트 + 메일박스
agent = client.agents.create(name: "Support Bot", slug: "support-bot")
mailbox = client.mailboxes.create(agent.id, local_part: "support")
# 발송 (멱등 키로 중복 방지)
msg = client.messages.send(
mailbox_id: mailbox.id,
to: ["recipient@example.com"],
subject: "Hello",
body_text: "World",
idempotency_key: "welcome-42"
)
# 수신 폴링 → ack
inbox = client.mailboxes.list_inbox(mailbox.id)
client.mailboxes.ack_inbox(mailbox.id, inbox.data.map(&:id))응답은 가벼운 객체입니다(msg.id, msg.status …). 서버가 새 필드를 추가해도 깨지지 않으며, msg["새필드"] 또는 msg.raw 로 원본 해시에 접근할 수 있습니다.
initializer 를 생성합니다:
rails generate loftbox:installconfig/initializers/loftbox.rb:
LoftBox.configure do |config|
config.api_key = ENV["LOFTBOX_API_KEY"]
# config.base_url = "https://api.loftbox.net"
# config.timeout = 30
end이후 어디서든 메모이즈된 전역 클라이언트를 씁니다:
LoftBox.client.messages.send(
mailbox_id: "mb_xxx",
to: ["recipient@example.com"],
subject: "Hello",
body_text: "World"
)Rails 의존성은 gem 의 런타임 의존성에 포함되지 않습니다. railtie 는
Rails::Railtie가 정의된 환경에서만 로드되므로 non-Rails 사용자에게 영향이 없습니다.
LoftBox::Client.new(
api_key: "lb_live_xxx", # 필수
base_url: "https://api.loftbox.net", # 기본값
timeout: 30, # 초, 기본 30
http: nil # 선택: 커스텀 HTTP 어댑터(테스트/프록시)
)수신 메일은 임의 외부 발신자가 보낸 untrusted 입력입니다. 두 가지 통제를 제공합니다.
수신 메시지마다 휴리스틱 점수(injection_score, 0~1)와 발화 카테고리(injection_categories)가 붙습니다. LoftBox 는 차단하지 않으며, 에이전트가 판단합니다.
inbox = client.mailboxes.list_inbox("mb_xxx")
inbox.data.each do |msg|
if msg.injection_score && msg.injection_score >= 0.7
# 예: 사람 승인 후에만 메일 내 지시를 따른다.
warn "의심 메일 #{msg.id}: #{msg.injection_categories&.join(', ')}"
end
end발신자 리스트로 수신 자체를 통제합니다(SMTP 거부). allow 리스트가 하나라도 있으면 미매치 발신자는 거부됩니다(화이트리스트). mailbox_id 를 생략하면 org 전체에 적용됩니다.
client.inbound_rules.create(rule_type: "block", pattern_type: "domain", pattern: "evil.com")
client.inbound_rules.create(
rule_type: "allow", pattern_type: "address",
pattern: "partner@trusted.com", mailbox_id: "mb_xxx"
)
rules = client.inbound_rules.list(mailbox_id: "mb_xxx")
client.inbound_rules.remove("rule_id")모든 API 에러는 LoftBox::Error 의 서브클래스이며 status_code / body / request_id 를 노출합니다.
begin
client.messages.send(mailbox_id: "mb", to: ["a@b.com"], subject: "Hi")
rescue LoftBox::RateLimitError => e
sleep(e.retry_after_secs) if e.retry_after_secs
rescue LoftBox::NotFoundError => e
warn "#{e.status_code} #{e.message} (request=#{e.request_id})"
rescue LoftBox::Error => e
warn "loftbox error: #{e.message}"
end매핑: 400/422 → ValidationError, 401 → AuthenticationError, 403 → PermissionError, 404 → NotFoundError, 409 → ConflictError, 429 → RateLimitError(retry_after_secs), 그 외 → LoftBox::Error.
목록 메서드는 LoftBox::Page 를 반환합니다(data 배열 + next_cursor). Enumerable 이므로 바로 순회할 수 있습니다.
page = client.messages.list(mailbox_id: mb.id, limit: 50)
loop do
page.data.each { |m| process(m) }
break unless page.next_cursor
page = client.messages.list(mailbox_id: mb.id, limit: 50, cursor: page.next_cursor)
endauth, agents, mailboxes, messages, threads, webhooks, domains, suppressions, inbound_rules(#370), attachments.
examples/quickstart.rb, examples/inbound_safety.rb, examples/rails_usage.rb.
bundle install
rake test # minitest + webmock
rubocop # 정적 검사MIT