問い合わせメールをLINEに自動転送する仕組み|受信トリガーの作り方と、通知が二重に飛ばない設計
問い合わせメールをLINEに自動転送する仕組み|受信トリガーの作り方と、通知が二重に飛ばない設計
問い合わせをメールで受けている店舗や小さな会社では、担当が2人以上になった時点で見落としが起きはじめます。実際に運用を引き継いだ案件で、共有の問い合わせアドレスの未読が半年以上分たまっていたことがありました。全員が「自分が見る番だと思っていなかった」だけです。
これを仕組みで潰す方法が、受信したメールをスタッフのグループLINEへ自動で流すことです。全員のスマホに同時に出るので、見落としは「気づかなかった」から「読んだうえで誰も動かなかった」に変わります。後者になれば運用ルールで解決できます。
先に完成形を示します。
| 段 | やること | 使うもの |
|---|---|---|
| 1 | 問い合わせアドレスの受信を、通知専用のGmailへ転送する | レンタルサーバーの転送設定(原本は残す) |
| 2 | 数分おきに「まだ通知していないメール」を検索する | GASの時間主導トリガー+Gmail検索 |
| 3 | 差出人・件名・本文の冒頭だけを整形する | GAS |
| 4 | LINE公式アカウントからグループへ送る | Messaging APIのプッシュ送信 |
設計上の急所は2つだけです。
- メール受信をきっかけに動くトリガーは用意されていない。フォーム送信には「送信時」のトリガーがありますが、メール受信にはそれがありません。だから「定期実行+未通知の検索」で代替します
- 二重通知を防ぐのは、送信できたものにだけ印を付ける設計。通知した件数を数える方式は、途中で失敗したときにずれます
着手前に必ず確認する:そのメールアドレスは自分で触れるか
段1の転送設定は、そのメールを受け取っているサーバー側で入れます。つまり、対象のアドレスが自分たちの管理下にあることが前提です。ここを確認せずに実装から入ると、コードは完成しているのに転送設定だけ入れられず、仕組みが起動しないまま止まります。
判定はMXレコードを引くだけで済みます。
dig +short MX example.com
dig +short A メールサーバーのホスト名
返ってきたホスト名が、自分が契約しているレンタルサーバーのものであれば触れます。見覚えのない事業者のホスト名なら、そのメールは別の会社が管理しているサーバーで受信されています。
実際にあったのは、サイトに載っている問い合わせ先が運営元の会社が持つアドレスで、MXを引いたら弊社が契約しているサーバーとは別事業者のメールサーバーだったケースです。この場合に取れる手は2つです。
| 状況 | 判断 |
|---|---|
| 管理会社に転送設定を依頼できる | 依頼して段1だけ任せる。以降は同じ構成で組める |
| 依頼が通らない・窓口が不明 | 問い合わせ先そのものを自社管理ドメインのアドレスへ変更する。サイトとECの表記を差し替えてから仕組みを載せる |
このケースでは後者を選びました。触れないサーバーを迂回する工夫をするより、問い合わせ先を自分の管理下に移すほうが、その後の運用がすべて楽になります。
Gmailを1枚挟む理由と、通知専用アカウントを分ける理由
サーバーのメールボックスをGASから直接読む構成(IMAP接続)も可能ですが、接続情報の管理と例外処理が増えます。Gmailに一度落とすと、検索クエリで「まだ通知していないメール」を1行で表現できるため、実装量が大きく減ります。
このとき決めておくことが2つあります。
サーバー側の転送は「転送してメールボックスにも残す」にする。 転送のみにすると、Gmail側で問題が起きたときに原本が残りません。容量は文字だけのメールならほぼ問題になりません。
通知専用のGoogleアカウントを新規に作り、個人のGmailに相乗りさせない。 理由は3つです。
- GASに与える権限は、そのアカウントのメール全体に及ぶ。私信が同じ権限範囲に入る
- 通知対象のメールと個人宛のメールが混ざり、検索条件が複雑になる
- 担当者が変わったときにアカウントごと引き継げる
受信をきっかけに動かす部分の作り方
メール受信には送信時トリガーがないため、時間主導トリガー(5分間隔)+検索クエリで組みます。未通知の判定は、処理済みのメールに付けるラベルの有無で行います。
const LABEL_DONE = 'LINE転送済み';
const MAX_PER_RUN = 10;
function checkNewMail() {
const done = GmailApp.getUserLabelByName(LABEL_DONE)
|| GmailApp.createLabel(LABEL_DONE);
const threads = GmailApp.search('in:inbox -label:' + LABEL_DONE, 0, MAX_PER_RUN);
threads.forEach(function (thread) {
const msg = thread.getMessages()[0];
const text = [
'【問い合わせ】',
'差出人: ' + msg.getFrom(),
'件名: ' + msg.getSubject(),
'',
msg.getPlainBody().slice(0, 200)
].join('\n');
if (pushToLine(text)) { // 送信できたときだけ true を返す
thread.addLabel(done); // 成功したものにだけ印を付ける
}
});
}
決めておくべき値は次の3つです。
- 実行間隔:社内通知なら5分で足ります。1分間隔にすると1日の実行回数が増え、無料枠の実行時間を圧迫します
- 1回の処理上限:10通程度で区切ります。上限を設けないと、溜まったメールを一度に処理して実行時間の制限に当たります
- 送る文字数:本文は冒頭200字程度で切ります。全文を送ってもLINEでは読みづらく、原本はメールに残っています
二重通知を防ぐのは「送信できたものにだけ印を付ける」順番
ここは順番だけで結果が変わります。
- 印を付けてから送信 → 送信が失敗したメールは二度と拾われず、問い合わせが1件消える
- 送信してから印を付ける → 失敗したメールは次回の実行でもう一度拾われる。自動リトライになる
通知した件数や最終行の番号をカウンタで持つ方式でも動きますが、途中で1通失敗すると番号だけ進んで実体とずれます。印は1通ごとに独立して付けるほうが、後から状態を目で確認できる点でも有利です。稼働中の仕組みも成功時のみラベルを付ける方式で組んでいます。
初回の1回だけは「送らずに印を付ける」
この処理を入れずにトリガーを有効にすると、受信箱に溜まっていた過去分がすべて通知として流れます。未読が数か月分あるアドレスでは実害が出ます。LINEのトーク画面が埋まって当日の問い合わせが埋もれ、月間の無料送信数も消費します。
対策は、初回に印だけを付ける関数を1回実行してから、トリガーを有効にすることです。
function markAllAsDone() { // 初回に1回だけ実行する
const done = GmailApp.getUserLabelByName(LABEL_DONE)
|| GmailApp.createLabel(LABEL_DONE);
GmailApp.search('in:inbox -label:' + LABEL_DONE, 0, 500)
.forEach(function (t) { t.addLabel(done); });
}
スプレッドシートの行番号で管理する方式でも同じです。最初の1回は基準となる行番号を記録するだけにして、過去分を送らない。
通知が多すぎると誰も見なくなる:人からのメールだけに絞る
転送を入れた直後にほぼ必ず出てくる指摘が「通知が多すぎる」です。共有アドレスには、サーバーの通知、決済サービスの明細、各種サービスのお知らせ、迷惑メールが日常的に届きます。それが全部グループLINEに流れると、1週間で誰も見なくなります。見落とし対策として作ったものが、見落としを増やす状態です。
そこで、機械が送っているメールを落とす判定を入れます。件名のキーワードで弾くと取りこぼしが多いので、メールヘッダで判定するのが確実です。
| 判定材料 | 何が分かるか |
|---|---|
| 差出人のパターン(no-reply / mailer-daemon / postmaster / newsletter など) | 返信を受け付けない自動送信 |
List-Unsubscribe ヘッダを持つ |
配信停止リンク付きの一斉配信=メルマガ |
Precedence: bulk / list |
一斉配信・メーリングリスト |
Auto-Submitted が no 以外 |
自動応答・自動生成メール |
function isMachineMail(msg) {
const from = msg.getFrom().toLowerCase();
if (/no-?reply|noreply|mailer-daemon|postmaster|newsletter/.test(from)) return true;
const raw = msg.getRawContent();
if (/^List-Unsubscribe:/im.test(raw)) return true;
if (/^Precedence:\s*(bulk|list)/im.test(raw)) return true;
if (/^Auto-Submitted:\s*(?!no)/im.test(raw)) return true;
return false;
}
決済・配送・広告・サーバー各社のドメインを差出人の除外リストに足していくと精度は上がりますが、足しすぎると本物の問い合わせを落とします。だから次の作りが必要になります。
除外したメールは消さず、別のラベルを付けて残す
除外したメールには「LINE転送対象外」のような別のラベルを付けて受信箱に残します。通知されないだけで、メールは消えません。
これがないと、除外条件を厳しくした結果として本物の問い合わせが落ちたことに気づけません。ラベルで残しておけば、Gmailでそのラベルを開くだけで「何を落としたか」を後から監査できます。除外条件は運用しながら足していくものなので、外した判断を見返せる状態を最初から用意しておくのが前提条件です。
送信先とトークンで、先に確定させておくこと
LINEへ送る側でつまずきやすいのは次の3点です。
送信先のIDは記録を信じず、テスト送信で確定させる。 グループIDのような値は、過去の作業メモや別のスクリプトに複数残っていることがあります。実際に、2つのグループIDが記録に残っていてどちらが現行か判断できない状態から着手した案件がありました。この場合は送信だけを行うテスト関数をそれぞれのIDで1回叩き、正常応答が返るほうを採用します。推測で選ぶより早く確定します。
アクセストークンはコードに直書きせず、スクリプトプロパティに置く。 直書きした構成では、コードを貼り替えるときに認証情報の行を巻き込んで消す事故が起こりえます。プロパティに退避しておけば、コード側は全選択で貼り替えても壊れません。直書きされた既存スクリプトを引き継ぐ場合は、貼り付ける範囲の開始行を画面で確認してから選択するのが当面の予防策です。
送信APIの応答は必ず記録する。 前述の「送信できたときだけ印を付ける」判定に直結します。応答を捨てる実装にすると、送信の失敗が外から見えなくなり、通知が来ないのに仕組みは正常終了しているように見えます。
判断基準:そもそも作るべきかを先に決める
この仕組みは常に必要なものではありません。
| 状況 | 適した手 |
|---|---|
| 見るのは1人だけ/スマホでメールを確認できている | サーバーの転送設定だけで足りる。GASは不要 |
| 複数人のグループで受けたい・見落としを組織で防ぎたい | 本記事の構成が効く |
| 数秒の即時性が必要 | メールのポーリングでは数分遅れる。フォーム送信時のトリガーから直接送る設計にする |
| 問い合わせの大半がメール | 問い合わせ導線の設計を先に見直す |
最後の行が実務では一番重要です。ある案件では、問い合わせの主導線をLINEに寄せ、メールは「どうしてもメールがよい人向け」に残す方針を先に決めたうえで、そのメール側の見落とし対策としてこの転送を載せました。順番が逆になると、メールの母数が減らないまま通知だけが増えます。 この仕組みは、導線の設計を終えたあとの保険として置くのが正しい位置づけです。
つまずきやすい点と予防
| 起こりうること | 予防 |
|---|---|
| 転送設定が入れられず起動しない | 着手前にMXレコードで管理下かを確認する |
| 過去分が一斉に流れる | 初回は印を付けるだけの処理を1回実行してからトリガーを有効化 |
| 通知が多すぎて誰も見なくなる | ヘッダ判定で機械送信を除外する |
| 除外しすぎて本物を落とす | 除外分は別ラベルで残し、監査できる状態にする |
よくある質問
Q. 5分おきだと遅くないですか?
社内通知の用途では実害が出ません。5分後に全員のスマホに出る状態は、誰かがメールボックスを開くまで気づかない状態より確実に速いです。秒単位の即時性が要る場合は、メールを経由せずフォーム送信のタイミングで送る設計にします。
Q. 転送設定だけで足りるのでは?
1人で見るなら足ります。転送先を複数人にすることもできますが、メールは「誰かが対応したか」が共有されません。グループLINEに流すと、誰が反応したかがその場で見えます。通知の速さより、対応状況が共有される点が効きます。
Q. エンジニアがいなくても作れますか?
サーバーの転送設定は管理画面の操作だけで済み、GASも30行程度です。ただし認証情報の扱いと初回処理の設計は、間違えると実害が出ます。そこだけ外部に見てもらうのが現実的です。
Q. LINEの送信数の上限は気になりますか?
グループへの通知は問い合わせ件数分しか送らないので、通常の運用で上限が問題になることはほぼありません。上限に当たるのは初回の一斉送信を防げなかったときだけです。
まとめ
問い合わせメールをLINEへ自動転送する仕組みは、次の順番で組みます。
- 対象アドレスのMXレコードを引き、自分で転送設定を入れられるかを先に確定させる
- 触れないなら、問い合わせ先を自社管理ドメインのアドレスへ変更してから始める
- 通知専用のGoogleアカウントを新規に作り、サーバー側の転送で受ける(原本は残す)
- 時間主導トリガーで数分おきに「まだ通知していないメール」を検索する
- 送信できたものにだけ印を付ける。この順番が二重通知と取りこぼしの両方を防ぐ
- 初回だけは印を付けるだけの処理を1回実行し、過去分を送らない
- ヘッダ判定で機械送信を落とし、除外分は別ラベルで残して監査できる状態にする
技術的な難所は多くありません。実装で差が出るのは「印を付ける順番」と「初回の1回」、運用で差が出るのは「通知を絞る設計」です。ここを外すと、見落としを防ぐために作った仕組みが、見落としを増やす側に回ります。
問い合わせ導線の設計から通知の自動化まで含めて相談したい場合は、graciautoにお問い合わせください。現在の受け方を伺えば、仕組みを作るべきか、導線を先に整えるべきかの判断からお伝えします。