Azure Data FactoryパイプラインからOutlookメールアドレスにメールを送信してみた

# はじめに
以下のリンクを参考に検証してみましたので、備忘として残しておきます。

https://learn.microsoft.com/ja-jp/azure/data-factory/tutorial-control-flow-portal

# 前提条件
- Azureアカウントは開設済み
- ストレージアカウントは作成済み
- Azure Data Factoryは作成済み
- ADFパイプラインは未作成

# 作業内容
## Azure Logic Appsの構築
最初にLogic Appsを作成します。
ホスティングオプションは従量課金を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/fef4866a-b24e-a36d-e114-a8095b532fbe.png)

リソースグループ、ロジックアプリ名、リージョンを設定します。
特に指定はないですが、ADFと同じリージョンにしておいたほうがよいでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/a437d7d8-e6ca-e046-a08b-e99b319c0a24.png)

ロジックアプリが作成できたら、「ロジックアプリデザイナー」からトリガーの追加を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/0e53d109-3291-f509-aaa8-6cf9f2e8b312.png)

上部の検索欄に"http"と入力し、表示された「When a HTTP request is received」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/077e120a-7e51-ab8a-3c02-679db9a95b6b.png)

ドキュメントに記載されているJSONをBodyに入力します。

```
{
    "properties": {
        "dataFactoryName": {
            "type": "string"
        },
        "message": {
            "type": "string"
        },
        "pipelineName": {
            "type": "string"
        },
        "receiver": {
            "type": "string"
        }
    },
    "type": "object"
}
```
https://learn.microsoft.com/ja-jp/azure/data-factory/tutorial-control-flow-portal#success-email-workflow

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/e76d2f6d-037c-6987-e20e-11ea6bbb8a28.png)

上部の折りたたむからフロー画面に戻り、「＋」→「アクションの追加」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/8be9f4f8-0f14-4168-e60b-77eb578c9a2a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/de9944cd-5697-e1c5-9e6a-0db7c9eddd21.png)

続いてメール送信アクションを設定します。
検索欄に"outlook"と入力して、"Office 365 Outlook"の「メールの送信（V2）」を選択します。
※"Outlook.com"は個人MSアカウント、"Office 365 Outlook"は学校や企業のMSアカウントなので必要に応じて選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/1102c562-f5cc-a99b-3374-6a2efd6f55de.png)

宛先欄にカーソルをあてると左側にマークが2つ表示されるので、稲妻のようなマークを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/8732d7ea-fdf0-9190-306e-c31531afec1a.png)

1つ目のアクションの本文に指定したJSONから動的パラメータが一覧で表示されるため、ドキュメントの説明と同じように"receiver"を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/9b18b725-e0bb-18a4-a037-e34a8b7df65e.png)

そのほかの項目もドキュメントと同じように設定します。
参考までに設定内容を以下に記載します。
※"~~変数"は上記手順を参考に動的パラメータ名を設定してください。

- 宛先： 「"receiver変数"」
- 件名： 「[Copy]: your V2 pipeline had a successful copy: "pipelineName変数"」
- 本文： 「Data Factory Name: "dataFactoryName変数" Details of the successful copy: "message変数"」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/3ffaafb0-be49-5fe9-0040-42208b78e1d4.png)

ここまでできたら「保存」ボタンを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/b1a0ac89-e846-8d4a-3b09-8e9ac1790ae1.png)

ADFから参照するためにHTTP URLをコピーしてローカルにメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/01366c0c-e6f9-2011-29e5-cff78ba65c53.png)

これでLogic Appsの構築は完了です。

## インプットデータの準備
次にインプットデータの準備です。

ローカル環境で以下のようなファイルを作成しておきます。

```input.txt
John,Doe
Jane,Doe
```

自分のストレージアカウントに移動して、"adfv2branch"という名前のコンテナーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/51b9a77f-f537-8fe5-b9ca-f54b4d7eb92b.png)

先ほど作成したファイルをアップロードします。
このとき、アップロード先のフォルダーに"input"と設定するのを忘れないようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/566203be-ca39-6d31-185a-12cadce66171.png)

アップロードが成功すると、Blobコンテナーから対象のファイルが確認できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/b9e08f18-7ff0-12b7-8982-421a2b54b193.png)


## ADFパイプラインの構築
最後にLogic Appsを呼び出すADF Pipalineを構築します。
ADFは既に構築済み想定なので、概要ページからスタジオを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/2026254e-9277-8ad4-3652-2943269c5f30.png)

新規でパイプラインを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/898e3748-0afb-1962-c45c-31c6f57fbaab.png)

パラメータタブの新規ボタンを押下して、以下3つのパラメータを設定します。
設定値はパイプラインの実行時に指定するため、値は空のままで問題ありません

- sourceblobcontainer
- sinkblobcontainer
- receiver

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/f0f56191-281c-d516-eae8-f9e491db27a9.png)

アクティビティから「データのコピー」をドラッグ＆ドロップして、名前を"Copy1"に修正します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/1596c390-88e5-c459-879f-f23fbec47b7c.png)

ソースタブから新規を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/f86bbdda-e66f-ca99-9d1e-538aa8fc3ab5.png)

Azure Blobストレージを選択して続行を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/dd588fb5-41f7-d3d5-718c-7666715dc5b8.png)

DelimitedTextを選択して続行を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/8b85ca2c-f0c7-a716-cd93-0c8d39393dc4.png)

プロパティの名前を入力して、リンクサービスを新規作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/8e35f5ba-7045-585f-afb9-bb5c5ebc1c20.png)

自分のストレージアカウント名を選択して、作成を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/3279c465-1c69-12b7-edc4-b3bcb9c4636d.png)

ファイルパスはパイプライン実行時に指定するため、以下のように設定しOKを押下します。
※スキーマのインポートを"なし"にしないとエラーが出るため注意

- コンテナー： @pipeline().parameters.sourceblobcontainer
- ディレクトリ： 設定なし
- ファイル名： input.txt
- 先頭行をヘッダーとして：未チェック
- スキーマのインポート：なし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/09e99ad8-416b-e183-8ba1-c4be2c6dea7a.png)

これでソースタブの設定は完了のため、続いてシンクタブに移動して新規を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/61bde032-3875-ecc7-fc89-917400539da1.png)

同様の手順でAzure BlobストレージとDelimitedTextを選択して、プロパティを設定します。ここでは次のように設定します。

- コンテナー： @pipeline().parameters.sinkblobcontainer
- ディレクトリ： 設定なし
- ファイル名： @concat(pipeline().RunId, '.txt')
- 先頭行をヘッダーとして：未チェック
- スキーマのインポート：なし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/aa105862-a1f5-ce5d-5b5e-c56034e86ecb.png)

Blobストレージの設定はできたので、Logic Appsを呼び出す設定を追加します。
全般→WebからWebアクションを配置し、設定タブから以下の項目を設定します。

- URL： ※Logic Apps手順で最後に確認したHTTP URL
- メソッド： POST
- 本文： 以下参照
- ヘッダー： 
  - Name: Content-Type
  - Value: application/json

※本文(ドキュメントから引用)

```
{
    "message": "@{activity('Copy1').output.dataWritten}",
    "dataFactoryName": "@{pipeline().DataFactory}",
    "pipelineName": "@{pipeline().Pipeline}",
    "receiver": "@pipeline().parameters.receiver"
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/248d7c95-bb95-511b-df7d-ce4e105e3d5f.png)

データコピーアクティビティからWebアクティビティに接続します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/c0adb5e2-9397-9ffc-447e-2a37b8537985.png)

上部の「すべて発行」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/84068b94-31c2-d2af-dedf-b852545424fd.png)

発行を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/db4fa8db-4b30-8e19-2e0d-e31e066b4f47.png)

「トリガーの追加」から「今すぐトリガー」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/233a677a-6874-fb7b-43ce-940d8a6cf929.png)

パラメータに以下の内容を設定してOKを押下してパイプラインを実行します。

- sourceblobcontainer： adfv2branch/input
- sinkblobcontainer： adfv2branch/input
- receiver： ※送信先メールアドレス

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/42a9ed5e-7541-8335-51b5-5e15fd08993b.png)

少し待つとパイプラインが正常終了したことが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/f5cece84-d804-a383-3236-8b57e6dcb343.png)

メールが届いており、動的パラメータで設定された箇所が実行したADFパイプライン名などに置き換わっていることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/7c3d5d28-d986-9c17-69e0-1f9f0ebf03c8.png)

# おわりに
普段Logic Appsを利用することはあまりないので、中々思うように進まない箇所はありましたが、終わってみると設定内容自体はそこまで複雑ではないのかなと感じました。
ただ、ドキュメントはAWSに比べると読みづらさはあるので、どちらかというとそちらの方が大変だったかもしれません。

この記事がどなたかの参考になれば幸いです。