django-anysms
Envio de SMS e WhatsApp com uma API Django consistente e provedores intercambiáveis. A versão 0.1 inclui Twilio, mensagens síncronas e parsing validado de callbacks de entrega.
Instalação
python -m pip install django-anysms
python -m pip install 'django-anysms[twilio]'
A v0.1 suporta Python 3.10–3.13, Django 5.2 LTS e Django 6.0. O SDK da Twilio é opcional e não é importado pelo core.
Configuração
Configure aliases em suas settings Django:
import os
ANYSMS = {
"DEFAULT": "twilio",
"PROVIDERS": {
"twilio": {
"CLASS": "django_anysms.providers.twilio.TwilioProvider",
"OPTIONS": {
"account_sid": os.environ["TWILIO_ACCOUNT_SID"],
"auth_token": os.environ["TWILIO_AUTH_TOKEN"],
"from_": "+5511999999999",
},
},
},
}
O pacote não precisa ser adicionado a INSTALLED_APPS.
SMS
from django_anysms import SMSMessage
result = SMSMessage(
to="+5511888888888",
body="Seu código é 123456",
status_callback="https://example.com/webhooks/twilio/status/",
).send()
print(result.message_id, result.status)
Cada mensagem possui exatamente um destinatário em formato E.164. Números nacionais não são corrigidos ou completados automaticamente.
Um recurso específico pode ser informado sem contaminar a API comum:
message = SMSMessage(
to="+5511888888888",
body="Olá",
provider_options={
"twilio": {"messaging_service_sid": "MG..."},
},
)
message.send(using="twilio")
Texto livre dentro de uma conversa permitida pelo WhatsApp:
from django_anysms import WhatsAppMessage
WhatsAppMessage(
to="+5511888888888",
body="Seu pedido saiu para entrega.",
).send()
Mensagem proativa com um Content Template aprovado:
WhatsAppMessage(
to="+5511888888888",
content_sid="HX0123456789abcdef0123456789abcdef",
variables={"1": "Rafael", "2": "15/08/2026"},
).send()
body e content_sid são mutuamente exclusivos. O provider adiciona o
prefixo whatsapp:; a API pública recebe somente E.164.
Provider explícito
Settings são opcionais quando a aplicação precisa de credenciais dinâmicas:
from django_anysms import SMSMessage
from django_anysms.providers.twilio import TwilioProvider
provider = TwilioProvider(
account_sid="AC...",
auth_token="...",
from_="+5511999999999",
)
result = SMSMessage(to="+5511888888888", body="Olá").send(provider=provider)
A prioridade é: instância em provider=, alias em using= e, por último,
ANYSMS["DEFAULT"]. provider e using não podem ser usados juntos.
Erros
Falhas esperadas herdam de AnySMSError. Por padrão elas são lançadas. Para
um fluxo compatível com fail_silently, use:
result = message.send(fail_silently=True)
if not result.accepted:
report(result.error)
accepted=True significa que o provedor aceitou a chamada, não que a
mensagem chegou ao aparelho. Não há retry automático para evitar duplicatas
após falhas ambíguas.
A hierarquia pública inclui ConfigurationError, MessageValidationError,
ProviderNotInstalledError, ProviderError, InvalidWebhookSignature e
InvalidWebhookPayload, todos em django_anysms.exceptions.
Callback de entrega
A aplicação controla sua própria URL e persistência. Exemplo de view:
from django.http import HttpRequest, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django_anysms.exceptions import InvalidWebhookPayload, InvalidWebhookSignature
from django_anysms.registry import get_provider
@csrf_exempt
def twilio_status(request: HttpRequest) -> HttpResponse:
provider = get_provider("twilio")
try:
event = provider.parse_webhook(
public_url=request.build_absolute_uri(),
form=request.POST,
signature=request.headers.get("X-Twilio-Signature"),
)
except InvalidWebhookSignature:
return HttpResponse(status=403)
except InvalidWebhookPayload:
return HttpResponse(status=400)
consume_delivery_event(event)
return HttpResponse(status=204)
Em ambientes com proxy, public_url precisa ser exatamente a URL pública
assinada pela Twilio. A biblioteca valida a assinatura antes de projetar o
payload.
DeliveryEvent.raw preserva o formulário decodificado completo, inclusive
campos desconhecidos e valores repetidos. Tanto ele quanto SendResult.raw
podem conter telefones e outros dados pessoais; não registre ou persista esses
mappings sem uma política adequada.
Callbacks podem chegar fora de ordem. A v0.1 não persiste, deduplica ou ordena
eventos, e o status inicial existe apenas em SendResult.
Brasil
Regras de sender, horário, operadora e delivery report mudam fora do ciclo de release da biblioteca. Consulte regularmente as diretrizes oficiais da Twilio para SMS no Brasil.
Fora da v0.1
Mensagens recebidas, MMS/mídia, lotes, agendamento, models, views prontas, signals, async/Celery, retries, fallback entre provedores, normalização de números e gerenciamento de templates não fazem parte desta versão.
O design completo está em
docs/superpowers/specs/2026-08-15-django-anysms-v01-design.md.
Releases
O projeto usa Release Please
com Conventional Commits. Pushes em main atualizam uma Release PR; ao
mesclá-la, o mesmo workflow cria a tag e a GitHub Release, constrói sdist e
wheel com Hatchling e publica no PyPI via Trusted Publisher (OIDC). Releases
criadas manualmente no GitHub não são publicadas.
Antes do primeiro release:
-
Em Settings > Actions > General > Workflow permissions, habilite Allow GitHub Actions to create and approve pull requests.
-
Crie o environment
pypiem Settings > Environments. Proteções e aprovação manual são opcionais. -
No PyPI, configure um Trusted Publisher — ou um pending publisher para o primeiro upload — com estes valores:
- Owner:
davisilvarafacho - Repository:
django-anysms - Workflow:
release.yml - Environment:
pypi
- Owner:
O workflow não usa PYPI_API_TOKEN. A primeira Release PR publica v0.1.0;
as próximas versões são calculadas a partir dos commits feat, fix e
mudanças incompatíveis.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_anysms-0.1.0.tar.gz.
File metadata
- Download URL: django_anysms-0.1.0.tar.gz
- Upload date:
- Size: 51.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc1efebcdbe4dc23e89359bbe78e20fafd7fc85dbe575cd7633245355cded774
|
|
| MD5 |
f5d629df86c7e4f878b0889403f9e189
|
|
| BLAKE2b-256 |
23f8fd8930e6c8dd84ee9fe570a5758c146944610d3977cf79e7cff13000b8e4
|
Provenance
The following attestation bundles were made for django_anysms-0.1.0.tar.gz:
Publisher:
release.yml on davisilvarafacho/django-anysms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_anysms-0.1.0.tar.gz -
Subject digest:
cc1efebcdbe4dc23e89359bbe78e20fafd7fc85dbe575cd7633245355cded774 - Sigstore transparency entry: 2731629158
- Sigstore integration time:
-
Permalink:
davisilvarafacho/django-anysms@b710deb051624da8a01f8439b1791cebcef6fc73 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/davisilvarafacho
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b710deb051624da8a01f8439b1791cebcef6fc73 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_anysms-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_anysms-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7b63ffe760fca86f68dd504c7a34352206e358773683813d0b8d895784f4973
|
|
| MD5 |
94049d16673f277dda4df9e7319b1017
|
|
| BLAKE2b-256 |
efd31c2480fbc5cca94ea42e916782819f1f7fc0a54af023f0023775f1420cb9
|
Provenance
The following attestation bundles were made for django_anysms-0.1.0-py3-none-any.whl:
Publisher:
release.yml on davisilvarafacho/django-anysms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_anysms-0.1.0-py3-none-any.whl -
Subject digest:
b7b63ffe760fca86f68dd504c7a34352206e358773683813d0b8d895784f4973 - Sigstore transparency entry: 2731629957
- Sigstore integration time:
-
Permalink:
davisilvarafacho/django-anysms@b710deb051624da8a01f8439b1791cebcef6fc73 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/davisilvarafacho
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b710deb051624da8a01f8439b1791cebcef6fc73 -
Trigger Event:
push
-
Statement type: