SDK Python
Este guia mostra como instalar e usar o SDK Python. O pacote no PyPI se chama usesend — é o SDK do projeto open-source que dá origem ao Madmail, e é esse nome que você instala e importa.
Instalação
Instale pelo PyPI:
pip install usesend
Inicialização
from usesend import UseSend, types
# Opção A: passar os valores direto (prático em scripts e testes)
client = UseSend("us_xxx")
# Opção B: URL base própria (instância self-hosted)
client = UseSend("us_xxx", url="https://app.madmail.com.br")
Enviar um email
EmailCreate é um TypedDict, serve só para o editor te ajudar; em tempo de execução você passa um dict comum. O cliente aceita from ou from_ (ele normaliza from_ para from).
from usesend import UseSend, types
client = UseSend("us_xxx")
payload: types.EmailCreate = {
"to": "cliente@exemplo.com.br",
"from": "nao-responda@suaempresa.com.br",
"subject": "Boas-vindas",
"html": "<strong>Olá!</strong>",
"headers": {"X-Campaign": "boas-vindas"},
}
data, err = client.emails.send(payload)
print(data or err)
O Madmail repassa os seus cabeçalhos personalizados para o SES. Só os cabeçalhos X-Usesend-Email-ID e References são controlados automaticamente.
Anexos e agendamento:
from datetime import datetime, timedelta
payload: types.EmailCreate = {
"to": ["cliente1@exemplo.com.br", "cliente2@exemplo.com.br"],
"from": "nao-responda@suaempresa.com.br",
"subject": "Relatório",
"text": "Segue em anexo.",
"attachments": [
{"filename": "relatorio.txt", "content": "SGVsbG8gd29ybGQ="}, # base64
],
"scheduledAt": datetime.utcnow() + timedelta(minutes=10),
}
data, err = client.emails.create(payload)
Envio em lote
items: list[types.EmailBatchItem] = [
{"to": "a@exemplo.com.br", "from": "nao-responda@suaempresa.com.br", "subject": "A", "html": "<p>A</p>"},
{"to": "b@exemplo.com.br", "from": "nao-responda@suaempresa.com.br", "subject": "B", "html": "<p>B</p>"},
]
data, err = client.emails.batch(items)
Consultar e gerenciar emails
Buscar um email:
email, err = client.emails.get("email_123")
Mudar o horário do agendamento:
from datetime import datetime, timedelta
update: types.EmailUpdate = {"scheduledAt": datetime.utcnow() + timedelta(hours=1)}
data, err = client.emails.update("email_123", update)
Cancelar um email agendado:
data, err = client.emails.cancel("email_123")
Contatos
Toda operação com contatos precisa do id da lista de contatos (book_id).
Criar um contato:
create: types.ContactCreate = {
"email": "cliente@exemplo.com.br",
"firstName": "Ana",
"properties": {"plan": "pro"},
}
data, err = client.contacts.create("book_123", create)
Buscar um contato:
contact, err = client.contacts.get("book_123", "contact_456")
Atualizar um contato:
update: types.ContactUpdate = {"subscribed": False}
data, err = client.contacts.update("book_123", "contact_456", update)
Criar ou atualizar (upsert) um contato:
upsert: types.ContactUpsert = {
"email": "cliente@exemplo.com.br",
"firstName": "Ana",
}
data, err = client.contacts.upsert("book_123", "contact_456", upsert)
Excluir um contato:
data, err = client.contacts.delete(book_id="book_123", contact_id="contact_456")
Tratamento de erros
Por padrão o cliente levanta UseSendHTTPError em respostas que não sejam 2xx. Para receber o erro como valor de retorno, passe raise_on_error=False.
from usesend import UseSend, UseSendHTTPError
# Levanta exceção em caso de erro (padrão)
client = UseSend("us_xxx")
try:
data, _ = client.emails.get("email_123")
except UseSendHTTPError as e:
print("a requisição falhou:", e)
# Retorna (None, erro) em vez de levantar
client = UseSend("us_xxx", raise_on_error=False)
data, err = client.emails.get("email_123")
if err:
print("erro:", err)