跳至主要內容
睞特股份有限公司

Gmail AI 一鍵回覆:免費安裝,三步驟搞定

教學指南

上一篇我們聊了怎麼用 AI 處理商業信件的五個常見場景。但如果每封信都要開 ChatGPT、貼 prompt、再複製回 Gmail,省下的時間又被操作流程吃掉了。

這篇直接教你把 AI 裝進 Gmail 裡。打開任何一封信,按一下按鈕,AI 就自動讀取信件內容、幫你草擬回覆,直接開在回覆框裡。確認沒問題就寄出,整個流程不到 30 秒。

不用裝 Chrome 擴充功能、不用付月費、不用寫程式。用的是 Google 自家的 Apps Script,搭配 Gemini AI,完全免費。

這個工具能做什麼?

  • 一鍵草擬回覆——AI 讀完信件後自動生成回覆,直接開在 Gmail 回覆框裡
  • 五種場景切換——客訴回覆、客戶跟進、婉拒合作、結案感謝,或讓 AI 自動判斷
  • 四種語氣風格——專業親切、正式商務、輕鬆友善、簡短直接
  • 補充指示——告訴 AI 額外條件,例如「可以提供全額退款」
  • 信件摘要——長信件一鍵摘出 3-5 個重點

你需要準備的東西

只要兩樣:

  • 一個 Gmail 帳號(你正在用的就行)
  • 一個 Gemini API Key(免費,下面會教你怎麼拿)

開始安裝

下方填入你的 Gemini API Key 和公司名稱,程式碼會自動幫你帶入。然後照著三個步驟操作就好。

你輸入的資料只會寫進程式碼裡,不會傳到我們的伺服器。
還沒有?到 Google AI Studio 免費申請

步驟一:建立 Apps Script 專案

  1. script.google.com 建立新專案
  2. 點左邊齒輪「專案設定」→ 勾選「在編輯器中顯示 appsscript.json 資訊清單檔案」

步驟二:貼上設定檔

  1. 按下方「複製」複製設定檔內容(點開可檢視完整程式碼)
  2. 回到 Apps Script,點左邊「appsscript.json」→ 全選刪除 → 貼上
appsscript.json
{
  "timeZone": "Asia/Taipei",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "AI 信件助手",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/smart_toy_black_24dp.png",
      "layoutProperties": {
        "primaryColor": "#0A47B0"
      }
    },
    "gmail": {
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "onGmailMessageOpen"
        }
      ]
    }
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.execute",
    "https://www.googleapis.com/auth/gmail.addons.current.message.readonly",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/script.external_request"
  ]
}

步驟三:貼上主程式

  1. 按下方「複製」複製主程式內容(點開可檢視完整程式碼)
  2. 回到 Apps Script,點左邊「程式碼.gs」→ 全選刪除 → 貼上
  3. 按上方 儲存 或 Ctrl+S 儲存
程式碼.gs
// ============================================================
// Gmail AI 一鍵回覆 — Google Apps Script
// 在 Gmail 側邊欄加入「AI 草擬回覆」按鈕
// 使用 Gemini API 自動讀取信件內容並生成回覆草稿
// ============================================================

// ── 設定區 ─────────────────────────────────────────────────

const CONFIG = {
  GEMINI_API_KEY: "在這裡貼上你的 Gemini API Key",
  MODEL: "gemini-2.5-flash",
  COMPANY_NAME: "你的公司名稱",
  DEFAULT_TONE: "專業但親切,用『我們』而不是『本公司』,不用『敬啟者』等過於正式的稱呼",
};

// ── 場景預設 ───────────────────────────────────────────────

const SCENES = {
  auto: {
    label: "自動判斷",
    instruction: "請根據信件內容自動判斷最適合的回覆方式",
  },
  complaint: {
    label: "客訴回覆",
    instruction:
      "這是一封客訴信。回覆時請先表達同理心、承認對方的不便,再說明具體的處理方式。不要推卸責任,語氣要讓對方感覺被重視",
  },
  followup: {
    label: "客戶跟進",
    instruction:
      "這是一封跟進信,對方之前聯絡過但還沒回覆。語氣要輕鬆自然、不要有壓力感。給對方一個「順便回覆」的理由,不要用「不知道您是否有空」這種太客氣的說法。結尾提供一個具體的下一步",
  },
  decline: {
    label: "婉拒合作",
    instruction:
      "需要婉拒對方的提議或合作邀約。語氣真誠、不卑不亢,讓對方覺得被尊重而不是被敷衍。保留未來合作的可能性,但不要過度承諾",
  },
  thankyou: {
    label: "結案感謝",
    instruction:
      "專案或合作已經結束,這是一封感謝信。感謝要具體(提到合作中對方做得好的地方),不要只說「感謝合作」。結尾自然地提到未來還能合作的方向",
  },
};

// ── 側邊欄入口 ─────────────────────────────────────────────

function onGmailMessageOpen(e) {
  const card = CardService.newCardBuilder()
    .setHeader(
      CardService.newCardHeader()
        .setTitle("AI 信件助手")
        .setSubtitle("讓 AI 幫你草擬回覆")
        .setImageUrl("https://www.gstatic.com/images/icons/material/system/1x/smart_toy_black_24dp.png")
    )
    .addSection(buildSceneSection())
    .addSection(buildActionSection())
    .build();

  return [card];
}

function buildSceneSection() {
  const sceneDropdown = CardService.newSelectionInput()
    .setType(CardService.SelectionInputType.DROPDOWN)
    .setFieldName("scene")
    .setTitle("回覆場景");

  let isFirst = true;
  for (const key in SCENES) {
    sceneDropdown.addItem(SCENES[key].label, key, isFirst);
    isFirst = false;
  }

  const toneDropdown = CardService.newSelectionInput()
    .setType(CardService.SelectionInputType.DROPDOWN)
    .setFieldName("tone")
    .setTitle("語氣風格")
    .addItem("專業親切", "專業但親切,用詞溫和不冷冰冰", true)
    .addItem("正式商務", "正式的商務語氣,用詞嚴謹", false)
    .addItem("輕鬆友善", "輕鬆自然的語氣,像朋友之間的對話", false)
    .addItem("簡短直接", "簡短有力,不廢話,直接講重點", false);

  return CardService.newCardSection()
    .addWidget(sceneDropdown)
    .addWidget(toneDropdown)
    .addWidget(
      CardService.newTextInput()
        .setFieldName("extra_instruction")
        .setTitle("補充指示(選填)")
        .setHint("例如:可以提供全額退款、請對方約下週開會")
    );
}

function buildActionSection() {
  return CardService.newCardSection().addWidget(
    CardService.newButtonSet()
      .addButton(
        CardService.newTextButton()
          .setText("✨ AI 草擬回覆")
          .setComposeAction(
            CardService.newAction().setFunctionName("onDraftReply"),
            CardService.ComposedEmailType.REPLY_AS_DRAFT
          )
          .setTextButtonStyle(CardService.TextButtonStyle.FILLED)
      )
      .addButton(
        CardService.newTextButton()
          .setText("📋 AI 摘要")
          .setOnClickAction(
            CardService.newAction().setFunctionName("onSummarize")
          )
          .setTextButtonStyle(CardService.TextButtonStyle.TEXT)
      )
  );
}

// ── 核心功能:AI 草擬回覆 ──────────────────────────────────

function onDraftReply(e) {
  try {
    const messageId = e.gmail.messageId;
    const message = GmailApp.getMessageById(messageId);
    const thread = message.getThread();

    const senderName = extractName(message.getFrom());
    const subject = message.getSubject();
    const body = extractPlainText(message);

    const sceneKey = e.formInput.scene || "auto";
    const scene = SCENES[sceneKey] || SCENES.auto;
    const tone = e.formInput.tone || CONFIG.DEFAULT_TONE;
    const extraInstruction = e.formInput.extra_instruction || "";

    const prompt = buildReplyPrompt(senderName, subject, body, scene, tone, extraInstruction);
    const aiReply = callGemini(prompt);

    const cleanReply = aiReply
      .replace(/\*\*(.*?)\*\*/g, "$1")
      .replace(/\*(.*?)\*/g, "$1")
      .replace(/^#+\s*/gm, "")
      .replace(/^[-*]\s+/gm, "・")
      .trim();

    const draft = thread.createDraftReply(cleanReply);

    return CardService.newComposeActionResponseBuilder()
      .setGmailDraft(draft)
      .build();
  } catch (error) {
    return CardService.newActionResponseBuilder()
      .setNotification(
        CardService.newNotification().setText("❌ 發生錯誤:" + error.message)
      )
      .build();
  }
}

// ── 附加功能:AI 信件摘要 ──────────────────────────────────

function onSummarize(e) {
  try {
    const messageId = e.gmail.messageId;
    const message = GmailApp.getMessageById(messageId);
    const body = extractPlainText(message);

    const prompt =
      "請用繁體中文,用 3 到 5 個重點摘要以下這封信的內容。" +
      "每個重點用一句話講完。如果信中有需要回覆或處理的事項,請特別標註。\n\n" +
      "信件內容:\n" + body;

    const summary = callGemini(prompt);

    const card = CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle("📋 信件摘要"))
      .addSection(
        CardService.newCardSection().addWidget(
          CardService.newTextParagraph().setText(summary)
        )
      )
      .addSection(buildActionSection())
      .build();

    return CardService.newActionResponseBuilder()
      .setNavigation(CardService.newNavigation().pushCard(card))
      .build();
  } catch (error) {
    return CardService.newActionResponseBuilder()
      .setNotification(
        CardService.newNotification().setText("❌ 發生錯誤:" + error.message)
      )
      .build();
  }
}

// ── Gemini API 呼叫 ────────────────────────────────────────

function callGemini(prompt) {
  const url =
    "https://generativelanguage.googleapis.com/v1beta/models/" +
    CONFIG.MODEL +
    ":generateContent?key=" +
    CONFIG.GEMINI_API_KEY;

  const payload = {
    contents: [{ parts: [{ text: prompt }] }],
    generationConfig: {
      temperature: 0.7,
      maxOutputTokens: 8192,
    },
  };

  const options = {
    method: "post",
    contentType: "application/json",
    payload: JSON.stringify(payload),
    muteHttpExceptions: true,
  };

  const response = UrlFetchApp.fetch(url, options);
  const data = JSON.parse(response.getContentText());

  if (data.error) {
    throw new Error(data.error.message);
  }

  if (!data.candidates || !data.candidates[0]) {
    throw new Error("Gemini 沒有回傳內容,請稍後再試");
  }

  const candidate = data.candidates[0];
  const fullText = candidate.content.parts.map(function(p) { return p.text || ""; }).join("");
  return fullText;
}

// ── Prompt 組合 ────────────────────────────────────────────

function buildReplyPrompt(senderName, subject, body, scene, tone, extraInstruction) {
  let prompt =
    "你是「" + CONFIG.COMPANY_NAME + "」的信件助理。" +
    "請根據以下收到的信件,用繁體中文草擬一封回覆。\n\n" +
    "【回覆場景】\n" +
    scene.instruction + "\n\n" +
    "【回覆規則】\n" +
    "・語氣:" + tone + "\n" +
    "・長度:200 到 300 字,完整但不囉唆\n" +
    "・不要加主旨,只寫信件內文\n" +
    "・不要加「敬啟者」「此致敬禮」等過於正式的用語\n" +
    "・開頭直接稱呼對方名字\n" +
    "・不要使用 markdown 格式,純文字即可\n";

  if (extraInstruction) {
    prompt += "・補充指示:" + extraInstruction + "\n";
  }

  prompt +=
    "\n【收到的信件】\n" +
    "寄件人:" + senderName + "\n" +
    "主旨:" + subject + "\n" +
    "內容:\n" + body;

  return prompt;
}

// ── 工具函式 ───────────────────────────────────────────────

function extractName(from) {
  const match = from.match(/^"?(.+?)"?\s*<.*>$/);
  return match ? match[1].trim() : from.split("@")[0];
}

function extractPlainText(message) {
  let body = message.getPlainBody();

  if (!body || body.trim().length === 0) {
    body = message.getBody().replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
  }

  if (body.length > 3000) {
    body = body.substring(0, 3000) + "\n...(內容過長,已截斷)";
  }

  return body;
}

步驟四:安裝到 Gmail

  1. 點上方「部署」→「測試部署作業」
  2. 選取類型選「Google Workspace 外掛程式」
  3. 按「安裝」→「完成」
  4. 如果出現授權視窗,點「進階」→「前往(不安全)」→ 允許
  5. 打開 Gmail,開任何一封信,右側邊欄會出現 AI 信件助手 圖示,點開就是「AI 信件助手」

功能說明

  • 回覆場景:自動判斷、客訴回覆、客戶跟進、婉拒合作、結案感謝
  • 語氣風格:專業親切、正式商務、輕鬆友善、簡短直接
  • 補充指示:可以額外告訴 AI 特殊需求(例如「可以全額退款」)
  • AI 摘要:一鍵摘要長信件的重點
  • 直接回覆:草稿自動開在回覆框裡,確認後直接寄出

裝好之後怎麼用?

打開 Gmail,點開任何一封信。右邊側邊欄會出現「AI 信件助手」的圖示,點開它:

  1. 選擇回覆場景(不確定就選「自動判斷」)
  2. 選擇語氣風格
  3. 如果有特殊需求,在「補充指示」欄位填寫
  4. 按「AI 草擬回覆」

AI 會讀取信件內容,幾秒鐘後直接在回覆框裡產生草稿。你看過沒問題,按寄出就好。

如果只想快速了解一封長信在講什麼,按「AI 摘要」就會列出 3-5 個重點。

常見問題

安全嗎?我的信件內容會被看到嗎?

信件內容只會傳給 Google 的 Gemini API 處理,不會經過任何第三方伺服器。這跟你直接在 Google AI Studio 裡貼文字是一樣的。

要花錢嗎?

Gemini API 有免費額度,一般日常使用完全夠用。除非你一天回覆上百封信,否則不會碰到付費門檻。

AI 寫的信可以直接寄嗎?

建議還是看過再寄。AI 生成的是草稿,幫你跳過「從零開始想措辭」的痛苦。花兩分鐘微調細節和語氣,比自己從頭寫快得多。

有想法?聊聊就對了
免費諮詢,不收取任何前期費用
預約諮詢