CAKE20

AI Web PaaS

Gmail 알람

사이트 소유자의 Google 계정에서 같은 Gmail 계정으로 관리자 알람을 보냅니다.

Gmail 전송 권한 연결

  • 내 사이트의 설정에서 Gmail 설정 탭을 엽니다.
  • Gmail 연결을 누르고 Google 공식 화면에서 Gmail 전송 권한만 허용합니다.
  • Cake20 로그인 권한과 Gmail 전송 권한은 분리됩니다. Gmail 알람을 사용하는 사이트 소유자만 한 번 추가로 연결합니다.
  • Gmail 연결은 Cake20 사용자 계정에 저장되어 같은 사용자가 보유한 여러 사이트에서 공유합니다. 사이트마다 활성화 여부는 따로 선택합니다.
  • Gmail 알람 활성화를 선택하고 설정을 저장한 뒤 웹사이트를 다시 시작합니다.
  • 사이트 소유권이 이전되거나 Gmail 연결이 해제되면 알람을 자동으로 비활성화합니다.

Cake20은 Gmail 메일을 읽거나 검색하지 않습니다. gmail.send 전송 권한과 암호화된 Refresh Token만 사용하며 Google 비밀번호는 받지 않습니다.

관리자에게 메일 보내기

  • gmail은 API, Route, Middleware, Task와 Job 같은 서버 코드에서만 사용합니다.
  • gmail.active는 사이트 설정이 활성화되고 현재 소유자의 Gmail 권한이 연결됐을 때 true입니다.
  • gmail.send에는 subject와 text가 필요하고 html은 선택 사항입니다.
  • subject는 1~200자, text는 1~50,000자, html은 최대 200,000자입니다.
  • 결과에는 Gmail messageId와 threadId가 들어 있습니다.
  • 발신자와 수신자는 현재 사이트 소유자의 연결된 Gmail로 고정됩니다. to, from 또는 OAuth Token 인자는 제공하지 않습니다.
// server/api/order.post.ts
export default async () => {
  // 주문 저장 후 사이트 소유자에게 알림
  if (gmail.active) {
    await gmail.send({
      subject: "새로운 주문이 접수되었습니다.",
      text: "주문번호 #1024를 확인해 주세요.",
      html: "<h2>새로운 주문</h2><p>주문번호 <strong>#1024</strong></p>"
    });
  }
  return { ok: true };
};

재사용 이메일 템플릿

  • 공식 Gmail 관리자 알람 템플릿(gmail-alert)은 사이트 사용자의 로그인 버튼을 Google 하나만 제공하고, 로그인한 사용자의 요청을 소유자 Gmail로 전달하는 예제입니다.
  • 템플릿의 Google 사용자 로그인 OAuth와 사이트 소유자의 Gmail 전송 OAuth는 서로 다른 권한입니다. 사용자 로그인만으로 gmail.send가 활성화되지 않습니다.
  • 사용자 입력을 HTML에 넣을 때는 반드시 HTML escape 처리합니다.
  • 알람 실패가 주문·문의 저장을 취소하면 안 되는 경우 try/catch로 정책을 명확히 정합니다.
  • 로그인, 댓글, 주문, 문의나 오류 중 어떤 사건에 보낼지는 사이트 소유자가 선택하며 Cake20이 기본 알람을 임의로 추가하지 않습니다.
// server/utils/owner-alert.ts
type AlertInput = {
  title: string;
  summary: string;
  action: string;
};

export function ownerAlert(input: AlertInput) {
  return {
    subject: `[${project.title}] ${input.title}`,
    text: `${input.summary}\n\n확인: ${input.action}`,
    html: `
      <div style="font-family:Arial,sans-serif;line-height:1.6">
        <h2>${input.title}</h2>
        <p>${input.summary}</p>
        <p><a href="${input.action}">사이트에서 확인하기</a></p>
      </div>
    `
  };
}

// server/api/inquiry.post.ts
export default async () => {
  if (gmail.active) {
    await gmail.send(ownerAlert({
      title: "새 문의가 등록되었습니다.",
      summary: "관리자 확인이 필요한 새 문의가 있습니다.",
      action: `${app.url}/admin/inquiries`
    }));
  }
  return { ok: true };
};

에디터의 API, Task 또는 Job 테스트에서 gmail.send가 실행되면 실제 Gmail로 전송됩니다. 반복 테스트 전에 사이트 소유자에게 알리세요.