Olá pessoal…
Hoje trago para vocês uma rotina que desenvolvi para disparo de e-mails com opção de múltiplos anexos.
A rotina funciona instanciando a tMailManager e tMailMessage, utizando os seguintes parâmetros:
* MV_RELACNT – Conta de login do e-Mail – Ex.: email@servidor.com.br
* MV_RELPSW – Senha de login do e-Mail – Ex.: senha
* MV_RELSERV – Servidor SMTP do e-Mail – Ex.: smtp.servidor.com.br:587
* MV_RELTIME – TimeOut do e-Mail – Ex.: 120
Para utilizar a rotina, ela recebe até 6 parâmetros de dados, sendo:
cPara – Destinatário que irá receber o e-Mail
cAssunto – Assunto do e-Mail
cCorpo – Corpo do e-Mail (com suporte à html)
aAnexos – Anexos que estarão no e-mail (devem estar na mesma pasta da protheus data)
lMostraLog – Define se será mostrado mensagem de log ao usuário (uma tela de aviso)
lUsaTLS – Define se irá utilizar o protocolo criptográfico TLS
Segue abaixo a rotina desenvolvida.
//Bibliotecas #Include "Protheus.ch" /*/{Protheus.doc} zEnvMail Função para disparo do e-mail utilizando TMailMessage e tMailManager com opção de múltiplos anexos @author Atilio @since 26/05/2017 @version 1.0 @type function @param cPara, characters, Destinatário que irá receber o e-Mail @param cAssunto, characters, Assunto do e-Mail @param cCorpo, characters, Corpo do e-Mail (com suporte à html) @param aAnexos, array, Anexos que estarão no e-mail (devem estar na mesma pasta da protheus data) @param lMostraLog, logical, Define se será mostrado mensagem de log ao usuário (uma tela de aviso) @param lUsaTLS, logical, Define se irá utilizar o protocolo criptográfico TLS @return lRet, Retorna se houve falha ou não no disparo do e-Mail @example Exemplos: ----- 1 - Mensagem Simples de envio u_zEnvMail("teste@servidor.com.br", "Teste", "Teste TMailMessage - Protheus", , .T.) ----- 2 - Mensagem com anexos (devem estar dentro da Protheus Data) aAnexos := {} aAdd(aAnexos, "\pasta\arquivo1.pdf") aAdd(aAnexos, "\pasta\arquivo2.pdf") aAdd(aAnexos, "\pasta\arquivo3.pdf") u_zEnvMail("teste@servidor.com.br", "Teste", "Teste TMailMessage com anexos - Protheus", aAnexos) @obs Deve-se configurar os parâmetros: * MV_RELACNT - Conta de login do e-Mail - Ex.: email@servidor.com.br * MV_RELPSW - Senha de login do e-Mail - Ex.: senha * MV_RELSERV - Servidor SMTP do e-Mail - Ex.: smtp.servidor.com.br:587 * MV_RELTIME - TimeOut do e-Mail - Ex.: 120 /*/ User Function zEnvMail(cPara, cAssunto, cCorpo, aAnexos, lMostraLog, lUsaTLS) Local aArea := GetArea() Local nAtual := 0 Local lRet := .T. Local oMsg := Nil Local oSrv := Nil Local nRet := 0 Local cFrom := Alltrim(GetMV("MV_RELACNT")) Local cUser := SubStr(cFrom, 1, At('@', cFrom)-1) Local cPass := Alltrim(GetMV("MV_RELPSW")) Local cSrvFull := Alltrim(GetMV("MV_RELSERV")) Local cServer := Iif(':' $ cSrvFull, SubStr(cSrvFull, 1, At(':', cSrvFull)-1), cSrvFull) Local nPort := Iif(':' $ cSrvFull, Val(SubStr(cSrvFull, At(':', cSrvFull)+1, Len(cSrvFull))), 587) Local nTimeOut := GetMV("MV_RELTIME") Local cLog := "" Default cPara := "" Default cAssunto := "" Default cCorpo := "" Default aAnexos := {} Default lMostraLog := .F. Default lUsaTLS := .F. //Se tiver em branco o destinatário, o assunto ou o corpo do email If Empty(cPara) .Or. Empty(cAssunto) .Or. Empty(cCorpo) cLog += "001 - Destinatario, Assunto ou Corpo do e-Mail vazio(s)!" + CRLF lRet := .F. EndIf If lRet //Cria a nova mensagem oMsg := TMailMessage():New() oMsg:Clear() //Define os atributos da mensagem oMsg:cFrom := cFrom oMsg:cTo := cPara oMsg:cSubject := cAssunto oMsg:cBody := cCorpo //Percorre os anexos For nAtual := 1 To Len(aAnexos) //Se o arquivo existir If File(aAnexos[nAtual]) //Anexa o arquivo na mensagem de e-Mail nRet := oMsg:AttachFile(aAnexos[nAtual]) If nRet < 0 cLog += "002 - Nao foi possivel anexar o arquivo '"+aAnexos[nAtual]+"'!" + CRLF EndIf //Senao, acrescenta no log Else cLog += "003 - Arquivo '"+aAnexos[nAtual]+"' nao encontrado!" + CRLF EndIf Next //Cria servidor para disparo do e-Mail oSrv := tMailManager():New() //Define se irá utilizar o TLS If lUsaTLS oSrv:SetUseTLS(.T.) EndIf //Inicializa conexão nRet := oSrv:Init("", cServer, cUser, cPass, 0, nPort) If nRet != 0 cLog += "004 - Nao foi possivel inicializar o servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Define o time out nRet := oSrv:SetSMTPTimeout(nTimeOut) If nRet != 0 cLog += "005 - Nao foi possivel definir o TimeOut '"+cValToChar(nTimeOut)+"'" + CRLF EndIf //Conecta no servidor nRet := oSrv:SMTPConnect() If nRet <> 0 cLog += "006 - Nao foi possivel conectar no servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Realiza a autenticação do usuário e senha nRet := oSrv:SmtpAuth(cFrom, cPass) If nRet <> 0 cLog += "007 - Nao foi possivel autenticar no servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Envia a mensagem nRet := oMsg:Send(oSrv) If nRet <> 0 cLog += "008 - Nao foi possivel enviar a mensagem: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf EndIf //Disconecta do servidor nRet := oSrv:SMTPDisconnect() If nRet <> 0 cLog += "009 - Nao foi possivel disconectar do servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF EndIf EndIf EndIf EndIf //Se tiver log de avisos/erros If !Empty(cLog) cLog := "zEnvMail - "+dToC(Date())+ " " + Time() + CRLF + ; "Funcao - " + FunName() + CRLF + CRLF +; "Existem mensagens de aviso: "+ CRLF +; cLog ConOut(cLog) //Se for para mostrar o log visualmente e for processo com interface com o usuário, mostra uma mensagem na tela If lMostraLog .And. ! IsBlind() Aviso("Log", cLog, {"Ok"}, 2) EndIf EndIf RestArea(aArea) Return lRet
Também foi realizado uma alteração no fonte, para adaptação para quem usa o Envio Locaweb, que é uma conta específica para disparo. Para usar essa funcionalidade, é necessário criar 3 parâmetros MV_X_NCNT,
MV_X_NPSW e MV_X_NSRV (Conta, Senha e Servidor). Abaixo o código.
//Bibliotecas #Include "Protheus.ch" /*/{Protheus.doc} zEnvMail Função para disparo do e-mail utilizando TMailMessage e tMailManager com opção de múltiplos anexos @author Atilio @since 26/05/2017 @version 1.0 @type function @param cPara, characters, Destinatário que irá receber o e-Mail @param cAssunto, characters, Assunto do e-Mail @param cCorpo, characters, Corpo do e-Mail (com suporte à html) @param aAnexos, array, Anexos que estarão no e-mail (devem estar na mesma pasta da protheus data) @param lMostraLog, logical, Define se será mostrado mensagem de log ao usuário (uma tela de aviso) @param lUsaTLS, logical, Define se irá utilizar o protocolo criptográfico TLS @return lRet, Retorna se houve falha ou não no disparo do e-Mail @example Exemplos: ----- 1 - Mensagem Simples de envio u_zEnvMail("teste@servidor.com.br", "Teste", "Teste TMailMessage - Protheus", , .T.) ----- 2 - Mensagem com anexos (devem estar dentro da Protheus Data) aAnexos := {} aAdd(aAnexos, "\pasta\arquivo1.pdf") aAdd(aAnexos, "\pasta\arquivo2.pdf") aAdd(aAnexos, "\pasta\arquivo3.pdf") u_zEnvMail("teste@servidor.com.br", "Teste", "Teste TMailMessage com anexos - Protheus", aAnexos) u_zEnvMail("informatica@patral.com.br", "Teste", "Teste TMailMessage", , .T.) @obs Deve-se configurar os parâmetros: * MV_RELACNT - Conta de login do e-Mail - Ex.: email@servidor.com.br * MV_RELPSW - Senha de login do e-Mail - Ex.: senha * MV_RELSERV - Servidor SMTP do e-Mail - Ex.: smtp.servidor.com.br:587 * MV_RELTIME - TimeOut do e-Mail - Ex.: 120 /*/ User Function zEnvMail(cPara, cAssunto, cCorpo, aAnexos, lMostraLog, lUsaTLS, lNovo) Local aArea := GetArea() Local nAtual := 0 Local lRet := .T. Local oMsg := Nil Local oSrv := Nil Local nRet := 0 Local cFrom := Alltrim(GetMV("MV_RELACNT")) Local cUser := SubStr(cFrom, 1, At('@', cFrom)-1) Local cPass := Alltrim(GetMV("MV_RELPSW")) Local cSrvFull := Alltrim(GetMV("MV_RELSERV")) Local cServer := "" Local nPort := 0 Local nTimeOut := GetMV("MV_RELTIME") Local cLog := "" Local cContaAuth := "" Local cPassAuth := "" Local nAtu := 0 Local cProcessos := "" Default cPara := "" Default cAssunto := "" Default cCorpo := "" Default aAnexos := {} Default lMostraLog := .F. Default lUsaTLS := .T. Default lNovo := .F. //Se tiver em branco o destinatário, o assunto ou o corpo do email If Empty(cPara) .Or. Empty(cAssunto) .Or. Empty(cCorpo) cLog += "001 - Destinatario, Assunto ou Corpo do e-Mail vazio(s)!" + CRLF lRet := .F. EndIf If lRet If lNovo cContaAuth := Alltrim(GetMV("MV_X_NCNT")) cPassAuth := Alltrim(GetMV("MV_X_NPSW")) cSrvFull := Alltrim(GetMV("MV_X_NSRV")) Else cContaAuth := cFrom cPassAuth := cPass EndIf cServer := Iif(':' $ cSrvFull, SubStr(cSrvFull, 1, At(':', cSrvFull)-1), cSrvFull) nPort := Iif(':' $ cSrvFull, Val(SubStr(cSrvFull, At(':', cSrvFull)+1, Len(cSrvFull))), 587) //Cria a nova mensagem oMsg := TMailMessage():New() oMsg:Clear() //Define os atributos da mensagem //oMsg:cDate := cValToChar(Date()) oMsg:cFrom := cFrom oMsg:cTo := cPara oMsg:cSubject := cAssunto oMsg:cBody := cCorpo //Percorre os anexos For nAtual := 1 To Len(aAnexos) //Se o arquivo existir If File(aAnexos[nAtual]) //Anexa o arquivo na mensagem de e-Mail nRet := oMsg:AttachFile(aAnexos[nAtual]) If nRet < 0 cLog += "002 - Nao foi possivel anexar o arquivo '"+aAnexos[nAtual]+"'!" + CRLF EndIf //Senao, acrescenta no log Else cLog += "003 - Arquivo '"+aAnexos[nAtual]+"' nao encontrado!" + CRLF EndIf Next //Cria servidor para disparo do e-Mail oSrv := tMailManager():New() //Define se irá utilizar o TLS If lUsaTLS oSrv:SetUseTLS(.T.) EndIf //Inicializa conexão nRet := oSrv:Init("", cServer, cUser, cPass, 0, nPort) If nRet != 0 cLog += "004 - Nao foi possivel inicializar o servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Define o time out nRet := oSrv:SetSMTPTimeout(nTimeOut) If nRet != 0 cLog += "005 - Nao foi possivel definir o TimeOut '"+cValToChar(nTimeOut)+"'" + CRLF EndIf //Conecta no servidor nRet := oSrv:SMTPConnect() If nRet <> 0 cLog += "006 - Nao foi possivel conectar no servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Realiza a autenticação do usuário e senha nRet := oSrv:SmtpAuth(cContaAuth, cPassAuth) If nRet <> 0 cLog += "007 - Nao foi possivel autenticar no servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf If lRet //Envia a mensagem nRet := oMsg:Send(oSrv) If nRet <> 0 cLog += "008 - Nao foi possivel enviar a mensagem: " + oSrv:GetErrorString(nRet) + CRLF lRet := .F. EndIf EndIf //Disconecta do servidor nRet := oSrv:SMTPDisconnect() If nRet <> 0 cLog += "009 - Nao foi possivel disconectar do servidor SMTP: " + oSrv:GetErrorString(nRet) + CRLF EndIf EndIf EndIf EndIf //Se tiver log de avisos/erros If !Empty(cLog) //Busca todas as funções nAtu := 0 cProcessos := "" /* While ! (ProcName(nAtu) == '') cProcessos += ProcName(nAtu) + "; " nAtu++ EndDo */ cLog := "+======================= zEnvMail =======================+" + CRLF + ; "zEnvMail - "+dToC(Date())+ " " + Time() + CRLF + ; "Funcao - " + FunName() + CRLF + ; "Processos - " + cProcessos + CRLF + ; "Para - " + cPara + CRLF + ; "Assunto - " + cAssunto + CRLF + ; "Corpo - " + cCorpo + CRLF + ; "Existem mensagens de aviso: "+ CRLF +; cLog + CRLF +; "+======================= zEnvMail =======================+" //ConOut(cLog) //Se for para mostrar o log visualmente e for processo com interface com o usuário, mostra uma mensagem na tela If lMostraLog .And. ! IsBlind() Aviso("Log", cLog, {"Ok"}, 2) EndIf EndIf RestArea(aArea) Return lRet
Update – Setembro de 2021:
Pessoal, para quem quer usar uma rotina mais padrão possível, existe a função GPEMail, que utiliza os parâmetros MV_RELAUTH, MV_RELSERV, MV_RELACNT, MV_RELPSW, MV_RELSSL, MV_RELTLS e MV_RELFROM. Abaixo um exemplo de como acioná-la:
User Function zEnvMail(cPara, cAssunto, cCorpo, aAnexos) Local aArea := GetArea() Local lEnvioOK := .F. lEnvioOK := GPEMail(cAssunto, cCorpo, cPara, aAnexos) RestArea(aArea) Return lEnvioOK
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Essa rotina server para enviar e-mail de forma automática através de schedule?
Sim, ela serve para qualquer rotina, em tela, em relatório, em schedule.
Basta você configurar os parâmetros, e chamar ela com o u_ antes.
Um grande abraço.
Muito chique, e muito bem escrito. Parabéns
Valeu mano Súlivan.
Um grande abraço jovem.
Bom dia Mestre, rotina excelente, parabéns. Admiro muito seu trabalho, grande abraço.
Opa, que isso mano Charles, eu que agradeço jovem.
Um grande abraço.
Ótimo exemplo para substituir uma rotina antiga aqui ainda com “SEND MAIL”, que iria ajustar para múltiplos anexos. Obrigado, Daniel!
Bom dia Ric.
Opa, eu que agradeço jovem.
Um grande abraço.