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

教學指南
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": "#2377FC"
      }
    },
    "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 生成的是草稿,幫你跳過「從零開始想措辭」的痛苦。花兩分鐘微調細節和語氣,比自己從頭寫快得多。

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