mailcore-sdk 0.1.0a1__tar.gz
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.
- mailcore_sdk-0.1.0a1/CHANGELOG.md +25 -0
- mailcore_sdk-0.1.0a1/CONTRIBUTING.md +46 -0
- mailcore_sdk-0.1.0a1/LICENSE +21 -0
- mailcore_sdk-0.1.0a1/MANIFEST.in +9 -0
- mailcore_sdk-0.1.0a1/PKG-INFO +142 -0
- mailcore_sdk-0.1.0a1/README.md +118 -0
- mailcore_sdk-0.1.0a1/SECURITY.md +43 -0
- mailcore_sdk-0.1.0a1/docs/cobertura.md +148 -0
- mailcore_sdk-0.1.0a1/docs/integracao-api-interrupcao.json +27 -0
- mailcore_sdk-0.1.0a1/docs/integracao-api.json +52 -0
- mailcore_sdk-0.1.0a1/docs/integracoes.md +145 -0
- mailcore_sdk-0.1.0a1/docs/python-3.11.18.json +22 -0
- mailcore_sdk-0.1.0a1/docs/python-3.12.16.json +22 -0
- mailcore_sdk-0.1.0a1/docs/python-3.13.18.json +22 -0
- mailcore_sdk-0.1.0a1/docs/python-3.14.10.json +22 -0
- mailcore_sdk-0.1.0a1/docs/python-3.15.2.json +22 -0
- mailcore_sdk-0.1.0a1/docs/verificacao.md +81 -0
- mailcore_sdk-0.1.0a1/exemplos/compartilhado.py +130 -0
- mailcore_sdk-0.1.0a1/exemplos/django_app.py +65 -0
- mailcore_sdk-0.1.0a1/exemplos/fastapi_app.py +69 -0
- mailcore_sdk-0.1.0a1/exemplos/flask_app.py +61 -0
- mailcore_sdk-0.1.0a1/pyproject.toml +51 -0
- mailcore_sdk-0.1.0a1/setup.cfg +4 -0
- mailcore_sdk-0.1.0a1/src/mailcore/__init__.py +47 -0
- mailcore_sdk-0.1.0a1/src/mailcore/assinatura.py +105 -0
- mailcore_sdk-0.1.0a1/src/mailcore/cliente.py +105 -0
- mailcore_sdk-0.1.0a1/src/mailcore/erros.py +42 -0
- mailcore_sdk-0.1.0a1/src/mailcore/py.typed +0 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/__init__.py +93 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/automacoes.py +252 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/base.py +51 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/caixas.py +784 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/campanhas.py +391 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/chaves_api.py +109 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/cli.py +78 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/contatos.py +892 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/dominios.py +179 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/emails.py +266 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/eventos.py +159 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/modelos.py +484 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/recebimento.py +211 -0
- mailcore_sdk-0.1.0a1/src/mailcore/recursos/webhooks.py +252 -0
- mailcore_sdk-0.1.0a1/src/mailcore/tipos.py +164 -0
- mailcore_sdk-0.1.0a1/src/mailcore/transporte.py +602 -0
- mailcore_sdk-0.1.0a1/src/mailcore/versao.py +3 -0
- mailcore_sdk-0.1.0a1/src/mailcore_sdk.egg-info/PKG-INFO +142 -0
- mailcore_sdk-0.1.0a1/src/mailcore_sdk.egg-info/SOURCES.txt +48 -0
- mailcore_sdk-0.1.0a1/src/mailcore_sdk.egg-info/dependency_links.txt +1 -0
- mailcore_sdk-0.1.0a1/src/mailcore_sdk.egg-info/requires.txt +2 -0
- mailcore_sdk-0.1.0a1/src/mailcore_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Histórico de alterações
|
|
2
|
+
|
|
3
|
+
## 0.1.0a1 — 14/11/2026
|
|
4
|
+
|
|
5
|
+
Primeira versão alpha local da distribuição `mailcore-sdk`, importada como
|
|
6
|
+
`mailcore`. Ainda não publicada no PyPI.
|
|
7
|
+
|
|
8
|
+
- Clientes síncrono e assíncrono com estado e pools próprios, fechamento explícito
|
|
9
|
+
e suporte a `with`/`async with`.
|
|
10
|
+
- Dezesseis recursos principais e 151 operações por variante, com campos e nomes
|
|
11
|
+
PT-BR, preservando o contrato HTTP Mailcore.
|
|
12
|
+
- Tipos de envio, lote, aceitação e configuração, `Resposta[T]` e marcador PEP 561.
|
|
13
|
+
Entidades complexas continuam parcialmente tipadas como `Resposta[Any]`.
|
|
14
|
+
- Downloads autenticados, bytes e fluxos limitados; verificação local de
|
|
15
|
+
assinatura sobre o corpo bruto dos webhooks.
|
|
16
|
+
- HTTPS verificado, redirecionamentos recusados, ausência de cookies/proxies do
|
|
17
|
+
ambiente, respostas limitadas e nenhuma repetição automática.
|
|
18
|
+
- Exemplos opcionais Flask, FastAPI e Django com token de aplicação separado,
|
|
19
|
+
envelope fixo, idempotência externa e leitura limitada.
|
|
20
|
+
- Verificação em Docker para a matriz CPython 3.11–3.15, testes de contrato,
|
|
21
|
+
transporte HTTPS e API local isolada, sem publicação ou entrega SMTP.
|
|
22
|
+
|
|
23
|
+
`tempo_limite` segue a inatividade de cada etapa HTTPX. Ele não representa prazo
|
|
24
|
+
total de relógio. Consulte [a cobertura](docs/cobertura.md) para os limites e o
|
|
25
|
+
alcance desta versão.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Contribuir
|
|
2
|
+
|
|
3
|
+
O projeto está em alpha e distribui `mailcore-sdk`, importado como `mailcore`.
|
|
4
|
+
Mantenha código e documentação em português do Brasil e preserve os nomes e
|
|
5
|
+
envelopes do contrato público da API Mailcore.
|
|
6
|
+
|
|
7
|
+
## Implementação
|
|
8
|
+
|
|
9
|
+
- Confirme a rota, o DTO, o escopo de autorização e a resposta no backend antes
|
|
10
|
+
de acrescentar uma operação. Capacidade de API não comprova uma tela ou fluxo.
|
|
11
|
+
- Mantenha paridade entre `Cliente` e `ClienteAsync`, sem estado global de
|
|
12
|
+
credenciais. Reutilize o transporte e seus pools, em vez de criar clientes a
|
|
13
|
+
cada pedido.
|
|
14
|
+
- Preserve omissão, `None`, `False`, revisões e envelopes de paginação. Não
|
|
15
|
+
traduza valores do protocolo nem normalize DTOs diferentes para um só formato.
|
|
16
|
+
- Atualize os tipos públicos e a cobertura sem anunciar TypedDicts completos
|
|
17
|
+
quando a resposta ainda for `Resposta[Any]`.
|
|
18
|
+
- Recursos gerados são mantidos pela especificação de
|
|
19
|
+
`scripts/gerar_recursos.py`. Alterações nesse contrato devem atualizar a fonte
|
|
20
|
+
e as duas variantes, com teste de caminho, query, corpo e retorno.
|
|
21
|
+
|
|
22
|
+
Os exemplos dos frameworks ficam separados do pacote principal. O SDK básico não
|
|
23
|
+
deve importar Flask, FastAPI ou Django. Mantenha testes de autenticação,
|
|
24
|
+
idempotência, limites e sanitização ao alterar esses exemplos.
|
|
25
|
+
|
|
26
|
+
## Verificação
|
|
27
|
+
|
|
28
|
+
Use o verificador Docker do projeto para executar formatação, lint, tipagem,
|
|
29
|
+
testes e empacotamento, sem instalar dependências no host. A matriz é CPython
|
|
30
|
+
3.11–3.15; o conjunto de frameworks respeita a compatibilidade de cada versão.
|
|
31
|
+
Consulte os scripts e relatórios locais para os comandos e as imagens do ensaio.
|
|
32
|
+
|
|
33
|
+
Testes que iniciam serviços devem usar rede Docker interna ou loopback do próprio
|
|
34
|
+
container, dados sintéticos exclusivos, nenhuma porta publicada e limpeza dos
|
|
35
|
+
recursos criados. Não use produção, tokens pessoais, SMTP ou contas reais nos
|
|
36
|
+
testes do SDK. Use CA de teste confiada explicitamente; não desative a verificação
|
|
37
|
+
TLS. Não publique pacotes ou aplicações durante a verificação local.
|
|
38
|
+
|
|
39
|
+
Inclua verificações pertinentes à mudança: contrato e tipos, HTTP real quando o
|
|
40
|
+
transporte mudar, fechamento de fluxos, cancelamento, erros sem repetição e
|
|
41
|
+
ausência de segredos nas respostas. Diferencie resultados de um transporte falso,
|
|
42
|
+
HTTPS sintético, API local e serviço de produção.
|
|
43
|
+
|
|
44
|
+
Descreva a mudança, sua motivação, as validações executadas e limites conhecidos.
|
|
45
|
+
Atualize `CHANGELOG.md` quando houver alteração pública. Relate problemas de
|
|
46
|
+
segurança conforme [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mailcore
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
include LICENSE README.md CHANGELOG.md SECURITY.md CONTRIBUTING.md pyproject.toml
|
|
2
|
+
recursive-include src/mailcore *.py py.typed
|
|
3
|
+
recursive-include docs *.md *.json
|
|
4
|
+
recursive-include exemplos *.py
|
|
5
|
+
prune testes
|
|
6
|
+
prune scripts
|
|
7
|
+
prune build
|
|
8
|
+
prune .git
|
|
9
|
+
global-exclude __pycache__ *.py[cod] .env .env.*
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mailcore-sdk
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Cliente Python da API Mailcore com recursos síncronos e assíncronos.
|
|
5
|
+
Author: Mailcore
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://mailcore.com.br
|
|
8
|
+
Project-URL: Repository, https://github.com/mailcore-hq/mailcore-python
|
|
9
|
+
Project-URL: Issues, https://github.com/mailcore-hq/mailcore-python/issues
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: httpx<0.29,>=0.28.1
|
|
22
|
+
Requires-Dist: anyio<5,>=4.8
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Mailcore para Python
|
|
26
|
+
|
|
27
|
+
[Código-fonte](https://github.com/mailcore-hq/mailcore-python) · [Problemas e sugestões](https://github.com/mailcore-hq/mailcore-python/issues)
|
|
28
|
+
|
|
29
|
+
Cliente Python da API Mailcore, em versão `0.1.0a1`. O pacote de distribuição é
|
|
30
|
+
`mailcore-sdk` e o módulo importado é `mailcore`. Esta versão ainda não foi
|
|
31
|
+
publicada no PyPI. Requer Python 3.11 ou superior.
|
|
32
|
+
|
|
33
|
+
## Instalação local e primeiro envio
|
|
34
|
+
|
|
35
|
+
Depois da verificação Docker, instale o arquivo local em sua aplicação Python:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
python -m pip install /caminho/mailcore_sdk-0.1.0a1-py3-none-any.whl
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
O pip pode buscar as dependências no PyPI; o arquivo do próprio SDK é local.
|
|
42
|
+
Também é possível instalar o `.tar.gz` de `dist/`, ou o checkout em modo editável
|
|
43
|
+
durante o desenvolvimento da sua aplicação.
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import os
|
|
47
|
+
from mailcore import Cliente, PedidoEmail
|
|
48
|
+
|
|
49
|
+
pedido: PedidoEmail = {
|
|
50
|
+
"remetente": "Equipe <equipe@example.com>",
|
|
51
|
+
"destinatarios": ["pessoa@example.com"],
|
|
52
|
+
"assunto": "Bem-vindo",
|
|
53
|
+
"html": "<p>Sua conta está pronta.</p>",
|
|
54
|
+
}
|
|
55
|
+
with Cliente(chave_api=os.environ["MAILCORE_API_KEY"]) as cliente:
|
|
56
|
+
resposta = cliente.emails.enviar(pedido, chave_idempotencia="pedido-123-confirmacao")
|
|
57
|
+
print(resposta["id"])
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use a chave somente no servidor, com remetente de domínio verificado. A aceitação
|
|
61
|
+
da intenção não comprova entrega SMTP. Preserve chave e conteúdo ao repetir uma
|
|
62
|
+
intenção; o SDK não faz tentativas automáticas após erro ou timeout.
|
|
63
|
+
|
|
64
|
+
## Cliente assíncrono
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from mailcore import ClienteAsync, PedidoEmail
|
|
68
|
+
|
|
69
|
+
async def enviar(pedido: PedidoEmail) -> str:
|
|
70
|
+
async with ClienteAsync() as cliente:
|
|
71
|
+
resposta = await cliente.emails.enviar(pedido, chave_idempotencia="pedido-123-confirmacao")
|
|
72
|
+
return resposta.dados["id"]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Os dois clientes oferecem os mesmos recursos. As chamadas async usam HTTPX
|
|
76
|
+
assíncrono nativo. Reutilize o cliente durante a vida da aplicação; `with`,
|
|
77
|
+
`async with` ou `fechar()` liberam os pools. Não compartilhe um cliente async
|
|
78
|
+
entre event loops. A chave pode ser uma função sem argumentos, resolvida por
|
|
79
|
+
operação, para permitir rotação sem alterar um estado global.
|
|
80
|
+
Um fornecedor que retorne uma chave inválida falha; não usa outra chave do ambiente.
|
|
81
|
+
O pool padrão permite até 100 conexões e 20 ociosas, configuráveis por
|
|
82
|
+
`maximo_conexoes` e `conexoes_ociosas`.
|
|
83
|
+
|
|
84
|
+
## Respostas e erros
|
|
85
|
+
|
|
86
|
+
`Resposta.dados` preserva os campos e envelopes JSON da API. `status` e
|
|
87
|
+
`cabecalhos` expõem metadados HTTP, e `resposta["id"]` abrevia o acesso ao JSON.
|
|
88
|
+
Bytes de downloads são `bytes`; prévias HTML são `str`. `ErroApi` preserva código
|
|
89
|
+
e status da rejeição; `ErroTransporte` trata rede/prazo; `ErroResposta` trata
|
|
90
|
+
conteúdo inválido ou excedido; `ErroConfiguracao` trata opções inválidas.
|
|
91
|
+
|
|
92
|
+
O cliente exige TLS verificado, não segue redirecionamentos, não armazena cookies
|
|
93
|
+
e não herda proxies do ambiente. Uma CA privada pode ser informada por
|
|
94
|
+
`certificado_ca`. Somente loopback pode usar HTTP com `permitir_http_local=True`.
|
|
95
|
+
`transporte_http` permite um adaptador HTTPX explicitamente fornecido pela aplicação;
|
|
96
|
+
esse adaptador e sua política de rede são responsabilidade de quem o configura.
|
|
97
|
+
|
|
98
|
+
`tempo_limite` (30 segundos por padrão) segue a semântica HTTPX: limite de
|
|
99
|
+
inatividade de cada etapa de conexão, pool, escrita ou leitura. **Não é um prazo
|
|
100
|
+
total de relógio**. A conexão tem limite adicional de 10 segundos. Uma aplicação
|
|
101
|
+
async que precise de prazo total pode envolver a operação em `asyncio.timeout()`;
|
|
102
|
+
o cancelamento é propagado e a resposta é fechada. Um prazo vencido não desfaz
|
|
103
|
+
uma intenção já aceita.
|
|
104
|
+
|
|
105
|
+
A resposta tem teto padrão de 16 MiB, inclusive em fluxo, ajustável por operação
|
|
106
|
+
com `limite_resposta_bytes`. O JSON de pedido admite até 50 MiB para o envelope de
|
|
107
|
+
importação CSV; os limites específicos de cada DTO pertencem à API. A comunicação
|
|
108
|
+
solicita `Accept-Encoding: identity` e recusa codificações não negociadas.
|
|
109
|
+
|
|
110
|
+
## Downloads e webhooks
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
with Cliente() as cliente:
|
|
114
|
+
with cliente.recebimento.baixar_original_fluxo("id-da-mensagem") as fluxo:
|
|
115
|
+
with open("mensagem.eml.parcial", "wb") as arquivo:
|
|
116
|
+
for parte in fluxo:
|
|
117
|
+
arquivo.write(parte)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
No cliente async, use `async with` e `async for`. Os fluxos preservam bytes MIME,
|
|
121
|
+
exigem consumo dentro do contexto e liberam a conexão ao terminar, interromper
|
|
122
|
+
ou cancelar. Só trate arquivos parciais como completos depois de sucesso.
|
|
123
|
+
Downloads usam rotas autenticadas; URLs temporárias de metadados não são acessadas
|
|
124
|
+
automaticamente.
|
|
125
|
+
|
|
126
|
+
`verificar_assinatura(corpo_bruto, cabecalhos, segredo)` verifica HMAC-SHA256
|
|
127
|
+
`svix-*`, com comparação em tempo constante e janela de cinco minutos. Passe o
|
|
128
|
+
corpo bruto antes de interpretar JSON. Deduplicação e confirmação durável dos
|
|
129
|
+
eventos pertencem ao consumidor.
|
|
130
|
+
|
|
131
|
+
## Documentação e desenvolvimento
|
|
132
|
+
|
|
133
|
+
Consulte [cobertura](docs/cobertura.md), [integrações Flask/FastAPI/Django](docs/integracoes.md)
|
|
134
|
+
e [verificação](docs/verificacao.md). Não há dependência de framework no runtime
|
|
135
|
+
do pacote. Instalação local usa os arquivos `.whl`/`.tar.gz` preparados em `dist/`.
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
sh scripts/verificar.sh
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
O desenvolvimento e os testes usam Docker, sem instalar Python, pip ou frameworks
|
|
142
|
+
no host. Nenhum comando publica no PyPI ou faz deploy.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Mailcore para Python
|
|
2
|
+
|
|
3
|
+
[Código-fonte](https://github.com/mailcore-hq/mailcore-python) · [Problemas e sugestões](https://github.com/mailcore-hq/mailcore-python/issues)
|
|
4
|
+
|
|
5
|
+
Cliente Python da API Mailcore, em versão `0.1.0a1`. O pacote de distribuição é
|
|
6
|
+
`mailcore-sdk` e o módulo importado é `mailcore`. Esta versão ainda não foi
|
|
7
|
+
publicada no PyPI. Requer Python 3.11 ou superior.
|
|
8
|
+
|
|
9
|
+
## Instalação local e primeiro envio
|
|
10
|
+
|
|
11
|
+
Depois da verificação Docker, instale o arquivo local em sua aplicação Python:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
python -m pip install /caminho/mailcore_sdk-0.1.0a1-py3-none-any.whl
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
O pip pode buscar as dependências no PyPI; o arquivo do próprio SDK é local.
|
|
18
|
+
Também é possível instalar o `.tar.gz` de `dist/`, ou o checkout em modo editável
|
|
19
|
+
durante o desenvolvimento da sua aplicação.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import os
|
|
23
|
+
from mailcore import Cliente, PedidoEmail
|
|
24
|
+
|
|
25
|
+
pedido: PedidoEmail = {
|
|
26
|
+
"remetente": "Equipe <equipe@example.com>",
|
|
27
|
+
"destinatarios": ["pessoa@example.com"],
|
|
28
|
+
"assunto": "Bem-vindo",
|
|
29
|
+
"html": "<p>Sua conta está pronta.</p>",
|
|
30
|
+
}
|
|
31
|
+
with Cliente(chave_api=os.environ["MAILCORE_API_KEY"]) as cliente:
|
|
32
|
+
resposta = cliente.emails.enviar(pedido, chave_idempotencia="pedido-123-confirmacao")
|
|
33
|
+
print(resposta["id"])
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Use a chave somente no servidor, com remetente de domínio verificado. A aceitação
|
|
37
|
+
da intenção não comprova entrega SMTP. Preserve chave e conteúdo ao repetir uma
|
|
38
|
+
intenção; o SDK não faz tentativas automáticas após erro ou timeout.
|
|
39
|
+
|
|
40
|
+
## Cliente assíncrono
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from mailcore import ClienteAsync, PedidoEmail
|
|
44
|
+
|
|
45
|
+
async def enviar(pedido: PedidoEmail) -> str:
|
|
46
|
+
async with ClienteAsync() as cliente:
|
|
47
|
+
resposta = await cliente.emails.enviar(pedido, chave_idempotencia="pedido-123-confirmacao")
|
|
48
|
+
return resposta.dados["id"]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Os dois clientes oferecem os mesmos recursos. As chamadas async usam HTTPX
|
|
52
|
+
assíncrono nativo. Reutilize o cliente durante a vida da aplicação; `with`,
|
|
53
|
+
`async with` ou `fechar()` liberam os pools. Não compartilhe um cliente async
|
|
54
|
+
entre event loops. A chave pode ser uma função sem argumentos, resolvida por
|
|
55
|
+
operação, para permitir rotação sem alterar um estado global.
|
|
56
|
+
Um fornecedor que retorne uma chave inválida falha; não usa outra chave do ambiente.
|
|
57
|
+
O pool padrão permite até 100 conexões e 20 ociosas, configuráveis por
|
|
58
|
+
`maximo_conexoes` e `conexoes_ociosas`.
|
|
59
|
+
|
|
60
|
+
## Respostas e erros
|
|
61
|
+
|
|
62
|
+
`Resposta.dados` preserva os campos e envelopes JSON da API. `status` e
|
|
63
|
+
`cabecalhos` expõem metadados HTTP, e `resposta["id"]` abrevia o acesso ao JSON.
|
|
64
|
+
Bytes de downloads são `bytes`; prévias HTML são `str`. `ErroApi` preserva código
|
|
65
|
+
e status da rejeição; `ErroTransporte` trata rede/prazo; `ErroResposta` trata
|
|
66
|
+
conteúdo inválido ou excedido; `ErroConfiguracao` trata opções inválidas.
|
|
67
|
+
|
|
68
|
+
O cliente exige TLS verificado, não segue redirecionamentos, não armazena cookies
|
|
69
|
+
e não herda proxies do ambiente. Uma CA privada pode ser informada por
|
|
70
|
+
`certificado_ca`. Somente loopback pode usar HTTP com `permitir_http_local=True`.
|
|
71
|
+
`transporte_http` permite um adaptador HTTPX explicitamente fornecido pela aplicação;
|
|
72
|
+
esse adaptador e sua política de rede são responsabilidade de quem o configura.
|
|
73
|
+
|
|
74
|
+
`tempo_limite` (30 segundos por padrão) segue a semântica HTTPX: limite de
|
|
75
|
+
inatividade de cada etapa de conexão, pool, escrita ou leitura. **Não é um prazo
|
|
76
|
+
total de relógio**. A conexão tem limite adicional de 10 segundos. Uma aplicação
|
|
77
|
+
async que precise de prazo total pode envolver a operação em `asyncio.timeout()`;
|
|
78
|
+
o cancelamento é propagado e a resposta é fechada. Um prazo vencido não desfaz
|
|
79
|
+
uma intenção já aceita.
|
|
80
|
+
|
|
81
|
+
A resposta tem teto padrão de 16 MiB, inclusive em fluxo, ajustável por operação
|
|
82
|
+
com `limite_resposta_bytes`. O JSON de pedido admite até 50 MiB para o envelope de
|
|
83
|
+
importação CSV; os limites específicos de cada DTO pertencem à API. A comunicação
|
|
84
|
+
solicita `Accept-Encoding: identity` e recusa codificações não negociadas.
|
|
85
|
+
|
|
86
|
+
## Downloads e webhooks
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
with Cliente() as cliente:
|
|
90
|
+
with cliente.recebimento.baixar_original_fluxo("id-da-mensagem") as fluxo:
|
|
91
|
+
with open("mensagem.eml.parcial", "wb") as arquivo:
|
|
92
|
+
for parte in fluxo:
|
|
93
|
+
arquivo.write(parte)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
No cliente async, use `async with` e `async for`. Os fluxos preservam bytes MIME,
|
|
97
|
+
exigem consumo dentro do contexto e liberam a conexão ao terminar, interromper
|
|
98
|
+
ou cancelar. Só trate arquivos parciais como completos depois de sucesso.
|
|
99
|
+
Downloads usam rotas autenticadas; URLs temporárias de metadados não são acessadas
|
|
100
|
+
automaticamente.
|
|
101
|
+
|
|
102
|
+
`verificar_assinatura(corpo_bruto, cabecalhos, segredo)` verifica HMAC-SHA256
|
|
103
|
+
`svix-*`, com comparação em tempo constante e janela de cinco minutos. Passe o
|
|
104
|
+
corpo bruto antes de interpretar JSON. Deduplicação e confirmação durável dos
|
|
105
|
+
eventos pertencem ao consumidor.
|
|
106
|
+
|
|
107
|
+
## Documentação e desenvolvimento
|
|
108
|
+
|
|
109
|
+
Consulte [cobertura](docs/cobertura.md), [integrações Flask/FastAPI/Django](docs/integracoes.md)
|
|
110
|
+
e [verificação](docs/verificacao.md). Não há dependência de framework no runtime
|
|
111
|
+
do pacote. Instalação local usa os arquivos `.whl`/`.tar.gz` preparados em `dist/`.
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
sh scripts/verificar.sh
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
O desenvolvimento e os testes usam Docker, sem instalar Python, pip ou frameworks
|
|
118
|
+
no host. Nenhum comando publica no PyPI ou faz deploy.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Segurança
|
|
2
|
+
|
|
3
|
+
Esta distribuição está em alpha (`0.1.0a1`) e ainda não foi publicada no PyPI.
|
|
4
|
+
O pacote de distribuição é `mailcore-sdk`; o módulo importado é `mailcore`.
|
|
5
|
+
As linhas CPython adotadas na matriz são 3.11–3.15, com versões corrigidas das
|
|
6
|
+
dependências do projeto.
|
|
7
|
+
|
|
8
|
+
## Relatar um problema
|
|
9
|
+
|
|
10
|
+
Antes da publicação, comunique vulnerabilidades por um canal privado acordado com
|
|
11
|
+
os mantenedores. Informe versão, comportamento observado, impacto e uma reprodução
|
|
12
|
+
mínima com dados sintéticos. Não inclua chaves, segredos de webhook, MIME de
|
|
13
|
+
clientes, destinatários reais ou URLs temporárias de download em relatos públicos.
|
|
14
|
+
Não há prazo de resposta ou correção garantido nesta etapa alpha.
|
|
15
|
+
|
|
16
|
+
## Proteções e responsabilidades
|
|
17
|
+
|
|
18
|
+
O transporte padrão verifica TLS, aceita CA privada, recusa redirecionamentos,
|
|
19
|
+
solicita `identity`, recusa outra codificação e não usa cookies ou proxies do
|
|
20
|
+
ambiente. A opção de HTTP é explícita e limitada a loopback. Transportes injetados
|
|
21
|
+
para testes ou integração têm sua política de rede sob responsabilidade de quem
|
|
22
|
+
os configura.
|
|
23
|
+
|
|
24
|
+
O limite padrão de resposta é 16 MiB, também durante downloads e erros. O teto de
|
|
25
|
+
JSON de pedido é 50 MiB; ele não substitui o limite de CSV de 8 MiB ou limites
|
|
26
|
+
menores dos endpoints. Os timeouts HTTPX são por inatividade de etapa, não um
|
|
27
|
+
prazo total. Nenhum timeout ou cancelamento comprova que um envio foi desfeito.
|
|
28
|
+
|
|
29
|
+
Use chaves somente no servidor, com o menor escopo necessário. Preserve uma chave
|
|
30
|
+
de idempotência estável para repetir explicitamente uma intenção. Separe clientes
|
|
31
|
+
e credenciais entre organizações. Feche pools e respostas em fluxo pelos gestores
|
|
32
|
+
de contexto; evite registrar corpos, dados pessoais ou cabeçalhos de autenticação.
|
|
33
|
+
|
|
34
|
+
Verifique webhooks antes de interpretar seus efeitos, usando o corpo bruto e o
|
|
35
|
+
segredo correto. A janela de timestamp não substitui a deduplicação do
|
|
36
|
+
identificador do evento na aplicação. Original e anexos recebidos devem ser
|
|
37
|
+
tratados como conteúdo externo; a disponibilidade obedece à retenção do servidor.
|
|
38
|
+
Os downloads do SDK usam rotas autenticadas e não navegam automaticamente nas
|
|
39
|
+
URLs temporárias contidas nos metadados.
|
|
40
|
+
|
|
41
|
+
Os exemplos HTTP exigem um token próprio e enviam uma mensagem fixa. A aplicação
|
|
42
|
+
que os hospedar continua responsável por entrada HTTPS, limites do servidor,
|
|
43
|
+
autorização de negócio, proteção de logs e gestão de segredos.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Cobertura do SDK Python
|
|
2
|
+
|
|
3
|
+
A versão `0.1.0a1`, distribuída como `mailcore-sdk` e importada como `mailcore`,
|
|
4
|
+
oferece **16 recursos principais, 30 classes e 151 operações por variante**.
|
|
5
|
+
`Cliente` e `ClienteAsync` totalizam 60 classes de recursos e 302 métodos. As duas
|
|
6
|
+
variantes acessam o mesmo contrato HTTP; esses números não representam 302 rotas
|
|
7
|
+
distintas. Esta versão alpha ainda não foi publicada no PyPI.
|
|
8
|
+
|
|
9
|
+
A superfície preserva o contrato dos SDKs Mailcore Ruby e Node. O
|
|
10
|
+
[ensaio de API local](integracao-api.json) identifica a revisão do backend e o
|
|
11
|
+
SHA256 das fontes usados na validação. Revisão Git e hash de conteúdo são
|
|
12
|
+
identificadores distintos; o relatório registra o estado do ensaio, não uma
|
|
13
|
+
afirmação sobre o HEAD atual do backend.
|
|
14
|
+
|
|
15
|
+
## Recursos
|
|
16
|
+
|
|
17
|
+
Os caminhos abaixo partem de uma instância de `Cliente` ou `ClienteAsync`.
|
|
18
|
+
|
|
19
|
+
| Recurso principal | Superfície incluída | Operações por variante |
|
|
20
|
+
| ----------------------- | -------------------------------------------------------------------------------------- | ---------------------: |
|
|
21
|
+
| `emails` | Enviar, listar, obter, reagendar, cancelar, eventos, consulta por idempotência e anexo | 8 |
|
|
22
|
+
| `lotes` | Enviar e consultar por idempotência | 2 |
|
|
23
|
+
| `dominios` | CRUD, capacidades, tracking, registros DNS e verificação | 7 |
|
|
24
|
+
| `chaves_api` | Criar, listar, renomear e revogar | 4 |
|
|
25
|
+
| `contatos` | CRUD, lote, segmentos, tópicos, importações e exportações | 20 |
|
|
26
|
+
| `segmentos` | Criar, listar, obter, atualizar e remover | 5 |
|
|
27
|
+
| `topicos` | Criar, listar, obter, atualizar e remover | 5 |
|
|
28
|
+
| `propriedades_contatos` | Criar, listar, obter, atualizar e remover | 5 |
|
|
29
|
+
| `modelos` | CRUD, publicação, duplicação, prévias, testes, versões e pastas | 18 |
|
|
30
|
+
| `webhooks` | CRUD, eventos, tentativas e reenvio | 9 |
|
|
31
|
+
| `campanhas` | CRUD, duplicação, revisão, envio/cancelamento, prévias, testes e métricas | 15 |
|
|
32
|
+
| `automacoes` | CRUD, duplicação, parada e consulta de execuções | 9 |
|
|
33
|
+
| `eventos` | Definição, consulta, edição, remoção, listagem e envio de ocorrência | 6 |
|
|
34
|
+
| `recebimento` | Consulta, anexos, original MIME e downloads comuns ou em fluxo | 8 |
|
|
35
|
+
| `caixas` | CRUD, etiquetas, conversas, mensagens, respostas, encaminhamento e rascunhos | 28 |
|
|
36
|
+
| `cli` | Listar e revogar concessões | 2 |
|
|
37
|
+
| **Total** | **151 operações com a mesma superfície nas duas variantes** | **151** |
|
|
38
|
+
|
|
39
|
+
Os recursos subordinados usam propriedades, como `contatos.exportacoes`,
|
|
40
|
+
`modelos.versoes`, `webhooks.eventos`, `caixas.conversas.emails` e `cli.concessoes`.
|
|
41
|
+
Os nomes dos métodos permanecem iguais no cliente assíncrono: use
|
|
42
|
+
`await cliente.emails.enviar(...)`, sem sufixo adicional no nome.
|
|
43
|
+
|
|
44
|
+
## Pedidos, respostas e tipagem
|
|
45
|
+
|
|
46
|
+
Pedidos e filtros aceitam `Mapping` com os campos em português do DTO HTTP, como
|
|
47
|
+
`remetente`, `destinatarios`, `agendada_em` e `revisao`. Opções de transporte são
|
|
48
|
+
argumentos nomeados, como `chave_idempotencia`, `tempo_limite` e
|
|
49
|
+
`limite_resposta_bytes`. O servidor continua responsável pelas regras de negócio,
|
|
50
|
+
permissões, revisões e limites específicos de cada endpoint.
|
|
51
|
+
|
|
52
|
+
O transporte aceita valores JSON: chaves String, texto UTF-8, números finitos,
|
|
53
|
+
booleanos, listas, tuplas convertidas em arrays, mapeamentos e `None`. Objetos
|
|
54
|
+
arbitrários, bytes em campos JSON e números não finitos são recusados. Um campo
|
|
55
|
+
omitido difere de um campo enviado com `None`; `None` e `False` permanecem no corpo.
|
|
56
|
+
Na query, `None` é omitido e `False` é enviado como `false`. Identificadores são
|
|
57
|
+
codificados como segmentos, preservando o prefixo da API.
|
|
58
|
+
|
|
59
|
+
As respostas usam `Resposta[T]`, com `dados`, `status` e `cabecalhos` separados.
|
|
60
|
+
JSON mantém chaves String, inclusive nos objetos internos; resposta sem conteúdo
|
|
61
|
+
pode produzir `dados=None`. Downloads comuns retornam `Resposta[bytes]` e prévias
|
|
62
|
+
textuais usam `str`. `resposta["id"]` consulta o campo em `dados`.
|
|
63
|
+
|
|
64
|
+
Há tipos públicos para envio direto/modelo, anexos, lote, respostas de aceitação,
|
|
65
|
+
configuração e opções, além do marcador PEP 561 `py.typed`. Entre eles estão
|
|
66
|
+
`PedidoEmail`, `PedidoEmailLote`, `RespostaEnvio` e `RespostaLote`. Essa tipagem não
|
|
67
|
+
é um schema completo de todas as entidades: recursos complexos ainda aceitam
|
|
68
|
+
`Mapping[str, Any]` e retornam `Resposta[Any]`, preservando o DTO do servidor.
|
|
69
|
+
TypedDict não substitui a validação de runtime nem a validação da API.
|
|
70
|
+
|
|
71
|
+
A paginação é explícita: uma chamada consulta uma página e conserva o envelope e
|
|
72
|
+
os cursores recebidos. O SDK não percorre páginas automaticamente nem uniformiza
|
|
73
|
+
envelopes distintos do backend.
|
|
74
|
+
|
|
75
|
+
## Contratos relevantes
|
|
76
|
+
|
|
77
|
+
- Envio direto permite composição Cc/Cco, cabeçalhos e anexos Base64/CID conforme
|
|
78
|
+
o DTO. Envio por modelo tem seu próprio formato, sem misturar campos exclusivos
|
|
79
|
+
da composição direta. O cliente não baixa anexos remotos por iniciativa própria.
|
|
80
|
+
- Lotes seguem o array e a aceitação atômica do backend, sem dividir pedidos nem
|
|
81
|
+
repetir automaticamente. Agendamento usa `agendada_em` ISO 8601 com fuso e as
|
|
82
|
+
regras de estado do servidor. Aceitação não comprova entrega SMTP.
|
|
83
|
+
- Importações recebem CSV UTF-8 no corpo JSON. O limite de CSV é 8 MiB no contrato
|
|
84
|
+
da API; o transporte admite JSON de até 50 MiB para acomodar escapes. Esse teto
|
|
85
|
+
geral não amplia limites menores dos demais endpoints.
|
|
86
|
+
- Modelos, campanhas, automações e caixas preservam revisões, estados e campos
|
|
87
|
+
anuláveis. Parar ou cancelar não desfaz efeitos já aceitos pelo servidor.
|
|
88
|
+
- A chave secreta de API só aparece na criação. Revogação pode retornar resposta
|
|
89
|
+
vazia. Concessões CLI incluem consulta/revogação, sem iniciar autenticação
|
|
90
|
+
interativa ou renovar tokens.
|
|
91
|
+
|
|
92
|
+
## Recebimento e fluxos
|
|
93
|
+
|
|
94
|
+
Original MIME, anexos recebidos e exportações usam rotas fixas autenticadas. URLs
|
|
95
|
+
temporárias presentes nos metadados são capacidades sensíveis; o SDK não as segue
|
|
96
|
+
automaticamente nem transfere a credencial para um destino informado pela API.
|
|
97
|
+
Retenção e disponibilidade do conteúdo são determinadas pelo servidor.
|
|
98
|
+
|
|
99
|
+
`baixar_original_fluxo`, `baixar_anexo_fluxo` e `baixar_fluxo` devolvem gestores de
|
|
100
|
+
contexto. Use `with` no cliente síncrono e `async with` no assíncrono; dentro do
|
|
101
|
+
contexto, consuma bytes por `for` ou `async for`. O leitor expõe `status`,
|
|
102
|
+
`cabecalhos` e `total_bytes`. O gestor assíncrono não recebe `await` antes de
|
|
103
|
+
`async with`. A saída do contexto fecha a resposta, inclusive no encerramento
|
|
104
|
+
antecipado do consumo.
|
|
105
|
+
|
|
106
|
+
O teto padrão de resposta é **16 MiB**, inclusive em fluxo e em respostas de erro;
|
|
107
|
+
`limite_resposta_bytes` permite ajustar a operação. O limite é aplicado durante a
|
|
108
|
+
leitura, não apenas depois de acumular o conteúdo.
|
|
109
|
+
|
|
110
|
+
## Transporte e limites
|
|
111
|
+
|
|
112
|
+
Cada cliente reutiliza seu pool HTTPX e deve ser fechado com contexto ou
|
|
113
|
+
`fechar()`; `ClienteAsync` usa fechamento aguardado e também oferece
|
|
114
|
+
`fechar_async()`. A comunicação padrão usa HTTPS verificado, recusa
|
|
115
|
+
redirecionamentos, não armazena cookies e não herda proxies do ambiente. Uma CA
|
|
116
|
+
privada pode ser configurada. HTTP é uma opção explícita restrita a loopback para
|
|
117
|
+
ensaios locais. Um transporte HTTP injetado tem sua política de rede sob controle
|
|
118
|
+
de quem o fornece.
|
|
119
|
+
|
|
120
|
+
O SDK solicita `Accept-Encoding: identity` e recusa codificações não negociadas.
|
|
121
|
+
Isso preserva os bytes de MIME, anexos e CSV e mantém o limite de leitura
|
|
122
|
+
previsível. Nenhuma falha produz repetição automática; preserve chave e conteúdo
|
|
123
|
+
ao decidir repetir uma intenção.
|
|
124
|
+
|
|
125
|
+
`tempo_limite`, por padrão **30 segundos**, limita a inatividade de cada etapa
|
|
126
|
+
HTTPX: pool, conexão, escrita ou leitura. A conexão usa no máximo o menor valor
|
|
127
|
+
entre esse limite e `tempo_conexao`, cujo padrão é **10 segundos**. **Não existe
|
|
128
|
+
um prazo total de relógio embutido**: um fluxo que continua avançando pode durar
|
|
129
|
+
mais. A aplicação assíncrona pode envolver a operação em `asyncio.timeout()` quando
|
|
130
|
+
precisar desse prazo total. Cancelar a espera não desfaz uma intenção aceita.
|
|
131
|
+
|
|
132
|
+
## Alcance da validação
|
|
133
|
+
|
|
134
|
+
A matriz do projeto é CPython **3.11–3.15**. Os exemplos opcionais exercitam Flask
|
|
135
|
+
e Django síncronos e FastAPI assíncrono; o exemplo Django é uma view direta, sem
|
|
136
|
+
implementar um backend de email. Veja [as integrações](integracoes.md) para as
|
|
137
|
+
versões e seus limites. SDK e frameworks têm contratos de compatibilidade distintos.
|
|
138
|
+
|
|
139
|
+
Os testes de contrato conferem as 151 operações de cada variante com um
|
|
140
|
+
transporte coletor. Ensaios HTTPS sintéticos verificam o transporte; o
|
|
141
|
+
[relatório de API local](integracao-api.json) registra a execução contra backend
|
|
142
|
+
isolado com dados sintéticos. Esses resultados não demonstram entrega SMTP,
|
|
143
|
+
produção, capacidade de escala ou deploy cloud.
|
|
144
|
+
|
|
145
|
+
Esta cobertura descreve a seleção implementada, não toda a API do produto.
|
|
146
|
+
Não inclui recursos globais de logs, uso ou supressões, autorização OAuth
|
|
147
|
+
interativa, helpers de sessão/dashboard nem renderização React. Campos adicionais
|
|
148
|
+
dos DTOs não implicam métodos ou fluxos novos no SDK.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"data_utc": "2026-11-14T14:29:54.661686+00:00",
|
|
3
|
+
"resultado": "falhou",
|
|
4
|
+
"ambiente": "api_postgres_tls_exclusivos_sem_worker_sem_portas",
|
|
5
|
+
"instalacao_host": false,
|
|
6
|
+
"rede_interna": true,
|
|
7
|
+
"portas_publicadas": false,
|
|
8
|
+
"worker_executado": false,
|
|
9
|
+
"smtp_executado": false,
|
|
10
|
+
"deploy_executado": false,
|
|
11
|
+
"tls_api_verificado": false,
|
|
12
|
+
"tls_postgres": "nao_verificado",
|
|
13
|
+
"cenarios": [],
|
|
14
|
+
"etapa": "preparar_identidades",
|
|
15
|
+
"imagens": {
|
|
16
|
+
"cliente": "sha256:41ff4552dda1fb72f2b97f34efd9a3742a0c31d9a8b19309846a29b0fd74cce4",
|
|
17
|
+
"api_runtime": "sha256:158e95e9b87f2a126c038e6931b2f956fe6120f3566fd047a29250bd7783ff33",
|
|
18
|
+
"compilador": "sha256:8fa55b2f3ddf97471ab6a767bfa3f37e6bad0986ba823e75fea57e2a2a5c3073",
|
|
19
|
+
"postgres": "sha256:f1ea2a1a4fb7b68d4836be1fdcb8a6466a89b072158bf9d97663600538c294c5"
|
|
20
|
+
},
|
|
21
|
+
"backend_revisao": "c00da750773435140fda072b88c7070fdfda22c7",
|
|
22
|
+
"backend_fontes_sha256": "d31c825268a64c858276827f47d27e506f543421327f487d7165e511359e248f",
|
|
23
|
+
"backend_fontes_alterados": false,
|
|
24
|
+
"api_compilada_neste_ensaio": true,
|
|
25
|
+
"falha": "Ensaio interrompido; recursos exclusivos serão removidos.",
|
|
26
|
+
"limpeza_concluida": true
|
|
27
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"data_utc": "2026-11-14T14:58:46.486693+00:00",
|
|
3
|
+
"resultado": "aprovado",
|
|
4
|
+
"ambiente": "api_postgres_tls_exclusivos_sem_worker_sem_portas",
|
|
5
|
+
"instalacao_host": false,
|
|
6
|
+
"rede_interna": true,
|
|
7
|
+
"portas_publicadas": false,
|
|
8
|
+
"worker_executado": false,
|
|
9
|
+
"smtp_executado": false,
|
|
10
|
+
"deploy_executado": false,
|
|
11
|
+
"tls_api_verificado": true,
|
|
12
|
+
"tls_postgres": "verify-full",
|
|
13
|
+
"cenarios": [
|
|
14
|
+
"chaves_full_sending_escopo_repr",
|
|
15
|
+
"envio_composto_idempotencia_409_download_cancelamento",
|
|
16
|
+
"envio_async_replay_mesma_intencao",
|
|
17
|
+
"lote_atomico_repeticao_conflito",
|
|
18
|
+
"dominios_capacidades_tracking_crud",
|
|
19
|
+
"contatos_nulos_catalogos_exportacao_csv_fluxo",
|
|
20
|
+
"modelos_pastas_versoes_previa_publicacao_cas",
|
|
21
|
+
"marketing_crud_sem_disparo",
|
|
22
|
+
"caixas_etiquetas_rascunhos_cas_sem_envio",
|
|
23
|
+
"recebimento_mime_real_pendente_bytes_fluxo",
|
|
24
|
+
"recebimento_async_bytes_contexto_fluxo",
|
|
25
|
+
"cli_revogacao_e_limpeza_crud"
|
|
26
|
+
],
|
|
27
|
+
"etapa": "concluido",
|
|
28
|
+
"imagens": {
|
|
29
|
+
"cliente": "sha256:a8a48dc98d737ee421afe7422e846c5bf17bdc14033170a4380eae2cd9c5f0d9",
|
|
30
|
+
"api_runtime": "sha256:158e95e9b87f2a126c038e6931b2f956fe6120f3566fd047a29250bd7783ff33",
|
|
31
|
+
"compilador": "sha256:8fa55b2f3ddf97471ab6a767bfa3f37e6bad0986ba823e75fea57e2a2a5c3073",
|
|
32
|
+
"postgres": "sha256:f1ea2a1a4fb7b68d4836be1fdcb8a6466a89b072158bf9d97663600538c294c5"
|
|
33
|
+
},
|
|
34
|
+
"backend_revisao": "27789fd7c7bfbeaaed4a4f517e417921ae8ca60b",
|
|
35
|
+
"backend_fontes_sha256": "d31c825268a64c858276827f47d27e506f543421327f487d7165e511359e248f",
|
|
36
|
+
"backend_fontes_alterados": false,
|
|
37
|
+
"api_compilada_neste_ensaio": true,
|
|
38
|
+
"api_binario_sha256": "3cd977ab90dbfcc0067b7d0b85d120ae9132f4e873cc223298f901fc1dbd35bf",
|
|
39
|
+
"migracoes_aplicadas": 23,
|
|
40
|
+
"python": "3.12.16",
|
|
41
|
+
"httpx": "0.28.1",
|
|
42
|
+
"recebimento_processado_por_worker": false,
|
|
43
|
+
"async_exercitado": true,
|
|
44
|
+
"async_envio_repetiu_intencao_existente": true,
|
|
45
|
+
"persistencia_sintetica": {
|
|
46
|
+
"mensagens": 3,
|
|
47
|
+
"tarefas_envio": 3,
|
|
48
|
+
"recebidos": 1,
|
|
49
|
+
"recebidos_pendentes": 1
|
|
50
|
+
},
|
|
51
|
+
"limpeza_concluida": true
|
|
52
|
+
}
|