miércoles, 8 de octubre de 2014

Envío de Correos utilizando UTL_SMTP 1.2

Después de mucho tiempo de no publicar nada, el día de hoy publico la nueva versión del procedimiento de envío de correos con adjuntos utilizando UTL_SMTP.

He de agradecer a todos los que han realizado comentarios sobre dudas, errores y ajustes que han sido necesarios realizar al programa.

Los cambios son menores (de hecho van comentados en un pequeño encabezado) y con se han realizado correcciones a algunos errores detectados.

Espero a partir de hoy, poder realizar publicaciones con mayor regularidad para seguir compartiendo y aprendiendo de mis lectores.

Les dejo el código, para ejecutarlo se utiliza la misma sentencia que está en el post Envío de Correos utilizando UTL_SMTP

-- Envio de Correos a multiples destinatarios con multiples adjuntos utilizando UTL_SMTP                                  
PROCEDURE P_SendMailAttach(p_DestinatariosPara     IN VARCHAR2 CHARACTER SET ANY_CS, 
                           p_DestinatariosCC       IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT NULL,
                           p_DestinatariosBcc      IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT NULL,
                           p_Mensaje               IN LONG DEFAULT 'Haga caso omiso a este mensaje',
                           p_Remitente             IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT 'correo@dominio.com',
                           p_Asunto                IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT 'Este correo no tiene asunto',
                           p_TipoMensaje           IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT 'TEXT',
                           p_Directorio            IN VARCHAR2 CHARACTER SET ANY_CS DEFAULT 'ATTACHMENTS',
                           p_ArchivosAdjuntos      IN VARCHAR2 CHARACTER SET ANY_CS)
AS
-----------------------------------------------------------------------------------------------
-- Programa     : P_SendMailAttach
-- Descripción  : Procedimiento  para  el  envío   de  correos  planos  y  HTML  con  adjuntos
--                utilizando el package UTL_SMTP.
-- Notas        : Los listados de remitentes deberán contener las direcciones separadas por un
--                colon (,)
--                El mensaje por default esta definido como texto plano
--                El Cuerpo del Mensaje no debe superar los 32K (Resolved)

--   When         Who                         What

--   ===========  ======================      =================================================
--   21-MAR-2012  Rogelio Rodríguez           Initial Creation
--
--   16-APR-2012  Rogelio Rodríguez           Se agrega la clausula CHARACTER SET ANY_CS   para
--                                            permitir el uso de caracteres  especiales  en los
--                                            valores de tipo VARCHAR2 de manera automática
--   16-APR-2012  Rogelio Rodríguez           Se modifican  las  rutinas  para la separación de
--                                            Items, cambiando  el  reemplaxo  de  espacios  en
--                                            blanco por un TRIM y un  replace '; ' que  es  lo
--                                            más  común
--
--   20-JUN-2012  Rogelio Rodriguez           Se modifica el envío del mensaje y asunto, utili-
--                                            zando  la  conversión  a RAW  para que respete el
--                                            juego  de  caracteres  iso-8859-1 en los procedi-
--                                            mientos SendMail y SendMailAttach.
--
--   15-OCT-2012  Rogelio Rodríguez           Se modifica la variable p_Mensaje de VARCHAR2

--                                            a LONG para que no tenga el límite de los 32K.

--
--   08-OCT-2014  Rogelio Rodríguez           Se modifica el orden de inserción de  encabezados
--                                            y límites para la separación de  adjuntos  ya que
--                                            bajo  el  servidor  SMTP  Exchange  2010  no   se
--                                            realizaba  de  manera  correcta  la  adición   de
--                                            Adjuntos en el procedimiento SendMailAttach.
----------------------------------------------------------------------------------------------- 

c utl_smtp.connection;

l_ServidorSMTP VARCHAR2(30);
l_PuertoSMTP   VARCHAR2(10);
l_MensajeRaw   LONG RAW;

--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_Cadena := replace(l_Cadena,', ',',');

l_Cadena := trim(l_Cadena);
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_Cadena := replace(l_Cadena,', ',',');

l_Cadena := trim(l_Cadena);
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-Transfer-Encoding', 'base64' );
    send_header('Content-Disposition', 'attachment; filename="' || p_Archivo || '"');
    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_Cadena := replace(l_Cadena,', ',',');

l_Cadena := trim(l_Cadena);
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));
              dbms_output.put_line(l_Archivo);
              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

    l_ServidorSMTP := F_RetornaValorParametro('LOCAL_SERVER_MAIL');
    l_PuertoSMTP   := F_RetornaValorParametro('LOCAL_SERVER_MAIL_PORT');
    
    c := utl_smtp.open_connection(l_ServidorSMTP,l_PuertoSMTP); 
    utl_smtp.helo(c, l_ServidorSMTP); 
    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;
    
    -- Demás Cabeceras
    send_header('From', p_Remitente); -- De
    send_header('MIME-Version','1.0');
    send_header('Content-Type','multipart/mixed; boundary="MIME.Bound"');
    
    -- Escritura del Asunto
    l_MensajeRaw := utl_raw.cast_to_raw('Subject:'||p_Asunto);
    utl_smtp.write_raw_data(c, l_MensajeRaw);
    utl_smtp.write_data(c, utl_tcp.CRLF);
    
    -- Inicia bloques de escritura de Mensaje y Archivos con sus respectivos Boundaries
    utl_smtp.write_data(c,'--MIME.Bound'||utl_tcp.CRLF);
    
    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=iso-8859-1');
            send_header('Content-Disposition', 'inline');
        ELSE
            send_header('MIME-Version','1.0');
            send_header('Content-Type', 'text/html;charset=iso-8859-1');
            send_header('Content-Disposition', 'inline');
            send_header('Content-Transfer-Encoding', '8bit');
        END IF;
    
    END IF;

    -- Bloque de Escritura del Mensaje 

    l_MensajeRaw := utl_raw.cast_to_raw(p_Mensaje); 
    utl_smtp.write_data(c, utl_tcp.CRLF);
    utl_smtp.write_raw_data(c, l_MensajeRaw);
    utl_smtp.write_data(c, 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(-20100, 'Unable to send mail: '||sqlerrm);
     WHEN OTHERS THEN
        -- Bloque de Cierre de Conexión
        utl_smtp.quit(c); 
        raise_application_error(-20100, 'Unable to send mail: '||sqlerrm);
    


END P_SendMailAttach;


Espero nuevamente les sea de utilidad el código, me llevo de tarea una mejor implementación del mismo de forma tal que las funciones y procedimientos internos puedan ser reutilizables.

Así mismo espero sus comentarios sobre funcionamiento u otras mejoras a agregar.

26 comentarios:

  1. HOla amigo buena tarde, una pregunta tal vez muy obvia pero me resulta raro que en tu proceso esta construido para recibir 9 parametros y en tu ejemplo para ejecutarlo tu dices que solo se le pasan 7, como esta esto? Gracias y saludos.

    ResponderEliminar
    Respuestas
    1. Hola estimado.
      Esto se logra con el uso de valores por default en los parámetros. Como puedes ver de los 9 proyectos solo 3 deben llevar valores de manera obligatoria.

      Eliminar
  2. Buenas Roger no tengo la funcion F_RetornaValorParametro,
    con la version anterior tenia el siguiente error.

    ORA-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 283
    ORA-24247: network access denied by access control list (ACL)
    ORA-06512: at line 2

    Saludos

    ResponderEliminar
    Respuestas
    1. Hola compañero!

      Primera Respuesta: La función F_RetornaValorParametro es una función que devuelve un valor en base a un nombre de parámetro, estos valores los tengo almacenados en una tabla.
      Puedes cambiar estas líneas de código colocando directamente los valores que necesites
      l_ServidorSMTP := 10.10.10.10 --F_RetornaValorParametro('LOCAL_SERVER_MAIL');
      l_PuertoSMTP := 26 --F_RetornaValorParametro('LOCAL_SERVER_MAIL_PORT');

      Segunda Respuesta: 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.

      Deberá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

      Eliminar
    2. Muchas gracias por responder Roger,

      ya verifique y mire el lick que me pasaste ahora me salta el siguiente error.

      ORA-29277: invalid SMTP operation
      ORA-06512: at "SYS.UTL_SMTP", line 80
      ORA-06512: at "SYS.UTL_SMTP", line 210
      ORA-06512: at "SYS.UTL_SMTP", line 688
      ORA-06512: at "SYS.UTL_SMTP", line 699
      ORA-06512: at "SOFTTEN.P_SENDMAILATTACH", line 324
      ORA-06502: PL/SQL: numeric or value error: invalid LOB locator specified: ORA-22275
      ORA-06512: at line 2

      Ahora ya es el otro el error que me salta desde ya muchas gracias

      Eliminar
    3. Este comentario ha sido eliminado por el autor.

      Eliminar
    4. El procedimiento utiliza un directorio lógico y en él debe estar el archivo que vayas a adjuntar. Si consideras que este no es tu problema, enviame un email a wazu03560032@gmail.com con el código tal cual lo estás tratando de implementar.

      Saludos

      Roger

      Eliminar
  3. Que tal Roger,
    mi problema ahora es para adjuntar el archivo, cree un directorio
    CREATE DIRECTORY cmc_dir AS 'C:\ManuelCardozo\firma'
    luego pase al procedimiento
    'cmc_dir' ,'hola.txt'
    y me da este error

    ORA-22285: non-existent directory or file for GETLENGTH operation

    sera que podes ayudar con este error.

    Saludos

    ResponderEliminar
    Respuestas
    1. Cuando das de alta un directorio en tu Base de Datos, la ruta debe estar en el sistema de archivos de la Base de Datos, no a una ruta de tu PC, que al parecer es lo que te está sucediendo.
      En la creación del directorio lógico la BD no valida la existencia del path que asignas, hasta que se utiliza te das cuenta que pusiste un path erróneo.

      Saludos

      Roger

      Eliminar
    2. Gracias Roger

      Me podes indicar como mas o menos debo hacer, la verdad no estoy entendiendo bien.

      Saludos.

      Eliminar
    3. Una disculpa por la tardanza en responder (casi un año), pero espero sirva para otros compañeros.

      Los directorios lógicos de las Bases de Datos deben apuntar a una ubicación del sistema de archivos donde se encuentra la instancia o una ubicación de red a la que tenga acceso. Si donde está ejecutándose la instancia de la base de datos existe el directorio 'C:\ManuelCardozo\firma' no debería marcarte error alguno.

      Eliminar
  4. hola

    Tengo un problema, el procedimiento me funciona correctamente y me adjunta cualquier archivo, el perfomance es muy rapido y esta super bien. Mi unico problema es que no manda ningun mensaje en el cuerpo del mensaje. agrego cualquier oración en HTML o en TEXT, pero el correo no se integra este mensaje y llega en blanco :(
    Si alguien tiene el mismo error me podrían decir como lo solucionaron?

    Muchas Gracias,

    ResponderEliminar
    Respuestas
    1. Si me muestras como estás ejecutando el procedimiento, para revisarlo.

      Eliminar
    2. hola Roger.

      Te lo mandé por correo :)

      Eliminar
    3. Hola Vanessa, me sucede lo mismo que a Roger, ¿podrías decirme cómo lo has solucionado?
      Muchas gracias,
      Luis

      Eliminar
    4. Alguna solución al problema? me pasa exactamente lo mismo

      Eliminar
  5. Buenas tardes. Para realizar pruebas puedo hacerlo desde un conputador normal con Oracle instalado. Estoy empezando con Oracle y de verdad estoy muy perdido. Pregunto porque la funcion Mailer de PHP no funciona en "servidores locales" como xampp, etc.

    ResponderEliminar
  6. Buenas tardes. Para realizar pruebas ¿puedo hacerlo desde un computador normal con Oracle instalado? Estoy empezando con Oracle y de verdad estoy muy perdido. Pregunto porque la librería Mailer de PHP no funciona en "servidores locales" como xampp, etc.

    ResponderEliminar
  7. Hola Roger.

    Ante todo agradecer el procedimiento compartido que es de gran utilidad. Muchas gracias. Lo he instalado en Oracle 11G XE bajo Centos7. Hago la llamada desde Forms6i bajo Windows 10 v.1703 y funciona razonablemente bien y a veces muy bien. A veces, y de ahí lo de razonablemente bien, sin saber porqué, envía 20 correos o más en 1 segundo y en otras ocasiones para enviar un solo correo tarda 10 segundos. He observado que cuando tarda tanto lo hace en esta parte del procedimiento, cuando abre la comunicación:

    cx := utl_smtp.open_connection(l_ServidorSMTP, l_PuertoSMTP);

    El resto del procedimiento es muy rápido, inclusive si hay attachments. Que quede claro que no tarda más cuando hay archivos adjuntos. Mi pregunta es, si podrías ayudarme a descubrir el porqué en ocasiones puede ir tan lento? Si sabes cual puede ser el motivo? Que seguramente es algún problema de comunicación con el MTA, pero que yo no se descubrir.

    Lo siguiente, más que una consulta, es algo que me ha llevado de cabeza mucho tiempo y quiero compartir por si le puede servir a alguien. También está instalado el procedimiento en Oracle 12c bajo Centos 6.9. Hago la llamada desde Forms12c bajo Windows 10 v.1703 y el problema antes mencionado persiste. A veces va muy rápido y a veces lento, y cuando es lento, es lento al abrir la comunicación. Hasta aquí nada nuevo. Pero, como he empezado diciendo, la cuestión aquí es otra. Lo que ocurre es que el procedimiento llamado desde el sqldeveloper funciona perfectamente, pero desde Forms 12c no funciona y se rompe precisamente al abrir la comunicación, es decir, la línea de código que he puesto más arriba. El error que sale es muy extraño: ORA-64610: bad depth indicator. No he hallado documentación sobre el mismo. Ni solución. Sin embargo, por casualidad, se me ocurrió cambiar el procedimiento por una función. Evidentemente el error fue el mismo y en la misma línea de código. Parece una tontería pensar que si un procedimiento falla en un punto concreto, el pasarlo a función vaya a funcionar bien, que en lo único que apenas varia es que al final hago un return('OK'), así de simple. Pues Sres. no es tan tontería, también por casualidad se me ocurrió cambiar la llamada a la función, que antes era, "v_res:=F_SendMailAttach(todos los parametros...)" por "Select F_SendMailAttach(todos los parametros...) into v_res from dual;" y FUNCIONA!!! y bien!!! Increíble!!! He visto otras personas con este mismo problema en otros blogs que trataré de localizar para proponerles esta misma solución. No es lo mejor pero funciona! No obstante, si a alguien le ha pasado esto último y tiene alguna solución le rogaría que la comparta. Muchas gracias.

    Jacques.

    ResponderEliminar
    Respuestas
    1. can you explain same in English, as we also are experiencing same.

      if possible pls send mail to desai.utpal@rediffmail.com

      Eliminar
    2. Hola Jacques!

      Cuando tuve ese “problema” de comunicación con mi server de correo el detalle era que mis compañeros que administraban el servicio pasaban los mensajes por un servicio de filtrado antispam y eso me “alentaba” los envíos.
      No me parece tu caso, pero que bueno que ya encontraste una solución.

      Eliminar
  8. Estimado Roger, te saludo con mucho gusto y espero que todo se encuentre bien.

    Primero muchas gracias por tu apoyo.

    Estoy enviando copia a 2 direcciones y tengo el siguiente inconveniente:

    Action: failed
    Final-Recipient: rfc822;correo2@midominio.com
    Status: 5.0.0
    Remote-MTA: dns; outbound.mailspamprotection.com
    Diagnostic-Code: smtp; 550 Messages should have one or no Cc headers, not 2.

    lo enviamos así:
    P_SendMailAttach(p_destinatariospara => 'destinario@sucorreo.com',
    p_destinatarioscc => 'correo1@midominio.com,correo2@midominio.com',
    p_remitente => 'remite@micorreo.com',
    p_asunto => 'Prueba de correo');

    Me podrías apoyar por favor.

    Saludos cordiales

    ResponderEliminar
    Respuestas
    1. Tu servidor de correo no permite en el campo de CC mas ee una dirección. Revisa con tu administrador del servicio si puede ponerte una excepción en el servidor de mail o usa una lista de distribución.

      Saludos!

      Eliminar
  9. Ola amigo estoy tratando de usar este procedimiento, ya mucho tiempo recien lo encontre pero me da este error etoy usando smtp.gmail.com

    esto uso y eso el error que me dio

    begin
    P_SENDMAILATTACH(p_DestinatariosPara =>'wlasan@hotmail.com',
    p_DestinatariosCC => 'wlasan@hotmail.com',
    p_Remitente => 'wlasan@gmail.com',
    p_Mensaje =>'cuerpo del Informe',
    p_Asunto => 'Envío de Informe Empresa1',
    p_ArchivosAdjuntos => 'B1.SQL',
    p_TipoMensaje => 'HTML');

    end;
    /*

    ORA-20100: Unable to send mail: ORA-29279: error permanente de SMTP: 530 5.7.0 Must issue a STARTTLS command first. o5sm3002152vsa.4 - gsmtp
    ORA-06512: en "GADSPP.P_SENDMAILATTACH", línea 321
    ORA-06512: en línea 2




    */

    ResponderEliminar
  10. luego de poner las claves me sigue dando error porfa tu ayuda gracias

    l_encoded_username := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw('xxx@gmail.com')));
    l_encoded_password := UTL_RAW.cast_to_varchar2(UTL_ENCODE.base64_encode(UTL_RAW.cast_to_raw('xxxxx')));

    -- Open connection and send EHLO and AUTH messages

    -- Bloque de Apertura de Conexión
    c := utl_smtp.open_connection('smtp.gmail.com',587); --Recuerden que puede ser el nombre NetBios o la IP
    utl_smtp.command( c, 'AUTH LOGIN');
    utl_smtp.helo(c, 'smtp.gmail.com');
    UTL_SMTP.starttls (c);
    UTL_SMTP.command(c, l_encoded_username);
    UTL_SMTP.command(c, l_encoded_password);

    ORA-20100: Unable to send mail: ORA-29279: error permanente de SMTP: 502 5.5.1 Unrecognized command. i7sm1862968vkh.24 - gsmtp
    ORA-06512: en "GADSPP.P_SENDMAILATTACH", línea 327
    ORA-06512: en línea 2

    ResponderEliminar

Deja tu comentario aquí