AWSの請求書PDFを毎月支払い者に送付する

## この記事の概要

- 筆者は大学で研究室のAWS管理を任されている
- 毎月教授に請求書のPDFをメールで送らなければいけない
- GASを用いて自動化したのでその記録を残す

## 課題

AWSには、デフォルトで「PDF 形式の請求書を E メールで受信」という設定があります。

https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/emailed-invoice.html

しかし、この設定をオンにすると対象のメールアドレスに不必要なアラートが届いたり、件名が英語だったりと不親切です。指導教員の先生にメールを探させる手間をかけるのは申し訳ないので、**私のメールアドレス**から**日本語**で送付する必要が出てきました。

## アプローチ

GASを1ヶ月に1回走らせて、Gmailを件名でフィルタする。そこから請求書を取得して教授に転送します。
AWSからの件名は「Amazon Web Services Invoice Available [Account: {{アカウントID}}] [Invoice ID: {{請求書ID}}]」 、請求書が送られてくる日付は**毎月3日頃**です。
これだけで作れる人もいると思いますが、ここからは実装方法を書いていきます。

## 実装方法

### AWSから自分のメールに請求書を毎月送るように設定する

先ほど紹介したAWSの記事を参考にします。記事中の「Receive PDF Invoice by Email」は日本語設定だと「PDF 形式の請求書を E メールで受信」です。

https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/emailed-invoice.html

教授のメールではなく、自分のメールに送るようにしましょう。

### 毎月送るメールのテンプレートを作成する

#### ドキュメントを作成する
今回はメールの本文をテンプレートを用いて作成します。
テンプレートの置き場はGoogle ドキュメントを使用します。

``` text:テンプレート例
〇〇先生

{{month}}月分のAWS請求書を送付いたします。
〜〜〜〜〜
```

`{{month}}`が請求書の日付に置換されます。

#### IDをコピーしておく

ドキュメントのURLの、ID部分をコピーしておきます。


`https://docs.google.com/document/d/{ここがID}/edit`


### 自分のGoogleアカウントでGASの設定を行う

#### ソースコード作成

GASを開き、下記コードをコピペします。大元のコードは記事の最後に載せておきます。

```js
var props = PropertiesService.getScriptProperties();
var month = new Date().getMonth() + 1 - 1; // 前の月の請求書を取得する
function createAndSendMail(invoicePDF) {
    var TEMPLATE_ID = props.getProperty("TEMPLATE_ID");
    if (TEMPLATE_ID == null) {
        throw new Error("TEMPLATE_IDが設定されていません");
    }
    var template = DocumentApp.openById(TEMPLATE_ID).getBody().getText();
    var bossMailAddress = props.getProperty("BOSS_MAIL_ADDRESS");
    if (bossMailAddress == null) {
        throw new Error("BOSS_MAIL_ADDRESSが設定されていません");
    }
    var toBossMailTitle = month + "月分のAWS請求書送付";
    var toBossMailBody = template.replace("{{month}}", month.toString());
    GmailApp.sendEmail(bossMailAddress, toBossMailTitle, toBossMailBody, {
        attachments: [invoicePDF]
    });
}
function getInvoicePDF() {
    var awsMailAddress = "no-reply-aws@amazon.com";
    var AWS_ACCOUNT_ID = props.getProperty("AWS_ACCOUNT_ID");
    if (AWS_ACCOUNT_ID == null) {
        throw new Error("AWS_ACCOUNT_IDが設定されていません");
    }
    var invoiceMailTitle = "Amazon Web Services Invoice Available [Account:" +
        AWS_ACCOUNT_ID +
        "]";
    var invoiceMailThreads = GmailApp.search("from:" + awsMailAddress + " subject:" + invoiceMailTitle + "newer_than:1m");
    if (invoiceMailThreads.length == 0) {
        throw new Error("請求書メールが見つかりませんでした");
    }
    var invoiceMail = invoiceMailThreads[0].getMessages()[0];
    return invoiceMail.getAttachments()[0];
}
function main() {
    var invoicePDF = getInvoicePDF();
    createAndSendMail(invoicePDF);
}
```

#### GASのプロパティ設定を行う

プロジェクトの設定→スクリプト プロパティに下表のプロパティを入力

|       キー        |                 値                 |
| :---------------: | :--------------------------------: |
|  AWS_ACCOUNT_ID   |     AWSのアカウント ID (12 桁)     |
| BOSS_MAIL_ADDRESS |        送信先メールアドレス        |
|    TEMPLATE_ID    | 先ほど作ったGoogleドキュメントのID |

#### GASのトリガー設定をする

トリガー→トリガーを追加を選択
下図のように設定します。

![トリガーの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623593/2719e671-cb74-49f1-1443-b5437a97aa36.png)

|                 項目                 |         値          |
| :--------------------------------: | :----------------: |
|         実行する関数を選択         |        main        |
|          デプロイ時に実行          |        Head        |
|       イベントのソースを選択       |     時間主導型     |
| 時間ベースのトリガーのタイプを選択 | 月ベースのタイマー |
|              日を選択              |        10日        |
|             時刻を選択             |    午前9時~10時    |
|           エラー通知設定           | 毎日通知を受け取る |

これで、毎月10日の朝に最新の請求書が送付されます。

## まとめ

GASを用いてAWSの請求書をメール送信することができるようになりました。
これらのコードはClaspを用いてTypeScriptで作成しており、下記GitHubからアクセスできます。

https://github.com/taikis/aws-invoice-sender


何か間違いや改善点がありましたら、コメントや編集リクエストを送っていただけると幸いです。