Oracle FunctionsでEmail Deliveryと連携しメール送信

OCI (Oracle Cloud Infrastructure)のEmail Deliveryサービスと連携して、Oracle FunctionsでEメールを送信します。
Oracle Functionsって？という方は[こちら](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)。

※やり方自体変更したため再投稿しています。
[・Oracle Functionsについて](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)
[・Email Deliveryについて](https://docs.cloud.oracle.com/iaas/Content/Email/Concepts/overview.htm)
## 構成イメージ
<img width="321" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/d5ea009e-f159-d6f8-10b8-c25fa4804d23.png">

## 前提
・Oracle Functions開発、実行環境が構築されていること。
　⇒[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)
・Email Deliveryのセットアップが完了していること。
　⇒以下Oracle Cloud公式ブログのチュートリアルを手順通りに実施すれば設定できます(その1の環境構築が完了していれば十分です)。
[Email Deliveryを利用した外部へのメール送信(その1　配信環境構築編)](https://community.oracle.com/docs/DOC-1026797)
[Email Deliveryを利用した外部へのメール送信(その2　メール送信編)](https://community.oracle.com/docs/DOC-1028420)

## ソースコードを配置
こちらを使います。
https://github.com/y-araki-git/fn-email-deliver
公開されているgoのコードに誤りがあったため修正しました。
流れとしては、
1.ソースコードを用意しデプロイ。
2.本文を記載するテキストを作成。
3.スクリプトを実行する。
　　・スクリプト内テキストをjson形式で作成
　　・スクリプト内でOracleFunctions起動(メール送信)
という形でやってみます。

golangのコードをちょっといじってOracle Functions単体でもメール送信できますが(もちろんそれがサーバレス)、
いろんな使い方を模索してるため今回このように何かスクリプトと連携し、ファンクションにjson形式の値を渡して実行します。

※Oracle Functions開発サーバ内での作業です。

## アプリケーション作成
```
fn create app fn-email-app --annotation oracle.com/oci/subnetIds='["OracleFunctios用に作成したPhoenixリージョンのサブネットOCID"]'
```
## ソースコード配置
```
クローンする
git clone https://github.com/y-araki-git/fn-email-deliver.git

移動
cd fn-email-deliver
```
## EmailDelivery用変数設定
```
vi func.yaml
※以下記載。us-phonenix-1リージョンでEmailDeliveryの設定をした場合の例。

schema_version: 20180708
name: sendemail
version: 0.0.21
runtime: go
entrypoint: ./func
config:
  OCI_EMAIL_DELIVERY_APPROVED_SENDER: EmailDeliveryのApproved Senderで設定したアドレス＝送信元アドレス
  OCI_EMAIL_DELIVERY_SMTP_SERVER: smtp.us-phoenix-1.oraclecloud.com
  OCI_EMAIL_DELIVERY_USER_OCID: EmailDelivery用ユーザのSMTP Credential USERNAME
  OCI_EMAIL_DELIVERY_USER_PASSWORD: EmailDelivery用ユーザのSMTP Credential PASSWORD
  REGION: us-phoenix-1
```
ちなみに開発環境で記載した変数はOCI側にデプロイされるため、極端な話開発サーバが壊れてなくなってもファンクションをまた動かすことはできます(開発サーバ側でずっと値を持っておく必要はないということです。もちろんそれがサーバレス)。

## デプロイ 
```
fn -v deploy --app fn-email-app
```
## メール本文作成
```
vi send-mail.txt
※送信されるメールの内容です。既に以下記載されています。
　ジョブのエラーを検知するような例ですが、送信したい内容で編集してください。 
  %JOBNAME%,%ERRORCODE% に変数を渡して実行するなどの使い方もよいかと。
　(今回はやりません)。

---
* This email is sent automatically from %HOSTNAME%

The following error occurred when JOB was executed.

%JOBNAME%
[ %ERRORCODE% ]


---
Information system department
phone: xxx-xxx-xxx
```

## ファンクション実行
```
権限付与
chmod +x send-mail.sh

実行
※引数に送信先アドレスを指定。
./send-mail.sh xxx@test.co.jp
```
すると以下のようにメールが送信されました(本文右上のaraki-stpというのはスクリプトを実行したホスト名を自動で変換しています)。
![Inkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/f1fb276d-fb6a-53c0-27f6-45866979624f.jpeg)

## メール送信スクリプトについて
今回は簡単に以下スクリプト(send-mail.sh)を作成したため、このように送信されました。一応スクリプトログも出しています。
件名も引数にしたり、メール本文を他にもたくさん用意しメール送信専用システムを作ってもいいかもしれません。

```bash
#!/bin/bash
#
######################################################################
#
# [スクリプト名]
#  send-mail.sh
#
# [処理概要]
#  Oracle Functionsを使用したメール送信
#  1.メール送信関数(Oracle Functions)に渡すjsonファイル作成
#  2.ファンクションを実行しメール送信
#
# [引数]
#  1.送信先アドレス
#
# [関連ファイル]
#  ./send-mail.txt (メール本文記載ファイル)
#
######################################################################
# バージョン 作成／更新者   更新日      変更内容
#---------------------------------------------------------------------
# 001-01     yu araki     2019/07  新規作成
#
######################################################################
######################################################################
# 事前処理
######################################################################
#---------------------------------------------------------------------
# 変数、定数定義
#---------------------------------------------------------------------
## 作業用変数
# タイムスタンプ
NOW=`date "+%Y-%m-%d %H:%M:%S"`
# 日付
TODAY=`date "+%Y%m%d"`
# 作業ディレクトリ
WORK_DIR="$(dirname $0)/"
# このスクリプト名
SCRIPT_NAME=$(basename $0)
# ログディレクトリ
LOG_DIR="${WORK_DIR}log/"
# スクリプトログ
SCRIPT_LOG="${LOG_DIR}${TODAY}.send-mail.script.log"
# エラーログ
ERROR_LOG="${LOG_DIR}${TODAY}.send-mail.error.log"

## 引数
# 引数1.送信先アドレス
TO="$1"

## OracleFunctionsのメール送信関連
# メール本文ファイル
MAIL_FILE="send-mail.txt"
# メール本文ファイルパス
MAIL_DIR="${WORK_DIR}${MAIL_FILE}"
# 一時作成jsonファイル名
TMP_JSON="tmp.json"
# 一時作成jsonファイルパス
TMP_JSON_DIR="${WORK_DIR}${TMP_JSON}"
# メール件名
SUBJECT="Urgent! ORA Error detection of XXX job"
# メール本文をjson用に変換　※実際は一つ下を使用
BODY=$(cat ${MAIL_DIR} | sed -e 's/$/\\'\n'/g' | tr -d '\r' | tr -d '\n' | sed -e "s/%HOSTNAME%/$(hostname)/")
# メール本文をjson用に変換　(%JOBNAME%,%ERRORCODE%に値を入れられるようsed等で変換する。)
#BODY=$(cat send-mail.txt | sed -e 's/$/\\'\n'/g' | tr -d '\r' | tr -d '\n' | sed -e "s/%HOSTNAME%/$(hostname)/" -e "s/%JOBNAME%/$(grep xxx)/" -e "s/%ERRORCODE%/$(grep "ora-" /xxx/xxx/xxx.log)/")

## スクリプト失敗通知関連
# メール件名
FAIL_SUBJECT="Script execution failed"

######################################################################
# 共通処理
######################################################################
#---------------------------------------------------------------------
# スクリプト終了時自動実行処理
# ・一時ファイル(tmp.json)削除
# ・事後処理終了ログ出力
#---------------------------------------------------------------------
trap fnc_trap_process 0

######################################################################
# 関数定義
######################################################################
#---------------------------------------------------------------------
# ログ出力関数
#---------------------------------------------------------------------
function fnc_output_scriptlog() {
  (echo "$SCRIPT_NAME: $1 $NOW" >>$SCRIPT_LOG) 2>/dev/null
  return $?
}
#---------------------------------------------------------------------
# スクリプト失敗通知関数
#---------------------------------------------------------------------
function fnc_alert_mail() {
  echo -e "$1 \n\nfilename: $SCRIPT_NAME" | mail -s "$FAIL_SUBJECT" $TO
  return $?
}

#---------------------------------------------------------------------
# スクリプト終了時自動実行関数
#---------------------------------------------------------------------
function fnc_trap_process() {

  ## 一時ファイル削除
  [[ "$TMP_JSON_DIR" ]] && rm -rf $TMP_JSON_DIR

  # 事後処理終了メッセージ出力
  fnc_output_scriptlog "The temporary file ${TMP_JSON_DIR} has been deleted."

  exit 0
}

######################################################################
# メイン処理
######################################################################
#---------------------------------------------------------------------
# 1.メール送信関数(Oracle Functions)に渡すjsonファイル作成
#---------------------------------------------------------------------
# 開始ログ出力
fnc_output_scriptlog "[Start] Start send-mail.sh process."

# ログディレクトリ確認
mkdir -p ${LOG_DIR}

# 作業ディレクトリ移動
cd ${WORK_DIR}

# メール送信用jsonファイル作成
cat <<EOF > ${TMP_JSON_DIR}
{
    "To": "$TO",
    "Subject": "$SUBJECT",
    "Body": "$BODY"
}
EOF

# 成否確認
if [ "$?" = "0" ];then
  fnc_output_scriptlog  "Succeeded in creating json file."
else
  # エラー通知
  for i in fnc_output_scriptlog fnc_alert_mail; do ${i} "Failed to create json file."; done
  # エラー終了
  exit 1
fi

#---------------------------------------------------------------------
# 2.ファンクションを実行しメール送信
#---------------------------------------------------------------------
# jsonファイルを渡しメール送信ファンクション実行
cat ${TMP_JSON_DIR} | fn invoke fn-email-app sendemail 2>> $ERROR_LOG

# 成否確認
if [ "$?" = "0" ];then
  fnc_output_scriptlog  "Succeeded in sending mail using Oracle FUnctions."
else
  # エラー通知
  for i in fnc_output_scriptlog fnc_alert_mail; do ${i} "Failed to send mail using Oracle FUnctions."; done
  # エラー終了
  exit 1
fi

######################################################################
# 終了処理
######################################################################
# 終了ログ出力
fnc_output_scriptlog "[End] send-mail.sh process is complete."

exit 0

```
ただひとつ困っていることが、日本語を表示させるのに
文字コードを何にしたらよいかわかっていない事です。
いろいろ変換してもメールで文字化けするので、どなたか教えてほしいです。


## 関連記事
[・Oracle Functionsに関するメモ](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)
[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)
[・Oracle FunctionsでAPEXのRestful Serviceと連携](https://qiita.com/y-araki-qiita/items/03e67f5bca570c526a7c)
[・Oracle FunctionsでTensorFlowによる画像分類](https://qiita.com/y-araki-qiita/items/fefebb7e7b20d8573095)
[・Oracle FunctionsでObject Storage操作 (テキストを格納・取得+テキストをPDFに変換)](https://qiita.com/y-araki-qiita/items/e55bfe111794feda7716)
[・Fn Project - Fn Server構築 (Oracle Linux7.6)](https://qiita.com/y-araki-qiita/items/e11369243723792d1a6e)
[・Oracle FunctionsでOCI Go SDKを使いインスタンス操作](https://qiita.com/y-araki-qiita/items/c927aea9e743a4468c61)

## 参考
https://github.com/abhirockzz/fn-email-app