
Compartilhar:
Tonya é ex-promotora de desenvolvedores Python na Vonage.
Como enviar SMS com Python, FastAPI e Vonage
Tempo de leitura: 24 minutos
Imagine que você está em uma ilha, abandonado. Você só tem seu computador e o Wi-Fi. As águas do oceano estão começando a subir, e você teme ficar submerso se não agir rapidamente.
A única saída é criar um site em Python e enviar uma mensagem de texto para alguém. Felizmente, você é programador e recentemente experimentou a nova estrutura web FastAPI. Você também já testou a Messages API do Vonage para enviar mensagens SMS.
Com todo esse novo conhecimento na bagagem, você pega seu laptop para começar.
Instalando a CLI da Vonage
A primeira coisa a fazer é instalar o novo CLI da Vonage. Ela permite que você crie rapidamente um aplicativo de painel de controle. Você precisa de um aplicativo Vonage para interagir com a Messages API. No seu terminal, execute estes comandos e siga as instruções passo a passo durante a instalação:
Você tem o NodeJS e o npm instalados, então o primeiro comando deve funcionar, dependendo se o seu $PATH está correto ou não.
Puf! Deu certo! Agora você tem o Vonage CLI instalado no seu computador.
Você quer ter certeza de que a instalação foi bem-sucedida, então digita:

Em seguida, você acessa o painel de controle para obter sua chave de API e seu segredo de API. Você já está cadastrado. Basta fazer login.
Em seguida, configure suas chaves da seguinte maneira:
É isso aí, você consegue! Caso tenha esquecido algum comando do Vonage, pode usar o sinalizador de ajuda:
Como usar a CLI da Vonage
Agora vem a parte divertida. Você precisa criar seu aplicativo, então execute este comando:
Você dá a ele um Nome do aplicativo de enviar SMS e pressione Return.

Em seguida, na opção “Selecionar recursos do aplicativo”, escolha Mensagens.

Agora, crie seus webhooks de entrada e de status.
Você escolhe “Y” para Criar webhooks de mensagem.

Em seguida, continue usando os valores padrão pressionando a tecla Return para cada opção até criar seu aplicativo.

Agora você tem um aplicativo e está super feliz com isso. Em pouco tempo, você poderá assistir à temporada inteira de “Loki” de uma vez só. Você quer confirmar se ele foi criado, então volta ao painel de controle. Você clica em Seus Applications e lá está ela.

Você verifica se a opção da Messages API está ativada. Você também quer verificar se seus webhooks foram criados corretamente, então seleciona a opção de editar.


Está tudo ótimo! Você também sabe que não precisa repetir essa etapa todas as vezes, já que ela serve apenas para conferir novamente.
A água está subindo até além dos joelhos. Seu maior medo é ficar sozinho nessa ilha com uma bola de vôlei. Você odiou aquele filme.
Agora é hora de você criar seu aplicativo FastAPI para poder enviar suas mensagens SMS.
Você já sabe que o FastAPI oferece uma experiência maravilhosa para o desenvolvedor e agiliza o tempo de programação. Além disso, seu desempenho é extremamente rápido devido à sua natureza assíncrona.
Perfeito.
Criação do ambiente virtual do Python
A primeira coisa a fazer é acessar ou cd para o diretório onde deseja criar seu projeto em Python.
Em seguida, crie uma nova pasta chamada send_sms executando este comando a partir do seu diretório:
Para acessar esse diretório, faça o seguinte:
Você pensa que esse seria um bom momento para criar um ambiente virtual, então executa:
Para verificar se esse novo ambiente virtual foi criado, verifique se existe um chamado venv está no seu novo diretório; para isso, digite:
Pronto!! Aí está.
Agora é hora de ativá-lo para que você possa instalar o FastAPI e seus outros pacotes. Para isso, faça o seguinte:
Você vê que (venv) aparece no início do nome de usuário no seu terminal, então você sabe que ele foi ativado.
Nossa, o sol está batendo forte no seu rosto e há um reflexo na tela do computador. Você mal consegue enxergar nada e gostaria de estar com seus óculos escuros. Você se lembra que, logo antes de sair de casa e ficar na mão, seu cachorro os comeu!
Instalando o FastAPI
Agora é hora de você instalar o FastAPI.
Da última vez que foi instalado, foi preciso atualizar o pip primeiro, desta forma:
Agora, instale o FastAPI da seguinte maneira:
Agora você já tem o FastAPI instalado e está muito feliz por tê-lo instalado com o [all] , pois ela fornece todas as dependências e recursos, como async-generators, o módulo requests, JSON, Jinja2 para modelagem em HTML, Pydantic etc.
"Hello World" rápido com FastAPI
Você quer colocar um exemplo “Hello World” em funcionamento rapidamente, para poder testar se a instalação deu certo. Você cria um arquivo main.py no diretório do seu projeto.
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def home():
return {"hello": "world"}A linha from fastapi import FastAPI importa o FastAPI como uma classe do Python.
app = FastAPI() cria uma instância do FastAPI chamada app.
Aqui @app.get("/") cria uma operação de rota. Uma rota se refere ao destino para o qual você deseja ser direcionado ao acessar seu endpoint. Você também pode pensar nela como uma URL. A raiz da página ou localhost (http://127.0.0.1:8000) é para onde você é direcionado. A operação se refere ao método HTTP. Para lidar com um GET, use o decorador @app.get, que indica para você ler os dados e seguir para a rota. A rota aqui é (“/”) ou a página raiz.
Aqui está uma função assíncrona async def home():. Elas podem processar solicitações antes que outras tenham sido concluídas. Elas são executadas em paralelo, o que é ótimo, pois torna tudo muito mais rápido do que a execução síncrona, ou seja, em ordem. Você também pode definir uma função aqui simplesmente com: def home(): se você não se importar com código assíncrono.
Esta linha return {"hello": "world"} retorna um dicionário ao navegador.
Para executar seu código no modo de desenvolvimento, faça o seguinte:
Você pode pensar no uvicorn como uma implementação super-rápida do servidor ASGI (Asynchronous Server Gateway Interface). No main:app, main é o nome do seu arquivo main.py. O nome da sua instância do FastAPI é app. O --reload permite que você use o recarregamento dinâmico, o que possibilita fazer alterações no código em tempo real.
No terminal, acesse o localhost http://127.0.0.1:8000/ no navegador e verá {"hello": "world"}. Perfeito!
Envio de sua mensagem SMS
Agora é hora de escrever o código para enviar seu SMS.
O céu está escuro e o vento está forte. Um tornado está se formando.
Você precisa se apressar!
No seu arquivo main.py, substitua o código “Hello World” por este:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def get_message(request: Request):
return templates.TemplateResponse("index.html", {"request": request})Aqui você também está importando o `Request` desta forma:from fastapi import FastAPI, Request. Isso Request permite que você obtenha detalhes ou solicitações recebidas pela sua função.
Importe o Jinja para poder usar seu mecanismo de modelos from fastapi.templating import Jinja2Templates.
Nesta linha, from fastapi.responses import HTMLResponse você precisa permitir um HTMLResponse.
Aqui você monta a pasta “templates” (você vai criar uma daqui a pouco) e define que ela deve conter todos os seus arquivos HTML em um diretório chamado templates. Sua linha de código fica assim: templates = Jinja2Templates(directory="templates").
No decorador de rota @app.get("/", response_class=HTMLResponse). O HTMLResponse indica que a resposta recebida contém HTML.
Esta é outra função assíncrona async def get_message(request: Request):. Você declara uma função de operação de rota com um parâmetro do tipo Request.
Por fim, return templates.TemplateResponse("index.html", {"request": request}) renderiza seu modelo ou sua resposta. Ele recebe como argumentos o arquivo HTML (index.html) e o contexto, que mantém o controle dos dados que recebemos da nossa solicitação.
Você criou a rota que realiza o GET ) anteriormente. Você também precisa criar um POST , pois precisa enviar dados para um formulário. Antes disso, você decide criar os pasta “templates” no diretório do seu projeto para armazenar seus arquivos HTML. Você cria dois arquivos HTML dentro da pasta “templates”: index.html e sent_sms.html.
Em seguida, no seu index.html, você inclui esta marcação:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Send a Text Message</h1>
<form action="/sent_sms" method="POST" novalidate>
<input type="text" placeholder="Enter number to text" name="to_number">
<button type=submit">Send Text</button>
</form>
</body>
</html>
Esta linha é fundamental: <form action="/sent_sms" method="POST" novalidate>. O atributo indica como enviar os dados do formulário por meio de uma solicitação POST. O atributo especifica para qual página os dados do formulário devem ser enviados. Você os envia para sent_sms.html. Observe que o método POST, neste caso, não exibe os dados na URL como faria o método GET. Em vez disso, ele anexa os dados ao corpo da solicitação HTTP.
Aqui <input type="text" placeholder="Enter number to text" name="to_number" > você define um elemento de entrada do tipo texto e atribui a ele um texto provisório que será exibido dentro da caixa de texto. Em seguida, você define um atributo de nome chamado to_number , que especifica o nome do elemento de entrada. Isso é importante quando você consultar o atributo para obter o número para o qual está enviando o SMS.
Nesta linha <button type=submit">Send Text</button> você define um botão com type=”submit". O texto será enviado quando você clicar no botão.
Em seguida, você cria a página de SMS enviados.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Send a Text Message</h1>
<h3>Thank you {{ number }} | {{ error}}!</h3>
</body>
</html>
Se o SMS for enviado com sucesso, você verá esta página. A única coisa que pode dar um pouco de trabalho é o seguinte: {{ number }} | {{ error}}, que é a linguagem de modelagem Jinja. Ela exibirá o número de telefone que você inseriu no formulário ou uma mensagem de erro. O número de telefone é aquele para o qual você deseja enviar o SMS. Você está prestes a escrever a rota POST e verá como ela funciona.
Você está se sentindo muito bem agora, porque já está na reta final. Mas está chovendo, e você está preocupado que seu laptop possa se danificar. Então, seus dedos começam a digitar o código.
Você continua no arquivo arquivo main.py adicionando este método POST:
from fastapi import FastAPI, Request, Form
from base64 import b64encode
import requests
import json
@app.post("/send_sms", response_class=HTMLResponse)
async def send_message(request: Request, to_number: str = Form(...)):
payload = {
"to": {
"type": "sms",
"number": to_number
},
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}
}
}
key = 'abcde'
secret = '12345'
encoded_credentials = b64encode(bytes(f'{key}:{secret}',
encoding='ascii')).decode('ascii')
auth_header = f'Basic {encoded_credentials}'
headers = {"content-type": "application/json", "Authorization": auth_header}
response = requests.post("https://api.nexmo.com/v0.1/messages",
auth=(key, secret),
headers=headers,
data=json.dumps(payload))
if response:
return templates.TemplateResponse("send.html", {"request": request, "number": to_number})
return templates.TemplateResponse("send.html", {"request": request, "error": "There is an error!"})Aqui você importa o Formulário Form from fastapi import FastAPI, Request. O Form permite que você receba dados dos campos do formulário.
Esta linha, from base64 import b64encode, é necessária para codificar a chave da API e o segredo da API.
Você import requests enviar solicitações HTTP e import JSON porque você precisa fazer algumas coisas com JSON.
Essa linha deve parecer um pouco familiar @app.post("/send_sms", response_class=HTMLResponse). Aqui você tem uma @app.post operação de rota e passa uma resposta HTML.
Você tem sua função assíncrona novamente async def send_message(request: Request, to_number: str = Form(...)): . Você define os parâmetros do formulário como uma sugestão de tipo e os lê usando Form(...).
A carga útil ou o corpo de dados que você enviará na sua solicitação:
payload = {
"to": {
"type": "sms",
"number": to_number
},
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}
}
}Algumas observações sobre este par chave/valor na carga útil: "number": to_number. to_number é o mesmo valor que aparece em nosso index.html, com o atributo name definido como to_number. Para usá-lo, você precisará utilizar sua chave: number.
"to": {
"type": "sms",
"number": to_number
},Outro detalhe a ser observado na carga útil é o número: [SEU_NÚMERO_VONAGE], que será o seu número de telefone da Vonage que você adquirir aqui.
"from": {
"type": "sms",
"number": [YOUR_VONAGE_NUMBER]
},Por fim, na carga útil, deixe o tipo definido como “text”, desta forma "type": "text" e insira uma mensagem para o seu texto assim "text": "Me ajude! Preciso assistir Loki!".
"message": {
"content": {
"type": "text",
"text": "Help me! I need to watch Loki!"
}Em seguida, você define os cabeçalhos da solicitação, indicando que o formato do corpo da solicitação é JSON:
headers = {"content-type": "application/json"}Faça uma pausa aqui por um segundo e lembre-se de que precisará usar a autenticação na próxima linha de código. Você pode escolher entre usar uma autenticação JWT ou básica, e você opta pela última.
Você armazena sua chave e seu segredo da API nessas variáveis:
key = 'abcde'
secret = '12345'Em seguida, você cria uma variável chamada `encoded_credentials` e realiza a codificação Base64 usando uma f-string e passando sua chave e seu segredo.
encoded_credentials = b64encode(bytes(f'{key}:{secret}',
encoding='ascii')).decode('ascii')Você cria seu cabeçalho de autorização, um par chave/valor que inclui seu nome de usuário e sua senha codificados em Base64. Esse par autentica suas solicitações e permite que você acesse a API.
auth_header = f'Basic {encoded_credentials}'Em seguida, você passa o cabeçalho de autorização:
headers = {"content-type": "application/json", "Authorization": auth_header}Agora vem a parte divertida! Aqui você usa o módulo `requests` e envia uma solicitação POST requests.post para a API da Vonage. Você passa a URL da API (https://api.nexmo.com/v0.1/messages) e usa a autenticação HTTP Basic do módulo `requests`. A palavra-chave `auth` oferece um atalho e permite que você faça autenticação básica. Em seguida, você passa seus cabeçalhos headers=headers e o corpo da solicitação, um objeto de dicionário em Python. Você o converte em uma string JSON data=json.dumps(payload).
response = requests.post("https://api.nexmo.com/v0.1/messages",
auth=(key, secret),
headers=headers,
data=json.dumps(payload))A última etapa é renderizar o modelo. Aqui, você verifica se a resposta é 200 ou “ok” com if response. Em seguida, você passa o arquivo send.html, a solicitação e o contexto. O contexto "number": to_number exibirá o número em send.html. Por fim, você renderiza a mensagem de erro caso algo dê errado.
if response:
return templates.TemplateResponse("send.html", {"request": request, "number": to_number})
return templates.TemplateResponse("send.html", {"request": request, "error": "There is an error!"})Chegou a hora da verdade.
Inicie o servidor:
Você acessa o seu localhost http://127.0.0.1:8000/
Você digita um número de telefone para enviar um SMS para seu amigo.

Você está super nervoso e se pergunta se a pessoa vai receber o SMS. Ótima notícia! A pessoa recebeu a mensagem!


Você vê um barco se aproximando e percebe que é para você.
Você entra nele, pois ele o leva para um lugar seguro.
Mais tarde naquela noite, você estava deitado na cama assistindo a Loki, pensando consigo mesmo: “Ainda bem que existe o Python”.
Fim.
Me avise se você enviou um SMS seguindo este tutorial. Você pode me enviar um tweet em @tonyasims.