Utilitário para envio de e-mails por linha de comando.
Este utilitário foi desenvolvido por conta da necessidade de atualizar a versão do TLS utilizada pelo ERP Desktop.
Se optou pelo uso da linguagem Python, e pelo fornecimento de um executável, porque está sendo estudada a possibilidade de realizar novos desenvolvimentos do dektop já em python, para permitir reaproveitamento de código para o ERP 4 e/ou JobManager.
Obs.: Esta documentação pressupõe que o programador esteja utilizado ambiente Windows (visto que se destina à integração com o ERP Desktop).
Siga os passos abaixo para montar o ambiente de desenvolvimento (pré requisito: Python 3.9.5, ou superior, e VSCode instalados):
- Clone o repositório:
git clone [email protected]:Nasajon/mail_sender_util.git
- Crie um ambiente virtual python local:
python -m venv .venv
- Iniciei o ambiente:
..venv\Scripts\activate.bat
- Instale as dependências do projeto:
pip install -r requirements
-
Faça uma cópia do arquivo
.env.dist
, renomeando para.env
-
Configure a variável PYTHONPATH, contida no arquivo
.env
, para apontar para a raiz do projeto -
Rode o comando abaixo para testar o envio de e-mail (substituindo por uma conta GMail válida, e configurada para envio por meio de aplicativos com menor nível de segurança; o que é uma exigência do GMail para usar o protocolo SMTP; e substituindo o endereço de destino do e-mail):
python mail_sender_util/mail_cmd.py -j "{"user": "USUARIO", "password": "SENHA", "host": "smtp.gmail.com", "port": "465", "crypt_method": "ssl_tls", "tls_version": "v1.2", "emails": [{"assunto": "Teste 1", "remetente": "USUARIO", "destinatarios": ["DESTINATARIO"], "msg_html": "Teste 1"}]}
Se optou pelo desenvolvimento de um utilitário que receba um JSON como parâmetro de entrada, contendo os seguintes padrão:
{
"user": "str", // Conta de e-mail para autenticação junto ao servidor (normalmente igual ao remetente dos e-mails)
"password": "str", // Senha do e-mail para autenticação junto ao servidor
"port": "str", // Porta SMTP do servidor de e-mails
"crypt_method": "str", // Método de criptografia para o envio dos e-mails (opções: "null", "ssl_tls" ou "start_tls")
"tls_version": "str", // Versão da criptografia TLS, caso utilizada (opções: "v1.0", "v1.1" ou "v1.2")
"emails": [ // Lista de e-mails a enviar
{
"assunto": "str", // Assunto do e-mail
"remetente": "str", // Endereço de e-mail do rementente
"destinatários": [ // Lista dos endereços de e-mails dos destinatários
"str",
...
],
"dest_copia": [ // Lista dos endereços de e-mails dos destinatários em cópia
"str",
...
],
"dest_copia_oculta": [ // Lista dos endereços de e-mails dos destinatários em cópia oculta
"str",
...
],
"msg_html": "str", // Corpo do e-mail, opcionalmente em HTML
"anexos": [ // Lista de anexos a enviar junto ao e-mail
{
"file_name": "str", // Nome do anexo no e-mail
"path": "str" // Path do arquivo no disco local (utilizar "/" como separador de diretórios)
},
...
],
"imagens": [ // Lista de imagens a enviar inline no corpo do e-mail
{
"id": "str", // ID da imagem, que pode ser referenciado por meio de uma tag IMG, com o padrão: <img src="cid:ID">
"path": "str" // Path da imagem no disco local (utilizar "/" como separador de diretórios)
},
...
]
},
...
]
}
Obs. 1: O JSON é recebido como o parâmetro "-j", e deve ser enviado como um string codificada em Base64.
Obs. 2: A diferença entre as opções do atributo "crypt_method" é:
- "null": Sem criptografia
- "ssl_tls": A comunicação é criptografada por inteiro (e não apenas o contéudo dos e-mails)
- "start_tls": A comunicação é criptografada apenas na parte do corpo dos e-mails.
Caso se use algum tipo de criptografia, será necessário utilizar também a propriedade "tls_version".
O comando retorna um status inteiro conforme os padrões a seguir:
- 0 em caso de sucesso
- 1 em caso de erro conhecido
- Neste caso, a saída do comando também contém um JSON descrevendo os erros ocorridos.
- 2 (ou outro) em caso de erro desconhecido
No caso de erro conhecido, o JSON de erros segue o padrão abaixo:
{
"erros_gerais": [ // Lista de mensagens de erros gerais ocorridos (erros de conexão e etc, e não erros de qualquer mensagem em particular)
"str",
...
],
"erros_mensagens": { // Objeto JSON com os erros das mensagens, onde as chaves do JSON correspondem ao índice de cada mensagem no vetor de entrada (isto é, o primeiro e-mail da entrada, terá seus erros descritos na chave "0", por exemplo)
"0": [ // Lista de mensagens de erros ocorridos em cada mensagem (exemplo: endereço do remetente desconhecido)
"str",
...
],
...
}
}
O PyInstaller é a ferramenta utilizada para empactar este utilitário num executável stand alone (que pode ser usado sem instalação do Python na máquina cliente).
Para gerar o exe, rode o comando:
run-pyinstaller.bat
Adicionalmente ao comando, foi desenvolvido um utilitário do tipo wrapper, para uso do mesmo por meio de sistemas Delphi.
Este utilitário está versionado aqui.
Um exemplo de utilização:
var t_email: TMail;
var t_listaEmails: TObjectList<TMail>;
var t_anexo: TMailAnexo;
var t_mailSender: TMailSenderWrapper;
begin
t_listaEmails := nil;
t_mailSender := nil;
try
t_listaEmails := TObjectList<TMail>.Create();
t_email := TMail.Create();
t_email.assunto := 'Teste Assunto';
t_email.remetente := '[email protected]';
t_email.destinatarios.Add('[email protected]');
t_email.msgHtml := 'Corpo do e-mail';
t_anexo := TMailAnexo.Create();
t_anexo.nomeArquivo := 'anexo.pdf';
t_anexo.path := 'C:/Users/Sergio Silva/Downloads/Transformational Leadership.pdf';
t_email.anexos.Add(t_anexo);
t_listaEmails.Add(t_email);
t_mailSender := TMailSenderWrapper.Create(
'[email protected]',
'**********',
'smtp.gmail.com',
'465',
'ssl_tls',
'v1.2'
);
t_mailSender.enviar(t_listaEmails);
finally
if Assigned(t_listaEmails) then t_listaEmails.Free;
if Assigned(t_mailSender) then t_mailSender.Free;
end;
end;
Para correto funcionamento do wrapper, é preciso garantir que o executável "mail_cmd.exe" esteja contido no diretório nsbin
. O qual pode ser encontrado aqui.
Caso ocorra um erro no envio, o método "enviar" lança uma exceção do tipo "mail_sender_wrapper.TMailException", e para acessar as informações de erro (conforme apresentadas no JSON de retorno acima), é preciso se utiliza das propriedades "errosGerais" e "errosEmails" do objeto correspondente à exception.
O envio de e-mails registra logs, na tabela mail_sender_util
do schema logs
.