Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LoftBox Java SDK

LoftBox — AI 에이전트를 위한 API-first 이메일 인프라 — 의 공식 Java SDK 및 Spring Boot starter 입니다.

  • loftbox-sdk — 순수 Java 클라이언트. HTTP 는 JDK java.net.http.HttpClient(외부 의존 0), JSON 직렬화만 Jackson 에 의존합니다.
  • loftbox-spring-boot-starterapplication.yml 설정만으로 LoftBoxClient 빈을 자동 등록하는 Spring Boot starter.

Java 17+ 를 요구합니다.


설치

Maven

<dependency>
  <groupId>net.loftbox</groupId>
  <artifactId>loftbox-sdk</artifactId>
  <version>0.1.0</version>
</dependency>

Spring Boot 를 쓴다면 core 대신 starter 만 추가하면 됩니다(starter 가 core 를 전이 의존):

<dependency>
  <groupId>net.loftbox</groupId>
  <artifactId>loftbox-spring-boot-starter</artifactId>
  <version>0.1.0</version>
</dependency>

Gradle

implementation("net.loftbox:loftbox-sdk:0.1.0")
// 또는 Spring Boot:
implementation("net.loftbox:loftbox-spring-boot-starter:0.1.0")

빠른 시작 — plain Java

import net.loftbox.sdk.*;
import java.util.List;

LoftBoxClient client = LoftBoxClient.builder()
    .apiKey(System.getenv("LOFTBOX_API_KEY"))
    // .baseUrl("https://api.loftbox.net")  // 기본값
    // .timeout(Duration.ofSeconds(30))     // 기본값
    .build();

// 에이전트 + 메일박스
Agent agent = client.agents().create(
    AgentCreateParams.builder().name("Support Bot").slug("support").build());
Mailbox mailbox = client.mailboxes().create(agent.id(),
    MailboxCreateParams.builder().localPart("support").build());

// 메시지 발송 (멱등 키로 중복 방지)
Message sent = client.messages().send(SendMessageParams.builder()
    .mailboxId(mailbox.id())
    .to(List.of("customer@example.com"))
    .subject("환영합니다")
    .bodyText("LoftBox 로 발송된 첫 메일입니다.")
    .idempotencyKey("welcome-001")
    .build());

// 수신함 페이지네이션
Page<Message> inbox = client.mailboxes().listInbox(mailbox.id(), 50, null);
String next = inbox.nextCursor(); // null 이면 마지막 페이지

빠른 시작 — Spring Boot

application.yml:

loftbox:
  api-key: ${LOFTBOX_API_KEY}
  # base-url: https://api.loftbox.net   # 선택
  # timeout: 30s                        # 선택

LoftBoxClient 빈이 자동 등록됩니다 — 그대로 주입해서 쓰면 됩니다:

@Service
public class MailService {
  private final LoftBoxClient client;

  public MailService(LoftBoxClient client) {
    this.client = client;
  }

  public void notify(String mailboxId, String to) {
    client.messages().send(SendMessageParams.builder()
        .mailboxId(mailboxId).to(List.of(to))
        .subject("알림").bodyText("내용").build());
  }
}

loftbox.api-key 가 없으면 빈은 등록되지 않습니다. 직접 LoftBoxClient 빈을 정의하면 자동 구성은 물러납니다(@ConditionalOnMissingBean).


리소스

client.<resource>().<method>(...) 형태로 호출합니다.

리소스 주요 메서드
auth() signup, verifySignup
agents() create, get, list
mailboxes() create, listByAgent, listInbox, ackInbox
messages() send, get, list, addLabels, removeLabel, approve, reject
threads() list, listMessages
webhooks() create
domains() create, list, status
suppressions() list, create, remove
inboundRules() list, create, remove
attachments() listForMessage, presignedUrl

목록 메서드는 모두 Page<T> 를 반환합니다(data() + nextCursor()). 서버가 배열을 직접 반환해도 nextCursor=null 페이지로 정규화됩니다.


인바운드 안전 (#369 / #370)

LoftBox 는 에이전트가 받는 메일에 대한 두 가지 안전 장치를 노출합니다.

#369 프롬프트-인젝션 신호 (탐지)

수신 Message 에는 휴리스틱 신호가 실립니다 — 차단이 아니라 신호 전용입니다. LLM 에 본문을 넘기기 전에 게이트로 쓰세요.

for (Message m : client.mailboxes().listInbox(mailboxId).data()) {
  Double score = m.injectionScore(); // 0~1, 높을수록 의심 (null 가능)
  if (score != null && score > 0.5) {
    // m.injectionCategories() 예: ["instruction_override", "data_exfil"]
    // → 사람 검토로 보내거나 LLM 컨텍스트에서 제외
  }
  String clean = m.extractedText(); // #229 인용 제거 본문
}

#370 인바운드 발신자 규칙 (차단)

발신자 단위 allow/block 리스트로 수신 자체를 통제합니다.

// 특정 도메인 차단 (org 전체 — mailboxId 미지정)
client.inboundRules().create(InboundRuleCreateParams.builder()
    .ruleType("block").patternType("domain").pattern("spam.example").build());

// 특정 메일박스만 allow 리스트로 운영
client.inboundRules().create(InboundRuleCreateParams.builder()
    .ruleType("allow").patternType("address").pattern("ceo@partner.com")
    .mailboxId(mailboxId).build());

ruleTypeallow|block, patternTypeaddress(정확 주소)|domain 입니다. mailboxId 가 없으면 org 전체에 적용됩니다. block 매치 또는 allow 리스트 미매치 발신자는 수신이 거부됩니다.


에러 처리

모든 API 에러는 LoftBoxException(statusCode() / body() / requestId()) 의 서브클래스로 던져집니다.

예외 HTTP
ValidationException 400, 422
AuthenticationException 401
PermissionException 403
NotFoundException 404
ConflictException 409
RateLimitException 429 (retryAfterSecs() 제공)
LoftBoxException 그 외 / 전송·직렬화 실패
try {
  client.messages().send(params);
} catch (RateLimitException e) {
  Thread.sleep(e.retryAfterSecs() * 1000L); // 재시도
} catch (ValidationException e) {
  log.warn("잘못된 요청: {} (req {})", e.getMessage(), e.requestId());
}

에러 메시지는 응답 바디 {"error":{"message":...,"retry_after":...}} 에서 추출하며, Retry-After 헤더가 있으면 그 값을 우선합니다. x-request-id 응답 헤더는 requestId() 로 보존됩니다.


빌드 / 테스트

mvn -B verify

게시(메인테이너): mvn -Prelease deploy (source/javadoc JAR + GPG 서명 활성).

라이선스

MIT

About

LoftBox Java SDK + Spring Boot starter — AI 에이전트용 이메일 인프라 (net.loftbox:loftbox-sdk)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages