DBCSで APEX_MAILを使ってメール送信（～APEXインストール）

# TL;DR
Oracle Cloudの DBaaSに、APEXを入れて、パッケージ(APEX_MAIL) でメールを送信した。
ドキュメントを**チラ見した**だけじゃぁ、うまくいかなくて、Try & Errorが必要だった。
いちおうメール受信ができるとこまで確認できたので、
同じ案件でお困りの方の役に立てばと手順を晒しておく。何かの助けにナリマスように:pray:

---
## 作る環境（設計）
アーキテクチャ構成はこれ。
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1870464/8f7780e8-88e3-3d3d-cacc-b34d0d30d392.png" width="80%">

### 1. [SMTPサーバ](https://qiita.com/viva1000/items/000eb8f7295519d40493)
- 今回、SMTPサーバには OCIの Email Deliveryサービスを使う。
   - メール送信用に ドメインを用意する（サブドメでもOK）
   - メール送信時の From: のアドレスを決めておく
   - セキュリティ対策も考慮したい
     → SPFとDKIMのDNSレコードを登録
- APEXに設定するメール送信情報を整理しておく。
   - STMPサーバのURL　← Email Deliveryのエンドポイント
   - SMTPのユーザー名、パスワード ← SMTP資格証明の作成

### 2. DBCS構成
#### 2-1. バージョン・エディション
今回、試した Oracle Databaseは 以下。
- バージョン：19.14.0.0.0
- エディション：Standard Edition

#### 2-2. ネットワーク構成
APEXにはインターネット経由で接続したい。
<dl>
<dt>・サブネット</dt>
  <dd>DBCSは、パブリック・サブネットにプロビジョニング</dd>
  <dd>→ DBCSノードには、パブリックIPを持たせとく。</dd>
  <dd>→ CNAMEレコードを設定しても良いかも。（今回、やらない）</dd>
<dt>・ネットワーク・セキュリティ・グループ</dt>
  <dd>通信は、SSLで暗号化（今回、8443/tcp を使う）</dd>
  <dd>DBCSノードのリッスン・ポートに、外からアクセスできるように</dd>
  <dd>→ 適宜、穴を開ける。</dd>
<dt>・ゲートウェイ</dt>
  <dd>インターネットゲートウェイ</dd>
  <dd>→ APEXの管理サービスに、外からアクセスするのでNAT-GWじゃダメ。</dd>
</dl>

### 3. APEX関連
事前に決めておきたいこと。
- APEXのバージョン（最新で良いと思う。今回試したのは以下のもの）
  - APEX：21.1
  - Oracle REST Data Services (ORDS)：21.4.2.062.1806
- APEXインストール先
  - PDB：pdb1
  - パス：/home/oracle/APEX（どこでもいいけど、今回はこの配下に入れる）
- 各アカウントのパスワード
  APEXの管理者ユーザーは、定期的にパスワードを変更する方針。
  DBユーザ（ADMIN以外）は、パスワードを無期限にしてメンテ運用をラクに。
  そのかわり、パスワードはめっちゃ複雑にして、セキュリティを強化する方針。

|アカウント名 |パスワード|備考|
|------------|----------|---|
|ADMIN（変更可能）|(例)Passw0rd_#1|APEXの管理者ユーザー
|APEX_PUBLIC_USER|(例)Jz7v_5r#Tf|DBのプロファイルで設定されている複雑性が必要
|APEX_LISTENER|(例)Yk1_9fs#fZ|〃（同上）
|APEX_REST_PUBLIC_USER|(例)Ur5_6pq#Aj|〃（同上）
|ORDS_PUBLIC_USER|(例)Ri9_0is#Hx|〃（同上）

### 4. その他
インストール中に、入力する・指定する項目は、概ね上記で足りるはず。
ここまでに決めきれてない項目は、[インストレーション・ガイド](https://docs.oracle.com/cd/F47280_01/htmig/installing-and-configuring-apex-and-ords.html)を参考に適宜きめるw

---

## 環境を作る（構築作業）
### 1. はじめに
- DBCSノード上にディレクトリを準備
- oracleユーザにスイッチ
- サービスネームの確認（pdb1）
```
[opc@node1 ~]$ sudo mkdir /opt/APEX
[opc@node1 ~]$ sudo chown oracle:oinstall /opt/APEX
[opc@node1 ~]$ sudo su - oracle
[oracle@node1 ~]$ ln -s /opt/APEX/
[oracle@node1 ~]$ lsnrctl status| grep pdb1
Service "pdb1.subnetNNNNNNNN.vcnNNNNNNNN.oraclevcn.com" has 1 instance(s).
                                                    --------> サービス名を確認
```
### 2. 資材準備
#### 2-1. ダウンロード（Downloadサイト→ローカルPC）
事前に、下記から２つのzipをGetしておく。
- Oracle APEX 21.1 - All languages
  https://www.oracle.com/jp/tools/downloads/apex-downloads.html
  → **apex_21.1.zip**
- Oracle REST Data Services
  https://www.oracle.com/database/technologies/appdev/rest-data-services-downloads.html
  → **ords-21.4.2.062.1806.zip**

#### 2-2. アップロード（ローカルPC→DBCSノードの/tmp）
(例) `scp -i SSHキー apex_21.1.zip ords-21.4.2.062.1806.zip opc@DCBSノードのパブリックIP:/tmp`

### 3. APEXのインストール
標準出力のうち確認が不要なものや、スペースや改行を省略しています。
```
$ cd /home/oracle/APEX
$ unzip /tmp/apex_21.1.zip
$ cd apex
$ sqlplus / as sysdba
SQL> ALTER SESSION SET CONTAINER = pdb1;
Session altered. ----------------------------------------------> メッセージを確認
SQL> @apexins.sql SYSAUX SYSAUX TEMP /i/
（省略）
PL/SQL procedure successfully completed. ----------------------> メッセージを確認
1 row selected.
...null1.sql
SYS> @apxchpwd.sql
...set_appun.sql
================================================================================
This script can be used to change the password of an Application Express
instance administrator. If the user does not yet exist, a user record will be
created.
================================================================================
Enter the administrator's username [ADMIN] --------------------> Enterキー押下
User "ADMIN" does not yet exist and will be created.
Enter ADMIN's email [ADMIN] -----------------------------------> Enterキー押下
Enter ADMIN's password [] -------------------------------------> "Passw0rd_#1"と入力
Created instance administrator ADMIN. -------------------------> メッセージを確認
SYS> ALTER USER APEX_PUBLIC_USER ACCOUNT UNLOCK; --------------> エラーがないことを確認
SYS> ALTER USER APEX_PUBLIC_USER IDENTIFIED BY Jz7v_5r#Tf; ----> エラーがないことを確認
SYS>@apex_rest_config.sql
Enter a password for the APEX_LISTENER user [] ----------------> "Yk1_9fs#fZ"と入力
Enter a password for the APEX_REST_PUBLIC_USER user [] --------> "Ur5_6pq#Aj"と入力
...set_appun.sql
...setting session environment
...create APEX_LISTENER and APEX_REST_PUBLIC_USER users -------> メッセージを確認
SYS> quit
```

### 4. ORDSのインストール
標準出力のうち確認が不要なものや、スペースや改行を省略しています。
```
$ mkdir /home/oracle/APEX/ords
$ cd /home/oracle/APEX/ords
$ unzip /tmp/ords-21.4.2.062.1806.zip
$ java -jar ords.war install advanced
This Oracle REST Data Services instance has not yet been configured.
Please complete the following prompts

Enter the location to store configuration data: ---------------> "config"と入力（構成ファイル格納ディレクトリの名前を指定）
Enter number for [1] Basic  [2] TNS  [3] Custom URL [1]: ------> Enterキー押下
Enter the name of the database server [localhost]: ------------> DBCSノードのDNS名を入力 ([例] node1.subnetNNNNNNNN.vcnNNNNNNNN.oraclevcn.com)
Enter the database listen port [1521]: ------------------------> Enterキー押下
Enter 1 to specify the database service name, or 2 to specify the database SID [1]: 
                                                    -----------> Enterキー押下
Enter the database service name: ------------------------------> pdb1のサービス名を入力 ([例] pdb1.subnetNNNNNNNN.vcnNNNNNNNN.oraclevcn.com)
Enter 1 if you want to verify/install Oracle REST Data Services schema or 2 to skip this step [1]:
                                                    -----------> Enterキー押下
Enter the database password for ORDS_PUBLIC_USER: -------------> "Ri9_0is#Hx"と入力
Confirm password: ---------------------------------------------> "Ri9_0is#Hx"と入力
Requires to login with administrator privileges to verify Oracle REST Data Services schema.

Enter the administrator username: -----------------------------> "sys"と入力
Enter the database password for SYS AS SYSDBA: ----------------> sysのパスワードを入力（DBCS作成時に指定したもの）
Confirm password: ---------------------------------------------> sysのパスワードを入力
Connecting to database user: SYS AS SYSDBA url: jdbc:oracle:thin:@//node1.subnetNNNNNNNN.vcnNNNNNNNN.oraclevcn.com:1521/pdb1.subnetNNNNNNNN.vcnNNNNNNNN.oraclevcn.com
                                                ---------------> メッセージを確認

Retrieving information.
Enter the default tablespace for ORDS_METADATA [SYSAUX]: ------> Enterキー押下
Enter the temporary tablespace for ORDS_METADATA [TEMP]: ------> Enterキー押下
Enter the default tablespace for ORDS_PUBLIC_USER [USERS]: ----> Enterキー押下
Enter the temporary tablespace for ORDS_PUBLIC_USER [TEMP]: ---> Enterキー押下
Enter 1 if you want to use PL/SQL Gateway or 2 to skip this step.
If using Oracle Application Express or migrating from mod_plsql then you must enter 1 [1]:
                                                ---------------> Enterキー押下
Enter the PL/SQL Gateway database user name [APEX_PUBLIC_USER]: -> Enterキー押下
Enter the database password for APEX_PUBLIC_USER: -------------> "Jz7v_5r#Tf"と入力
Confirm password: ---------------------------------------------> "Jz7v_5r#Tf"と入力
Enter 1 to specify passwords for Application Express RESTful Services database users (APEX_LISTENER, APEX_REST_PUBLIC_USER) or 2 to skip this step [1]:
                                                ---------------> Enterキー押下
Enter the database password for APEX_LISTENER: ----------------> "Yk1_9fs#fZ"と入力
Confirm password: ---------------------------------------------> "Yk1_9fs#fZ"と入力
Enter the database password for APEX_REST_PUBLIC_USER: --------> "Ur5_6pq#Aj"と入力
Confirm password: ---------------------------------------------> "Ur5_6pq#Aj"と入力
Enter a number to select a feature to enable:
   [1] SQL Developer Web  (Enables all features)
   [2] REST Enabled SQL
   [3] Database API
   [4] REST Enabled SQL and Database API
   [5] None
Choose [1]: ---------------------------------------------------> Enterキー押下

Enter 1 if you wish to start in standalone mode or 2 to exit [1]: -> Enterキー押下
Enter the APEX static resources location: ----------------------> "/home/oracle/APEX/apex/images"と入力
Enter 1 if using HTTP or 2 if using HTTPS [1]: -----------------> "2"と入力
Enter the HTTPS port [8443]: -----------------------------------> Enterキー押下
Enter the SSL hostname: ----------------------------------------> "ssl"と入力
Enter 1 to use the self-signed certificate or 2 if you will provide the SSL certificate [1]:
                                                 ---------------> Enterキー押下
```
うまくいけけば、ORDSのサービスが起動するはず。
エラーでサービスが起動できない or 不意に停止してしまう... と、ならないことが確認できたら
Ctrl+Cでサービスを強制終了させる。

### 5. ネットワーク接続設定
#### 5-1. DBのACL設定 (12c以降：接続権限の付与)
[6.5.3 Granting Connect Privileges in Oracle Database 12c or Later](https://docs.oracle.com/en/database/oracle/application-express/21.1/htmig/enabling-network-services-in-Oracle-db11g-or-later.html#GUID-CA19B8DF-B210-46FC-BC3A-F0DC76AE5625)
```
$ cd
$ sqlplus / as sysdba
SQL> ALTER SESSION SET CONTAINER = pdb1;
Session altered. -----------------------------------------------> メッセージを確認
SQL> SELECT username FROM dba_users WHERE username LIKE 'APEX%';
USERNAME
--------------------------------------------------------------------------------
APEX_LISTENER
APEX_PUBLIC_USER
APEX_REST_PUBLIC_USER
APEX_210100 ----------------------------------------------------> スキーマ名を確認
SQL> BEGIN
  2      DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
  3          host => '*',
  4          ace => xs$ace_type(
  5              privilege_list => xs$name_list('connect'),
  6              principal_name => 'APEX_210100',  -------------> 確認したスキーマ名を入力する
  7              principal_type => xs_acl.ptype_db
  8          )
  9      );
 10  END;
 11  /
PL/SQL procedure successfully completed. -----------------------> メッセージを確認
SQL> QUIT
$ exit
```

#### 5-2. NSGのポート開放
8443/tcpへの接続を許可する（例: ↓）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1870464/241dd912-f0a2-d2de-29af-872be22d9172.png)


#### 5-3. iptables/firewalldのポート開放
8443/tcpへの接続を許可する
##### ・iptablesの場合
```
$ sudo su -
# id -nu
root -----------------------------------------------------------> メッセージを確認
# iptables --list ----------------------------------------------> 今設定されている状況
# cat /etc/sysconfig/iptables > iptables.old -------------------> バックアップ
# iptables -I INPUT 7 -p tcp -m state --state NEW -m tcp --dport 8443 -j ACCEPT -m comment --comment "Required for APEX (SSL) traffic. "
# /sbin/service iptables save
# cat /etc/sysconfig/iptables > iptables.new
# diff iptables.old iptables.new -------------------------------> 追加した設定が差分になっていることを確認
# service iptables restart
# iptables --list| grep -i apex --------------------------------> 追加した設定を確認できること。
# exit
```
##### ・firewalldの場合
インスタンスを作成したタイミングによっては、
iptablesではなくfirewalldが有効になっている（もしくはどちらも動いていない）かも。

### 6. APEX日本語化
```
$ sudo su - oracle
$ export NLS_LANG=American_America.AL32UTF8
$ cd $HOME/APEX/apex/builder/ja
$ sqlplus / as sysdba
SQL> ALTER SESSION SET CONTAINER = pdb1;
Session altered.
SQL> ALTER SESSION SET CURRENT_SCHEMA = APEX_210100; -----------> "SELECT username FROM dba_users WHERE username LIKE 'APEX%';"で、確認したスキーマ名を入力する
Session altered.
SQL> @load_ja.sql
PL/SQL procedure successfully completed. -----------------------> メッセージを確認
SQL> QUIT
$ exit
```

### 7. APEX(ORDS)を起動する
```
$ sudo su - oracle
$ cd $HOME/APEX/ords
$ java -jar ords.war standalone &
```
うまく起動できるようになったら(w)、systemctl等での自起動を仕込むと良いかも。

### 8. APEX管理サービス・サインイン
- URL： https://パブリックIPアドレス:8443/apex/apex_admin
- 表示言語： 日本語を選択可能
- アカウント名： ADMIN
- パスワード： 　Passw0rd_#1

※証明書エラーとなっているだろうけど、ここでは気にしないことにする。
　https://support.oracle.com/knowledge/Middleware/2865903_1.html
　本来は、self-signed.pem, self-signed.keyを使って....するのだろうけど。

---
# さいごに
APEXの試用が目的なら、ここまでの作業で十分ためせると思います。
APEX_MAILでメールを送信するための設定は、[次の記事](https://qiita.com/viva1000/private/eedf5ae7886de07d4704)で書きたいとおもいますー