csc-cia-stne 0.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ from .karavela import Karavela
2
+ from .utilitarios import Util
3
+ from .servicenow import ServiceNow
4
+ from .cia_logging import logger
5
+ from .stne_admin import StoneAdmin
6
+ from .bc_sta import BC_STA
7
+ from .bc_correios import BC_Correios
8
+ from .gcp_bigquery import BigQuery
@@ -0,0 +1,516 @@
1
+ import json
2
+ import logging
3
+ from zeep import Client
4
+ from zeep.transports import Transport
5
+ from requests import Session
6
+ from requests.auth import HTTPBasicAuth
7
+ from datetime import timedelta, datetime, time
8
+ from typing import List, Tuple, Union, Optional
9
+ from pydantic import BaseModel
10
+
11
+ class PastasAutorizadas(BaseModel):
12
+ MensagemErro: Optional[str] = None
13
+ OcorreuErro: bool
14
+ PastasAutorizadas: Optional[list] = None
15
+ QuantidadePastasAutorizadas: int
16
+
17
+ class ItemListaCorreio(BaseModel):
18
+
19
+ Assunto: str
20
+ Data:datetime
21
+ UnidadeDestinataria: str
22
+ DependenciaDestinataria: Optional[str] = None
23
+ UnidadeRemetente: str
24
+ DependenciaRemetente: Optional[str] = None
25
+ Grupo: Optional[str] = None
26
+ Status: str
27
+ TipoCorreio: str
28
+ NumeroCorreio: int
29
+ Pasta: dict
30
+ Setor: Optional[str] = None
31
+ Transicao: int
32
+ Versao: int
33
+
34
+ class ItemMsgCorreio(ItemListaCorreio):
35
+
36
+ OcorreuErro: bool
37
+ MensagemErro: Optional[str] = None
38
+ #NumeroCorreio = None
39
+ #Transicao = None
40
+ #Versao = None
41
+ #Assunto = None
42
+ Ementa: Optional[list] = None
43
+ Conteudo: str
44
+ #TipoCorreio = None
45
+ De: str
46
+ Para: str
47
+ EnviadaPor: str
48
+ EnviadaEm: datetime
49
+ RecebidaPor: str
50
+ RecebidaEm: datetime
51
+ Despachos: Optional[list] = None
52
+ Anexos: Optional[list] = None
53
+
54
+ class AnexoDict(BaseModel):
55
+
56
+ IdAnexo: int
57
+ NomeAnexo: str
58
+ Conteudo: str
59
+
60
+ class BC_Correios:
61
+
62
+ def __init__(self, wsdl_url:str, usuario:str, senha:str, correios_por_pasta_pasta_unidade_nome:str='40797', correios_por_pasta_pasta_unidade_ativa:bool=True, correios_por_pasta_pasta_unidade_tipo:str='InstituicaoFinanceira', correios_por_pasta_pasta_tipo:str='CaixaEntrada',correios_por_pasta_apenas_mensagens:bool=True, correios_por_pasta_pesquisar_em_todas_as_pastas:bool=True):
63
+
64
+ try:
65
+
66
+ session = Session()
67
+ session.auth = HTTPBasicAuth(usuario,senha)
68
+
69
+ transport = Transport(session=session,timeout=120,operation_timeout=120)
70
+
71
+ self.client = Client(wsdl_url, transport=transport)
72
+ self.is_connected = True
73
+ self.error = None
74
+ self.CorreiosPorPastaPastaUnidadeNome = correios_por_pasta_pasta_unidade_nome
75
+ self.CorreiosPorPastaPastaUnidadeAtiva = correios_por_pasta_pasta_unidade_ativa
76
+ self.CorreiosPorPastaPastaUnidadeTipo = correios_por_pasta_pasta_unidade_tipo
77
+ self.CorreiosPorPastaPastaTipo = correios_por_pasta_pasta_tipo
78
+ self.CorreiosPorPastaApenasMensagens = correios_por_pasta_apenas_mensagens
79
+ self.CorreiosPorPastaPesquisarEmTodasAsPastas = correios_por_pasta_pesquisar_em_todas_as_pastas
80
+
81
+ except Exception as e:
82
+
83
+ self.is_connected = False
84
+ self.error = e
85
+
86
+ def consultar_pastas_autorizadas(self)->Tuple[bool, Union[PastasAutorizadas, Exception]]:
87
+ """
88
+ Retorna as pastas de correio e os setores que o usuário tem permissão de acessar.
89
+ """
90
+
91
+ try:
92
+
93
+ response = self.client.service.ConsultarPastasAutorizadas()
94
+
95
+ if response.OcorreuErro:
96
+
97
+ raise Exception(response.MensagemErro)
98
+
99
+ pastas = PastasAutorizadas(MensagemErro=response.MensagemErro, OcorreuErro=response.OcorreuErro, QuantidadePastasAutorizadas=response.QuantidadePastasAutorizadas,PastasAutorizadas=response.PastasAutorizadas.PastaAutorizadaWSDTO)
100
+
101
+ return True, pastas
102
+
103
+ except Exception as e:
104
+
105
+ return False, e
106
+
107
+ def consultar_correios_por_pasta(self,ultimos_x_dias:int=None,data_inicial:datetime=None,data_final:datetime=None)->Tuple[bool, Union[List['ItemListaCorreio'], Exception]]:
108
+
109
+ """
110
+ Retorna uma lista com os cabeçalhos dos correios contidos em uma pasta.
111
+
112
+ A consulta pode ser realizada de 2 maneiras:
113
+ 1. Especificando um intervalo de dias relativos ao dia atual (com `ultimos_x_dias`).
114
+ 2. Informando explicitamente uma `data_inicial` E `data_final`.
115
+
116
+ Args:
117
+ ultimos_x_dias (int, opcional): O número de dias a contar para trás a partir da data atual. Se especificado, ignorará `data_inicial` e `data_final`.
118
+ data_inicial (datetime, opcional): Data inicial do intervalo para filtrar os correios.
119
+ data_final (datetime, opcional): Data final do intervalo para filtrar os correios.
120
+
121
+ Returns:
122
+ tuple: Um par contendo:
123
+ - bool: Indica se a operação foi bem-sucedida (True) ou falhou (False).
124
+ - Union[list[ItemListaCorreio], Exception]: Retorna uma lista de objetos `ItemListaCorreio` contendo os detalhes dos correios encontrados, ou uma exceção em caso de erro.
125
+ """
126
+
127
+ try:
128
+
129
+ if ultimos_x_dias is not None and isinstance(ultimos_x_dias,int):
130
+
131
+ agora = datetime.now()
132
+
133
+ # Pegando mensagens antigas, ja lidas, no desenvolvimento, para nao atrapalhar o time com as mensagens nao lidas atuais
134
+ #logger.warning("VERIFICAR DATA DO 'AGORA'!")
135
+ #agora = datetime.now() - timedelta(days=150)
136
+
137
+ dt_inicial_iso_format = agora - timedelta(days=ultimos_x_dias)
138
+ dt_inicial_iso_format = datetime.combine(dt_inicial_iso_format.date(), time.min)
139
+ dt_inicial_iso_format = dt_inicial_iso_format.isoformat()
140
+
141
+ dt_final_iso_format = datetime.combine(agora.date(), time.max)
142
+ dt_final_iso_format = agora.isoformat()
143
+
144
+ elif data_inicial is isinstance(data_inicial,datetime) and data_final is isinstance(data_final,datetime):
145
+
146
+ dt_inicial_iso_format = data_inicial.isoformat()
147
+ dt_final_iso_format = data_final.isoformat()
148
+
149
+ else:
150
+
151
+ raise ValueError("ultimos_x_dias se for informado, precisa ser um numero inteiro. Ou entao se for informado data_inicial E data_final, esses 2 parametros precisam ser datetime")
152
+
153
+ correios_filtrados = []
154
+ correios_repetidos = []
155
+ pagina_atual = 1
156
+
157
+ def objeto_ja_existe_na_lista(novo_item, lista_de_correios):
158
+
159
+ for item in lista_de_correios:
160
+
161
+ if (str(item.NumeroCorreio) == str(novo_item.NumeroCorreio)):
162
+
163
+ return True
164
+
165
+ return False
166
+
167
+ proxima_centena = 100
168
+ while True:
169
+
170
+ correios = None
171
+ params = {
172
+ 'Pasta': {
173
+ 'Unidade': {
174
+ 'Nome': self.CorreiosPorPastaPastaUnidadeNome,
175
+ 'Ativa': self.CorreiosPorPastaPastaUnidadeAtiva,
176
+ 'Tipo': self.CorreiosPorPastaPastaUnidadeTipo
177
+ },
178
+ 'Tipo': self.CorreiosPorPastaPastaTipo
179
+ },
180
+ 'ApenasMensagens': self.CorreiosPorPastaApenasMensagens,
181
+ 'PesquisarEmTodasAsPastas': self.CorreiosPorPastaPesquisarEmTodasAsPastas,
182
+ 'Pagina': pagina_atual,
183
+ 'DataInicial': dt_inicial_iso_format,
184
+ 'DataFinal': dt_final_iso_format,
185
+ }
186
+
187
+ response = self.client.service.ConsultarCorreiosPorPasta(params)
188
+
189
+ if response.OcorreuErro:
190
+ raise Exception(f"Erro ao consultar correios: {response.MensagemErro}")
191
+
192
+ # Verifica a quantidade total de correios na primeira iteração
193
+ try:
194
+
195
+ # Acessa a lista de correios diretamente
196
+ correios = response.Correios.ResumoCorreioWSDTO
197
+
198
+ if not correios:
199
+
200
+ # Se não houver mais itens, paramos a busca
201
+ break
202
+ except:
203
+
204
+ # Fim da listagem de correios
205
+ break
206
+
207
+ for correio in correios:
208
+
209
+ item_de_lista_de_correios = ItemListaCorreio(
210
+ Assunto=correio.Assunto,
211
+ Data=correio.Data,
212
+ UnidadeDestinataria=correio.UnidadeDestinataria,
213
+ DependenciaDestinataria=correio.DependenciaDestinataria,
214
+ UnidadeRemetente=correio.UnidadeRemetente,
215
+ DependenciaRemetente=correio.DependenciaRemetente,
216
+ Grupo=correio.Grupo,
217
+ Status=correio.Status,
218
+ TipoCorreio=correio.TipoCorreio,
219
+ NumeroCorreio=correio.NumeroCorreio,
220
+ Pasta={
221
+ 'Unidade': correio.Pasta.Unidade,
222
+ 'Dependencia': correio.Pasta.Dependencia,
223
+ 'Setor': correio.Pasta.Setor,
224
+ 'Tipo': correio.Pasta.Tipo
225
+ },
226
+ Setor=correio.Setor,
227
+ Transicao=correio.Transicao,
228
+ Versao=correio.Versao
229
+ )
230
+ if objeto_ja_existe_na_lista(novo_item=item_de_lista_de_correios,lista_de_correios=correios_filtrados) == False:
231
+
232
+ correios_filtrados.append(item_de_lista_de_correios)
233
+ else:
234
+ correios_repetidos.append(item_de_lista_de_correios)
235
+
236
+ if len(correios_filtrados) >= proxima_centena:
237
+
238
+ logging.info(f"Página #{pagina_atual}: {len(correios_filtrados)} correios armazenados no total")
239
+ proxima_centena = proxima_centena + 100
240
+
241
+ # Avança para a próxima página
242
+ pagina_atual += 1
243
+
244
+ return True, correios_filtrados
245
+
246
+ except Exception as e:
247
+
248
+ return False, e
249
+
250
+ def ler_correio(self, numero:int,data_rebimento:datetime,tipo:str,transicao:int,versao:int,pasta:str)-> Tuple[bool, Union[ItemMsgCorreio, Exception]]:
251
+ """
252
+ Retorna o conteúdo de um correio.
253
+
254
+ Args:
255
+ correio (ItemListaCorreio): objeto da classe ItemListaCorreio (item da listagem de mensagens)
256
+
257
+ Returns:
258
+ tuple: Um par contendo:
259
+ - bool: Indica se a operação foi bem-sucedida (True) ou falhou (False).
260
+ - Union[ItemMsgCorreio, Exception]: Retorna um objeto da classe ItemMsgCorreio contendo os detalhes do correio lido, ou uma exceção em caso de erro.
261
+ """
262
+
263
+ try:
264
+
265
+ # Substituir aspas simples por aspas duplas
266
+ pasta = pasta.replace("'", '"').replace("None", "null")
267
+ pasta = json.loads(pasta)
268
+ #params = {
269
+ # 'Correio': {
270
+ # 'NumeroCorreio': correio.NumeroCorreio,
271
+ # 'Data': correio.Data.isoformat(),
272
+ # 'TipoCorreio': correio.TipoCorreio,
273
+ # 'Transicao': correio.Transicao,
274
+ # 'Versao': correio.Versao,
275
+ # 'Pasta': correio.Pasta
276
+ # }
277
+ #}
278
+
279
+ params = {
280
+ 'Correio': {
281
+ 'NumeroCorreio': numero,
282
+ 'Data': data_rebimento.isoformat(),
283
+ 'TipoCorreio': tipo,
284
+ 'Transicao': transicao,
285
+ 'Versao': versao,
286
+ 'Pasta': {
287
+ 'Unidade': pasta["Unidade"],
288
+ 'Dependencia': pasta["Dependencia"],
289
+ 'Setor': pasta["Setor"],
290
+ 'Tipo': pasta["Tipo"],
291
+ }
292
+ }
293
+ }
294
+
295
+ response = self.client.service.LerCorreio(params)
296
+
297
+ #novo start
298
+
299
+ #print("antes")
300
+ #print("response type:",type(response))
301
+ #print("response:")
302
+ #print(response)
303
+ if response.OcorreuErro:
304
+ raise Exception(f"Erro ao detalhar correio: {response.MensagemErro}")
305
+
306
+ #msg_detail = ItemMsgCorreio()
307
+ #msg_detail.OcorreuErro = response.OcorreuErro
308
+ #msg_detail.MensagemErro = response.MensagemErro
309
+ ##msg_detail.NumeroCorreio = response.DetalheCorreio.NumeroCorreio
310
+ ##msg_detail.Transicao = response.DetalheCorreio.Transicao
311
+ ##msg_detail.Versao = response.DetalheCorreio.Versao
312
+ ##msg_detail.Assunto = response.DetalheCorreio.Assunto
313
+ #msg_detail.Ementa = response.DetalheCorreio.Ementa
314
+ #msg_detail.Conteudo = response.DetalheCorreio.Conteudo
315
+ ##msg_detail.TipoCorreio = response.DetalheCorreio.TipoCorreio
316
+ #msg_detail.De = response.DetalheCorreio.De
317
+ #msg_detail.Para = response.DetalheCorreio.Para
318
+ #msg_detail.EnviadaPor = response.DetalheCorreio.EnviadaPor
319
+ #msg_detail.EnviadaEm = response.DetalheCorreio.EnviadaEm
320
+ #msg_detail.RecebidaPor = response.DetalheCorreio.RecebidaPor
321
+ #msg_detail.RecebidaEm = response.DetalheCorreio.RecebidaEm
322
+ #msg_detail.Despachos = response.DetalheCorreio.Despachos
323
+ #if response.DetalheCorreio.Anexos:
324
+ # msg_detail.Anexos = response.DetalheCorreio.Anexos.AnexoWSDTO
325
+
326
+
327
+ #msg_detail = ItemMsgCorreio(
328
+ # **correio.model_dump(),
329
+ # OcorreuErro = response.OcorreuErro,
330
+ # MensagemErro = response.MensagemErro,
331
+ # #msg_detail.NumeroCorreio = response.DetalheCorreio.NumeroCorreio
332
+ # #msg_detail.Transicao = response.DetalheCorreio.Transicao
333
+ # #msg_detail.Versao = response.DetalheCorreio.Versao
334
+ # #msg_detail.Assunto = response.DetalheCorreio.Assunto
335
+ # Ementa = response.DetalheCorreio.Ementa,
336
+ # Conteudo = response.DetalheCorreio.Conteudo,
337
+ # #msg_detail.TipoCorreio = response.DetalheCorreio.TipoCorreio
338
+ # De = response.DetalheCorreio.De,
339
+ # Para = response.DetalheCorreio.Para,
340
+ # EnviadaPor = response.DetalheCorreio.EnviadaPor,
341
+ # EnviadaEm = response.DetalheCorreio.EnviadaEm,
342
+ # RecebidaPor = response.DetalheCorreio.RecebidaPor,
343
+ # RecebidaEm = response.DetalheCorreio.RecebidaEm,
344
+ # Despachos = response.DetalheCorreio.Despachos,
345
+ # Anexos = response.DetalheCorreio.Anexos.AnexoWSDTO
346
+ #)
347
+
348
+
349
+ msg_detail = {
350
+ "OcorreuErro": response.OcorreuErro,
351
+ "MensagemErro": response.MensagemErro,
352
+ #msg_detail.NumeroCorreio = response.DetalheCorreio.NumeroCorreio
353
+ #msg_detail.Transicao = response.DetalheCorreio.Transicao
354
+ #msg_detail.Versao = response.DetalheCorreio.Versao
355
+ #msg_detail.Assunto = response.DetalheCorreio.Assunto
356
+ "Ementa": response.DetalheCorreio.Ementa,
357
+ "Conteudo": response.DetalheCorreio.Conteudo,
358
+ #msg_detail.TipoCorreio = response.DetalheCorreio.TipoCorreio
359
+ "De": response.DetalheCorreio.De,
360
+ "Para": response.DetalheCorreio.Para,
361
+ "EnviadaPor": response.DetalheCorreio.EnviadaPor,
362
+ "EnviadaEm": response.DetalheCorreio.EnviadaEm,
363
+ "RecebidaPor": response.DetalheCorreio.RecebidaPor,
364
+ "RecebidaEm": response.DetalheCorreio.RecebidaEm,
365
+ "Despachos": response.DetalheCorreio.Despachos,
366
+ "Anexos": response.DetalheCorreio.Anexos.AnexoWSDTO
367
+ }
368
+
369
+
370
+ #print("depois")
371
+ #print("response novo type:",type(msg_detail))
372
+ #print("response novo:")
373
+ #print(msg_detail)
374
+ #print(msg_detail.Anexos)
375
+
376
+
377
+ """
378
+ xx = {
379
+ 'MensagemErro': None,
380
+ 'OcorreuErro': False,
381
+ 'DetalheCorreio': {
382
+ 'NumeroCorreio': 124311198,
383
+ 'Transicao': 46142046,
384
+ 'Versao': 670,
385
+ 'Assunto': 'SOLJUD 2024087211',
386
+ 'Ementa': None,
387
+ 'Conteudo': '\n<pre>\nOfício 026707/2024-BCB/Deati/Coadi-1\nPE 262353/e-BC 2024211930 Brasília, 23 de setembro de 2024.\nJUD/EXT - 2024/087211E\n\nA todas as instituições financeiras.\n\nAssunto: Ofício S\\N, de 13 de setembro de 2024\nProcesso: 5094191-48.2024.8.09.0142\n\nPrezados Senhores,\n\nAtendendo à requisição do(a) Juíz de Direito MARLI PIMENTA NAVES, do(a) Juizado Especial Cível, encaminhamos, em anexo, para exame e adoção das\nprovidências julgadas cabíveis, a determinação judicial exarada no ofício em epígrafe.\n\n\n2. A propósito, esclarecemos que eventuais dúvidas a respeito da ordem, inclusive com relação a número de CPF/CNPJ, somente serão dirimidas\njunto ao Juízo demandante, ou ao órgão por ele designado, para onde devem ser encaminhadas as correspondências alusivas ao assunto,\nmencionando-se os números do ofício e do processo.\n\n\n3. Finalmente, alertamos que a inobservância à norma do sigilo bancário contido na Lei Complementar 105, de 10 de janeiro de 2001, sujeitará os\nresponsáveis às sanções previstas no artigo 10 da mencionada Lei, cabendo ainda à instituição zelar por manter a privacidade das informações\nrelativas a clientes (artigo 5º, item X, da CF/88).\n\n\nAtenciosamente,\n\nDepartamento de Atendimento Institucional – DEATI\nGerência de Relacionamento Institucional – GERIN\n\n\nGILDO TEREZA DOS REIS\nTECNICO\n\nMAURO MAGNO MACHADO JUNIOR \nTECNICO \n\nDocumento transmitido por correio eletrônico, via BC Correio, dispensado de assinatura.\n</pre>\n',
388
+ 'TipoCorreio': 'MENSAGEM',
389
+ 'De': 'DEATI',
390
+ 'Para': '40797 (Transmissão para grupo geral F1)',
391
+ 'EnviadaPor': 'DEATI.GILDO',
392
+ 'EnviadaEm': datetime.datetime(2024, 9, 23, 10, 40, 19),
393
+ 'RecebidaPor': '407970001.PALCANTARA',
394
+ 'RecebidaEm': datetime.datetime(2024, 9, 25, 14, 45, 51),
395
+ 'Despachos': None,
396
+ 'Anexos': {
397
+ 'AnexoWSDTO': [
398
+ {
399
+ 'IdAnexo': 538648,
400
+ 'NomeAnexo': '-2024-171630-211930--20092024233504.PDF',
401
+ 'Conteudo': None
402
+ }
403
+ ]
404
+ }
405
+ }
406
+ }
407
+ """
408
+
409
+
410
+ #logger.debug("parou aqui 6757576")
411
+ #sys.exit(0)
412
+ #novo end
413
+
414
+ #return True, response
415
+ return True, msg_detail
416
+
417
+ # Serializa o objeto SOAP em um dicionário Python
418
+ #serialized_response = serialize_object(response)
419
+
420
+ # Converte o dicionário em um JSON formatado
421
+ #response_json = json.dumps(serialized_response, indent=4, default=str)
422
+
423
+ #return True, response_json
424
+
425
+ except Exception as e:
426
+
427
+ return False, e
428
+
429
+ def obter_anexo(self, numero:int, versao:int, transicao:int,pasta:str,anexo_id:int,file_name:str,conteudo:str)-> Tuple[bool,Union[dict, Exception]]:
430
+ """
431
+ Obtém um anexo de um correio eletrônico.
432
+
433
+ Args:
434
+ correio (ItemListaCorreio): objeto da classe ItemListaCorreio (item da listagem de mensagens)
435
+ anexo (AnexoDict): um item do dicionário da lista de anexos de ItemListaCorreio
436
+
437
+ Returns:
438
+ tuple: Um par contendo:
439
+ - bool: Indica se a operação foi bem-sucedida (True) ou falhou (False).
440
+ - Union[dict, Exception]: Retorna um dicionario com dados do anexo, ou uma exceção em caso de erro.
441
+
442
+ """
443
+ #logger.info("ANEXOS PARA OBTER")
444
+ #print(correio.Anexos)
445
+ try:
446
+
447
+ pasta = pasta.replace("'", '"').replace("None", "null")
448
+ pasta = json.loads(pasta)
449
+
450
+ # Monta os parâmetros para a requisição SOAP
451
+ params = {
452
+ 'NumeroCorreio': numero,
453
+ 'Versao': versao,
454
+ 'Transicao': transicao,
455
+ #'Pasta': pasta,
456
+ 'Pasta': {
457
+ 'Unidade': pasta["Unidade"],
458
+ 'Dependencia': pasta["Dependencia"],
459
+ 'Setor': pasta["Setor"],
460
+ 'Tipo': pasta["Tipo"],
461
+ },
462
+ #'Pasta': {
463
+ # 'Unidade': {
464
+ # 'Nome': pasta['Unidade']['Nome'],
465
+ # 'Ativa': pasta['Unidade']['Ativa'],
466
+ # 'Tipo': pasta['Unidade']['Tipo']
467
+ # },
468
+ # 'Dependencia': pasta['Dependencia'],
469
+ # 'Setor': {
470
+ # 'Nome': pasta['Setor']['Nome'],
471
+ # 'Ativo': pasta['Setor']['Ativo']
472
+ # },
473
+ # 'Tipo': pasta['Tipo']
474
+ #},
475
+ 'Anexo': {
476
+ 'IdAnexo': anexo_id,
477
+ 'NomeAnexo': file_name,
478
+ 'Conteudo': conteudo # Conteúdo em base64
479
+ }
480
+ }
481
+
482
+ # Faz a requisição SOAP para o método ObterAnexo
483
+ response = self.client.service.ObterAnexo(parametros=params)
484
+ #logger.info("response")
485
+ #logger.info(response)
486
+
487
+ # Acessa os dados da resposta (IdAnexo, NomeAnexo, Conteudo)
488
+ if response and hasattr(response, 'Anexo'):
489
+ id_anexo = response.Anexo.IdAnexo
490
+ nome_anexo = response.Anexo.NomeAnexo
491
+ conteudo_anexo = response.Anexo.Conteudo
492
+
493
+ # Retorna os dados capturados como um dicionário
494
+ return True, {
495
+ 'IdAnexo': id_anexo,
496
+ 'NomeAnexo': nome_anexo,
497
+ 'Conteudo': conteudo_anexo
498
+ }
499
+ else:
500
+ return False, Exception("Correio não possui anexo")
501
+
502
+ except Exception as e:
503
+
504
+ return False, e
505
+
506
+ def encerrar(self):
507
+ """Fecha o cliente e libera a sessão."""
508
+
509
+ try:
510
+
511
+ self.client.transport.session.close()
512
+
513
+ except:
514
+
515
+ pass
516
+