Como enviar SMS no FastAPI com a Twilio
Tempo de leitura: 7 minutos
O propósito da Twilio é impulsionar a comunicação de forma conveniente e rápida em qualquer linguagem. No entanto, se você tiver um aplicativo Python escrito com o pacote asyncio, talvez não fique totalmente claro como traduzir os exemplos da documentação em um código sem bloqueio que funcione bem com um loop assíncrono.
Neste tutorial, você aprenderá como fornecer notificações via SMS corretamente por meio de um aplicativo FastAPI. As técnicas mostradas aqui também são aplicáveis a outras estruturas asyncio.
Requisitos do tutorial
- Python 3.6 ou mais recente. Se o seu sistema operacional não fornecer um interpretador Python, acesse python.org para fazer download de um instalador.
- Uma conta da Twilio. Se você é novo na Twilio, clique aqui para criar uma conta gratuita e receba 10 dólares de crédito ao atualizar para uma conta paga. Confira os recursos e as limitações de uma conta gratuita da Twilio.
- Um smartphone com sinal para testar o projeto.
Comprar um número de telefone Twilio
Caso ainda não tenha feito isto, sua primeira tarefa é comprar um número de telefone Twilio para poder enviar SMS.
Faça login no Console da Twilio, selecione Phone Numbers (Números de telefone) e clique no sinal de adição vermelho para comprar um número Twilio. Observe que, se você tiver uma conta gratuita, você usará seu crédito de avaliação para esta compra.
Na página "Buy a Number" (Comprar um número), selecione seu país e marque SMS no campo "Capabilities" (Recursos). Se você solicitar um número local da sua região, poderá introduzir o seu código de área no campo "Number" (Número).
Clique no botão "Search" (Pesquisar) para ver quais números estão disponíveis e, em seguida, clique em "Buy" (Comprar) para adquirir o número de sua preferência exibido nos resultados. Depois de confirmar a compra, clique no botão "Close" (Fechar).
Instalar e configurar o projeto
Nesta seção, você fará configuração de um novo projeto FastAPI. Para manter a organização, abra um terminal ou prompt de comando, encontre um local adequado e crie um novo diretório onde o projeto que você está prestes a criar será armazenado:
Como criar um ambiente virtual
Com base nas práticas recomendadas do Python, você criará um ambiente virtual, no qual instalará as dependências do Python necessárias para esse projeto.
Se você estiver usando um sistema Unix ou MacOS, abra um terminal e digite os seguintes comandos:
Se você estiver seguindo o tutorial no Windows, digite os seguintes comandos em uma janela de prompt de comando:
Com o ambiente virtual ativado, você está pronto para instalar as dependências do Python necessárias para esse projeto:
Os seis pacotes Python que esse projeto usa são:
- A estrutura FastAPI, para criar o aplicativo Web.
- python-dotenv, para importar a configuração do aplicativo de um arquivo .env.
- aiofiles, para possibilitar que o FastAPI forneça arquivos estáticos.
- python-multipart, para possibilitar que o FastAPI processe dados de formulários.
- uvicorn, para fornecer o aplicativo FastAPI.
- E o Biblioteca auxiliar Twilio para Python, para trabalhar com as APIs do Twilio.
Configurar as credenciais e o número de telefone Twilio
Para poder enviar um SMS com o Twilio, o aplicativo FastAPI precisará ter acesso às credenciais da conta Twilio para autenticação. Além disso, para enviar um SMS, você precisará fornecer um número de remetente, o número Twilio adquirido anteriormente.
A maneira mais segura de estabelecer esses valores de configuração é definindo variáveis de ambiente para eles. E a maneira mais conveniente de gerenciar suas variáveis de ambiente em um aplicativo FastAPI é usando um arquivo .env.
Abra um novo arquivo chamado .env (veja que há um ponto à esquerda) no editor de texto e digite o seguinte conteúdo:
Será necessário substituir todos os xxxxxxxxx
pelos valores corretos que se aplicam a você. As duas primeiras variáveis são seu SID de conta e seu token de autenticação Twilio. Você pode encontrá-los no dashboard do Console da Twilio:
A variável TWILIO_NUMBER
é o número de telefone que você comprou na etapa acima. Quando você digitar esse número de telefone no arquivo .env, use o formato E.164, que inclui um sinal de adição e o código do país. Por exemplo, um número dos Estados Unidos seria fornecido como +1aaabbbcccc
, em que aaa
é o código de área e bbb-cccc
é o número local.
Para incorporar essas três variáveis ao aplicativo FastAPI, crie um arquivo chamado config.py com o seguinte conteúdo:
O FastAPI depende da classe BaseSettingsdo pydantic
para gerenciar sua configuração. As subclasses de BaseSettings
importam automaticamente variáveis definidas como atributos das variáveis de ambiente ou diretamente do arquivo .env com sua integração com o dotenv.
Você aprenderá a trabalhar com a classe Settings
na próxima seção.
Enviar um SMS com o FastAPI
Agora, estamos prontos para iniciar a codificação do aplicativo FastAPI. Faremos isso em algumas etapas.
Aplicativo FastAPI básico
Abaixo, você pode ver a primeira iteração do nosso aplicativo FastAPI. Esta versão apenas retorna a página principal, que apresenta um formulário da Web no qual o usuário pode digitar o número de telefone em que receberá o SMS.
Abra um novo arquivo chamado app.py no seu editor de texto ou IDE e digite este código:
O decorador @app.get(‘/’)
define um endpoint que é mapeado para o URL raiz do aplicativo. A implementação desse endpoint retorna uma resposta que é carregada com base em um arquivo estático denominado index.html.
Para que esse endpoint funcione, agora precisamos criar o arquivo HTML. Abra um novo arquivo chamado index.html no seu editor ou IDE e digite o seguinte código HTML:
Executar o servidor
O aplicativo está incompleto, mas funcional o suficiente para ser iniciado. Certifique-se de que os arquivos app.py, index.html e .env tenham sido criados anteriormente no diretório do projeto e inicie o aplicativo usando o seguinte comando:
Uvicorn é o servidor recomendado para executar aplicativos FastAPI. Estamos iniciando o servidor com a opção --reload
, que fará com que o uvicorn veja nossos arquivos de origem e reinicie automaticamente o servidor quando as alterações forem feitas. Você pode deixar o servidor em execução durante todo o restante do tutorial.
Para verificar se o aplicativo está correto, abra um navegador da Web e digite http://localhost:8000 na barra de endereços. O navegador deve carregar a página principal do aplicativo, que se parece com esta:
Gerenciar dados de formulário
Se você tentar enviar o formulário, o FastAPI retornará a mensagem de erro "Method not allowed" (Método não permitido). Isso ocorre porque ainda não implementamos o endpoint de envio de formulário.
Se você observar o elemento <form>
no index.html, definimos o formulário com o atributo method
definido como post
e nenhum atributo action
. Isso significa que o formulário será enviado com uma solicitação POST para o URL de origem, que, neste caso, é o URL raiz do aplicativo.
O endpoint terá a seguinte estrutura. Você pode adicioná-lo na parte inferior do app.py, mas observe as linhas que começam com # TODO
, que indicam partes da função que ainda não foram criadas.
Neste segundo endpoint, estamos usando o decorador @app.post(‘/’)
para definir um manipulador para as solicitações POST
. O formulário da Web que estamos usando tem um único campo chamado phone
, então esse será um argumento na função. O FastAPI analisará os dados do formulário e extrairá o valor desse campo passado pelo cliente, e o enviará para a função nesse argumento.
Embora a estrutura da função já esteja bem compreendida, temos trabalho a fazer para enviar o SMS e retornar uma resposta. Por esse motivo, continuaremos trabalhando nesse endpoint nas seções a seguir.
Enviar o SMS
Quando a função handle_form()
for chamada, teremos um número de telefone para o qual enviar um SMS. Podemos acessar as credenciais do Twilio e o número de telefone do remetente na classe Settings
que escrevemos anteriormente. Portanto, agora temos tudo o que precisamos para enviar um SMS com o Twilio.
O problema é que a biblioteca auxiliar do Twilio para Python não oferece suporte a aplicativos assíncronos. Como essa biblioteca fará solicitações de rede para servidores Twilio, ela bloqueará o loop se ele for usado diretamente na função assíncrona. Para evitar esse problema, encapsularemos todo o trabalho relacionado ao Twilio em uma função que chamaremos de send_sms()
e a executaremos dentro de um executor para manter o aplicativo assíncrono rodando sem problemas.
Abaixo, você pode ver uma versão atualizada da função handle_form()
de app.py com a lógica para executar a função send_sms()
em um executor.
Com o método run_in_executor()
do loop asyncio, é possível executar uma função de bloqueio em um thread ou processo separado para que o loop não seja bloqueado. O primeiro argumento é o executor de sua preferência, ou None
, se você não se importar de usar um executor de thread padrão. Os argumentos restantes são a função a ser executada e seus argumentos.
Agora, veremos a implementação da função send_sms()
. Observe que esse é um código síncrono padrão, portanto, essa função não é definida com a palavra-chave async
. Adicionar esta função a app.py:
A função cria uma instância do objeto Twilio Client e a inicializa com os valores de SID da conta e token de autenticação provenientes do objeto settings
.
Em seguida, o client.messages.create()
é usado para criar e entregar o SMS. Essa função usa os argumentos from_
, to
e body
para definir o remetente, destinatário e corpo do SMS, respectivamente. Observe que from_
é usado porque from
é uma palavra-chave reservada no Python.
Como enviar uma resposta
Na seção anterior, deixamos a função handle_form()
incompleta. Depois que o SMS é enviado pelo executor, o servidor precisa retornar uma resposta. A prática mais aceita ao lidar com um envio de formulário é responder com um redirecionamento, o que evita uma série de possíveis problemas, incluindo envios duplicados de formulário e avisos confusos exibidos no navegador para o usuário. Essa prática é conhecida como Post/Redirect/Get pattern ou PRG.
Neste aplicativo, podemos redirecionar para uma página que indica que o SMS foi enviado com êxito e dar a opção ao usuário de enviar outro SMS. Aqui está a implementação completa da função handle_form()
. Atualize sua versão no app.py.
A resposta instruirá o navegador a redirecionar imediatamente para o URL /success. Agora podemos criar um manipulador para esse URL. Esse manipulador é aplicado no final de app.py:
Esse é outro manipulador curto que renderiza uma página HTML, assim como o principal. Crie um arquivo success.html e copie o seguinte conteúdo nele:
Essa página solicita que o usuário verifique a mensagem em seu telefone e inclui um link para a página principal, caso o usuário queira enviar outro SMS.
Testar o aplicativo
Chegamos ao momento que você estava esperando. O aplicativo está concluído e estamos prontos para testá-lo. Verifique se o app.py está atualizado com todas as funções mostradas acima e se os arquivos config.py, .env, index.html e success.html também estão no diretório do projeto.
Se você deixou o uvicorn
em execução desde o início do tutorial, sempre que fizer uma atualização nos arquivos de origem, o servidor deverá reiniciar sozinho e, então, você estará pronto para começar. Se você não estiver executando o servidor, poderá iniciá-lo agora com o comando:
Abra o navegador da Web e navegue até http://localhost:8000. No formulário, digite seu número de celular pessoal usando o formato E.164. Clique no botão enviar e, logo em seguida, você receberá o SMS em seu telefone.
Se você estiver usando uma conta gratuita do Twilio, lembre-se de que o número que você usar como destinatário deverá ser verificado para poder receber um SMS. Esse requisito não se aplicará se você estiver usando uma conta paga.
Conclusão
Parabéns! Agora você sabe como enviar SMS com o FastAPI. Como mencionado na introdução, as técnicas que você aprendeu neste artigo podem ser aplicadas a outras estruturas baseadas em asyncio, como Quart, Sanic e Tornado. Para uma discussão aprofundada sobre como trabalhar com o Twilio em seus aplicativos assíncronos, verifique o artigo Using the Twilio Python Helper Library in your Async Applications (Usar a Biblioteca auxiliar do Twilio para Python em seus aplicativos assíncronos).
Adoraria ver suas criações com o Twilio e o asyncio!
Publicações relacionadas
Recursos relacionados
Twilio Docs
De APIs a SDKs e aplicativos de amostra
Documentação de referência de API, SDKs, bibliotecas auxiliares, guias de início rápido e tutoriais para sua linguagem e plataforma.
Centro de Recursos
Os mais recentes e-books, relatórios do setor e webinars
Aprenda com especialistas em engajamento do cliente para melhorar sua própria comunicação.
Ahoy
Centro da comunidade de desenvolvedores da Twilio
Melhores práticas, exemplos de código e inspiração para criar comunicações e experiências de engajamento digital.