Files
sam-docs/dev/guides/tenant-email-integration-guide.md
김보곤 73d64d4b03 docs: [email] 테넌트 이메일 연동 가이드 추가
- 테넌트 메일 연동 기술문서 신규 작성 (SMTP 프리셋, MNG 관리 화면, 연결 테스트)
- 기존 email-policy.md에 연동 가이드 참조 추가
- INDEX.md에 이메일 연동 문서 등록
2026-03-12 12:19:28 +09:00

31 KiB
Raw Blame History

테넌트 이메일 연동 가이드

작성일: 2026-03-11 상태: 설계 확정 관련 정책: 이메일 발송 정책


1. 개요

1.1 목적

SAM 멀티테넌시 환경에서 각 테넌트(회사)가 사용하는 다양한 메일 시스템을 SAM과 연동하는 방법을 정의한다. 본사(코드브릿지엑스)가 MNG 관리 화면에서 각 테넌트의 메일 설정을 대행 관리하는 방식으로 운영한다.

1.2 핵심 원칙

원칙 설명
🔴 본사 중앙 관리 테넌트 메일 설정은 MNG 관리자(본사)가 등록/수정한다
🔴 프리셋 기반 주요 메일 제공자별 SMTP 프리셋을 제공하여 설정 오류를 방지한다
🟡 연결 테스트 필수 설정 저장 전 SMTP 연결 테스트를 통과해야 한다
🟡 단계적 확장 플랫폼 발송(Phase 1) → SMTP 릴레이(Phase 2) → OAuth2(Phase 3)
🟢 가이드 제공 테넌트에게 앱 비밀번호 생성 등 사전 준비 절차를 안내한다

1.3 운영 모델

본사 (코드브릿지엑스)                    테넌트 (고객사)
┌────────────────────────┐              ┌────────────────────────┐
│  MNG 관리 화면          │              │                        │
│  ├── 테넌트 목록        │   SMTP 정보  │  기존 메일 시스템       │
│  ├── 메일 설정 등록     │ ←──── 전달 ──│  (Gmail, Naver 등)     │
│  ├── SMTP 프리셋 선택   │              │                        │
│  ├── 연결 테스트        │              │  앱 비밀번호 생성       │
│  └── 발송 현황 모니터링 │              │  (본사 안내에 따라)     │
└────────────────────────┘              └────────────────────────┘

테넌트는 MNG에 접근하지 않는다. 본사 관리자가 테넌트로부터 SMTP 정보를 전달받아 MNG에서 설정한다.


2. 테넌트 메일 환경 현황

2.1 한국 기업 메일 시스템 분류

유형 주로 사용하는 메일 예시 도메인 비율 (추정)
포털 메일 네이버, 다음 ceo@naver.com 소기업 30%
호스팅 메일 카페24, 가비아 admin@company.co.kr 중소기업 25%
Google Workspace Gmail 인프라 hong@company.com 중소~중견 20%
네이버웍스 네이버 인프라 hong@company.com 중소기업 15%
Microsoft 365 Exchange/Outlook hong@company.co.kr 중견~대기업 8%
자체 메일 서버 On-premise hong@company.com 대기업 2%

2.2 메일 제공자별 SMTP 정보

제공자 SMTP 호스트 포트 암호화 인증 방식 일일 한도
Gmail / Google Workspace smtp.gmail.com 587 TLS 앱 비밀번호 500건 (무료) / 2,000건 (Workspace)
네이버 smtp.naver.com 587 TLS 앱 비밀번호 500건
네이버웍스 smtp.worksmobile.com 587 TLS 앱 비밀번호 관리자 설정
다음/카카오 smtp.daum.net 465 SSL 앱 비밀번호 500건
Microsoft 365 smtp.office365.com 587 STARTTLS OAuth2 권장 10,000건
카페24 업체별 상이 587 TLS ID/PW 업체별 상이
가비아 smtp.gabia.com 587 TLS ID/PW 업체별 상이

3. 연동 방식 (3단계 전략)

3.1 Phase 1: 플랫폼 발송 + Reply-To (즉시 적용)

┌─────────────────────────────────────────────────────────┐
│  Phase 1 — 플랫폼 발송                                    │
│                                                           │
│  SAM 공용 SMTP로 발송하되, 테넌트 브랜딩 적용              │
│                                                           │
│  From: "주일블라인드" <noreply@sam.codebridge-x.com>       │
│  Reply-To: admin@juil-blind.co.kr                         │
│  Subject: [SAM] 전자서명 요청                              │
│                                                           │
│  테넌트 설정: from_name + reply_to만 입력하면 됨            │
│  provider: 'platform'                                      │
└─────────────────────────────────────────────────────────┘

장점: 테넌트가 SMTP 정보를 제공하지 않아도 즉시 사용 가능 단점: 발신 주소가 @sam.codebridge-x.com으로 보임 (신뢰도 하락 가능)

적합 대상: 메일 설정이 어렵거나 SMTP 정보를 제공하지 않는 테넌트

3.2 Phase 2: SMTP 릴레이 (핵심 — 대부분의 테넌트)

┌─────────────────────────────────────────────────────────┐
│  Phase 2 — SMTP 릴레이                                    │
│                                                           │
│  테넌트의 SMTP 서버를 통해 발송                             │
│                                                           │
│  From: "주일블라인드" <admin@juil-blind.co.kr>              │
│  Subject: 전자서명 요청                                     │
│                                                           │
│  테넌트 설정: SMTP 프리셋 선택 + 계정/비밀번호 입력          │
│  provider: 'smtp'                                          │
│  → 수신자에게는 테넌트 회사 메일에서 온 것처럼 보임           │
└─────────────────────────────────────────────────────────┘

장점: 테넌트 도메인으로 발송, 높은 신뢰도 단점: 테넌트에게 앱 비밀번호 생성을 요청해야 함

적합 대상: SMTP 접근 가능한 대부분의 테넌트

3.3 Phase 3: OAuth2 연동 (고급 — 향후)

┌─────────────────────────────────────────────────────────┐
│  Phase 3 — OAuth2 연동                                    │
│                                                           │
│  Google / Microsoft 계정 OAuth2 인증                       │
│  비밀번호 저장 없이 토큰 기반 발송                           │
│                                                           │
│  provider: 'google_oauth' | 'microsoft_oauth'              │
│  → 가장 안전하지만 구현 복잡도 높음                          │
└─────────────────────────────────────────────────────────┘

장점: 비밀번호 저장 불필요, 보안 최상 단점: 구현 복잡도 높음, Google/MS만 지원, Azure AD 등록 필요

적합 대상: Google Workspace / Microsoft 365 사용 중견기업 이상

3.4 단계별 구현 우선순위

Phase 범위 대상 테넌트 구현 난이도 우선순위
Phase 1 플랫폼 발송 + Reply-To 전체 (기본값) 낮음 🔴 필수
Phase 2 SMTP 릴레이 + 프리셋 SMTP 정보 제공 가능 중간 🔴 필수
Phase 3 OAuth2 연동 Google/MS 365 사용 업체 높음 🟢 권장

4. SMTP 프리셋 시스템

4.1 프리셋 설정 파일

위치: /home/aweso/sam/mng/config/mail-presets.php (MNG) /home/aweso/sam/api/config/mail-presets.php (API)

<?php

return [
    'gmail' => [
        'label' => 'Gmail / Google Workspace',
        'host' => 'smtp.gmail.com',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'gmail',
        'daily_limit' => 500,
        'notes' => '앱 비밀번호 필요 (2단계 인증 활성화 후 생성)',
    ],
    'naver' => [
        'label' => '네이버 메일',
        'host' => 'smtp.naver.com',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'naver',
        'daily_limit' => 500,
        'notes' => '네이버 메일 설정 > POP3/SMTP > SMTP 사용 활성화 필요',
    ],
    'naverworks' => [
        'label' => '네이버웍스 (NAVER WORKS)',
        'host' => 'smtp.worksmobile.com',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'naverworks',
        'daily_limit' => null,
        'notes' => '관리자 콘솔에서 SMTP 허용 설정 필요',
    ],
    'daum' => [
        'label' => '다음/카카오 메일',
        'host' => 'smtp.daum.net',
        'port' => 465,
        'encryption' => 'ssl',
        'guide_key' => 'daum',
        'daily_limit' => 500,
        'notes' => '카카오 계정 > 보안 > 앱 비밀번호 생성',
    ],
    'microsoft365' => [
        'label' => 'Microsoft 365 (Outlook)',
        'host' => 'smtp.office365.com',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'microsoft365',
        'daily_limit' => 10000,
        'notes' => 'Basic Auth 폐지 주의 — OAuth2 전환 권장',
    ],
    'cafe24' => [
        'label' => '카페24 호스팅 메일',
        'host' => '',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'cafe24',
        'daily_limit' => null,
        'notes' => 'SMTP 호스트는 호스팅 계정마다 상이 — 수동 입력',
    ],
    'gabia' => [
        'label' => '가비아 호스팅 메일',
        'host' => 'smtp.gabia.com',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => 'gabia',
        'daily_limit' => null,
        'notes' => '가비아 메일 관리 > SMTP 설정 확인',
    ],
    'custom' => [
        'label' => '직접 입력 (자체 서버 등)',
        'host' => '',
        'port' => 587,
        'encryption' => 'tls',
        'guide_key' => null,
        'daily_limit' => null,
        'notes' => '호스트, 포트, 암호화 방식을 직접 입력',
    ],
];

4.2 프리셋 선택 흐름

본사 관리자가 MNG에서 테넌트 메일 설정
    │
    ├── 1. 테넌트 선택
    │
    ├── 2. 발송 방식 선택
    │       ├── "SAM 기본" → Phase 1 (from_name + reply_to만 입력)
    │       └── "자체 SMTP" → Phase 2 (프리셋 선택 진행)
    │
    ├── 3. 프리셋 선택 (자체 SMTP 시)
    │       ├── [Gmail ▼] 선택 → host/port/encryption 자동 채움
    │       ├── [네이버 ▼] 선택 → host/port/encryption 자동 채움
    │       └── [직접 입력] 선택 → 모든 필드 수동 입력
    │
    ├── 4. 계정 정보 입력
    │       ├── SMTP 사용자명 (이메일 주소)
    │       └── SMTP 비밀번호 (앱 비밀번호)
    │
    ├── 5. 연결 테스트 [🔧 테스트] 버튼
    │       ├── 성공 → "SMTP 연결 성공 (230ms)" ✅
    │       └── 실패 → 에러 메시지 + 트러블슈팅 안내
    │
    └── 6. 저장 (테스트 통과 시에만 활성화)

5. MNG 관리 화면 설계

5.1 메뉴 위치

MNG 사이드바
└── 시스템 관리
    └── 테넌트 관리
        └── 이메일 설정    ← 신규 메뉴

라우트: GET /system/tenants/{tenant}/mail-config 컨트롤러: App\Http\Controllers\System\TenantMailConfigController

5.2 화면 구조 — 테넌트 메일 설정 폼

┌─ 이메일 설정 — [주일블라인드] ──────────────────────────┐
│                                                          │
│  ── 기본 정보 ────────────────────────────────────────── │
│  발신자명:     [주일블라인드          ]                    │
│  발신 이메일:  [admin@juil-blind.co.kr]                   │
│  회신 주소:    [admin@juil-blind.co.kr] (선택)            │
│  일일 발송 한도: [500] 건                                 │
│                                                          │
│  ── 발송 방식 ────────────────────────────────────────── │
│  ● SAM 기본 (플랫폼 SMTP)                                │
│    발신 주소: noreply@sam.codebridge-x.com                │
│    Reply-To에 위 발신 이메일 자동 적용                     │
│                                                          │
│  ○ 자체 SMTP                                             │
│    ┌─ SMTP 설정 ──────────────────────────────────────┐ │
│    │  프리셋:   [Gmail / Google Workspace ▼]            │ │
│    │             앱 비밀번호 필요 (가이드 보기)         │ │
│    │                                                    │ │
│    │  호스트:   [smtp.gmail.com    ] (자동)              │ │
│    │  포트:     [587               ] (자동)              │ │
│    │  암호화:   [TLS ▼             ] (자동)              │ │
│    │  사용자명: [admin@juil-blind.co.kr]                 │ │
│    │  비밀번호: [••••••••••••••••   ]                    │ │
│    │                                                    │ │
│    │  [🔧 연결 테스트]                                   │ │
│    │                                                    │ │
│    │  테스트 결과:                                       │ │
│    │  ✅ SMTP 연결 성공 (응답시간: 230ms)                │ │
│    │  ✅ 테스트 메일 발송 완료                            │ │
│    │     → admin@juil-blind.co.kr로 전송                 │ │
│    └────────────────────────────────────────────────────┘ │
│                                                          │
│  ── 브랜딩 (선택) ────────────────────────────────────── │
│  회사명:     [주일블라인드             ]                   │
│  로고:       [📎 업로드] sam_bi_logo.png                  │
│  테마 컬러:  [#1a56db] 🎨                                │
│  회사 주소:  [서울시 강남구...        ]                    │
│  연락처:     [02-1234-5678            ]                   │
│  푸터 문구:  [SAM 시스템에서 발송된 메일입니다]            │
│                                                          │
│  ── 상태 ─────────────────────────────────────────────── │
│  설정 상태: ✅ 활성  |  마지막 테스트: 2026-03-11 14:30   │
│  오늘 발송: 23/500건  |  이번 달 총 발송: 456건           │
│                                                          │
│             [💾 저장]     [↩️ 취소]                       │
└──────────────────────────────────────────────────────────┘

5.3 화면 구조 — 테넌트 목록 (메일 설정 현황)

┌─ 테넌트 이메일 설정 현황 ────────────────────────────────┐
│                                                          │
│  ┌────┬──────────┬──────────┬────────┬───────┬───────┐  │
│  │ ID │ 테넌트명  │ 발송 방식 │ 프리셋  │ 상태   │ 발송  │  │
│  ├────┼──────────┼──────────┼────────┼───────┼───────┤  │
│  │  1 │ 주일블라인드│ 자체 SMTP│ Gmail  │ ✅ 활성│ 23건  │  │
│  │  2 │ 경동스크린 │ SAM 기본 │ —      │ ✅ 활성│ 12건  │  │
│  │  3 │ 테스트업체 │ 미설정   │ —      │ ⚠️ 미설정│ 0건  │  │
│  └────┴──────────┴──────────┴────────┴───────┴───────┘  │
│                                                          │
│  ⚠️ 미설정 테넌트는 플랫폼 기본 SMTP로 발송됩니다         │
└──────────────────────────────────────────────────────────┘

5.4 파일 구조

mng/
├── app/Http/Controllers/System/
│   └── TenantMailConfigController.php     ← 컨트롤러
├── app/Services/Mail/
│   ├── TenantMailService.php              ← 메일 발송 서비스
│   └── SmtpConnectionTester.php           ← SMTP 연결 테스트
├── config/
│   └── mail-presets.php                   ← SMTP 프리셋 설정
└── resources/views/system/tenant-mail/
    ├── index.blade.php                    ← 테넌트 목록
    └── edit.blade.php                     ← 설정 폼

6. SMTP 연결 테스트

6.1 테스트 절차

[🔧 연결 테스트] 클릭
    │
    ├── 1. SMTP 서버 접속 (TCP 연결)
    │       └── 실패: "SMTP 서버에 접속할 수 없습니다 (호스트/포트 확인)"
    │
    ├── 2. TLS/SSL 핸드셰이크
    │       └── 실패: "암호화 연결 실패 (암호화 방식 확인)"
    │
    ├── 3. 인증 (AUTH LOGIN)
    │       └── 실패: "인증 실패 (사용자명/비밀번호 확인)"
    │
    ├── 4. 테스트 메일 발송 (선택)
    │       ├── 수신자: 입력한 from_address (자기 자신에게)
    │       ├── 제목: "[SAM] SMTP 연결 테스트"
    │       └── 본문: "이 메일은 SAM 시스템의 SMTP 연결 테스트입니다."
    │
    └── 5. 결과 반환
            ├── 응답시간 (ms)
            ├── 서버 배너 (SMTP EHLO 응답)
            └── 성공/실패 메시지

6.2 SmtpConnectionTester 서비스

위치: mng/app/Services/Mail/SmtpConnectionTester.php

class SmtpConnectionTester
{
    /**
     * SMTP 연결 테스트 실행
     *
     * @return array{
     *     success: bool,
     *     message: string,
     *     response_time_ms: int,
     *     server_banner: string|null,
     *     error_code: string|null
     * }
     */
    public function test(
        string $host,
        int $port,
        string $encryption,
        string $username,
        string $password,
        ?string $testRecipient = null
    ): array;
}

6.3 에러 코드 및 트러블슈팅

에러 코드 메시지 원인 해결 방법
CONN_REFUSED SMTP 서버 접속 거부 호스트/포트 오류, 방화벽 호스트/포트 확인, 프리셋 재선택
TLS_FAILED TLS 핸드셰이크 실패 암호화 방식 불일치 SSL ↔ TLS 전환 시도
AUTH_FAILED 인증 실패 비밀번호 오류, 앱 비밀번호 미사용 앱 비밀번호 재생성 안내
SMTP_DISABLED SMTP 비활성화 메일 설정에서 SMTP 미허용 메일 서비스 SMTP 활성화 안내
QUOTA_ERROR 발송 한도 초과 일일 한도 도달 시간 경과 후 재시도
TIMEOUT 연결 시간 초과 (10초) 네트워크, 서버 과부하 잠시 후 재시도

7. 테넌트 사전 준비 안내

7.1 안내 절차

본사 관리자가 테넌트에게 메일 연동을 위한 사전 준비를 안내한다.

본사 → 테넌트 안내 흐름:
    │
    ├── 1. 테넌트가 사용하는 메일 서비스 확인
    │       "현재 회사 메일이 Gmail인가요, 네이버인가요?"
    │
    ├── 2. 해당 서비스의 앱 비밀번호 생성 가이드 전달
    │       (SAM 도움말 페이지 링크 또는 PDF)
    │
    ├── 3. 테넌트가 앱 비밀번호 생성 후 본사에 전달
    │       ├── SMTP용 이메일 주소
    │       └── 앱 비밀번호 (일반 비밀번호 아님)
    │
    └── 4. 본사가 MNG에서 설정 → 연결 테스트 → 완료 통보

7.2 제공자별 앱 비밀번호 생성 안내

Gmail / Google Workspace

1. Google 계정 > 보안 > 2단계 인증 활성화 (필수 전제)
2. Google 계정 > 보안 > 앱 비밀번호
3. "앱 선택" → "기타 (맞춤 이름)" → "SAM" 입력
4. 생성된 16자리 비밀번호를 본사에 전달

네이버 메일

1. 네이버 메일 > 환경설정 > POP3/IMAP 설정
2. "IMAP/SMTP 사용" → "사용함" 체크
3. 네이버 계정 > 보안 설정 > 2단계 인증 활성화
4. "앱 비밀번호 관리" → 앱 이름 "SAM" 입력 → 생성
5. 생성된 비밀번호를 본사에 전달

네이버웍스

1. 네이버웍스 관리자 콘솔 접속 (관리자 권한 필요)
2. 보안 > 외부 앱 연동 > SMTP 허용
3. 사용할 계정의 이메일/비밀번호를 본사에 전달
   (또는 앱 전용 비밀번호 생성)

다음/카카오 메일

1. 다음 메일 > 환경설정 > IMAP/POP > SMTP 사용 체크
2. 카카오 계정 > 보안 > 앱 비밀번호 생성
3. 생성된 비밀번호를 본사에 전달

Microsoft 365

1. Microsoft 365 관리자 센터 > 인증 정책
2. SMTP AUTH 허용 (테넌트 수준 또는 사용자 수준)
3. 해당 사용자 계정의 이메일/비밀번호 전달
   ※ Basic Auth 폐지 추세 → OAuth2 연동(Phase 3) 권장

카페24 / 가비아 호스팅 메일

1. 호스팅 관리 패널에서 SMTP 서버 주소 확인
2. 메일 계정의 이메일/비밀번호를 본사에 전달
   (호스팅 메일은 별도 앱 비밀번호 없이 일반 비밀번호 사용)

8. tenant_mail_configs 확장 — options JSON

기존 이메일 발송 정책options 구조에 연동 관련 필드를 추가한다.

8.1 전체 options JSON 구조

{
    "smtp": {
        "host": "smtp.gmail.com",
        "port": 587,
        "username": "admin@juil-blind.co.kr",
        "password": "<encrypted>",
        "encryption": "tls"
    },
    "preset": "gmail",
    "branding": {
        "logo_url": "/storage/tenants/1/logo.png",
        "primary_color": "#1a56db",
        "company_name": "주일블라인드",
        "company_address": "서울시 강남구...",
        "company_phone": "02-1234-5678",
        "footer_text": "본 메일은 SAM 시스템에서 발송되었습니다."
    },
    "connection_test": {
        "last_tested_at": "2026-03-11T14:30:00",
        "last_result": "success",
        "response_time_ms": 230,
        "server_banner": "220 smtp.gmail.com ESMTP",
        "tested_by": "admin@codebridge-x.com"
    },
    "domain_auth": {
        "spf_verified": false,
        "dkim_verified": false,
        "dkim_selector": null,
        "verified_at": null
    },
    "oauth": {
        "provider": null,
        "access_token": null,
        "refresh_token": null,
        "expires_at": null
    }
}

8.2 options 키 설명

Phase 설명
smtp.* Phase 2 테넌트 SMTP 접속 정보
preset Phase 2 프리셋 식별자 (gmail, naver, custom 등)
branding.* Phase 1~2 메일 템플릿 브랜딩 정보
connection_test.* Phase 2 마지막 SMTP 연결 테스트 결과
domain_auth.* Phase 2+ SPF/DKIM 도메인 인증 상태
oauth.* Phase 3 OAuth2 토큰 정보 (향후)

9. 도메인 인증 (SPF/DKIM) — Phase 2+

9.1 필요성

Phase 1(플랫폼 발송)에서 테넌트 도메인이 아닌 SAM 도메인으로 발송하면 스팸 분류될 수 있다. 도메인 인증을 통해 SAM이 테넌트 도메인 대신 발송하는 것을 허용한다.

9.2 인증 항목

인증 역할 테넌트 조치
SPF "이 IP에서 보내는 메일은 정상" 테넌트 DNS에 SAM 발송 IP 추가
DKIM 메일 위변조 방지 서명 SAM이 생성한 TXT 레코드를 DNS에 등록
DMARC SPF+DKIM 정책 정의 선택 사항 (권장)

9.3 도메인 인증 흐름 (MNG 마법사)

본사 관리자가 MNG에서 도메인 인증 진행
    │
    ├── 1. 테넌트 도메인 입력 (예: juil-blind.co.kr)
    │
    ├── 2. SAM이 DNS 레코드 자동 생성
    │       ├── SPF: "v=spf1 include:sam.codebridge-x.com ~all"
    │       └── DKIM: sam2026._domainkey.juil-blind.co.kr → 공개키
    │
    ├── 3. 테넌트 IT 담당자에게 DNS 레코드 추가 요청
    │       (안내 메일 또는 텍스트로 전달)
    │
    ├── 4. [인증 확인] 버튼 → DNS 조회로 레코드 확인
    │       ├── 성공: domain_auth.spf_verified = true
    │       └── 실패: "DNS 전파 대기 중 (최대 48시간)"
    │
    └── 5. 인증 완료 시 Phase 1에서도 높은 도달률 확보

현실적 판단: 대부분의 중소기업 테넌트는 DNS 관리 역량이 없으므로, Phase 2(SMTP 릴레이)를 기본으로 권장하고 도메인 인증은 선택 사항으로 제공한다.


10. API 엔드포인트

10.1 MNG 내부 라우트

Method Path 설명
GET /system/tenants/{tenant}/mail-config 메일 설정 폼 화면
PUT /system/tenants/{tenant}/mail-config 메일 설정 저장
POST /system/tenants/{tenant}/mail-config/test SMTP 연결 테스트
GET /system/tenants/mail-config/presets 프리셋 목록 JSON
GET /system/tenants/mail-config/overview 전체 테넌트 설정 현황

10.2 연결 테스트 API

Request:

POST /system/tenants/1/mail-config/test
{
    "provider": "smtp",
    "preset": "gmail",
    "host": "smtp.gmail.com",
    "port": 587,
    "encryption": "tls",
    "username": "admin@juil-blind.co.kr",
    "password": "xxxx xxxx xxxx xxxx",
    "send_test_mail": true
}

Response (성공):

{
    "success": true,
    "message": "SMTP 연결 성공",
    "data": {
        "response_time_ms": 230,
        "server_banner": "220 smtp.gmail.com ESMTP",
        "test_mail_sent": true,
        "test_mail_to": "admin@juil-blind.co.kr"
    }
}

Response (실패):

{
    "success": false,
    "message": "인증 실패 — 앱 비밀번호를 확인하세요",
    "data": {
        "error_code": "AUTH_FAILED",
        "troubleshoot": "Gmail은 앱 비밀번호가 필요합니다. 2단계 인증 활성화 후 앱 비밀번호를 생성하세요.",
        "guide_url": "/docs/email-setup/gmail"
    }
}

11. 보안 규칙

11.1 필수 준수 사항

✅ SMTP 비밀번호는 encrypt()로 암호화 저장 (DB에 평문 금지)
✅ OAuth2 토큰도 encrypt()로 암호화 저장
✅ 연결 테스트 시 비밀번호는 HTTPS 전송만 허용
✅ MNG 관리자만 테넌트 메일 설정 접근 가능 (권한: system.tenant.mail)
✅ SMTP 비밀번호는 API 응답/뷰에서 마스킹 처리 (••••••••)
✅ 연결 테스트 결과는 mail_logs가 아닌 options.connection_test에 기록

11.2 금지 사항

❌ 테넌트가 직접 MNG에서 메일 설정 변경 금지 (본사만 가능)
❌ SMTP 비밀번호를 로그/콘솔에 출력 금지
❌ 암호화 없이 비밀번호 저장 금지
❌ 다른 테넌트의 SMTP 설정 조회 금지 (TenantScope 적용)

11.3 비밀번호 수명주기

비밀번호 입력 → encrypt() 암호화 → DB 저장
                                      │
연결 테스트 시 ← decrypt() 복호화 ────┘
메일 발송 시  ← decrypt() 복호화 ────┘
설정 폼 표시  → "••••••••" 마스킹 (원본 미노출)

12. 구현 체크리스트

Phase 1: 플랫폼 발송 (기반)

  • tenant_mail_configs 마이그레이션 (API)
  • TenantMailConfig 모델 생성 (API + MNG)
  • TenantMailService 생성 (MNG)
  • MNG 관리 화면 — 기본 설정 폼 (from_name, reply_to)
  • 기존 Mailable을 TenantMailService 경유로 전환

Phase 2: SMTP 릴레이

  • config/mail-presets.php 프리셋 설정 파일 생성
  • MNG 관리 화면 — 프리셋 선택 + SMTP 설정 폼
  • SmtpConnectionTester 서비스 구현
  • SMTP 연결 테스트 API 구현
  • 프리셋 선택 시 호스트/포트/암호화 자동 채움 (HTMX)
  • SMTP 비밀번호 encrypt/decrypt 처리
  • 테넌트별 앱 비밀번호 생성 가이드 페이지

Phase 3: OAuth2 연동 (향후)

  • Google OAuth2 연동 (Gmail API gmail.send scope)
  • Microsoft Graph OAuth2 연동 (Mail.Send scope)
  • OAuth 토큰 자동 갱신 (Refresh Token)
  • MNG에서 "Google 연결" / "Microsoft 연결" 버튼

관련 문서


최종 업데이트: 2026-03-11