Saturday, August 30, 2025

How to integrate gmail and send email from Oracle APEX

Manually managing communications with vendors and customers in today's enterprise environment is a time-consuming and often inefficient process. Juggling emails, follow-ups, and notifications can quickly become overwhelming, leading to missed opportunities and delays. To streamline this critical aspect of business, it's essential to modernize your communication system. By integrating email directly into your business software, you can automate these interactions, ensuring timely and consistent communication without the manual effort.

I have try to demonstrate step by step how to integrate gamil account with application in Oracle APEX. For better understanding, you can follow the email configuration system.

Step 1: Create Access Control List (ACL). Connect your sys user and execute the below command-

DECLARE

    l_acl_path    VARCHAR2(3000);

BEGIN

    SELECT acl

    INTO l_acl_path

    FROM dba_network_acls

    WHERE host = '*'

    AND lower_port IS NULL

    AND upper_port IS NULL;


    IF dbms_network_acl_admin.check_privilege(

        acl                => l_acl_path

        , user            => 'APEX_240200' -- Specify your apex_user

        , privilege    => 'connect'

    ) IS NULL THEN

        dbms_network_acl_admin.add_privilege(

            acl                => l_acl_path

            , principal    => 'APEX_240200' -- Specify your apex_user

            , is_grant      => TRUE

            , privilege    => 'connect'

        );

    END IF;

EXCEPTION

    WHEN no_data_found THEN

    dbms_network_acl_admin.create_acl(

        acl                => 'SEND_MAIL.xml'

        , description => 'Email integration with Oracle APEX and send mail'

        , principle    => 'APEX_240200'

        , is_grant    => true

        , privilege    => 'connect'

    );

    dbms_network_acl_admin.assign_acl(

        acl                => 'SEND_MAIL.xml'

        , host            => '*'

    );

END;

BEGIN

    dbms_network_acl_admin.append_host_acl(

        host    => '*'

        , ace    =>  xs$ace_type(

                                 privilege_list        => xs$name_list('connect')

                                , principal_name    => 'APEX_240200' -- replace your APEX user here.

                                , principal_type    => xs_acl.ptype_db

                         )

                    );

END;

Step 2: Connect your gmail account and ensure the two step verification is enabled. Follow the below step to enable -

    i. Login your gmail account.

    ii. Click on the user icon on top right corner and then click 'Manage your google account'.

    iii. Go to the security tab from the left side navigation menu bar.

    iv. Scroll down till 'How you sign in to Google'. 

        a. Click on the '2 Step Verification'.

        b. Click on the 'Add phone number' button.

       c. Choose your country from the drop down list from the first field and then enter your phone                    number in the second field. Click next.

        d. You will get an OTP from google. Enter your phone number by providing the OTP and                             click VerifyYou will get a successful message. Click OK to finish the process.

        e. Type  'app_password' in the search bar and press enter. You will redirect to a new page. Enter                 your app name here and click 'Create' button.

         f. A popup dialog box open with your app password. This is one time password. You can't show                 this password next time in readable format. So, copy it first and then press 'Done' button.

Step 3: Download SSL certificate to create wallet. Follow the bellow step-

    1. Log in your gmail account. Click on the icon immediate before the url.


     2. A popup menu open. Click on 'Connection is secure' and then click on 'Certificate is valid'.

     

    3. A new dialog box open. Select 'Details' tab and export all three certificate from the 'Certificate                 Hierarchy one by one.


Step 4: Create Wallet using the downloaded ssl certificate. 

    a. open cmd/cerminal and execute then below command-

        orapki wallet create -wallet 'Your wallet Directory here' -pwd 'Your wallet password' -auto_login

            Note: replace Your wallet Directory here' with your physical wallet location and 'Your wallet                  password'.

    b. Add all downloaded certificate to the wallet. Execute the below command to add-

        orapki wallet add -wallet 'Your wallet Directory here' -trusted_cert cert 'Your first downloaded                 certificate path' -pwd 'Your wallet password'.

        You need to execute three time the above command by providing the different certificate path.

    c. Check, if the certificate is added or not with the wallet. To check, execute the below command-

        orapki wallet display -wallet -pwd 'Your wallet password'.

Step 5: Instance Settings. To set the workspace instance setting, follow the step below-

    i. Login into internal workspace.

    ii. Click on "Manage Instance".

    iii. Click on "Instance Settings" under Manage Instance.

    iv. Select "Email" tab and set the below properties-

            Oracle APEX instance URL: Click on "Default URL"

            Oracle APEX Image URL   : Click on "Default URL"

            SMTP Host Address            : smtp.gmail.com

            SMTP Host Port                  : 465

            SMTP Authentication Username : "Your Gmail ID Here"

            SMTP Password                  : "Google Provided Password" Which one you get in step 2

            Confirm SMTP Password   : "Google Provided Password" Which one you get in step 2

            Use ssl/tls                            : Yes

            Default Email From Address"Your Gmail ID Here"

    v. Click on wallet tab and set wallet path like "file:\physical directory of your wallet".

Step 6: Loging your application workspace and open the application.

    i. Create a blank page and take a region

    ii. Create 6 items and rename them as like P2_FROM, P2_TO, P2_CC, P2_BCC, P2_SUBJECT &             P2_BODY. Create 2 buttons, one for send email and another for close the page.

     iii. Create a page process to send the email. 

            apex_mail.send(
                p_to                => :
P2_TO

                , p_cc              => :P2_CC

                , p_bcc            => :P2_BCC

                , p_from          => :P2_FROM

                , p_subj            => :P2_SUBJECT 

                , p_body           => :P2_BODY

            );

Note: This process is only for sending text mail. No attachment will send with this process.


Integrating email functionality into your Oracle APEX applications is a game-changer for any enterprise. The steps we've covered—from setting up email credentials to coding the PL/SQL logic—provide a robust foundation for building a more responsive and intelligent application. Embracing this integration not only streamlines your business operations but also significantly enhances the user experience, making your applications more powerful and efficient than ever before.

Happy Coding. lets enjoy!

            

             


 

    



Thursday, August 28, 2025

How to preview & download files from database or local directory in Oracle APEX

It is common for Oracle APEX developers to need to handle files. This blog post will show you how to preview and download files stored in a database or a local directory. The most common approach in Oracle APEX is to store files directly in the database, typically within a BLOB (Binary Large Object) column. The primary reason is that this method simplifies data management and backup.

Sometimes, you may need to handle files stored directly on the server's file system rather than in the database. This is common for large files or when files are managed by other systems.

We will cover the basic steps and code snippets required for each method. Before approaching this tutorial, you must need to cover (preview image in large scale and save file into database/local directory) these two tutorial.

Step 1: Create a blank page and then create 3 regions. Set these three regions properties as like below-

Region-1:

    Name:         Tab Container

    Template:    Tabs Container    

Region- 2:

    Name:        From Database

    Type:        Interactive Report

    Source:

                Location:    Local Database

                Type:        SQL Query

                SQL Query:

                        SELECT employee_id

                            , first_name||' '||last_name AS emp_name

                            , job_id

                            , department_id

                            , salary

                           , email

                            , phone_number

                            , hire_date

                            , CASE file_format WHEN 'PDF' THEN

                                '<div class="rpt-container rpt-img" style="background-image: url(#APP_FILES#pdf.png)">'

                              WHEN 'IMAGE' THEN

                                '<div class="rpt-container rpt-img"><img style="width:100px; height:80px" src="'||apex_util.get_blob_file_src('P15_EMP_PHOTO', employee_id)||'">'

                              END ||'

                                    <div class="download">

                                       <div id="'||employee_id||'" style="margin-right:5px" onclick="downloadFile(this)"><span class="download-img fa fa-download"></span></div>

                                       <div id="'||employee_id||'" style="margin-left:5px" onclick="previewFile(this)"><span class="download-img fa fa-eye-slash"></span></div>

                                    </div>

                            </div>'   AS file_handle

                  FROM employees

                  WHERE storage_type = 'S2T'

Parent Region:    Tab Container

Slot:                    Tabs


Region- 3:

Name:        Local Directory

Type:         Interactive Report

Source:

                Location:    Local Database

                Type:        SQL Query

                SQL Query:

                                SELECT employee_id

                                    , first_name||' '||last_name AS emp_name

                                    , job_id

                                    , department_id

                                    , salary

                                   , email

                                   , phone_number

                                    , hire_date

                                    , CASE file_format WHEN 'PDF' THEN

                                    '<div class="rpt-container rpt-img" style="background-image: url(#APP_FILES#pdf.png)">'

                                  WHEN 'IMAGE' THEN

                                '<div class="rpt-container rpt-img"><img style="width:100px; height:80px" src="'http://localhost:9090/i/IMAGE_DIR/'||employee_id||'.'||file_type||">'

                                  END ||'

                                    <div class="download">

                                       <div id="'||employee_id||'" style="margin-right:5px" onclick="downloadFile(this)"><span class="download-img fa fa-download"></span></div>

                                       <div id="'||employee_id||'" style="margin-left:5px" onclick="previewFile(this)"><span class="download-img fa fa-eye-slash"></span></div>

                                    </div>

                            </div>'   AS file_handle

                          FROM employees

                          WHERE storage_type = 'S2D'

Parent Region:    Tab Container

Slot:                    Tabs

Note: Replace local directory using you own files path.


Step 2: Create Ajax Callback Process to prepare the files for preview & download. 

    Name:    GET_FILETYPE

    Location:    Local Database

    PL/SQL Code:

                BEGIN

                    apex_json.open_array;

                    apex_json.open_object;

                    FOR i IN (

                        SELECT file_format

                            , storage_type

                            , file_type

                            , CASE storage_type WHEN 'S2T' THEN

                                apex_web_service.blob2clobbase64(emp_photo)

                              END file_src

                        FROM employees

                        WHERE employee_id = apex_application.g_x01

                    ) LOOP

                        apex_json.write('FILE_FORMAT', i.file_format);

                        apex_json.write('STORAGE_TYPE', i.storage_type);

                        apex_json.write('FILE_TYPE', i.file_type);

                        apex_json.write('FILE_SRC', i.file_src);

                    END LOOP;

                    apex_json.close_object;

                    apex_json.close_all;

                END;



Step 3: Create Javascript function in page level 'Function and Global Variable Declaration' section to preview and download files from database & local directory-

Open code editor and paste the below code-

function previewFile(file) {

    apex.message.clearErrors();

    var empId = file.id;

    apex.server.process(

        'GET_FILETYPE'

        , {

            x01: empId

        }

        , {

            dataType: 'json',

            success: function(pData) {

                var div = document.createElement('div');

                div.setAttribute('id', 'image-display');

                var spn = document.createElement('span');

                spn.innerText = 'x';

                var src;

                if (pData[0].FILE_FORMAT === 'IMAGE') {

                    var img = document.createElement('img');

                    var srcFile = file.closest('.download').previousElementSibling;

                    src = srcFile.getAttribute('src');

                    img.setAttribute('src', src);

                    div.appendChild(img);

                } else {

                    var iFrame = document.createElement('iframe');

                    if (pData[0].STORAGE_TYPE === 'S2D') {

                        src = 'http://localhost:9090/i/IMAGE_DIR/'+empId+'.'+pData[0].FILE_TYPE;

                    } else {

                        src = 'data:application/pdf;base64,'+pData[0].FILE_SRC ;

                    }

                    iFrame.setAttribute('src', src);

                    iFrame.setAttribute('height', '600px');

                    iFrame.setAttribute('width', '100%');

                    div.appendChild(iFrame);

                }

                div.appendChild(spn);

                document.body.appendChild(div);


                document.querySelector('#image-display').style.display = 'block';

                document.querySelector('#image-display span').onclick = () => {

                    document.querySelector('#image-display').remove();

                }

            }

        }

    )      

};


function downloadFile(file) {

    apex.message.clearErrors();

    var empId = file.id;

    apex.server.process(

        'GET_FILETYPE'

        , {

            x01: empId

        }

        , {

            dataType: 'json',

            success: function(pData) {

                var link = document.createElement('a');

                if (pData[0].STORAGE_TYPE === 'S2D') {

                    link.href = 'http://localhost:9090/i/IMAGE_DIR/'+empId+'.'+pData[0].FILE_TYPE;

                } else {

                    if (pData[0].FILE_FORMAT === 'IMAGE') {

                        link.href = 'data:image/'+pData[0].FILE_TYPE+';base64,'+pData[0].FILE_SRC;

                    } else {

                        link.href = 'data:application/'+pData[0].FILE_TYPE+';base64,'+pData[0].FILE_SRC;  

                    }

                }

                link.download = empId+'.'+pData[0].FILE_TYPE;

                link.click();

            }

        }

    )

}


Conclusion:

Both methods have their pros and cons. The database approach is generally recommended for its simplicity and robustness, but there is a little bit limitation of previewing large pdf file in this way while the local directory approach is better suited for specific use cases, such as handling very large files or integrating with other file-based systems. By understanding these techniques, you can choose the best method for your specific application requirements.

Happy developing!

                                

            

Monday, August 25, 2025

How to send SMS from Oracle APEX

In today’s digitalized business solution world, SMS notifications are one of the fastest ways to reach users. Whether it’s for OTP (One-Time Password), reminders, or alerts, integrating SMS with your Oracle APEX application can add huge value. In this guide, we’ll walk through different ways to send SMS from Oracle APEX. For better understand follow this Tutorial in Youtube.


Why Send SMS from Oracle APEX?

Oracle APEX already provides built-in features for sending emails, but sometimes email isn’t enough. SMS can be useful for:

  • OTP & Two-factor Authentication

  • Order Confirmations Text

  • Notifications

  • Promotional Messages


Process to Send SMS in Oracle APEX

1. Register with Third Party SMS Gateway

Most SMS providers (like Twilio, Nexmo, or local telecom gateways) expose a REST API to send SMS. Oracle APEX supports REST integrations, so you can call these APIs directly.

Steps:

  1. Choose an SMS provider (e.g., Twilio, Nexmo, Clickatell, or your local telecom).

  2. Get your API credentials (API Key, SID, Auth Token, etc.).




2. Create Application Page To Send SMS

In this step you need to create a page to send SMS from your application. In my case, I have try to shown in two ways to send SMS. First, try to send SMS to a single receiver. And lastly shown how to send SMS to multiple users at a time.




3. Create AJAX Callback Process to Prepare Mobile No. Lists of Receivers

 Select process tab on the left side navigation pane and follow the below process-
1. select AJAX Callback.
2. Right Click here and select Create Process.
3. Paste the below code Source > PL/SQL Code in properties section-

        BEGIN

                apex_json.open_array;

                FOR I IN (

                        SELECT last_name

                                , phone_number

                                , ‘Dear ‘||last_name||’, ‘||chr(10)||’Your salary is BDT‘||salary||’ transferred to your bank.’||chr(10)||’Thank You’||chr(10)||’Payroll Section’ AS MSG

                        FROM employees

                        WHERE INSTR(‘:’||REPLACE(apex_application.g_x01,’,’,’:’)||’:’,’:’||employee_id||’:’) > 0

                ) LOOP

                        apex_json.open_object;

                        apex_json.write(‘NAME’, i.last_name);

                        apex_json.write(‘MOBILE’, i.phone_number);

                        apex_json.write(‘MSG’, i.msg);

                        apex_json.close_object;

                END LOOP;

                apex_json.close_all;

        END;

Note: Please replace appropriate single code in your pl/sql code editor.




4. Create Javascript Function to Execute AJAX Callback Process

Select page from the left side navigation pane. Select Javascript > Function and Grobal Variable Declaration. Open the code editor and paste the below code-
        function sendSms(msg, to) {
            var url = “Your API URL here"; // Must return json data
            data = new FormData()
            data.set('token', ‘Your TOKEN here')
            data.set('message', msg)
            data.set('to', to)

            var xhr = new XMLHttpRequest();
            xhr.open("POST", url, true);

            xhr.send(data);
            xhr.onload = function() {
                var response = JSON.parse(this.responseText);
                console.log(response);
                apex.message.showPageSuccess(response[0].statusmsg);
            };
        }        



5. Create Dynamic Action to SEND_SMS button
Set the below properties for that dynamic action-

        a. Name-    Send Bulk SMS
        b. Change the true action
                Action- Execute Javascript Code
                Code - 
                            
var arr = [] ;
                            arr.push($v('P38_SELECTED_EMP'));

                            if (arr[0] != '') {
                                apex.server.process(
                                    'PREPARE_DATA'
                                    , {
                                        x01: $v('P38_SELECTED_EMP')
                                    }
                                   , {
                                        dataType: 'json' ,
                                        success: function(pData) {
                                            for (var i = 0; i < pData.length; i++) {
                                            sendSms(pData[i].MSG, pData[i].MOBILE);
                                    }
                                }
                            }
                        )
                    } else {
                        apex.message.showErrors(
                            [
                                {
                                    type: 'error' ,
                                    message: 'No employee selected to send SMS!' ,
                                    location: 'page',
                                    unsafe: false
                                }
                            ]
                        )
                    }

Conclusion

Sending SMS from Oracle APEX is straightforward if you use an SMS Gateway API like Twilio, Nexmo, or your local provider. By leveraging AJAX callback process and javascript function, you can easily send OTPs, alerts, and notifications from your APEX applications.

Start small with a test SMS, then integrate it into your workflows—your users will appreciate the instant updates!