Outlook (Microsoft 365) で受信したメールを Notion データベースに自動追加する仕組みを Power Automate で作ってみた

2023.12.10

こんにちは、CX 事業本部 Delivery 部の若槻です。

最近プライベートでノートテイキングアプリとして Notion を使い始めたのですが、同じくプライベートで契約している Microsoft 365(旧 Office 365) での受信メールを、Notion データベースに自動追加する方法を確認してみました。

Notion ではメール受信機能が無い

Evernote や Trello であれば、アカウントで発行できるメールアドレスにメールを送信することで、そのメールを新規ノートや新規カードとして作成できる機能があります。

しかし Notion にはそのような機能が無いため、Outlook で受信したメールを Notion データベースに新規ページとして作成するためには、別途仕組みを利用する必要があります。

Power Automate を使うと良さそう

そのような場合に使いたいのが、Microsoft 内外の多数のサービスを連携させるワークフローをローコードで作成できる Microsoft Power Automate です。

そして Power Automate には Notion コネクターがすでに用意されていました。その中にある Create a page というアクションを使えば良さそうです。

ここで Independent publisher とは、認定プログラムに参加している独立したコネクター発行者を指すそうです。コネクターの提供には Microsoft の認定が必要となるため、品質や安全性の検証は行われています。Notion コネクターは Independent publisher により提供されています。

外部サービスと連携するためのコネクターが Power Automate に用意されていなければ、自分で HTTP アクションを作り込まなけれないけないところですが、今回はこのコネクターが活用できました。

作ってみた

Notion データベースの作成

まず受信メールを保存するための Notion データベースを作成します。今回はデータベースのプロパティは以下のように設定しました。

プロパティ名 種類
差出人 メール
受信日時 日付
既読 チェックボックス
件名 タイトル

サンプルデータを追加した様子です。

この時データベース ID を控えておきます。データベース ID は URL に https://www.notion.so/<データベースID>?v=~ のような形式で含まれています。

Notion でインテグレーションを作成

https://www.notion.so/my-integrations からインテグレーションを作成します。

機能は、コンテンツ機能は コンテンツを挿入 のみ有効にし、ユーザー機能は ユーザー情報なし を選択します。

シークレットは Power Automate でのコネクション作成でで利用するため、コピーしておきます。

Notion データベースにコネクタを追加

受信メール用データベースに先程作成したインテグレーションをコネクトとして追加し、インテグレーション経由でアクセス可能にします。

Power Automate でコネクションを作成

Power Automate の コネクター一覧 で、Notion コネクターを検索して探し出し、追加します。追加時に先程コピーしたシークレットを入力します。

自身の環境に Notion コネクターを追加できました。

フローの作成

はじめに、今回作成したフローの全体像は以下のようになりました。

JSON 定義は以下のようになります。

{
  "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "$authentication": {
      "defaultValue": {},
      "type": "SecureObject"
    },
    "$connections": {
      "defaultValue": {},
      "type": "Object"
    }
  },
  "triggers": {
    "When_a_new_email_arrives_(V3)": {
      "type": "OpenApiConnectionNotification",
      "inputs": {
        "parameters": {
          "folderPath": "<フォルダーパスID>"
        },
        "host": {
          "apiId": "/providers/Microsoft.PowerApps/apis/shared_office365",
          "connectionName": "shared_office365",
          "operationId": "OnNewEmailV3"
        },
        "authentication": "@parameters('$authentication')"
      }
    }
  },
  "actions": {
    "For_each": {
      "foreach": "@triggerOutputs()?['body/value']",
      "actions": {
        "Html_to_text": {
          "runAfter": {
            "Create_a_page": [
              "Succeeded"
            ]
          },
          "type": "OpenApiConnection",
          "inputs": {
            "parameters": {
              "Content": "<p>@{item()?['body']}</p>"
            },
            "host": {
              "apiId": "/providers/Microsoft.PowerApps/apis/shared_conversionservice",
              "connectionName": "shared_conversionservice",
              "operationId": "HtmlToText"
            },
            "authentication": "@parameters('$authentication')"
          }
        },
        "Create_a_page": {
          "type": "OpenApiConnection",
          "inputs": {
            "parameters": {
              "body/parent/database_id": "<データベースID>",
              "body/properties": {
                "件名": {
                  "title": [
                    {
                      "text": {
                        "content": "@{item()?['subject']}"
                      }
                    }
                  ]
                },
                "差出人": {
                  "email": "@{item()?['from']}"
                },
                "受信日時": {
                  "date": {
                    "start": "@{item()?['receivedDateTime']}",
                    "end": null
                  }
                }
              }
            },
            "host": {
              "apiId": "/providers/Microsoft.PowerApps/apis/shared_notionip",
              "connectionName": "shared_notionip",
              "operationId": "CreateaPage"
            },
            "authentication": "@parameters('$authentication')"
          }
        },
        "Apply_to_each": {
          "foreach": "@split(replace(body('Html_to_text'),decodeUriComponent('%0D'),''), decodeUriComponent('%0A'))",
          "actions": {
            "Append_block_children": {
              "type": "OpenApiConnection",
              "inputs": {
                "parameters": {
                  "block_id": "@outputs('Create_a_page')?['body/id']",
                  "body/children": [
                    {
                      "object": "block",
                      "paragraph": {
                        "rich_text": [
                          {
                            "text": {
                              "content": "@{item()}"
                            }
                          }
                        ]
                      }
                    }
                  ]
                },
                "host": {
                  "apiId": "/providers/Microsoft.PowerApps/apis/shared_notionip",
                  "connectionName": "shared_notionip",
                  "operationId": "Appendblockchildren"
                },
                "authentication": "@parameters('$authentication')"
              }
            }
          },
          "runAfter": {
            "Html_to_text": [
              "Succeeded"
            ]
          },
          "type": "Foreach"
        }
      },
      "runAfter": {},
      "type": "Foreach"
    }
  },
  "outputs": {}
}

以降、各ステップの詳細を説明します。

office 365 Outlook When a new email arrives (V3) トリガー

トリガー office 365 Outlook When a new email arrives (V3) を使用して、メール受信時にフローが実行されるようにします。

Advanced parameters の指定は任意ですが、私の場合は仕分けルールの都合で アーカイブ というフォルダーに保存されたメールのみを対象とする設定としました。

Create a page アクション

Notion コネクターのページ作成アクションである Create a page で、受信メールを新規ページとして Notion データベースに作成します。パラメーターに先程取得したデータベース ID と、後述の JSON をプロパティとして指定します。

{
  "件名": {
    "title": [
      {
        "text": {
          "content": "@{item()?['subject']}"
        }
      }
    ]
  },
  "差出人": {
    "email": "@{item()?['from']}"
  },
  "受信日時": {
    "date": {
      "start": "@{item()?['receivedDateTime']}",
      "end": null
    }
  }
}

この時、office 365 Outlook When a new email arrives (V3) トリガーのアウトプットが指定されることにより、アクションが For each 配下になります。これはメールのサイズが大きい時にデータが分割される可能性があるためだと思われます。

Html to text アクション

受信メールの本文は HTML で記述されていることが多いですが、Notion では HTML コンテンツの記載は現時点でサポートされていません。

そこで Html to text アクションを使って、受信メールの本文を HTML からテキストに変換します。

この変換されたテキストを後続のアクションで Notion ページのブロックに追加することになります。

Apply to each アクション

Notion ページのコンテンツは、ブロック と呼ばれる単位で管理されます。このブロックにはいくつかタイプがあり、テキストデータを追加する場合は Paragraph タイプを使います。

しかしこの Paragraph ブロックには、最大文字数が 2000 文字という制限があり、メール本文をすべて一つの Paragraph ブロックに追加しようとした場合は、フローでのアクション実行時に次のようなエラーが発生します。

body failed validation: body.children[0].paragraph.rich_text[0].text.content.length should be ≤ 2000, instead was 49257.

そこで、まずは Apply to each アクションを使って、テキストを改行ごとに配列に分割します。split(replace(body('Html_to_text'),decodeUriComponent('%0D'),''), decodeUriComponent('%0A')) という式で対応できます。

Append block children アクション

分割したテキストを Paragraph ブロックに追加するためには、Append block children アクションを使います。このアクションは、指定したブロック ID のブロックに、指定したブロックを子ブロックとして追加します。今回は Block Id には Create a page アクションで作成した Notion ページの ID を指定します。また Body/Children には次のような形式で前述の Apply to each アクションの出力を指定します。

[
    {
        "object": "block",
        "paragraph": {
            "rich_text": [
                {
                    "text": {
                        "content": "@{item()}"
                    }
                }
            ]
        }
    }
]

これでメール本文が改行ごとに Paragraph ブロックに追加されます。

動作確認

以前に Gmail に届いたメールを Outlook に転送してみます。メール本文には HTML が含まれています。

メール受信トリガーでフローが実行され、実行が成功しました。Append block children アクションは今回は 91 回に分割されて実行されています。

Notion データベースには、メールの件名、差出人、受信日時、本文が設定されたページが作成されています。

本文の改行が多いような気もしますが、空のブロックが連続する場合は削除するような仕組みを追加しても良さそうです。

おわりに

Outlook (Microsoft 365) で受信したメールを Notion データベースに自動追加する仕組みを Power Automate で作ってみました。

当初はメールの本文を Notion にそのまま追加することを考えていましたが、ブロックの 2000 文字制限と HTML コンテンツ非対応という仕様に苦労しました。PDF 形式にする方法も考えましたが、メールが原文の HTML を保持することにこだわらなければ今回のようにテキストに変換する今回の方法は落とし所としてありなのではないでしょうか。

今回久しぶりに Power Automate を触ってデザイナーが新しくなっていることには驚きました。「モダンデザイナー」と言い、今年 11 月の Microsoft Ignite の開催に合わせて適用されたとのことです。しかし本記事中の動作確認のキャプチャのように、実行結果画面ではまだ旧デザイナーの UI のようです。そのうちこちらも刷新されるのでしょうか。

また Outlook を含む各種メールサービスから Notion への自動連携を可能とするツールとして、以下のようなものもありました。しかしどうやらメール本文の連携には対応していないようです。やはり HTML コンテンツ未対応であるのがネックなのでしょう。月 100 通以上の連携には有料プランが必要とのことなので、それなら本文も連携可能なしくみを今回のように Power Automate で作った方が良さそうです。

参考

以上