Sending Mail from OCI Databases

Oracle Cloud Infrastructure (OCI) offers various database management products such as Autonomous Data Warehouse (ADW), Autonomous Transaction Processing (ATP) and Database Cloud Service (DBCS). As we know, an Oracle database can be used to send outbound emails using utilities such as UTL_SMTP and UTL_MAIL. Additionally, APEX also offers it own utility APEX_MAIL (built on top of UTL_SMTP) which can be used to easily send emails from an APEX application. When dealing with OCI products though, it is important to note that enabling outbound email functionality involves separate set of steps depending on the product that you are using. I recently had to enable email functionality using APEX_MAIL on a Autonomous Data Warehouse (ADW) and a Database Cloud Service (DBCS) instance and the steps involved for these two OCI products are listed here. Please note that in both cases, one needs to have a subscription for Oracle Cloud Infrastructure Email Delivery service since that is the only email provider that is currently supported by ADW, ATP and DBCS. Please refer to the documentation for setting up OCI Email Delivery. At the very least, you need to create the SMTP credentials and setup the Approved Senders. Also, since the APEX_MAIL utility comes with APEX hence you need to have Apex installed as a prerequisite.

On Autonomous Data Warehouse (ADW) or Autonomous Transaction Processing (ATP)

The steps for configuring APEX_MAIL for ADW on Shared Exadata Infrastructure are relatively straightforward and are listed in this documentation. The steps for ATP instances on Shared Exadata Infrastructure are also the same. Once APEX_MAIL is configured, you can send email from an APEX application or from the APEX SQL workshop.

On Database Cloud Service (DBCS)

The corresponding steps for DBCS are slightly more complicated but the Note 2428364.1 – Database Cloud Service (DBCS / DBaaS) on OCI: How to Set Up APEX_MAIL provides all required details and some additional troubleshooting steps in case you run into issues. Maybe it is me but the instructions get a little fuzzy at the point where you need to modify the APEX Mail Server settings. Below is a screenshot from the note showing the steps to modify the APEX settings.

Here are some details on the values that need to be set for the Apex Mail Sever.

  • SMTP Host address: <Get this from your OCI Email Delivery Service instance>
  • SMTP Host Port: <Get this from your OCI Email Delivery Service instance>
  • SMTP Authentication Username: <OCID of the SMTP user that you are using>
  • SMTP Authentication Password: <Password of the SMTP user that you are using>
  • Use SSL/TLS: After connection is established
  • Default Email From Address: <You would have set this up in your OCI Email Delivery Service instance>

In DBCS, once you setup APEX_MAIL, you can then send mails using both APEX_MAIL as well as UTL_SMTP. This means that you can send outbound email not just from an APEX application but also from a custom PLSQL procedure. The latter option is quite useful since you can write a custom PLSQL procedure to send email notifications and you can call the procedure from Java Cloud Service (which does not have an in-built email functionality), Oracle Integration Cloud or any other Middleware.

Notes:

Once you have APEX_MAIL is configured, here are a couple of ways to send mails from outside the APEX application.

The first is to logon to the database from the schema associated with the APEX workspace and running the script provided below:


declare
  l_queue_id VARCHAR2 (50) := '-1';
  l_workspace VARCHAR2 (50) := 'MYWORKSPACE';
  l_security_group_id NUMBER;
BEGIN

  --initialize the session with the security attributes of the APEX workspace
  --bascially creating an APEX session in SQL
  l_workspace := SYS_CONTEXT ('userenv', 'current_schema' );
  l_security_group_id := APEX_UTIL.FIND_SECURITY_GROUP_ID(P_WORKSPACE => l_workspace);
  APEX_UTIL.SET_SECURITY_GROUP_ID(P_SECURITY_GROUP_ID => l_security_group_id);  

   l_queue_id:= APEX_MAIL.SEND(p_from => 'example_from@testing.com',
                               p_to   => 'example_to@testing.com',
                               p_subj => 'Test Subject',
                               p_body => 'Sent using APEX_MAIL');
  APEX_MAIL.PUSH_QUEUE;
END;
/

The second is to use UTL_SMTP.  You can use the PLSQL block listed in the Note 2428364.1 and pass your SMTP server/port details to send emails using UTL_SMTP.  In this case also, you have to logon to the database from the schema associated with the APEX workspace. Additionally, you also need to add an entry in the Access Control List (ACL) so that the schema user can connect to the SMTP server. You can check the ACL entry in the USER_NETWORK_ACL_PRIVILEGES view.


BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE (
  host => '',
  lower_port => null,
  upper_port => null,
  ace => xs$ace_type(privilege_list => xs$name_list('connect','resolve'),
  principal_name => '',
  principal_type => XS_ACL.PTYPE_DB));
END;
/

Using a Java Cloud Service (JCS) Instance as an SFTP Server

So, you happen to need an SFTP server for some quick-and-dirty work. But since you have moved your infrastructure to the cloud, you do not have anything on-premise to setup as an SFTP server. Well, there are many free as well as low-cost SFTP/SCP servers available online so you could use those.
Or, if you happen to have a Oracle Cloud Infrastructure (OCI) VM such as the one that comes with Java Cloud Service (JCS), you could set it up as an SFTP server.
Since the VM itself if a Unix-based system, you can configure it as an SFTP server like you would normally do for any *nix system. The steps for this are pretty much straightforward and are listed below:

  1. Login to the VM from the opc user.
  2. Change to the root user
    sudo su
  3. Create a new group for the SFTP user
    groupadd sftp_users
  4. Create a SFTP user and assign it to this group
    useradd -g sftp_users -d /myadmin -s /sbin/nologin myadmin
  5. Create SFTP root directory for the user
    mkdir -p /home/myadmin/upload
  6. Change ownership of the base directory to root
    chown -R root:sftp_users /home/myadmin
  7. Change ownership of the SFTP directory to the SFTP user
    chown -R myadmin:sftp_users /home/myadmin/upload
  8. Change permissions on the directories
    chmod 750 /home/myadmin
    chmod 750 /home/myadmin/upload
  9. Edit the sshd_config file. The changes you need to make here might differ slightly based on the VM you are using but the steps below should give you the general idea.
    vi /etc/ssh/sshd_config
  10. Edit the following parameter from no to yes
    PasswordAuthentication yes
  11. Edit the SFTP subsystem entry so that it is as shown below
    #Subsystem sftp /usr/libexec/openssh/sftp-server
    Subsystem sftp internal-sftp
  12. Add the user to AllowUsers
    AllowUsers opc oracle myadmin
  13. Add the following lines at the end of the file
    Match Group sftp_users
    ChrootDirectory /home/%u
    X11Forwarding no
    AllowTCPForwarding no
    ForceCommand internal-sftp
  14. Restart ssh services
    service sshd restart
  15. Add password to the SFTP user
    passwd myadmin
  16. The SFTP server is ready. You can access it using the IP address which you can see in the Cloud Console.