client

Classe responsável pela autenticação OAuth 2.0 e Basic para envio de e-mail no Protheus. Encapsula o ciclo de vida do token (obtenção, refresh e consentimento) e o gerenciamento da conexão SMTP, com base nas telas de provedor e contas.

Atributos

AtributoTipoDescrição
aScopesArrayLista de scopes configurados para a requisição OAuth
nEventNumericCódigo do último evento registrado; valores negativos indicam erro
cEventDescCharacterDescrição textual do último evento registrado
cAliasAccountCharacterNome do alias da tabela de contas (SYS_OAUTH_ACCOUNT)
cAliasProviderCharacterNome do alias da tabela de provedores (SYS_OAUTH_PROVIDER)
cTenantIdCharacterTenant ID descriptografado do provedor, quando aplicável
lCliCredentialsLogicalIndica se o fluxo de autenticação é client_credentials
cAuthUrlCharacterURL de autorização obtida do cadastro do provedor

Métodos

new(cEmail)

Método construtor da classe. Inicializa os atributos internos, define os aliases das tabelas de conta e provedor, e chama updateValues() para carregar as configurações com base no e-mail informado.

ParâmetroTipoDescrição
cEmailCharacterE-mail da conta a ser utilizada; deve existir na tabela SYS_OAUTH_ACCOUNT

Retorno: Object — instância da classe client.

Exemplo:

Local oClient as object
oClient := totvs.framework.oauth.client():New("[email protected]")

Destroy()

Método destruidor. Libera o array aScopes e o objeto oMailManager da memória e chama o destruidor da superclasse.

Exemplo:

oClient:Destroy()

SetScopes(aScopes)

Define os scopes de autenticação OAuth e os repassa à superclasse via SetAuthOptions(), concatenando-os no formato scope=valor1,valor2.

ParâmetroTipoDescrição
aScopesArrayLista de strings com os scopes a serem configurados

Exemplo:

oClient:SetScopes({"https://mail.google.com/", "openid"})

HasError(nEvent, cError)

Verifica se houve erro na última operação. Preenche as variáveis passadas por referência com o código e a descrição do evento registrado na instância.

ParâmetroTipoDescrição
nEventNumericVariável que receberá o código do evento registrado
cErrorCharacterVariável que receberá a descrição do evento registrado

Retorno: Logical  .T. se nEvent for menor que zero (erro), .F. caso contrário.

Exemplo:

Local nEvt as numeric
Local cMsg as character
If oClient:HasError(nEvt, cMsg)
    ConOut("Erro " + cValToChar(nEvt) + ": " + cMsg)
EndIf

ClearEvent()

Limpa o último evento registrado na instância, redefinindo nEvent para 0 e cEventDesc para vazio. Também chama ClearError() da superclasse.

Exemplo:

oClient:ClearEvent()

validEmail()

Valida se o e-mail informado no construtor existe na tabela SYS_OAUTH_ACCOUNT e se o provedor vinculado à conta existe na tabela SYS_OAUTH_PROVIDER. Em caso de falha, registra o evento de erro correspondente.

Retorno: Logical  .T. se o e-mail e o provedor forem encontrados, .F. caso contrário.

Exemplo:

If oClient:validEmail()
    ConOut("E-mail válido.")
EndIf

updateValues()

Atualiza as propriedades internas da instância com base nos dados da conta e do provedor cadastrados. Configura o tipo de autenticação (oauth2 ou basic), URLs, credenciais e o grant type (authorization_code ou client_credentials). Chamado automaticamente pelo construtor.

Exemplo:

oClient:updateValues()

GetValidToken(lOnlyGet, lCheckMail)

Obtém um token de acesso válido. O comportamento varia conforme o fluxo configurado:

  • lOnlyGet = .T. ou autenticação Basic: retorna o token atual sem validações adicionais.
  • client_credentials: verifica expiração e requisita novo token se necessário.
  • authorization_code: verifica tokens armazenados na tabela, realiza refresh automático quando expirado e atualiza o registro.
ParâmetroTipoDescrição
lOnlyGetLogicalSe .T., retorna o token atual sem validações ou requisições adicionais. Padrão: .F.
lCheckMailLogicalSe .T., valida o e-mail antes de processar o token, evitando chamadas duplicadas. Padrão: .T.

Retorno: Character — token de acesso válido; string vazia em caso de falha.

Exemplo:

Local cToken as character
cToken := oClient:GetValidToken()
If !Empty(cToken)
    ConOut("Token obtido: " + cToken)
EndIf

Consent()

Realiza o processo de consentimento OAuth. Adiciona o parâmetro login_hint às opções de autenticação (caso ainda não esteja presente) e acessa a URL de autorização configurada. Registra evento de erro se a operação falhar.

Retorno: Logical  .T. se o acesso à URL de autorização foi realizado com sucesso, .F. em caso de erro prévio ou falha no acesso.

Exemplo:

If oClient:Consent()
    ConOut("Consentimento realizado com sucesso.")
EndIf

SendMail(oMessage)

Realiza o envio de um e-mail utilizando o TMailManager configurado pela classe. Executa sequencialmente: conexão SMTP, autenticação (quando o provedor exige) e envio da mensagem. Registra o evento correspondente ao resultado de cada etapa.

ParâmetroTipoDescrição
oMessageObjectInstância de TMailMessage com a mensagem a ser enviada

Retorno: Logical  .T. se o e-mail foi enviado com sucesso, .F. em caso de falha em qualquer etapa.

Exemplo:

Local oMsg as object
oMsg := TMailMessage():New()
// ... configuração da mensagem ...
If oClient:SendMail(oMsg)
    ConOut("E-mail enviado com sucesso.")
EndIf

GetMailManager(lCheckMail)

Inicializa e configura uma instância de TMailManager com base nos dados do provedor e da conta (servidor SMTP, porta, TLS, SSL, timeout). Quando o tipo de autenticação é OAuth2, obtém e aplica o token de acesso via GetValidToken(). O objeto retornado não está conectado ao SMTP.

ParâmetroTipoDescrição
lCheckMailLogicalSe .T., valida o e-mail antes de configurar o gerenciador. Padrão: .T.

Retorno: Object — instância de TMailManager configurada, ou o valor atual do atributo oMailManager caso a validação falhe.

Exemplo:

Local oManager as object
oManager := oClient:GetMailManager()

GetMail()

Retorna o endereço de e-mail armazenado no atributo privado cEmail da instância.

Retorno: Character — endereço de e-mail do cliente.

Exemplo:

ConOut("E-mail configurado: " + oClient:GetMail())

IsBasic()

Indica se o tipo de autenticação configurado para a conta é Basic.

Retorno: Logical  .T. se o tipo de autenticação for "basic", .F. caso contrário.

Exemplo:

If oClient:IsBasic()
    ConOut("Autenticação Basic configurada.")
EndIf

IsOauth2()

Indica se o tipo de autenticação configurado para a conta é OAuth 2.0.

Retorno: Logical  .T. se o tipo de autenticação for "oauth2", .F. caso contrário.

Exemplo:

If oClient:IsOauth2()
    ConOut("Autenticação OAuth2 configurada.")
EndIf

isExpired(nExpireAt, nSecondsNow)

Função estática. Verifica se um token está expirado, aplicando uma margem de antecipação de 10 segundos antes do vencimento para forçar a renovação preventiva.

ParâmetroTipoDescrição
nExpireAtNumericTimestamp de expiração do token em microssegundos
nSecondsNowNumericTempo atual em microssegundos. Padrão: resultado de Microseconds()

Retorno: Logical  .T. se o token estiver expirado ou prestes a expirar (dentro de 10 segundos), .F. caso contrário.

Exemplo:

If isExpired(nTokenExpireAt)
    ConOut("Token expirado, necessário renovar.")
EndIf



Exemplos:

//-------------------------------------------------------------------
/*/{Protheus.doc} SendMail
	Envio de email com a classe totvs.framework.oauth.client
    Exibe mensagem de sucesso ou erro conforme o resultado do envio.
@type   function
@author Caio Lima
@since  27/04/2026
@param  cEmailLogon, character, endereço de e-mail utilizado para autenticar o cliente OAuth2 e definir o destinatário da mensagem.
@param  cTo, character, destinatário do email
@param  cSubject, character, assunto do email
@param  cBody, character, corpo do email a ser enviado
@param  oAuth2Client, object, objeto da classe oAuth.client, para envio do email
@return logical, .T. caso tenha conseguido enviar o email, do contrário retorna .F.
//-----------------------------------------------------------------*/
Function SendMail(cEmailLogon as character, cTo as character, cSubject as character, cBody as character) as logical
    Local oMessage as object
    Local oAuth2Client as object
    Local lRet := .F. as logical

    oAuth2Client := totvs.framework.oauth.client():New(cEmailLogon)

    If oAuth2Client:HasError()
        showError(oAuth2Client, "SendMail_Error")

    Else
        cTo := PadR( cEmailLogon , 200)
        cSubject := PadR( "Teste de envio" , 200)
        cBody := I18N("Teste de envio conta #1", {cEmailLogon}) + ;
            CRLF + I18N("Tipo de autenticação: #1", {(oAuth2Client:cAliasAccount)->TYPE_AUTH})

		oMessage := TMailMessage():New()
		oMessage:Clear()
		If !Empty((oAuth2Client:cAliasAccount)->MAIL_FROM)
			oMessage:cFrom	   := (oAuth2Client:cAliasAccount)->MAIL_FROM
		Else
			oMessage:cFrom	   := cEmailLogon
		EndIf
		oMessage:cTo	   := cTo
		oMessage:cSubject  := cSubject
		oMessage:cBody	   := "<HTML>" + StrTran(cBody,CRLF,"<br>") + "</HTML>"
		If oAuth2Client:SendMail(oMessage)
			FWAlertSuccess("Email enviado com sucesso!") //"Email enviado com sucesso!"
			lRet := .T.
		Else
			showError(oAuth2Client, "SendMail_Error")
		EndIf
		FwFreeObj(oMessage)
    EndIf

Return lRet

//-------------------------------------------------------------------
/*/{Protheus.doc} showError
    Exibe uma mensagem de erro em um aviso, 
    acrescentando ao texto informações de erro do cliente OAuth2 caso existam.
@type   function
@author Caio Lima
@since  29/04/2026
@param  oAuth2Client, object, objeto do cliente OAuth2 utilizado para verificar se há erros registrados.
@param  cTitle, character, título exibido na caixa de diálogo de aviso.
@param  cMsg, character, mensagem principal exibida na caixa de diálogo de aviso.
//-----------------------------------------------------------------*/
Function showError(oAuth2Client as object, cTitle as character, cMsg as character)
    Local nError as numeric
    Local cError as character
    
    FwDefault cMsg := ""
    FwDefault cTitle := ""

    If ValType(oAuth2Client) == "O" .AND. oAuth2Client:HasError(@nError, @cError)
        cMsg += CRLF + I18N("Erro #1", {nError}) + CRLF + cError
    EndIf
    Aviso( cTitle , cMsg ,{"OK"}, 3) //'OK'
Return