Nueva Versión!
Se ha publicado una actualización al procedimiento en el siguiente enlace
Puedes seguir leyendo este post como referencia.
Puedes seguir leyendo este post como referencia.
Desde que inicié en el mundo Oracle, me he encontrado con muchas implementaciones que te permiten hacer ciertos procesos desde la BD sin necesidad de hacerlos desde un programa externo. En esta ocasión veremos el envío de correos.
Tanto en la documentación de Oracle como en la web encontrarás muchos ejemplos y documentación, sin embargo ninguno (creo yo aplicado a un entorno real) y sin "partes ocultas".
A continuación mostraré un procedimiento que utiliza el package UTL_SMTP con el cual se pueden enviar correos a múltiples destinatarios en el Para, CC y CCO, así como múltiples adjuntos.
He de mencionar que tiene sus requerimientos.
- La lista de destinatarios y de archivos debe estar separadas por punto y coma (;) y sin espacios entre ellos (esta condición la pueden cambiar modificando el fuente), Ejemplo: 'usuario.uno@dominio.com;usuario.dos@dominio.dos.mx;usuario.tres@otrodominio.com'
- El procedimiento hace uso de un directorio lógico en donde se alojan los archivos a adjuntar, por lo que es necesario creen el directorio con el nombre que requieran en su BD y ahi coloquen los archivos.
- Se debe especificar el tipo de correo, ya sea HTML (en el parametro se coloca 'HTML') o Texto, que es el valor por default.
create or replace procedure P_SendMailAttach
(
p_DestinatariosPara VARCHAR2,
p_DestinatariosCC VARCHAR2 DEFAULT NULL,
p_DestinatariosBcc VARCHAR2 DEFAULT NULL,
p_Mensaje VARCHAR2 DEFAULT 'Haga caso omiso a este mensaje',
p_Remitente VARCHAR2 DEFAULT 'usuario@midominio',
p_Asunto VARCHAR2 DEFAULT 'Este correo no tiene asunto',
p_TipoMensaje VARCHAR2 DEFAULT 'TEXT',
p_Directorio VARCHAR2 DEFAULT 'ATTACHMENTS', -- Directorio lógico por default
p_ArchivosAdjuntos VARCHAR2
)
AS
-- ----------------------------------------------------------------------------------------------
-- Nombre : P_SendMailAttach
-- Autor : Ing. Rogelio "Wazu" Rodriguez
-- Descripcion : Envio de correos utilizando el package UTL_SMTP
-- Requerimientos : UTL_SMTP
-- Restricciones :
-- Revisiones:
-- Fecha Desarrollador Cambio
-- =========== ======================== =================================================
-- 03-APR-2012 Rogelio Wazu Rodriguez Creación Inicial
-- 30-JUL-2012 Rogelio Wazu Rodriguez Se modifica en el procedure
file_attach en content transfer
sea después de Disposition
-- 30-JUL-2012 Rogelio Wazu Rodriguez Se modifica en el procedure
file_attach en content transfer
sea después de Disposition
-- ----------------------------------------------------------------------------------------------
c utl_smtp.connection;
--Procedimiento para escritura de Headers
-----------------------------------------------------------------
PROCEDURE send_header(name IN VARCHAR2, header IN VARCHAR2) AS
BEGIN
utl_smtp.write_data(c, name || ': ' || header || utl_tcp.CRLF);
END;
-----------------------------------------------------------------
--Procedimiento para Adición de Destinatarios
-----------------------------------------------------------------------------------------------------------------------------------
PROCEDURE add_rcpt(p_Destinatarios in VARCHAR2) AS
l_Cadena varchar2(500) := p_Destinatarios;
l_LargoCadena number;
l_Comas number;
l_PosicionComa number := 0;
l_Destinatario varchar2(100);
BEGIN
l_LargoCadena := length(l_Cadena);
l_Comas := l_LargoCadena-length(replace(l_Cadena,';'));
--Bloque 1 Asginación del RCPT
IF l_Comas > 0 THEN
FOR l_segmento IN 1 .. l_Comas LOOP
l_Destinatario := substr(l_Cadena, l_PosicionComa + 1, instr(l_Cadena,';',1,l_segmento) - (l_PosicionComa + 1));
l_PosicionComa := instr(l_Cadena,';',1,l_Segmento);
utl_smtp.rcpt(c, l_Destinatario);
END LOOP;
END IF;
-- Fin de Bloque 1
-- Bloque 2: Para inserción del ultimo recipient solicitado (o el primero, si es unico)
l_Destinatario := substr(l_Cadena, l_PosicionComa + 1, l_LargoCadena);
utl_smtp.rcpt(c, l_Destinatario);
-- Fin Bloque 2
END;
---------------------------------------------------------------------------------------------------------------------------------
-- Procedimiento de adición de cabeceras para destinatarios
---------------------------------------------------------------------------------------------------------------------------------
PROCEDURE add_headers_rcpt(p_Destinatarios IN VARCHAR2, p_Type IN VARCHAR2) AS
l_Cadena varchar2(500) := p_Destinatarios;
l_LargoCadena number;
l_Comas number;
l_PosicionComa number := 0;
l_Destinatario varchar2(100);
BEGIN
l_LargoCadena := length(l_Cadena);
l_Comas := l_LargoCadena-length(replace(l_Cadena,';'));
--Bloque 1 Asginación del Destinatario al header
IF l_Comas > 0 THEN
FOR l_segmento IN 1 .. l_Comas LOOP
l_Destinatario := substr(l_Cadena, l_PosicionComa + 1, instr(l_Cadena,';',1,l_segmento) - (l_PosicionComa + 1));
l_PosicionComa := instr(l_Cadena,';',1,l_Segmento);
-- Se generan los encabezados para envio, en caso de Bcc no se agrega el Header
IF p_Type = 'TO' THEN
send_header('To', l_Destinatario);
ELSE
send_header('Cc', l_Destinatario);
END IF;
END LOOP;
END IF;
-- Fin de Bloque 1
-- Bloque 2: Para inserción del ultimo recipient solicitado (o el primero, si es unico)
l_Destinatario := substr(l_Cadena, l_PosicionComa + 1, l_LargoCadena);
IF p_Type = 'TO' THEN
send_header('To', l_Destinatario);
ELSE
send_header('Cc', l_Destinatario);
END IF;
-- Fin Bloque 2
END;
----------------------------------------------------------------------------------------------------------------------------------------------
-- Procedimiento para adjuntar los archivos al stream del correo
---------------------------------------------------------------------------------------------------------------------
PROCEDURE file_attach(p_Archivo varchar2) AS
-- Variables para el procesamiento de Archivos
rfile RAW(57);
flen NUMBER;
bsize NUMBER;
src_file bfile;
buffer_ integer := 57;
i integer := 1;
BEGIN
-- Escribir cabecera MIME
utl_smtp.write_data(c,'--MIME.Bound'||utl_tcp.CRLF);
send_header('Content-Type','application/octet-stream; name="' || p_Archivo || '"');
send_header('Content-Disposition', 'attachment; filename="' || p_Archivo || '"');
send_header('Content-Transfer-Encoding', 'base64' );
send_header('Content-Transfer-Encoding', 'base64' );
utl_smtp.write_data(c, utl_tcp.CRLF);
-- Adición del Archivo
src_file := bfilename(p_Directorio, p_Archivo);
flen := dbms_lob.getlength(src_file);
dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
while i < flen loop
dbms_lob.read( src_file, buffer_, i, rfile );
utl_smtp.write_raw_data(c, utl_encode.base64_encode(rfile));
utl_smtp.write_data(c, utl_tcp.CRLF);
i := i + buffer_;
end loop while_loop;
dbms_lob.fileclose(src_file);
utl_smtp.write_data(c, utl_tcp.CRLF||utl_tcp.CRLF);
END;
------------------------------------------------------------------------------------------------------------------------------------
--Procedimiento para separación y Adición de Archivos Adjuntos
------------------------------------------------------------------------------------------------------------------------------------
PROCEDURE add_attachments(p_Adjuntos in VARCHAR2) AS
l_Cadena varchar2(500) := p_Adjuntos;
l_LargoCadena number;
l_Comas number;
l_PosicionComa number := 0;
l_Archivo varchar2(100);
-- Variables para el procesamiento de Archivos
rfile RAW(57);
flen NUMBER;
bsize NUMBER;
src_file bfile;
buffer_ integer := 57;
i integer := 1;
BEGIN
l_LargoCadena := length(l_Cadena);
l_Comas := l_LargoCadena-length(replace(l_Cadena,';'));
--Bloque 1 Adición del Archivo
IF l_Comas > 0 THEN
FOR l_segmento IN 1 .. l_Comas LOOP
l_Archivo := substr(l_Cadena, l_PosicionComa + 1, instr(l_Cadena,';',1,l_segmento) - (l_PosicionComa + 1));
file_attach(l_Archivo);
l_PosicionComa := instr(l_Cadena,';',1,l_Segmento);
END LOOP;
END IF;
-- Fin de Bloque 1
-- Bloque 2: Para inserción del ultimo archivo (o el primero, si es unico)
l_Archivo := substr(l_Cadena, l_PosicionComa + 1, l_LargoCadena);
file_attach(l_Archivo);
-- Fin Bloque 2
END;
---------------------------------------------------------------------------------------------------------------------------------
-- Inicio del Programa Core para el correo
BEGIN
-- Bloque de Apertura de Conexión
c := utl_smtp.open_connection('165.254.254.32',25); --Recuerden que puede ser el nombre NetBios o la IP
utl_smtp.helo(c, '165.254.254.32');
utl_smtp.mail(c, p_Remitente);-- Remitente
-- Bloque de Adición de Destinatarios
IF p_DestinatariosPara IS NOT NULL THEN
add_rcpt(p_DestinatariosPara);
END IF;
IF p_DestinatariosCC IS NOT NULL THEN
add_rcpt(p_DestinatariosCC);
END IF;
IF p_DestinatariosBcc IS NOT NULL THEN
add_rcpt(p_DestinatariosBcc);
END IF;
--Bloque de Apertura de Datos
utl_smtp.open_data(c);
-- Bloque de Adición de Cabeceras de Mail
IF p_DestinatariosPara IS NOT NULL THEN
add_headers_rcpt(p_DestinatariosPara, 'TO');
END IF;
IF p_DestinatariosCC IS NOT NULL THEN
add_headers_rcpt(p_DestinatariosCC, 'CC');
END IF;
send_header('Subject', p_Asunto); --Asunto
send_header('From', p_Remitente); -- De
send_header('MIME-Version','1.0');
send_header('Content-Type','multipart/mixed; boundary="MIME.Bound"');
utl_smtp.write_data(c,'--MIME.Bound'||utl_tcp.CRLF);
send_header('MIME-Version','1.0');
IF p_Mensaje IS NOT NULL THEN
IF p_TipoMensaje = 'TEXT' THEN
send_header('MIME-Version','1.0');
send_header('Content-Type','text/plain; charset=us-ascii');
send_header('Content-Disposition', 'inline');
ELSE
send_header('MIME-Version','1.0');
send_header('Content-Type', 'text/html;charset=windows-1252');
send_header('Content-Disposition', 'inline');
send_header('Content-Transfer_Encoding', '8bit');
END IF;
END IF;
-- Bloque de Escritura del Mensaje
utl_smtp.write_data(c, utl_tcp.CRLF ||p_Mensaje||utl_tcp.CRLF);
utl_smtp.write_data(c, utl_tcp.CRLF);
-- Bloque de Envio de Adjuntos
add_attachments(p_ArchivosAdjuntos);
utl_smtp.write_data(c, utl_tcp.CRLF||'--MIME.Bound--'||utl_tcp.CRLF);
-- Bloque de Cierre de Datos y Envio del Mail
utl_smtp.close_data(c);
-- Bloque de Cierre de Conexión
utl_smtp.quit(c);
EXCEPTION
WHEN utl_smtp.Transient_Error OR utl_smtp.Permanent_Error then
-- Bloque de Cierre de Conexión
utl_smtp.quit(c);
raise_application_error(-20000, 'Unable to send mail: '||sqlerrm);
WHEN OTHERS THEN
-- Bloque de Cierre de Conexión
utl_smtp.quit(c);
raise_application_error(-20000, 'Unable to send mail: '||sqlerrm);
END;
END;
/
-- Ejemplo de uso
exec P_SENDMAILATTACH(p_DestinatariosPara =>'usuario.uno@empresa1.com;usuario.dos@empresa2.com',
p_DestinatariosCC => 'usuario@otraempresa.com',
p_Remitente => 'InformesEmpresa1@empresa1.com',
p_Mensaje =>'<h1> Informe </h1> <p>Cuerpo del Informe</p>',
p_Asunto => 'Envío de Informe Empresa1',
p_ArchivosAdjuntos => 'a6.pdf;a1.csv;A3.xml;A5.PDF;a6.txt',
p_TipoMensaje => 'HTML');
Espero les sea de utilidad el código y les confirmo que funciona al 100%, cualquier pregunta o comentario, pueden dejarlo en este post.
Hola Roger lo ejecuto y me genera el siguiente error:
ResponderEliminarOracle database error code ORA-29277 – invalid SMTP operation
A me sale el mismo error, cual sera el problema
EliminarAhi tenemos varias causas, desde que el servidor de correo no te responda (permisos de conexión, puerto o ip errónea), direcciones de email mal escritas o un comando mal enviado... necesitaría revisar como implementaste el código y como lo estás ejecutando. Puedes enviarmelo a mi email por favor.
EliminarUna disculpa por la tardanza en responder, en que línea te marca el error?
ResponderEliminarBuenos días Roger:
EliminarMe parece muy claro y útil el procedimiento y el ejemplo, y aunque aún no lo he implementado para un desarrollo que tengo que hacer en mi trabajo, tengo dos inquietudes: Primero, en la construcción del procedure P_SendMailAttach, se tienen 9 parámetros, mientras que en el ejemplo de ejecución solo hay 7 (falta el parámetro 3 (Bcc), y el 7, Directorio lógico), supongo que el 3 lo debo incluir en NULL si no requiero Bcc, y el 7 con el valor del directorio lógico ( para el caso de su ejemplo,"ATTACHMENTS", cierto? Y la segunda inquietud, es precisamente respecto al directorio lógico, en mi caso, los archivos a adjuntar los tengo guardados en un servidor de WCC (Web Center Content), y el path de ubicación es como "http://gestiondocumental:10300/url .../arch.pdf"
ese seria el directorio lógico ? o puedeo prescindir de ese parámetro y enviar toda la cadena del path incluyendo el nombre del archivo en el parámetro archivos adjuntos? Agradezco su pronta respuesta, pues me urge este desarrollo, Germán
Para el caso de tu primera inquietud, el procedimiento maneja valores por default para casi todos los parámetros, si los mandas con valor NULL puede que se presente algún error.
EliminarEn el caso del directorio lógico, la Base de Datos espera una referencia a una ubicación de FileSystem, esto lo puedes ver en la documentación de Oracle siguiente: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5007.htm
Ahora, algo que puedes hacer es hacer el llamado HTTP a tu WCC desde un procedimiento almacenado, y que el procedimiento procese el archivo como un BLOB y lo almacene en un directorio de la BD.
A mi punto de vista, si el archivo ya lo tienes en un BLOB solo tendrías que hacer unos ajustes al procedimiento interno fileattach para que procese ese BLOB y lo adjunte al correo quitando el paso de bajarlo a tu servidor y quede ahí almacenado.
Hola Roger:
ResponderEliminarAgradecerte muy sinceramente tu código; funciona muy, muy bien. Sólo comentarte que hay una pequeña errata en el procedimiento file_attach y es que la línea trasnfer_encodding debe ir tras la linea disposition.
Un saludo
Muchas gracias, haré la corrección del mismo. Sinceramente muy claras las reglas del HTML.
EliminarHola Roger,
ResponderEliminarEl procedimiento me genra este error :
Unable to send mail: ORA-29279: SMTP permanent error: 501 could not parse your mail from command
Saludos,
JF
En tu caso mi estimado, el problema radica en la sintaxis de la dirección de email, alguna no cumple con el patrón cuenta@dominio.
EliminarUtiliza la función UTL_SMTP.VRFY para validar tus direcciones de email.
Hola.. tengo el mismo problema
ResponderEliminarORA-20000: Unable to send mail: ORA-29279: SMTP permanent error: 530 5.7.0 Must issue a STARTTLS command first. n20sm10251459anl.19
Si lo han resuelto por favor escribirme a @n0rf3n en twitter..!!
GRacias.
Aqui el detalle es que para conectarte a tu servidor SMTP debes mandar tus credenciales de usuario para el mismo con el procedimiento UTL_SMTP.COMMAND, estoy buscando como hacer esa comprobación utilizando el protocolo STARTTLS. Si lo encuentro te lo envio, si lo encuentras primero, lo compartes =)
EliminarHola Roger,
ResponderEliminarmuchas gracias por el aporte, el procedure funciona perfecto, pero tengo una duda, cuando llega el correo, no llega con el adjunto, sino incrustado en el cuerpo del mensaje y codificado, podrias ayudarme?
Gracias.
Suso.
Técnicamente asi son los correos con adjuntos, estos van "incrustados"en el mensaje en código ilegible, pero el cliente de correo se encarga de interpretarlo.
EliminarDeberías revisar tu cliente de email o tu server de.correo, ya que por razones de seguridad bloquean cierto contenido.
Actualmemte tengo este procedimiento en mi entorno productivo y na ha habido detalles con la recepción de adjuntos
Hola muchas gracias por la ayuda, solo tengo un pequenio problema y es que al enviar el adjunto no me adjunta el archivo sino que manda una cadena asi :
ResponderEliminarssss --MIME.Bound Content-Type: application/octet-stream; name="NOMINA.PDF" Content-Disposition: attachment; filename="NOMINA.PDF" Content-Transfer-Encoding: base64 --MIME.Bound--
Que puede estar pasando??
Muchas gracias :)
Le comentarie estas lineas
ResponderEliminar-- Bloque de Escritura del Mensaje
-- utl_smtp.write_data(c, utl_tcp.CRLF ||p_Mensaje||utl_tcp.CRLF);
-- utl_smtp.write_data(c, utl_tcp.CRLF);
y me adjunto el archivo pero al momento de abrirlo ahora me sale que esta daniado.
:(
Listo lo solucione comentareando las lineas
ResponderEliminar-- Bloque de Escritura del Mensaje
-- utl_smtp.write_data(c, utl_tcp.CRLF ||p_Mensaje||utl_tcp.CRLF);
--utl_smtp.write_data(c, utl_tcp.CRLF);
-- Bloque de Envio de Adjuntos
add_attachments(p_ArchivosAdjuntos);
--utl_smtp.write_data(c, utl_tcp.CRLF||'--MIME.Bound--'||utl_tcp.CRLF);
Hola Sindy:
EliminarVeo que comentaste unas líneas, sin embargo, observo que quitaste la escritura del mensaje (cuerpo) del correo. Posiblemente en tu caso sobre la línea de inserción del Boundary únicamente.
En mi caso, utilizamos un servidor Exchange y no se me había presentado ese problema.
¿Qué servidor de correo utiliza?
Gracias por el apoyo :)
Como decimos en España, eres un máquina, un fiera, o lo más utilizado en Andalucía, un monstruo.
ResponderEliminarSaludos y gracias, es de gran utilidad.
Hola Roger tengo un problemita no con el procedimiento sino la forma en que guardo los archivos a enviar.
ResponderEliminarEn forms 6i tengo un procedimiento mando a imprimir pero en pdf, no lo manda a la impresora sino que los guarda en una carpeta. Dentro del codigo hago esto:
Add_Parameter(list_id, 'DESTYPE', TEXT_PARAMETER, 'FILE');
Add_Parameter(list_id, 'DESNAME', TEXT_PARAMETER, 'Y:\nomarchivo.PDF');
Add_Parameter(list_id, 'MODE', TEXT_PARAMETER, 'BITMAP');
Add_Parameter(list_id, 'PRINTJOB', TEXT_PARAMETER, 'NO');
Add_Parameter(list_id, 'DESFORMAT', TEXT_PARAMETER, 'PDF');
Run_Product(REPORTS, 'NOM1002.Rep', SYNCHRONOUS,RUNTIME,FILESYSTEM,list_id);
Destroy_Parameter_List(list_id);
ENV_EMAIL_ADJUNTO (mail,'NOMINATEAM2','nomarchivo.PDF');
La forma que contiene este codigo no se ejecuta en el servidor de oracle sino en un cliente y para esto creo una unidad de red "Y" que apunta a la carpeta que utilizo en el procedimiento ENV_EMAIL_ADJUNTO (que ya esta creada logicamente y fisicamente en el servidor). El me funciona perfectamente y envia los correos pero el punto es que no quiero que haya una unida de red en el cliente sino que exista una forma que lo haga sin crear la unidad en la opcion DESNAME. No se si logro explicarme.
NOMINATEAM2 es el directorio logico.
y el procedimiento ENV_EMAIL_ADJUNTO es un procedimiento almacenado.
Muchas gracias!!!
Hola Roger.
ResponderEliminarPara aclarar yo puedo colocarle en desname la ruta en C:\nomarchivo.pdf para q me genere el pdf en el equipo cliente el problema es que en el procedimiento como tu lo indicas debo crear el directorio logico y fisico en el servidor. Pero como hago para que me trabaje como yo quiero si el pdf se me genera es en C del cliente(en el caso que no utilice la unidad de red que si apunta a la carpeta creada en el servidor).
Gracias!!!!!
Aqui creo que esta mas explicado mi problema
ResponderEliminar1. - A traves de una Forma(Developer) generamos un documento en PDF en el disco local del cliente, pero no lo podemos enviar por correo.
2. - Desde el servidor de Base de Datos podemos enviar un correo con cualquier adjunto que este en una ruta dada del mismo, pero no logramos generar allí(en el servidor) el adjunto que queremos enviar.
Ahora bien, lo que se quiere es poder generar este reporte(PDF) en el servidor para poder enviarlo por correo posteriormente, como sabes el usuario final o cliente no podra copiar al servidor por tal motivo el proceso de generar dicha información debe quedar del lado del servidor en un 100%.
Conoces algún procedimiento almacenado propio de Oracle o alguno desarrollado que me pueda ayudar.
Gracias por su ayuda y colaboración.
Hola Sindy!
EliminarEn este caso podrías utilizar el directorio lógico apuntando a una carpeta compartida en la PC cliente, utilizando la nomenclatura de netbios (si tus usuarios usan windows). El detalle aquí, es que tendrías que crear tantos directorios lógicos como usuarios utilicen esa forma.
Si son pocos usuarios, creo que se solucionaría tu caso. Si esto no es factible y utilizando lo que ya tienes, en vez de crear la unidad mapeada en la máquina del usuario, en tu parámetro DESNAME coloca la ruta netbios de la carpeta compartida, algo así como \\nombredelservidor\carpeta.
De cualquier modo me llevo tu consulta de tarea por si encuentro otra solución.
Ignora la primer solución... se nota que estaba dormido ;-)
EliminarLo factible en lo que investigo si hay otro modo es la segunda.
Recuerda que debes de apoyarte con el administrador del servidor para aquello de los permisos en la carpeta compartida.
Sindy:
ResponderEliminarInvestigué un poco sobre tu caso, y al no encontrar nada que te pueda ayudar de manera directa, analizando un poco lo que ya te había propuesto se me ocurrió algo que te puede servir.
Requisitos:
El parámetro de Base de Datos UTL_FILE_DIR debe estar en '*' (se que eso lo ven como una vulnerabilidad de seguridad, para algunos auditores, sin embargo es controlable)
Crear una tabla en la que se almacene el Username y la ruta de la carpeta compartida en su PC en la forma \\nombrePC\CarpetaCompartida . Si tu usuario cambia de máquina de manera constante, te recomiendo almacenar el nombre de la PC (que puedes obtener desde Forms) y la ruta de la carpeta compartida.
En la carpeta compartida, el usuario maquina del servidor de Base de Datos (solicita apoyo con el administrador de servidores) debe tener permiso de lectura y escritura sobre dicha carpeta.
Con estos requisitos previos, modificas tu procedimiento para que reciba como parámetro el Username o el nombre del Equipo según lo que hayas decidido al crear la tabla. Buscas la ruta que tiene registrada y al enviar el correo le indicas dicha ruta para la obtención del archivo adjunto.
Espero te sirva la propuesta y si realizas otra, no se te olvide compartirla en este espacio.
Muchas gracias Roger me han servido tus comentarios, ya se que puedo crear un directorio logico apuntando a una carpeta compartida en el equipo del cliente y no en el servidor lo cual no seria necesario crear una unidad de red. Con respecto a la tabla para guardar el equipo y la carpeta compartida esta super voy a intentarlo.
ResponderEliminarMuchisimas gracias de nuevo
Hola Roger, muchas gracias por el código; por favor si me puedes indicar que hacer para el siguiente error al probar el procedure...
ResponderEliminarORA-29278: SMTP transient error: 421 Service not available
ORA-06512: at "SYS.UTL_SMTP", line 21
ORA-06512: at "SYS.UTL_SMTP", line 97
ORA-06512: at "SYS.UTL_SMTP", line 399
ORA-06512: at "BBRAUN.P_SENDMAILATTACH", line 332
ORA-29278: SMTP transient error: 421 Service not available
ORA-06512: at line 1
Slds
Wilson
Tarde pero seguro!
EliminarEn tu caso mi estimado, no se está estableciendo una conexión con tu servidor SMTP, ya sea por bloqueo o que el servicio no esté disponible (apagado, dado de baja...)
Perfecto , funcionó en el primer intento , muchas gracias
ResponderEliminarHola roger tengo una duda he hecho de todo para este proceso pero tengo un error y no se que es, ya verifique permisos y todo pero no se que es para que por favor me puedas colaborar..
ResponderEliminarORA-29277: invalid SMTP operation
ORA-06512: at "SYS.UTL_SMTP", line 44
ORA-06512: at "SYS.UTL_SMTP", line 150
ORA-06512: at "SYS.UTL_SMTP", line 383
ORA-06512: at "SYS.UTL_SMTP", line 399
ORA-06512: at "CO.P_SENDMAILATTACH", line 281
ORA-22285: non-existent directory or file for GETLENGTH operation
ORA-06512: at line 1
Disculpa que me intrometa, los errores que te marca son de que el archivo al que estas intentando acceder fue denegado por el servidor o no existe, comprueba que tu directorio sea valido y que tengas los permisos para acceder a el y a los archivos. Puedes crear un procedimiento para crear un archivo remoto, luego para escribirlo y leerlo y asi comprobaras los permisos para acceder al directorio. Suerte
EliminarMuchísimas gracias por tu trabajo, llevaba buscando un código que hiciera esto mismo desde hace mucho tiempo y el tuyo es perfecto para lo que necesito.
ResponderEliminarUn abrazo muy fuerte y gracias por compartir tus conocimientos.
Buenas tardes, a todos, a los que han logrado la implementacion los que aun no (me incluyo), las siguientes dudas:
ResponderEliminar1- Funciona para la version 10gR2.
2- Debo de crear los procedures en la base de datos? o puede ser desde una forma.
3- Roger, podrias crear un video tutorial en youtube, a veces es mas fácil visualizar procedimientos.
Saludos.
Rodrigo:
EliminarUna disculpa por la tardanza en contestar, pero por razones laborales no he podido entrar a ver comentarios ni actualizar entradas en mi blog.
Las respuestas a tus preguntas son las siguientes:
1.- Si, funciona para 11g, de hecho el código es funcional (probado) con versión 9i, 10g y 11g (que es donde lo tengo implementado actualmente)
2.- En efecto, el procedimiento es para crearse como Stored Procedure en la BD y ya si lo necesitas, lo mandas a llamar desde una forma.
3.- Si la agenda me lo permite, lo colgaré aquí mismo.
Muchas gracias amigo solo me faltaba agregarle el envio de adjuntos ademas me esta costando un poco integrarlo ya que para el envio de correos en mi procedimiento coloco banderas y excepciones de un proceso que corro antes que este, es decir si en el otro hay errores no debe enviar correo, y si no hay q enviarlo y cambiar banderas, en fin de todas formas muchisimas gracias!
ResponderEliminarNo funciona desde Forms, manda el siguiente mensaje error 29277
ResponderEliminarHola Carlos!
EliminarNecesitaría conocer como estás implementando el procedimiento y tu entorno (versión de Forms, Servidor de mail).
Yo lo he probado con Forms 6i y 10g y no me ha dado problema alguno.
Buena Tarde Roger, he implementado el Procedimiento y me genera un error
ResponderEliminarORA-20000: Unable to send mail: ORA-29279: SMTP permanent error: 503 5.5.1 Error: send HELO/EHLO first
ORA-06512: at "P_SENDMAILATTACH", line 279
ORA-06512: at line 23
espero me puedas ayudar.
Muchas Gracias.
Al parecer omitiste la línea utl_smtp.helo, o revisa la IP que estás pasando como parámetro.
EliminarSi el problema persiste, envíame tu implemetación para revisarla
Al parecer omitiste la línea utl_smtp.helo, o revisa la IP que estás pasando como parámetro.
ResponderEliminarSi el problema persiste, envíame tu implemetación para revisarla
Buenas tardes, has utilizado la funcion utl_smtp.vrfy?
ResponderEliminarEstoy tratando de implementar pero me regresa un codigo 252, 2.1.5 Cannot VRFY user
He leido en unos lugares(blog) que es por que el servidor SMTP no es compatible o algo asi, el servidor es un exchage que utilizo, verifico cuentas de hotmail, gmail, live, outlook, y del propio dominio y me sale el mismo codigo
Buena Tarde Roger la linea no fue omitida la tengo en el lugar donde tu la tienes,
ResponderEliminarc := utl_smtp.open_connection('10.18.117.200',25);
utl_smtp.command( c, 'AUTH LOGIN');
utl_smtp.helo(c, '10.18.117.200');
utl_smtp.mail(c, p_Remitente);
realice una prueba con otro procedimiento que no tiene datos adjuntos para mirar si era la ip pero el correo salio sin inconveniente, el error aun persiste, la ejecución que estoy haciendo es la siguiente:
DECLARE
P_DESTINATARIOSPARA VARCHAR2(32767);
P_DESTINATARIOSCC VARCHAR2(32767);
P_DESTINATARIOSBCC VARCHAR2(32767);
P_MENSAJE VARCHAR2(32767);
P_REMITENTE VARCHAR2(32767);
P_ASUNTO VARCHAR2(32767);
P_TIPOMENSAJE VARCHAR2(32767);
P_DIRECTORIO VARCHAR2(32767);
P_ARCHIVOSADJUNTOS VARCHAR2(32767);
BEGIN
P_DESTINATARIOSPARA := 'misama20@gmail.com';
P_DESTINATARIOSCC := NULL;
P_DESTINATARIOSBCC := NULL;
P_MENSAJE := 'Haga caso omiso a este mensaje';
P_REMITENTE := 'usuario@midominio.com';
P_ASUNTO := 'Este correo no tiene asunto';
P_TIPOMENSAJE := 'Prueba';
P_DIRECTORIO := '/orabackup/expSRH_dat061713.log';
P_ARCHIVOSADJUNTOS := '/orabackup/expSRH_dat061713.log';
HR.P_SENDMAILATTACH ( P_DESTINATARIOSPARA, P_DESTINATARIOSCC, P_DESTINATARIOSBCC, P_MENSAJE, P_REMITENTE, P_ASUNTO, P_TIPOMENSAJE, P_DIRECTORIO, P_ARCHIVOSADJUNTOS );
COMMIT;
END;
lo he intentado con las variables
P_DIRECTORIO := NULL;
P_ARCHIVOSADJUNTOS :=NULL;
Y aun asi me genera el mismo error.
ORA-20000: Unable to send mail: ORA-29279: SMTP permanent error: 503 5.5.1 Error: send HELO/EHLO first
ORA-06512: at "HR.P_SENDMAILATTACH", line 279
ORA-06512: at line 23
Espero me puedas colaborar muchas Gracias.
Buenas noches milton, no se si te pueda ayudar, pero puedes realizar un cambio en tu codigo: debes tener primero la conexion, despues el helo y despues el resto del codigo, veo que utilizas autenticacion con el server, pero no veo el codigo del usuario y pass, no se si asi el codigo se ejecute correctamente, puedes verificar si jala correctamente o no....
Eliminarc := utl_smtp.open_connection('10.18.117.200',25);
utl_smtp.helo(c, '10.18.117.200');
utl_smtp.command( c, 'AUTH LOGIN');
utl_smtp.mail(c, p_Remitente);
Milton, como menciona el compañero Anónimo y recordando como es el proceso del protocolo SMTP (ver http://es.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#Resumen_simple_del_funcionamiento_del_protocolo_SMTP) tiene razón en el orden que menciona. Podrías intentarlo por favor y comunicarnos el resultado obtenido.
EliminarAnónimo, muchas gracias por el apoyo!
Buenas tardes, has utilizado la funcion utl_smtp.vrfy?
ResponderEliminarEstoy tratando de implementar pero me regresa un codigo 252, 2.1.5 Cannot VRFY user
He leido en unos lugares(blog) que es por que el servidor SMTP no es compatible o algo asi, el servidor es un exchage que utilizo, verifico cuentas de hotmail, gmail, live, outlook, y del propio dominio y me sale el mismo codigo
Att: Anonimo.
Según la documentación de Oracle dicha función es para validar direcciones de correo electrónico con el servidor SMTP, sin embargo considero que por seguridad no deben permitir que una dirección externa o no administrativa realice tal validación.
EliminarRoger DBA gracias por tu codigo de envio de email con archivos atachados, una pregunta que tiempo demora en enviar el precedimiento el email con el archivo atachado? gracias, saludos jose
ResponderEliminarSi consideramos que tu servidor SMTP y Base de Datos están sobre una LAN y el tamaño de los archivos es de hasta 1024K, el tiempo de envío es mínimo (del orden de >1 a 10 segundos), si tu servidor SMTP o de Base de Datos se encuentran conectados en una MAN o WAN, considera el tiempo de transferencia del archivo a tu servidor de SMTP para poder enviarse (algo así como cuando envías un correo con adjuntos a traves de un webmail).
EliminarSi estás en una LAN y notas que el procedimiento se tarda, deberás revisar tu base de datos si no está sobrecargada (la lectura de archivos y su envío implican consumo de recursos), después tu servidor SMTP y por último la red de comunicación entre ellos.
Roger DBA, gracias por la respuesta.
EliminarTe comento que probe el procedimiento y me sale este error,ORA-29279 por favor me puedes ayudar con el error? gracias.
Te comento que la base de datos esta instalado sobre Linux.
En la pc que estoy ejecutando tiene windows xp y ya intale el IIS (Servicio de INternet de informacion server).
Gracias.
Saludos.
Roger DBA buenos dias, solucione el problema ORA-29279, ahora me sale el error ORA-29277 , por favor si me puedes ayudar. Gracias. Jose.
EliminarRoger ya encontre el problema, el procedimiento se ejecuta bien, cuando comento la linea de envio de arcvhivos, y se cae en el procedimiento file_attach en la linea --> flen := dbms_lob.getlength(src_file);
Eliminargracias por la respuesta.
José, sería necesario revises exactamente en que punto está generándose el error para poder ayudarte.
EliminarRealiza un debug del procedimiento ejecutándolo con los valores que te generen error.
Te recomiendo el uso de SQL Developer para esta actividad, además de que le digas a tu DBA te de privilegios de DEBUG en tu sesión y el procedimiento.
Si está fallando en esa línea es por que la base de datos no tiene permisos de lectura sobre el archivo o este no existe en la ruta especificada.
EliminarRevisa ese punto y me comentas.
Roger ya esta, ya envia email con archivos atachados, el problema era que no habia un directorio virtual , se creo, se almaceno los archivos que deseo envia y salio. Esta de la puta madre el procedimiento!! Gracias.
EliminarQue bueno que te haya servido y gracias a ti por la paciencia en la respuesta a tus preguntas.
EliminarRoger DBA, buenos dias, una consulta,
EliminarDesde la forma (oracle developer 10g), el usuario genera un archivo texto, y lo guarda en su disco C, luego deseo , ese archivo de texto, deseo guardarlo en el disco duro del servidor de base de datos o directorio virtual de oracle, para luego coger ese archivo de texto y enviarlo como archivo atachado, el problema es que , cuando deseo llevar el archivo de texto al servidor virtual no lo hace, para luego ese mismo archivo enviarlo por forms, conoces alguna herramienta que me ayude a gestionar el caso expuesto??, hey probado PSCP (transferencia de archivos, lo hago mediante archivo bath) y no me funciona. Gracias por la respuesta. saludos.
Buenos días:
EliminarPrimero hay que revisar por que no puedes enviar el archivo a la carpeta de tu server de base de datos. ¿Tienes acceso a la carpeta por medio de alguna ruta compartida? ¿Tiene el usuario permisos para escribir sobre esa carpeta?
Gracias por la respuesta. Para la primera interrogante si hay acceso a la ruta compartida, para la segunda interrogante: el usuario puede escribir.
ResponderEliminarAdicionalmente se menciona que ya existe otro archivo .BAT que usa el comando copy y funciona correctamente, claro que este archivo solo hace copias dentro del mismo servidor.
Nota: Ambos archivos .BAT estan contenidos en la misma carpeta.
No me queda muy claro el escenario, puedes pasarme una dirección de email para escribirte y apoyarte ya que tu problema siento que es más de privilegios y configuraciones a nivel SO que de Base de Datos.
EliminarRoger DBA, gracias, ya esta resuelto el tema, otra pregunta, como puedo obtener la clave del SYS , si me hey olvidado la clave de ese esquema.Gracias.
EliminarNo puedes saber la contraseña ni recuperarla, la única opción que tienes es ingresar con otro usuario que tenga permisos de SYSDBA, DBA o de ALTER USER y asignarle una nueva contraseña al usuario SYS. Si esto te funciona, como consejo, coloca una contraseña que te sea fácil no olvidar pero que a la vez sea compleja.
EliminarGracias Roger DBA.
EliminarHola Roger DBA, muy buen script, funciona correctamente, sabes de alguna manera de comprimir los archivos antes de que estos se adjunten al correo.
ResponderEliminarSaludos
Una opción es que crees un procedimiento almacenado java para ejecutar la compresión en .zip
EliminarOtra opción es el uso del package dbms_pipe, que según la documentación sirve para ejecutar comandos UNIX, en lo personal no lo he utilizado.
De igual forma si me describes tu escenario, puede que tenga una mejor respuesta o solución a tu necesidad.
Saludos
Roger gracias por tu respuesta, lo que hacemos es enviar correos con reportes semanales todos los viernes a la media noche, estos reportes ahora pasan los 1.5MB y ya no llegan a pasar por correo.
EliminarEsto lo hacemos desde un oracle express ya que solo tenemos acceso de lectura al server principal y segun lei no se puede ejecutar java desde oracle express, es cierto eso?
intentare hacer algo con el package dbms_pipe que indicas y te comento.
Saludos
Sobre la limitante de Oracle Express Edition es cierta, no puedes crear o compilar procedimientos java (aquí esta la tabla de características http://docs.oracle.com/cd/E17781_01/license.112/e18068/toc.htm#XELIC118).
EliminarSi lo de dbms_pipe no te funciona te recomendaría, para efectos prácticos, sea una aplicación (hasta en consola si quieres) que se encargue de extraer la información, generar el reporte, comprimirlo y enviarlo por correo. Puedes crear procedimientos en la base para la extracción de Info y el envío del correo si así lo deseas o dejarle todo el trabajo a la aplicación.
Saludos!
Roger DBA buenas noches, tu procedimiento como te comente dias atraz, funciona bien, la consulta que te queria hacer es, que hay momentos que envia bien el email con archivos atachados y otros momentos que envia el email con archivo atachado y sale lleno de codigo US7ASCII (codigo ascii 7 bits) el cuerpo del email enviado? porque sera? , gracias por la respuesta. saludos jose.
ResponderEliminarUna pregunta, cuando en el mail se muestra código ASCII ¿Qué tipo de archivos son? ¿Todo tipo? ¿TXT, PDF, etc?
EliminarSaludos!
Roger DBA buenas tardes, estoy haciendo mis pruebas con archivos PDF, gracias.
EliminarRoger por favor si puedes responderme.
EliminarRevisando lo mencionado, en el procedimiento que adjunta el archivo está la línea
Eliminarsend_header('Content-Type','application/octet-stream; name="' || p_Archivo || '"');
Ese tipo de Conten-Type es genérico para admitir cualquier tipo de archivos, pero no es interpretado de la misma manera por todos los clientes de correo.
En esta página vienen los códigos MIME para cada extensión de archivo http://en.wikipedia.org/wiki/Internet_media_type que en el caso de archivos PDF corresponde a application/pdf.
Por lo tanto la línea antes mencionada quedaría de la siguiente forma:
send_header('Content-Type','application/pdf; name="' || p_Archivo || '"');
Considera que si vas a enviar otro tipo de extensiones de archivo, deberás colocar el MIME Type correspondiente
Saludos!
Roger DBA, ya corregi lo que me dices, send_header('Content-Type','application/pdf; name="' || p_Archivo || '"'); , pero hey realizado la prueba y de cada 15 envios 4 se caen (envia con codigo ascii), que falta por corregir por favor?...saludos
EliminarRoger DBA, lo que pasa, es cuando lo decodifica los archivos en el proceso file_attach y los archicos son pesados, te envia cel email con codigo ascii, cual puede ser el error?
EliminarEl procedimiento no tiene límite para el tamaño de envío de adjuntos, aquí he enviado archivos de hasta 10MB sin problema.
EliminarSin embargo pueden ser otras las causas de que el archivo se trunque y por eso te salga código ASCII.
En los correos erróneos revisa en modo texto el archivo (con el notepad u otro editor) y ve si se completa el boundary de fin del archivo, si el proceso se trunca deberás realizar un debug del procedimiento para ver como está trabajando.
Otro punto a revisar es que el tamaño del archivo a adjuntar esté dentro de los límites permitidos por el servidor de correo saliente de tu empresa.
Roger BDA, buenos dias, realice un estudio en donde se cae y el correo envia con codigo ascci , se cae en la parte :
EliminarIF p_Mensaje IS NOT NULL THEN
IF p_TipoMensaje = 'TEXT' THEN
send_header('MIME-Version', '1.0');
send_header('Content-Type', 'text/plain; charset=us-ascii');
send_header('Content-Disposition', 'inline');
ELSE
send_header('MIME-Version', '1.0');
send_header('Content-Type', 'text/html;charset=windows-1252');
send_header('Content-Disposition', 'inline');
send_header('Content-Transfer_Encoding', '8bit');
END IF;
END IF;
Si yo comento la parte del codigo , mostrado lineas arriba, todos los correos enviados con archivos atacachados me SALE MUY BIEN (los crorreo se envian sin ningun mensaje en el cuerpo del email), y si vuelvo a colocar la parte de codigo mostrado arriba, de 15 envios , 5 envia con codigo ascii y 10 envia bien y asi sucesivamente.Que puede estar fallando ,.....Gracias por la respuesta. Jose.
Honestamente al día de hoy no me ha pasado nada similar, lo que me sorprende es que la muestra de exito y error es constante. Lo que puedes hacer es cambiar esta línea send_header('Content-Type', 'text/plain; charset=us-ascii'); por send_header('Content-Type', 'text/plain; charset=ISO-8859-1'); y también revisar que los boundary estén completos.
ResponderEliminarGracias voy a hacer lo que me dices.
EliminarVoy a subir más tarde una actualización al Procedimiento, sucede que el día de hoy se realizaron pruebas con un nuevo servidor SMTP en la empresa donde laboro y en mi caso el 100% de correos con adjuntos presentan el síntoma que describes (no me pasó el de unos sí y otros no).
EliminarHice pruebas enviando el correo con UTL_MAIL y ahí si se envió el adjunto correctamente.
Revisé el contenido de los mensajes con un editor de texto y ahí pude observar que no se interpreta del mismo modo el como yo estructuro los encabezados y mensaje del correo a enviar.
Ya realicé las modificaciones pertinentes y lo subiré en un nuevo post para que este quede tal cual está y puedan observar el cambio en la implementación.
Espero esto poder realizarlo a más tardar mañana, para por favor seas paciente.
Saludos!
Gracias Roger DBA, saludos. Queria hacerte otra pregunta, conoces de algun procedimiento, que realize la accion, desde la pc del usuario se seleccione un archivo pdf (que esta en directorio virtual del servidor de base de datos)y lo lleve a la pc del usuario, (al disco C), gracias. Jose.
EliminarJosé:
EliminarConsidero que puedes realizar un procedimiento o función que retorne un LOB, sin embargo, la aplicación o programa de donde lo llames deberá soportar recibir este tipo de dato como salida.
De igual forma, como te he pedido en otras ocasiones, si me explicas mas detalladamente el contexto de lo que requieres hacer, puedo apoyarte con una mejor respuesta.
Saludos!
Gracias por la respuesta, se realizo el envio del archivo mediante DOS desde forms y con la ayuda de un programa que hace ese transporte se realizo, lo llamas lo ejecutas y hace el transporte del archivo.GRacias,
EliminarTe queria hacer una consulta, deseo migrar programas de oracle forms de 6i a version oracle 10g , uno de los metodos es utilizando el Java Design-time API (JDAPI), mi preguntas es , si haz realizado migracion de oracle forms 6i a forms 10g? que metodo utilizastes y si tienes algun manual tecnico para que me ayude a configurar el Java Design-time API (JDAPI) y poder realizar la migracion masivamente, Gracias por la respuesta.
Hola José!
EliminarQue bueno que hayas encontrado solución a tu caso. ¡Felicidades!
Sobre la migración de Forms 6i a 10g con JDAPI, te comento que no he migrado ninguna forma con tal herramienta, leí un poco y te puedo decir que JDAPI no es un programa, es una librería que tienes que cargar en un IDE para Java (Eclipse, JDeveloper [preferentemente]) con la cual construyes programas Java que realizan cambios en las formas. Este link te puede ayudar http://blog.avanttic.com/2010/02/12/jdapi-nos-ayuda-a-migrar-aplicaciones-forms/
En su momento, hice migración de formas de manera manual, abriendo el fuente 6i en Forms Developer 10g, pero todo, lógicamente, lo tienes que hacer uno a uno.
Otro comentario que quiero hacerte es que Oracle tengo entendido va a descontinuar Forms y Reports (actualmente en su versión 11g) y todo apunta a ADF. No sé si tu compañía esté interesada en dar ese salto o la decisión definitiva es pasar a 10g.
Saludos!
Gracias Roger, por la respuesta, la empresa donde estoy solo desea migrar a 10g, el link que me distes ya le hize una consulta pero no responde, tienes otro link para consultar o manual para hacer migracion de 6i a 10g masivamente?...gracias. saludos jose.
EliminarHola Roger !!
EliminarGracias por la ayuda en este 2014, feliz navidad y feliz año!! saludos.
Jose.
Gracias por las felicitaciones, y de igual forma, espero la hayas pasado bien en estas fechas con la familia y seres queridos.
EliminarSobre el link, acabo de entrar en mi navegador y funciona correctamente, intenta de nuevo.
Saludos!
Hola Roger, gracias por la respuesta.
EliminarUna pregunta, queria preguntarte si haz tenido experiencia o desarrollas en EBS de oracle, deseo iniciarme en EBS y deseo conseguir tutoriales y links de los principales modulos. Gracias por la respuesta. Saludos!! Jose.
Este comentario ha sido eliminado por el autor.
EliminarEste comentario ha sido eliminado por el autor.
EliminarRoger buenos dias, por favor te deseo hacer una consulta, sobre report:
Eliminar- En mi PC tengo usuario adminitrador y otros usuarios, cuando ingreso con usuario adminustrador ,entro al menu y realizo cualquier reporte de oracle reporte sale bien y envio dicho reporte por email (la opcion de enviar nativo desde el oracle report) y envia bien.
- Cuando hago la misma operacion con otro usuaruio (diferente a administrador) , sale bien el reporte, pero cuando envio dicho reporte por email, me sale un error, el cual me menciona que no puede atachar los archivos, dicho error hace mencion, QUE NO PUEDE LEER LA CARPETA DESDE DONDE COGE EL ARCHIVO Y POR ESO SALE ERROR, ya hey dado permiso a dicho usuario, para que tenga acceso a todo el disco C , pero sigue slaiendo el mismo error.GRACIAS POR CONTESTAR LA PREGUNTA.
Que versión de Reports tienes?
EliminarHola Roger,
EliminarLa version de report es Oracle Developer 2000. Gracias.
Bueno, hace mucho que no uso Reports, y esta es la primera vez que oigo del uso de envío de reporte por email desde el mismo reports.
EliminarDado tu síntoma, observo que tiene que ver con el manejo de directorios lógicos desde la Base de Datos. Dentro de la BD se pueden crear "directorios" que apuntan a un path de sistema Operativo. Por ejemplo yo tengo uno que se llama 'Reportes' y este apunta al path C:\DatabaseShared\Reportes. Ahora, cuando creas un directorio lógico, el usuario administrador tiene permisos sobre él, si necesitas que un usuario no administrador pueda leer o escribir en dicho directorio lógico debes de dar los permisos necesarios.
Las instrucciones son GRANT READ ON DIRECTORY [DIRECTORIO] TO [USUARIO] y GRANT WRITE ON DIRECTORY [DIRECTORIO] TO [USUARIO]. Solo tienes que investigar el nombre del directorio lógico al que apunta el reporte (o Reports). Puedes revisar los directorios lógicos existentes en tu Base de Datos consultando la vista DBA_DIRECTORIES
hola roger, gracias por la respuesta.
EliminarHola Roger, he estado implementado lo de los correos todo anda bien en cuanto a los html, etc. pero con los atach tengo problemas, al parecer no encuentra el directorio. Si fue creado en el Linux.
ResponderEliminar22285. 00000 - "non-existent directory or file for %s operation"
*Cause: Attempted to access a directory that does not exist, or attempted
to access a file in a directory that does not exist.
*Action: Ensure that a system object corresponding to the specified
directory exists in the database dictionary, or
make sure the name is correct.
Hola wsoto!
ResponderEliminarLos procedimientos de attach buscan un directorio lógico creado en la base de datos, en el caso del procedimiento que puse de ejemplo se crea de la siguiente manera:
CREATE DIRECTORY ATTACHMENTS AS '/tudirectorio/enLinux';
y después de las permisos al usuario o esquema donde radica el procedimiento
GRANT READ, WRITE ON DIRECTORY ATTACHMENTS TO [USUARIO]
Espero te sirva la información!
Gracias, ya corre el proceso, solo que el adjunto realmente lo que hace es agregar con un monton de caracteres en el cuerpo del correo.
Eliminar--MIME.Bound Content-Type: application/pdf; name="Prueba.PDF" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Prueba.PDF" JVBERi0xLjENCjEgMCBvYmoNCjw8DQ
muchas gracias, seguire revizando que esta malo para que haga el attach.
Compañero, ese detalle fué arreglado en la versión 2 del procedimiento que puedes consultar en el siguiente post http://oracledbamex.blogspot.mx/2014/10/envio-de-correos-utilizando-utlsmtp-12.html
EliminarOk gracias voy a revisarlo.
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarHola Roger, deseo hacerte una pregunta.Deseo programar en EBS de oracle y queria preguntarte si tienes manuales de los Modulos de EBS de oracle, por favor si me puedes enviar links de dichos modulos o enviar dichos manuales a mi correo. Gracias por la respuesta. Saludos. Jose.
ResponderEliminarNo tengo manuales de EBS. Saludos
EliminarHola roger, primero felicitarte por el código, mi duda es si esto lo puedo utilizar en oracle 10g XE porque cuando le implemente me sale el ERROR ORA - 29278 error transitorio de SMTP: 421 estoy intentando conectar a un servidor en la nube de goddady que compre tengo la ip y el puerto pero me sale error... es por la versión de la base de datos o hay algo mas que agregar en el codigo algún permiso quisas.
ResponderEliminargracias
Hola roger, logre solucionar el error anterior "ORA 29278" pero me salio otro error que es "error permanente de SMTP: 550 Access denied - Invalid HELO name (see RFC2821 4.1.3)" gracias por el apoyo. saludos Jhon
ResponderEliminarJhon: Revisa las opciones de seguridad, en mi caso, puedo enviar correo de manera anónima, en el tuyo puede que sea necesario un usuario y contraseña enviandola antes del HELO
EliminarHay algún camino para poder envíar a un grupo de personas por Oracle 11g?
ResponderEliminarLo que pretendo es poner los alias de grupos que tengo en OUTLOOK, y colocarlos en mi JOB de Oracle para evitar que me salgan todos los correos en el mensaje que envío.
Para realizar lo que quieres hacer el grupo debe estar dado de alta en el servidor de Correo o Directorio Activo, ya que el procedimiento no toma las direcciones de correo que tienes registradas de manera local en OUTLOOK
EliminarEste comentario ha sido eliminado por un administrador del blog.
ResponderEliminarQue tal Roger tengo el siguiente error si me podes ayudar.
ResponderEliminarORA-29278: SMTP transient error: 421 Service not available
ORA-06512: at "SYS.UTL_SMTP", line 54
ORA-06512: at "SYS.UTL_SMTP", line 138
ORA-06512: at "SYS.UTL_SMTP", line 699
ORA-06512: at "SOFTTEN.P_SENDMAILATTACH", line 324
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at line 2
Saludos
A partir de la versión 11g, Oracle incluyó las listas de control de acceso (ACL) con la cual se restringe el uso de servicios externos (como los de servidores HTTP, FTP, POP, IMAP, SMTP, etc) a los procedimientos almacenados en los esquemas de la Base de Datos.
EliminarDeberás crear la lista ACL, después agregar los servicios a los que se va a tener acceso y, al final, asignar el permiso a los esquemas dueños de los procedimientos almacenados para que consuman dichos servicios.
Puedes consultar la siguiente URL de documentación de Oracle para ver un ejemplo
https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_networkacl_adm.htm
Si necesitas ayuda, agrega un comentario.
Saludos
Roger
compañero Roger, me salen estos errores cuando uso en XE.
ResponderEliminarError que empieza en la línea 123 del comando:
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE
(
host => '192.168.1.*',
lower_port => null,
upper_port => null,
ace => xs$ace_type(privilege_list => xs$name_list('jdwp'), principal_name => 'JOSE_CUENTAS', principal_type => xs_acl.ptype_db)
);
END;
Informe de error:
ORA-06550: line 7, column 9:
PLS-00201: identifier 'XS$ACE_TYPE' must be declared
ORA-06550: line 2, column 2:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Informe de error:
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at "SYS.UTL_TCP", line 17
ORA-06512: at "SYS.UTL_TCP", line 267
ORA-06512: at "SYS.UTL_SMTP", line 161
ORA-06512: at "SYS.UTL_SMTP", line 197
ORA-06512: at "SYSTEM.CORREO_SMTP", line 9
ORA-06512: at line 2
Leyendo los errores de abajo hacia arriba.
ResponderEliminar[ORA-06512: at "SYSTEM.CORREO_SMTP", line 9]
No puedes enviar correos por que no está el permiso en la Lista de Control de Acceso o esta no existe. Esto lo indica el error "ORA-24247: network access denied by access control list (ACL)"
[PLS-00201: identifier 'XS$ACE_TYPE' must be declared]
El procedimiento que estás utilizando para crear la Lista de Control de Acceso no corresponde a la versión de Base de Datos que tienes (la última versión de Oracle Database XE es 11gR2).
Te agrego dos enlaces, uno con una explicación y ejemplos
https://oracle-base.com/articles/11g/fine-grained-access-to-network-services-11gr1
y otro con la documentación de Oracle para esa versión
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_networkacl_adm.htm#ARPLS148
NOTA: La lista de control de Acceso debe ser creada de manera previa a la ejecución del procedimiento de envío de correo.
Espero te sea de utilidad la respuesta.
hola Roger. tengo un procedure que envia mail desde oracle
Eliminary no me muestra en el mail el destinatario y el remitente, pero envia al destino que lo indicas... ayuda
Revisa si tu procedimiento envía los headers en el mail, cuando el cliente no muestra esos datos, es por que no están definidos dentro del cuerpo del correo.
EliminarCREATE OR REPLACE PROCEDURE send_mail (p_to IN VARCHAR2 ,
Eliminarp_from IN VARCHAR2 ,
p_message IN VARCHAR2,
p_smtp_host IN VARCHAR2,
p_smtp_port IN NUMBER DEFAULT 25)
AS
l_mail_conn UTL_SMTP.connection;
BEGIN
l_mail_conn := UTL_SMTP.open_connection(p_smtp_host, p_smtp_port);
UTL_SMTP.helo(l_mail_conn, p_smtp_host);
UTL_SMTP.mail(l_mail_conn, p_from);
UTL_SMTP.rcpt(l_mail_conn, p_to);
UTL_SMTP.data(l_mail_conn, p_message || UTL_TCP.crlf || UTL_TCP.crlf);
UTL_SMTP.quit(l_mail_conn);
END;
Cómo hago para que el archivo adjunto sea leído desde un directorio en el servidor de aplicaciones y no desde la base de datos.
ResponderEliminarUna manera es que el directorio del servidor de aplicaciones esté como un recurso compartido visible por el servidor de base de datos. Como una carpeta compartida o un recurso NFS
Eliminar