Google Apps Scriptの個人的な使い所② 

# Gmailの整理

[第1弾](https://qiita.com/ksyk/items/c67fac379da86999e3d1)の続きです。
前回はGmailのクエリにマッチしたメールたちを迷惑メールフォルダーに移動したり、削除したり、アーカイブ化したりしました。
今回は下記2点をを紹介します。

1. メールエイリアスをメールのラベリングに使う & メールエイリアスを連絡先に登録する
2. 連絡先に登録されているメールから受信したら、連絡先グループをGmailにラベル適用する

## メールエイリアスをメールのラベリングに使う & メールエイリアスを連絡先に登録する

Gmailのメールエイリアスを多用していることが前提です。
同じことはGmailをフィルターで実現できますが、新しいエイリアスを使い始めたときにフィルターをいじりたくなく、任意のエイリアスに対して処理することがこのスクリプトの目的です。

今回やることは以下の通り

- メールエイリアスをメールにラベル付与する。つまり、`example+amazon@gmail.com`宛のメールを受信したら、`amazon`とラベルをつける。
- 自分の連絡先にメールエイリアスを登録する。つまり、連絡先の自分のエントリーに、「`amazon` : `example+amazon@gmail.com`」みたいなメールフィールドを追加する。

```.js
function createLabels() {
  // 自分のメールアドレスを取得して、ローカルパートとドメイン部分に分解しておく
  // myEmailLocal:  ローカルパート
  //                `example@gmail.com`なら`example`
  // myEmailDomain: ドメイン
  //                `example@gmail.com`なら`gmail.com`
  const myEmailAddress = Session.getEffectiveUser().getEmail();
  const myEmailAddressParts = myEmailAddress.match(/^(.+)@(.+)$/);
  const myEmailLocal = myEmailAddressParts[0].replace(/\./g, "").toLowerCase();
  const myEmailDomain  = myEmailAddressParts[1];
  // 自分の連絡先
  // ここに今まで使ったメールエイリアスを全部登録しておく
  const myContact = ContactsApp.getContact(myEmailAddress);

  // 受信トレイのメールをなめる
  GmailApp.getInboxThreads().forEach(function (thread) {
    thread.getMessages().forEach(function (message) {
      // ヘッダーの解析(parseAddressFields)については後述
      // ここではTo,Ccヘッダから、メールアドレスの配列を得た前提で進める
      parseAddressFields([message.getTo(), message.getCc()]).forEach(function (emailAddress) {

        // メールエイリアス形式であることと、
        // 自分のメールアドレスであることを2段階で確認
        var emailAddressParts = emailAddress.match(/^(.+)\+(.+)@(.+)$/);
        if (emailAddressParts) {
          const local = emailAddressParts[0].replace(/\./g, "").toLowerCase();
          const alias = emailAddressParts[1].replace(/\./g, "").toLowerCase();
          const domain = emailAddressParts[2];
          if (myEmailLocal === local && myEmailDomain === domain) {

            // メールエイリアスをメールにラベル付与
            thread.addLabel(GmailApp.getUserLabelByName(alias) || GmailApp.createLabel(alias));

            // 自分の連絡先にメールエイリアスを登録
            const emails = myContact.getEmails();
            if (!emails) {
              // 登録がない場合、追加
              myContact.addEmail(alias, emailAddress);
            }
          }
        }
      });
    });
  });
}
```

Gmailのメールアドレスは大文字小文字を区別しなかったり、任意の位置にドット(`.`)を入れられたりしているので、
`replace(/\./g, "")`したり、`toLowerCase()`したりしています。

自分のメールメールエイリアスを取得する部分は正規表現1発でできそうですが、結構ごちゃっとした実装になりそうなので、ローカルパートとドメインに分けて比較してます。

あと、ヘッダー部分からメールアドレスを取得するところは、関数に切り出してます。
コメントの通りです。

```.js
function parseAddressFields(addressFieldses) {
  const addresses = [];
  addressFieldses.forEach(function (addressFields) {
    // ToヘッダーやCcヘッダーは以下のように、アドレスフィードが,で区切られていて、
    // メールアドレスは<>で括られている
    // addressFields = "テスト1 <from1@example.jp>, テスト2 <from2@example.jp>"
    //                          ~~~~~~~~~~~~~~~~ :address
    //                  ~~~~~~~~~~~~~~~~~~~~~~~~~:addressField
    addressFields.split(/[,;]/).forEach(function (addressField) {
      const address = addressField.replace(/.*<(.* )?(.+@.+)( .*)?>.*/g, "$2");
      if (addresses.indexOf(address) < 0 && address) {
        addresses.push(address);
      }
    });
  });
  return addresses;
}
```

## 連絡先に登録されているメールから受信したら、連絡先グループをGmailにラベル適用する

連絡先にグループって設定できますよね。
家族とか、友達とか、親戚とか、仕事とか。
この連絡先グループをそのままメールにラベルつけしてやろうという算段です。

```.js
function applyLabels() {
  // 自分の連絡先エントリーを取得
  const myEmailAddress = Session.getEffectiveUser().getEmail();
  const myContact = ContactsApp.getContact(myEmailAddress);
  const myContactId = myContact.getId();

  // 受信トレイのメールをなめる
  GmailApp.getInboxThreads().forEach(function (thread) {
    thread.getMessages().forEach(function (message) {
      // ヘッダーの解析(parseAddressFields)については前述
      // ここではTo,Ccヘッダから、メールアドレスの配列を得た前提で進める
      parseAddressFields([message.getFrom()]).forEach(function (address) {
        // Fromヘッダーのメールアドレスをキーにして、連絡先エントリーを引っ張ってくる
        const contact = ContactsApp.getContact(address);
        // ただし、自分の連絡先エントリーは除外
        if (contact && contact.getId() !== myContactId) {
          // 複数のグループに所属しうる。
          contact.getContactGroups().forEach(function (group) {
            // システムグループも除外しておいたほうが(うざくなくて)いい
            if (!group.isSystemGroup()) {
              thread.addLabel(GmailApp.createLabel(group.getName()));
            }
          });
        }
      });
    });
  });
}
```