Mail 첫 계약 읽기
학습 목표: 알림 요청과 실제 전달 구분하기
섹션 제목: “학습 목표: 알림 요청과 실제 전달 구분하기”첫 mail 계약은 한 수신자에게 plain-text 메시지를 처리하는 타입을 제공합니다. Mail.send는 메시지와 논리 이벤트의 idempotency key를 받습니다. 같은 key와 같은 envelope는 같은 receipt를 돌려주며, 같은 key로 envelope를 바꾸면 IDEMPOTENCY_CONFLICT입니다. 현재 preview 상태는 해당 격리 앱 프로세스의 메모리에 한정되며 durable outbox나 자동 재시도가 아닙니다.
SIMULATED_ACCEPTED는 시뮬레이션 접수입니다. 실제 SMTP 발송·배달을 뜻하지 않습니다. production은 Java SPI 인터페이스이며 provider adapter는 포함·qualified되지 않았습니다. ACCEPTED도 배달 완료가 아니며, UNKNOWN이면 결과를 확인하지 못한 상태를 성공으로 바꾸지 않습니다. 새 상태 이름은 아래 actual metadata에서 확인하세요.
먼저 지원 경계를 읽기
섹션 제목: “먼저 지원 경계를 읽기”현재 metadata의 대상은 springBoot입니다. 라이브러리의 native 선언이 기존 콘솔 native runner에서도 동작한다는 의미는 아닙니다. 다른 언어·플랫폼이나 storage·파일 전송·billing·preview identity의 API를 이 mail 계약에서 추정하지 않습니다.
production profile을 고르는 것만으로 실메일 연결이 준비되지 않습니다. 정확히 한 adapter와 정의 hash/profile의 일치가 필요하며, adapter가 없을 때 preview provider로 자동 대체하지 않는 계약입니다. 실제 production adapter·설정·메일 발송 절차는 아직 제공하지 않습니다.
Unibase의 SDK와 생성물은 특정 host에 종속되지 않는 것이 설계 방향입니다. 제품 미리보기의 실행 환경과 provider는 SaaS가 맡고 Market은 진입과 상품 검증 정보를 제공합니다. 이 Mail 계약이 해당 세션 환경에 연결됐다는 의미는 아닙니다. 미리보기의 역할과 연결 상태를 함께 읽으세요.
공통 계약 UB-SVC-007 · schema 1 · definition 1.0.0. 아래 타입·제약·예제는 실제 compiler의 serviceLibraries 반환 snapshot에서 읽습니다.
연결된 생산자 요구사항: UB-SVC-001, UB-SVC-002, UB-SVC-007, UB-SVC-008. 제품 모델의 Revision과 Market release 권한을 대신하는 식별자가 아닙니다.
이 정의의 hash 확인
dc0037348372262549075d959428ada46384dd4144551f11f07675d050072c6a실제 typed API
섹션 제목: “실제 typed API”패키지는 unibase.mail입니다. 표의 타입 이름은 compiler가 파싱해 반환한 이름이며 원본 .uni 선언을 아래에서 함께 읽을 수 있습니다.
static MailResult send(MailMessage message, string idempotencyKey)MailMessage
| 필드 | 반환된 타입 |
|---|---|
from | string |
to | string |
subject | string |
text | string |
MailMessage(string from, string to, string subject, string text)MailResult
| 필드 | 반환된 타입 |
|---|---|
messageId | string |
state | string |
errorCode | string |
retryable | boolean |
compiler가 실제로 읽은 SDK 원본
package unibase.mail;
public native class Mail {
private native Mail();
public static native MailResult send(MailMessage message, string idempotencyKey);
}a4839769ecb34d07694ad402c714c452ac61e6fad90bdd339ccd9a80c6377335package unibase.mail;
public native class MailMessage {
public string from;
public string to;
public string subject;
public string text;
public native MailMessage(string from, string to, string subject, string text);
}9ee11642dff1f170bf94059cb7c6c378dde40a33a8e12802a47533e941254863package unibase.mail;
public native class MailResult {
private native MailResult();
public string messageId;
public string state;
public string errorCode;
public bool retryable;
}3ab22c07e5d0d29dfdc7920f4d33bbbea6f6ce81785749e13785a26bd91bd1f7provider와 profile
섹션 제목: “provider와 profile”목록에 선언된 대상은 springBoot입니다. 이 목록은 생성·빌드·실행·Market 연결의 QA 통과를 대신하지 않습니다.
| mode | provider | 계약의 productionQualified |
|---|---|---|
preview | in-memory-v1 | false |
production | java-spi-v1 | false |
생성 입력의 필드는 producer schema대로 정확히 다음 5개입니다. scopeId 값은 원본 생성 fixture의 합성 값이며 Market 로그인·소유권·방문 권한의 증거가 아닙니다.
{
"definitionVersion": "1.0.0",
"mailProvider": "in-memory-v1",
"mode": "preview",
"schemaVersion": 1,
"scopeId": "synthetic-app-1"
}입력과 처리 제약
섹션 제목: “입력과 처리 제약”| 메타데이터 항목 | 정의된 값 |
|---|---|
주소 최대 UTF-8 bytes addressBytesMax | 254 |
자동 재시도 automaticRetry | false |
본문 최대 UTF-8 bytes bodyBytesMax | 4096 |
내용 형식 content | plain-text |
동일 이벤트 처리 idempotency | same-key-same-envelope-same-receipt; changed-envelope-conflict; retained-until-process-exit |
이벤트 key 형식 keyPattern | [A-Za-z0-9_.:-]{1,128} |
결과 messageId 형식 messageIdPattern | [A-Za-z0-9_.:-]{1,128} |
preview bytes 한도 previewBytesMax | 1048576 |
preview receipt 한도 previewReceiptsMax | 256 |
production 예외의 상태 productionExceptionState | UNKNOWN |
수신자 수 recipients | 1 |
제목 최대 UTF-8 bytes subjectBytesMax | 512 |
상태 이름과 오류 이름도 같은 metadata에서 읽습니다. 상태 문자열이 실제 배달을 증명하지는 않습니다.
SIMULATED_ACCEPTEDACCEPTEDUNKNOWNREJECTED
INVALID_ENVELOPEINVALID_IDEMPOTENCY_KEYIDEMPOTENCY_CONFLICTQUOTA_EXCEEDEDPROVIDER_FAILUREPROVIDER_UNCONFIGUREDPROVIDER_VERSION_MISMATCHUNSUPPORTED_SERVICE_PROFILEUNSUPPORTED_SERVICE_TARGET
실제 생성 입력 예제 읽기
섹션 제목: “실제 생성 입력 예제 읽기”아래는 등록된 콘솔 runner 예제가 아닌 producer의 Spring Boot 생성 요청에 담긴 원본입니다. 실행 버튼을 제공하지 않으며 이 문서의 소비 검사로 앱 실행을 확인했다고 표시하지 않습니다.
package demo; import unibase.mail.*; public class Reply { public string messageId; public string state; public string errorCode; public bool retryable; public Reply(MailResult result) { this.messageId = result.messageId; this.state = result.state; this.errorCode = result.errorCode; this.retryable = result.retryable; } }package demo; import unibase.mail.*; @Controller public class Mailer implements MailApi { public Mailer() {} @Handler public Reply send(MailRequest input) { return Reply(Mail.send(MailMessage(input.from, input.to, input.subject, input.text), input.key)); } }package demo; @Api(path="/mail") public interface MailApi { @Post(path="") @Public Reply send(@Body(required=true, contentType="application/json") MailRequest input); }package demo; @Schema public class MailRequest { @Field(required=true) public string from; @Field(required=true) public string to; @Field(required=true) public string subject; @Field(required=true) public string text; @Field(required=true) public string key; public MailRequest() {} }아직 구현하지 않은 영역
섹션 제목: “아직 구현하지 않은 영역”object-storage— NOT_IMPLEMENTEDupload-download— NOT_IMPLEMENTEDbilling— NOT_IMPLEMENTEDpreview-identity— NOT_IMPLEMENTED
실행 가능한 예제로 넘어가는 조건
섹션 제목: “실행 가능한 예제로 넘어가는 조건”이 생성 fixture는 같은 업무 소스에서 명시적인 profile로 변환하는 예제입니다. Market 전체 export bundle·모델 revision·로그인 권한의 증거가 아닙니다. scopeId는 신뢰된 export/runtime binding으로 공급해야 하며 사용자가 넣은 소유자 ID로 권한을 대체하지 않습니다.
등록 ID/hash·허용 환경·실제 생성/빌드/응답·UI가 확인되어야 실행 확인으로 안내합니다. 문서의 기존 runner에 이 요청이나 임의 코드를 보내지 않습니다. 안전한 예제와 확인 범위에서 기존 결과 표시 수정과 신규 예제의 수용 기준을 읽으세요.
다음은 타입·provider·오류 확인과 AI의 실제 조회 계약입니다.