代表アドレスに届いたメールをGmail経由で担当者へ振り分け転送

中小企業に多いと思われる代表メールアドレスに顧客からのメールが届くパターン。
「サーバー側」で「担当者」へ「自動転送」させて、メールチェックの手間と機会損失を防ぐお話。

理想の転送環境は作るしかなかった

実現したい環境

  • 代表アドレスに届いたメールのドメインを判定して、担当者や責任者に自動転送させる

現在の環境

  • レンタルサーバーでのメール運用(お名前サーバー)
  • Outlook2016での受信

現状では実現できない理由

  • 会社で契約しているレンタルサーバーでは、全転送しかないため不可能。
  • メールソフト側で転送設定しても、常時起動のパソコンで定期的にチェックさせる必要がある。
  • Gmailに全転送して振り分けしても、アドレス指定の転送設定が20個しか作成できない。
  • Gmailは転送先メールアドレスに確認コードを送らなければいけない。なるべく社員を巻き込むのは避けたい。

それでもGmailを使って自動転送させる方法

Gmailに全転送して、Scriptで自動転送を行う。

準備するもの

準備するものは3つだけ

  1. 会社用Gmailアカウント
  2. Google Spreadsheet
  3. Google Script

転送フロー

  1. 会社のメールサーバーで、代表アドレスに届いたメールをGmailに全転送
  2. Gmailで転送したいメールに「転送」というラベルを付ける
  3. 未送信の「転送ラベル」が付いたメールを抽出する(GoogleScript)
  4. 「転送条件」に応じて、宛先を変更した「転送メール」を作成(GoogleScript)
  5. 「転送メール」を送信(GoogleScript)
  6. 送信済みメールには「スター」を付け、同時にログをSpreadSheetに記録(GoogleScript)

代表メールの転送設定

メールサーバーによって転送の設定方法が異なるため、自分の契約しているところで確認して欲しい。
ちなみに「お名前」サーバーでは以下の通り。

ここが不要な場合は、Gmailの設定

サーバーの管理画面にアクセスして

お名前サーバー管理画面でメール設定のメール転送をクリック
お名前サーバーのメール転送設定の変更で転送設定するメールを選択
メール転送設定の変更
メール転送設定の変更を確認する画面

Gmailの設定

Gmailでは、ラベルを作って、転送したいメールにフィルターで貼り付ける設定をするだけ。

ラベルの作成

Gmailの設定画面を呼び出す
Gmailのラベル設定で新しいラベルを作成する。
新しいラベル名を入力
新規ラベルが作成されたか確認

フィルタの作成

フィルタとブロック中のアドレス設定画面で新しいフィルタを作成
fromに検索条件をいれてフィルタを作成をクリック
ラベルを付けるにチェックしラベルを選択後フィルタを作成をクリック
作成したフィルタが表示されていればOK

以上で代表アドレスから転送されてきたメールのうち、
目的のドメイン(@マークの後ろの部分)の付いたメールにだけ「forward」というラベルが付きます。

GoogleScriptの作成

転送用メールの抽出と作成

今回のGoogleスクリプトは、転送ログをスプレッドシートに記録するためGoogleスプレッドシートから作成します。

Googleスプレッドシートを新規作成して

Googleスプレッドシートでスクリプトエディタを開く
プロジェクト名とスクリプトファイル名を変更

この時点で、エディタ画面には「function myFunction( )」というスクリプトがありますが、そのまま使ってもいいですが、後々わかりやすいように「function main( )」に変更します。
単純に「myFunction」を「main」に書き換えて上書き保存するだけでOK

今回のプロジェクトにはmainを含め5つのスクリプトを作ります。

  1. main( )
    • 入口となるスクリプトです。これを起点にしてメール転送を行います。
  2. forward_mail( )
    • 実際にメール転送するスクリプトです。
  3. get_forward_address( )
    • 転送先メールアドレスを設定するスクリプトです。
  4. save_spreadsheet( )
    • スプレッドシートに送信ログを記録するスクリプトです。
  5. fetch_file( )
    • 送信ログを記録するスプレッドシートを特定するスクリプトです。

では、順番に作成していきます。

転送設定の本体 - function main()

function main(){
  var start = 0;
  var max = 100;  //1回の動作で何通のメールを取得するか
   
  //ラベル「forward」のメールを取得する
  var label = GmailApp.getUserLabelByName('forward');
  var threads = label.getThreads(start,max);
    
  //threadsからメールを二次元配列に格納
  var getMessages = GmailApp.getMessagesForThreads(threads);
  
  //スターの付いていないメールが転送対象となるメールなので「スター」なしを抽出。
  for(var i in getMessages){

    for(var j in getMessages[i]){

       if(!getMessages[i][j].isStarred()){
           
          var values = {};
          values.date = getMessages[i][j].getDate(); //受信日時取得       
          values.from = getMessages[i][j].getFrom(); //送信元取得
          values.subject = getMessages[i][j].getSubject(); //件名取得
          values.body = getMessages[i][j].getPlainBody(); //本文取得
          values.attachment = getMessages[i][j].getAttachments(); //添付ファイル取得

          //件名に必要ないものを消す場合の処理
          //サーバー等で「***UNCHECKED***」という文字が付与される場合があるので
          //個別事情なのでなくても良い
          values.subject = values.subject.replace(/^\*.*\*/g,'')

          //件名の先頭に空白文字がある場合は消す
          values.subject = values.subject.replace(/^\s+/g,'')
          
          //転送先の設定
          var address = get_forward_address(values.from); 
          values.forward_to = address.to;
          values.forward_bcc = address.bcc;
                   
          //本文に注釈を挿入
          var info = "このメールは[○○○@△△△.co.jp]からの自動転送です。\n\nメール送信者:" + values.from + "\n\n---------以下、本文---------\n";
          values.body = info + values.body + "\n---------本文ここまで---------\n※件名に付く「***UNCHECKED***」マークは、添付ファイルが暗号化により、ウィルス検索出来なかったことを意味しています。";
          
          //送信処理
          forwardMail(values);

          //送信したメールに「スター」をつける
          getMessages[i][j].star();
          
          //添付ファイルをGoogleDriveに保存
          for(var k in values.attachment){
             var id = fetch_file(values.attachment[k]);  //fetch_fileだけでもOK
             values['id' + k] = id;  //送信ログに添付ファイルの記録を残すためにファイルidをセット
          }
          
          //送信ログに不要なものを削除
          delete values.body;
          delete values.attachment;
          delete values.forward_to;
          delete values.forward_bcc;
          
          //送信ログ記録用の配列を用意(別途作る必要はないかも)
          var i = 0;
          var setValues = [];
          for(key in values){
            setValues[i] = values[key];
            i++;
          }
          //スプレッドシートにログを記録
          saveSpreadSheet(setValues);         
      }
    }
  }
}

メールを送信する - function forward_mail(values)

main()から受信したメールを1通ずつ受け取って、送信するスクリプトです。
引数valuesがメール本体になります。

function forwardMail(values){ 
    GmailApp.sendEmail(values.forward_to, 
                       values.subject, 
                       values.body, 
                       {
       //送信者名、送信者メアド、cc、bcc、添付ファイルの設定
                         attachments:values.attachment,
         cc:values.foward_cc,
                         bcc: values.forward_bcc,  
                         from: '○○○@△△△.co.jp',  //Gmailのアドレスと違う場合はエイリアス設定が必要
                          //参考リンク参照
                         name: '会社転送メール'
                       });    
}

送信先メールアドレスを作成する - function get_forward_address(values)

function get_forwardAddress(value){
  //送信元アドレスで転送先を変更する処理
  //戻り値は、JSONで返す。
  
  var index = value.indexOf('@');  //メールのドメイン以降を抜き出すため@の位置を調べる
  var from = value.slice(index+1).replace('>','');  //送信元アドレスが<>で括られるときがあるので消去
  var forward;
  
  //ドメインごとに送信先を変更する
  if(from.match(/ドメインA/) != null){
    forward = JSON.parse('{"to":["メアドA,メアドB"],"cc":["メアドC"],"bcc":["メアドD"]}');
  }else if(from.match(/ドメインB/) != null){
    forward = JSON.parse('{"to":["メアドB,メアドC"],"cc":["メアドD"]}');
  }else if(from.match(/ドメインC/) != null) {
    forward = JSON.parse('{"to":["メアドC"],"cc":["メアドD"]}');
  }else{
    forward = JSON.parse('{"to":["メアドE"],"cc":"メアドD"}');
  }
  return forward;
}

Googleスプレッドシートに送信ログを保存 - function save_spreadsheet(values)

function save_spreadsheet(values){
  var ssId = "1ph*******************************w5w";  //スプレッドシートのID
  var ss = SpreadsheetApp.openById(ssId).getSheets()[0]; //スプレッドシートのシートを取得
  var row = ss.getLastRow() + 1;  //新規行を取得
  ss.appendRow(values);  //転送メールの概要を入力
}
GoogleスプレッドシートのシートID取得方法

Googleスプレッドシートを開いてアドレス部分を確認する

GoogleスプレッドシートのファイルIDを確認する

添付ファイルの保存 - function fetch_file(object)

function fetch_file(object){
    var folderId = "1H**********************z-";  //保存先のフォルダIDをセット
    var attFolder = DriveApp.getFolderById(folderId);  //保存先フォルダを取得
    var fileObj = attFolder.createFile(object);  //添付ファイルを保存
    var fileId = fileObj.getId();  //保存したファイルIDを取得
    
    return fileId;  //ファイルIDを返す(ファイルIDをログに記録しないなら要らない)
}
GoogleドライブのフォルダID取得方法

Googleドライブでログを記録したすスプレッドシートを保存しているフォルダを開いて確認

GoogleドライブのフォルダIDを確認する

スクリプトに実行権限を与える

スクリプトを作成して実行する場合、初回のみ承認作業が必要になる。

Googleスクリプトファイルの実行を選ぶ
認証許可を確認する
実行するスクリプトで利用するGmailアカウントを選択
このアプリは確認されていません
このアプリは確認されていません。スクリプトを信頼させるために移動
Gmailアカウントへのアクセス許可を与える

定期実行のためのトリガーを設定

定期的にスクリプトを実行させて、メール転送を行えるようにする。

スクリプトにトリガーを設定する
新規トリガーを作成
1時間ごとに実行するトリガーを作成する

運用上の注意点

Google Scriptには、「1日あたりの3つの制限」というモノがある。

  1. 実行回数の制限
  2. 実行時間の制限
  3. トリガー数の制限
  4. ファイル容量制限

今回の対象ユーザーは、中小企業の情シス、もしくは個人なので、あまり制限にかかることはないと思うが、気になる部分を紹介しておく。
ここに挙げた以外で、制限項目を知りたい場合は、下のURLで確認してもらいたい。


実行回数の制限
無料アカウント
メールの読み書き
(送信除く)
20,000/日

転送されてきたメールを取得するので、1日あたり20,000通以上あると実行できないが、そんなにメールがくる中小企業は少ないと思われる。

実行時間の制限
無料アカウント
スクリプト実行時間6分/実行
カスタム関数事項処理30秒/実行

いずれも今回のスクリプトでは問題のないレベル

トリガー数の制限
無料アカウント
トリガー20/ユーザー
or
20/スクリプト

このスクリプトのトリガーは、1つなので全く問題なし。

ファイルの容量制限
無料アカウント
メール送信ファイル数250/メッセージ
メールの本文サイズ200KB/メッセージ
メールの受信者数50/メッセージ
メール添付ファイルの総サイズ25MB/メッセージ

1メッセージあたりで、この制限にかかるのは、あまりないと思われる。
添付ファイルの総サイズには注意が必要か?
外部から来たメールの添付ファイルをそのまま転送するので、想定外があるかもしれない。

保守の頻度

管理者には、「転送先としての受信」と「転送元の直接受信」の両方できるようにしておけば、転送不具合に気付くのが早い。
が、それでは自動化した意味がないので、スクリプトのエラーメールを受け取れるようにしておこう。

運用が安定してくれば、1週間に1回程度のログファイルチェックで問題ない。

転送作業が自動化されるので、大幅に手間が省けるのは間違いない。

現状、時間ベースのトリガーでエラーが発生することがある。

スクリプトに関するエラーメール

メール転送は、正常に行われており、エラー内容がサーバーエラーなので、こちら側が原因ではないように思うが、原因調査中。

おすすめの記事