Cuando necesitamos enviar correos desde Oracle APEX, tenemos la posibilidad de usar el paquete APEX_MAIL o el paquete UTL_MAIL de la base de datos para la creación del proceso de envío de correos, sin embargo, al momento de llamar una función para enviar correos usando APEX_MAIL desde un job o una sesión fuera de las sesiones de Oracle APEX, tendremos el siguiente error: ORA-20001: This procedure must be invoked from within an application session.
¿Porqué se da el error?
El paquete APEX_MAIL debe ser llamado utilizando una sesión de Oracle APEX, es por ello que si lo llamamos usando PL/SQL fuera de una sesión de APEX o desde un job de base de datos, la función no se ejecutará.
Nota: Si desea aprender a configurar un servidor de correos en Oracle APEX, puede seguir la siguiente documentación:
https://oracle-max.com/configurando-un-servidor-de-correos-en-una-instancia-oracle-apex-19-usando-postfix/
Solución:
Para llamar el proceso y usarlo desde un job o PL/SQL, basta con decirle a la función desde cuál workspace se deberá ejecutar, para ello debemos añadirle al proceso de envío de correo las siguientes líneas:
l_workspace_id := apex_util.find_security_group_id (p_workspace => p_id_workspace); apex_util.set_security_group_id (p_security_group_id => l_workspace_id);
De esta manera nuestro proceso para enviar correos se verá de la siguiente manera, se añadieron las líneas 11, 15 y 16:
create or replace FUNCTION "ENVIO_CORREO"
(
p_to IN VARCHAR2,
p_subj IN NVARCHAR2,
p_body IN NVARCHAR2,
p_id_workspace IN VARCHAR2
)
return VARCHAR2
is
respuesta varchar2(20);
l_workspace_id number := null;
pragma autonomous_transaction;
BEGIN
l_workspace_id := apex_util.find_security_group_id (p_workspace => p_id_workspace);
apex_util.set_security_group_id (p_security_group_id => l_workspace_id);
apex_mail.send(
p_from => 'oracle.max.consultor@gmail.com',
p_to => p_to,
p_subj => p_subj,
p_body => p_body,
p_body_html => p_body
);
APEX_MAIL.PUSH_QUEUE('localhost',25); --Libera la cola de correos de Apex
respuesta := 'Correo Enviado';
return respuesta;
END;¿Cómo conseguimos el id de nuestros workspaces?:
Para saber cuál id tiene cada workspace, se debe ejecutar el siguiente select:
select WORKSPACE_ID, WORKSPACE from apex_workspaces;

Ahora solo debemos elegir el id del workspace que queramos usar para el envío de correos y enviarle ese id por parámetro al proceso, en mi caso el id es: 2300461183311886
ENVIO_CORREO('oracle.max.consultor@gmail.com','Correo de prueba','Prueba de envío','2300461183311886');De esta manera podemos llamar la función de envío de correos sin la necesidad de estar en una sesión de Oracle APEX.
