Enviando e-mails com PL/SQL em Bancos de Dados Oracle

Por Fabio Prado
Postado en junho 2013

Este artigo é a 1ª parte (1 de 2 partes) de um artigo em que vou compartilhar conhecimentos gerais sobre como enviar e-mails a partir de um SGBD Oracle e mostrarei como evitar os principais problemas que você poderá encontrar tentando realizar esta tarefa.

Para enviar e-mails a partir de um SGBD Oracle, comumente utilizamos as packages UTL_MAIL e UTL_SMTP, mas é possível utilizar também a package UTL_TCP. Todas elas foram desenvolvidas pela própria Oracle e algumas precisam de instalação adicional. A UTL_SMTP é mais antiga, existe desde o Oracle 8i e já vem instalada, por padrão no BD. A UTL_MAIL está disponível a partir do Oracle 10GR2, e nada mais é do que um wrapper que utiliza as packages UTL_SMTP e UTL_TCP. Ela foi criada para facilitar o envio de e-mails, mas infelizmente, ela possui algumas restrições.

Utilizar a package UTL_SMTP para mandar e-mail é bastante complexo e trabalhoso. É bem mais fácil e mais rápido utilizar a package UTL_MAIL, mas como eu havia dito no parágrafo acima, ela possui algumas restrições, tais como: enviar somente 1 anexo e o tamanho do anexo deve ser de no máximo 32K. Estas restrições não existem na package UTL_SMTP, que não vou abordar neste artigo. Na 2a. parte do artigo, vou compartilhar uma package que usa tanto a UTL_SMTP quanto a UTL_MAIL para enviar e-mails. O código desta package poderá servir como referência para quem pretende ver como usar qualquer uma delas.

Explicarei abaixo como usar a UTL_MAIL, por ser a opção mais simples e atualmente a mais utilizada. Para utilizá-la é necessário cumprir alguns pré-requisitos:

1- Instalar a package executando os scripts: $ORACLE_HOME/rdbms/admin/utlmail.sql e $ORACLE_HOME/rdbms/admin/prvtmail.plb. A instalação deve ser efetuada por um usuário que tenha privilégios administrativos;

2- Configurar o parâmetro de sistema SMTP_OUT_SERVER, com um valor contendo o nome ou IP + porta de um servidor SMTP válido. Se você omitir o endereço da porta, será utilizada como padrão, a porta 25. É importante salientar que a máquina host do BD tenha comunicação com o servidor SMTP, e também, autorização para enviar mensagens (no software do servidor SMTP não deve existir regras que bloqueiem mensagens da máquina host do BD).

Ex.: ALTER SYSTEM SET smtp_out_server = 'smtp.empresa.com.br:25';

Obs.: Para executar o comando acima é necessário ter privilégios administrativos.

3- O remetente (sender) do e-mail deve ser uma conta de e-mail que não requer autenticação para envio de mensagens.

Após cumprir os pré-requisitos acima, você já poderá utilizar a package UTL_MAIL. Segue abaixo, um bloco PL/SQL simples, que contém comentários sobre o que deve ser passado como valor em cada parâmetro, e que pode ser utilizado para enviar um e-mail sem anexo, utilizando a procedure UTL_MAIL .SEND :

     BEGIN
          UTL_MAIL.SEND
               (SENDER => 'email@oracle.com', -- remetente da mensagem
                  RECIPIENTS => 'fbifabio@gmail.com',  -- destinatário da mensagem
                  CC => null,  -- destinatário copiado na mensagem
                  BCC => null,  -- destinatário com cópia oculta da  mensagem
                  SUBJECT =>  'Assunto do e-mail', -- assunto da mensagem
                  MESSAGE => 'Mensagem do e-mail', -- mensagem do e-mail
                  MIME_TYPE => 'text/plain; charset=iso-8859-1' -- mime type + character set 
                  do texto da mensagem
               );
     END;

Como pode ser observado no bloco PL/SQL acima, é muito fácil enviar uma mensagem sem anexo usando a package UTL_MAIL, mas a coisa complica quando você tem que mandar mensagens com anexo, e fica impossível quando o anexo é maior que 32K. Um detalhe em que muitos profissionais encontram problemas e dificuldades, é a configuração dos caracteres do texto das mensagens e do texto dos anexos, que podem apresentar, em muitos casos, os chamados "caracteres desconfigurados". Para evitar estes caracteres desconfigurados é necessário passar o valor adequado para os parâmetros MIME_TYPE, que indicam o tipo de aplicação e o conjunto de caracteres que será utilizado para compor o texto da mensagem ou do anexo. Eu normalmente configuro o valor 'text/plain; charset=iso-8859-1'. Se para você esta configuração apresentar caracteres desconfigurados, troque o valor iso-8859-1 por utf-8 ou us-ascii (valor padrão). Para aqueles que ainda assim tiverem problemas e precisarem de mais informações sobre mime types, sugiro a leitura do artigo http://en.wikipedia.org/wiki/MIME.

Se você tentar mandar um e-mail em um BD 11G, possivelmente você irá se deparar com o erro ORA-24247: acesso à rede negado pela ACL (access control list), pois nesta versão do Oracle, para aumentar a segurança do BD, foi acrescentado um controle de acesso mais rígido às packages UTL_MAIL, UTL_SMTP e outras, em que é necessário conceder privilégios especiais ao usuários que irão executá-las. Não iremos entrar em detalhes sobre ACL neste artigo, mas para conceder estes privilégios a um usuário chamado FABIO, por exemplo, execute os blocos PL/SQL abaixo:

begin
 	dbms_network_acl_admin.create_acl (
        acl => 'grant_acl.xml',
        description => 'Permite enviar e-mail e usar outras packages',
        principal => 'FABIO', -- observe que o nome do usuário deve estar sempre em UPPERCASE 
        is_grant => TRUE,
        privilege => 'connect'  -- este privilégio concedido é que permite que o 
        usuário envie email através do servidor que será especificado no próximo 
        bloco que chama a SP "assign_acl"
        );
  commit;
end; /

begin 
   dbms_network_acl_admin.assign_acl( 
        acl => 'grant_acl.xml',
        host => 'hostname'  -- preencha aqui o nome do host do servidor SMTP
        );
   commit;
end; 
 /

Na próxima parte deste artigo, compartilharei uma package que eu desenvolvi para facilitar o trabalho de envio de e-mails com ou sem anexo. Essa package internamente utiliza a package UTL_MAIL para enviar mensagens sem anexo e a package UTL_SMTP para enviar mensagens com anexo. Essa package pode ser utilizada para padronizar o código de envio de e-mails e facilitar o envio de e-mails com anexos maiores que 32K, pois não é uma tarefa muito simples utilizar a package UTL_SMTP para essa finalidade!


Postado por Fabio Prado.