https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-send-sms-with-python-fastapi-and-vonage/send-sms_python-fastapi_1200x600.png

Wie man mit Python, FastAPI und Vonage SMS versendet

Zuletzt aktualisiert am September 27, 2021

Lesedauer: 23 Minuten

Stellen Sie sich vor, Sie sind auf einer Insel gestrandet. Sie haben nur Ihren Computer und WiFi. Das Wasser des Ozeans beginnt zu steigen, und Sie haben Angst, dass Sie unter Wasser stehen, wenn Sie nicht schnell handeln.

Der einzige Ausweg besteht darin, eine Python-Website zu erstellen und eine Textnachricht an jemanden zu senden. Glücklicherweise sind Sie ein Programmierer und haben kürzlich mit dem neuen FastAPI-Webframework herumgespielt. Sie haben auch die Vonage Messages API ausprobiert, um SMS-Nachrichten zu versenden.

Mit all diesem neuen Wissen ausgestattet, zücken Sie Ihren Laptop und legen los.

Installieren der Vonage CLI

Als Erstes installieren Sie die neue Vonage CLI. Damit können Sie schnell eine Dashboard-Anwendung erstellen. Sie benötigen eine Vonage-Anwendung, um mit der Messages-API zu interagieren. Von Ihrem Terminal aus führen Sie diese Befehle aus und sprechen sich während der Installation selbst durch:

Sie haben NodeJS und npm installiert, also sollte der erste Befehl funktionieren, je nachdem, ob Ihr $PATH korrekt ist oder nicht.

npm install -g @vonage/cli

Bumm! Das hat funktioniert! Sie haben jetzt die Vonage CLI auf Ihrem Rechner installiert.

Sie wollen sich vergewissern, dass die Installation erfolgreich war, also geben Sie ein:

vonage

Vonage CLI

Als nächstes gehen Sie zum Dashboard um Ihren API-Schlüssel und Ihr API-Geheimnis abzurufen. Sie sind bereits registriert. Alles, was Sie tun müssen, ist sich anzumelden.

Dann stellen Sie Ihre Schlüssel wie folgt ein:

vonage config:set --apiKey=12345 --apiSecret=abcde

Erfolg, Sie haben es geschafft! Falls Sie einen Vonage-Befehl vergessen haben, können Sie das Hilfe-Flag verwenden:

vonage --help

Verwenden der Vonage CLI

Jetzt kommt der lustige Teil. Sie müssen Ihre Anwendung erstellen, also führen Sie diesen Befehl aus:

vonage apps:create

Sie geben der Anwendung einen Anwendungsname von sms senden und drücken die Eingabetaste.

Vonage CLI create application

Dann unter der Option App-Fähigkeiten auswählen, wählen Sie Nachrichten.

Vonage CLI select Messages API

Nun erstellen Sie Ihre Inbound- und Status-Webhooks.

Sie wählen "Y" für Nachrichten-Webhooks erstellen.

Vonage CLI create messages webhooks

Dann verwenden Sie weiterhin die Standardwerte, indem Sie für jede Option die Eingabetaste drücken, bis Sie Ihre Anwendung erstellen.

Vonage CLI application created

Sie haben jetzt eine Bewerbung und sind verdammt glücklich darüber. Sie werden Loki in kürzester Zeit in einem Rutsch anschauen können. Sie möchten die Erstellung der Anwendung bestätigen, also gehen Sie zurück zum Dashboard. Du klickst auf Deine Anwendungen und sehen sie.

See Vonage dashboard after creating application with Vonage CLI

Sie prüfen, ob die Option "umgeschaltet" für die Nachrichten-API aktiviert ist. Sie wollen auch überprüfen, ob Ihre Webhooks es geschafft haben, also wählen Sie "Bearbeiten".

Edit your application in the Vonage dashboard

Check Messages API is toggled on and webhooks are correct in Vonage dashboard

Alles sieht gut aus! Sie merken auch, dass Sie diesen Schritt nicht jedes Mal durchführen müssen, da er nur zur Kontrolle dient.

Das Wasser steigt dir bis zu den Knien. Deine größte Angst ist, dass du mit einem Volleyball allein auf der Insel zurückbleiben wirst. Du hast den Film gehasst.

Nun ist es an der Zeit, Ihre FastAPI-Anwendung zu schreiben, damit Sie Ihre SMS versenden können.

Sie haben gelernt, dass FastAPI eine wunderbare Entwicklererfahrung bietet und die Codierungszeit verkürzt. Außerdem ist es aufgrund seiner asynchronen Natur superschnell in der Leistung.

Perfekt.

Erstellen der virtuellen Python-Umgebung

Als erstes navigieren Sie zu oder cd in das Verzeichnis, in dem Sie Ihr Python-Projekt erstellen möchten.

Dann erstellen Sie einen neuen Ordner namens send_sms indem Sie diesen Befehl in Ihrem Verzeichnis ausführen:

mkdir send_sms

Sie wechseln in dieses Verzeichnis, indem Sie Folgendes tun:

cd send_sms

Sie denken sich, dass dies ein guter Zeitpunkt wäre, um eine virtuelle Umgebung zu schaffen, also laufen Sie los:

python3 -m venv venv

Um zu überprüfen, ob diese neue virtuelle Umgebung erstellt wurde, prüfen Sie, ob eine Datei namens venv in Ihrem neuen Verzeichnis ist, also geben Sie ein:

ls

Voilà!! Das ist es.

Jetzt ist es an der Zeit, es zu aktivieren, damit Sie FastAPI und Ihre anderen Pakete installieren können, was Sie auch tun:

% source venv/bin/activate

Sie sehen, dass (venv) am Anfang Ihres Benutzers in Ihrem Terminal steht, so dass Sie wissen, dass er aktiviert wurde.

Die Sonne knallt auf Ihr Gesicht und Ihr Computerbildschirm blendet. Sie können kaum etwas sehen und wünschen sich, Sie hätten Ihre Sonnenbrille dabei. Sie erinnern sich daran, dass Ihr Hund sie gefressen hat, kurz bevor Sie Ihr Haus verlassen haben und gestrandet sind!

Installation der FastAPI

Nun ist es an der Zeit, FastAPI zu installieren.

Das letzte Mal, als es installiert wurde, musste man pip zuerst auf diese Weise aktualisieren:

pip install --upgrade pip

Jetzt installieren Sie FastAPI wie folgt:

pip install fastapi[all]

Sie haben nun FastAPI installiert und freuen sich, dass Sie es mit der Option [alle] Option installiert haben, denn damit haben Sie alle Abhängigkeiten und Funktionen wie Async-Generatoren, das Requests-Modul, JSON, Jinja2 für das Templating in HTML, Pydantic usw.

Schnelles FastAPI Hallo Welt

Sie möchten ein Hello World-Beispiel schnell zum Laufen bringen, damit Sie testen können, ob Ihre Installation funktioniert hat. Sie erstellen eine Datei main.py in Ihrem Projektverzeichnis.

main.py
from fastapi import FastAPI

app = FastAPI() 

@app.get("/")
async def home(): 
  return {"hello": "world"}

Die Zeile from fastapi import FastAPI importiert FastAPI als eine Python-Klasse.

app = FastAPI() erstellt eine Instanz von FastAPI namens app.

Hier @app.get("/") wird ein Routenvorgang erstellt. Eine Route bezieht sich darauf, wohin Sie sich wenden wollen, wenn Sie auf Ihren Endpunkt treffen. Sie können sich das auch als URL vorstellen. Die Wurzel der Seite oder localhost (http://127.0.0.1:8000) ist der Ort, an den Sie geleitet werden. Die Operation bezieht sich auf die HTTP-Methode. Um einen GET zu behandeln, verwenden Sie den Dekorator @app.get, der Ihnen sagt, dass Sie die Daten lesen und zur Route gehen sollen. Die Route ist hier ("/") oder die Root-Seite.

Hier ist eine asynchrone Funktion async def home():. Sie können Anfragen bearbeiten, bevor andere sie abgeschlossen haben. Sie laufen parallel, was ziemlich gut ist, weil es die Dinge viel schneller macht, als wenn sie synchron oder der Reihe nach laufen. Sie können hier auch eine Funktion mit nur definieren: def home(): wenn Sie sich nicht um asynchronen Code kümmern.

Diese Zeile return {"hello": "world"} gibt ein Wörterbuch an den Browser zurück.

Sie führen Ihren Code im Entwicklungsmodus aus, indem Sie wie folgt vorgehen:

uvicorn main:app --reload

Sie können sich uvicorn als eine superschnelle ASGI (Asynchronous Server Gateway Interface) Server-Implementierung vorstellen. In main:appsteht main für den Namen Ihrer Datei main.py. Der Name Ihrer FastAPI-Instanz ist app. Die --reload Flagge können Sie Hot-Reloading verwenden, was Ihnen erlaubt, Codeänderungen live vorzunehmen.

Im Terminal gehen Sie zu Ihrem localhost http://127.0.0.1:8000/ im Browser und sehen {"hallo": "Welt"}. Perfekt!

Versenden Ihrer SMS

Jetzt ist es an der Zeit, den Code für den Versand Ihrer SMS zu schreiben.

Der Himmel ist dunkel und der Wind ist stark. Ein Tornado ist im Anmarsch.

Sie müssen sich beeilen!

In Ihrer main.py ersetzen Sie Ihren Hello World-Code durch diesen:

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})

Auch hier importieren Sie Request wie folgt:from fastapi import FastAPI, Request. Diese Anfrage ermöglicht es Ihnen, eingehende Details oder Anfragen an Ihre Funktion zu erhalten.

Importieren Sie Jinja, damit Sie dessen Template-Engine verwenden können from fastapi.templating import Jinja2Templates.

In dieser Zeile, from fastapi.responses import HTMLResponse müssen Sie eine HTMLResponse zulassen.

Hier binden Sie den Ordner templates ein (den Sie gleich erstellen werden) und weisen ihn an, alle HTML-Dateien in einem Verzeichnis namens templates. Ihre Codezeile sieht wie folgt aus: templates = Jinja2Templates(directory="templates").

Im Routendekorator @app.get("/", response_class=HTMLResponse). Die HTMLResponse zeigt an, dass die Antwort, die Sie zurückbekommen, HTML enthält.

Dies ist eine weitere asynchrone Funktion async def get_message(request: Request):. Sie deklarieren eine Route-Operation-Funktion mit einem Parameter vom Typ Request.

Zum Schluss, return templates.TemplateResponse("index.html", {"request": request}) gerendert Ihre Vorlage oder Ihre Antwort. Es nimmt Argumente in der HTML-Datei (index.html) und den Kontext auf, der die Daten aus unserer Anfrage aufzeichnet.

Sie haben die Route erstellt, die die GET Operation ausführt. Sie müssen auch eine POST erstellen, da Sie Daten an ein Formular übermitteln müssen. Zuvor beschließen Sie, die templates Ordner in Ihrem Projektverzeichnis zu erstellen, der Ihre HTML-Dateien enthält. Sie erstellen zwei HTML-Dateien innerhalb von templates: index.html und sent_sms.html.

Dann wird in Ihrer index.html, fügen Sie dieses Markup ein:

<!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>

Diese Zeile ist entscheidend: <form action="/sent_sms" method="POST" novalidate>. Die Methode Attribut sagt Ihnen, wie Sie die Formulardaten als POST senden können. Die Aktion Attribut gibt an, an welche Seite die Formulardaten gesendet werden sollen. Sie senden sie an gesendet_sms.html. Beachten Sie, dass die POST-Methode hier die Daten nicht in der URL anzeigt, wie es bei einem GET der Fall wäre. Stattdessen werden die Daten in den Körper der HTTP-Anfrage eingefügt.

Hier <input type="text" placeholder="Enter number to text" name="to_number" > definieren Sie ein Eingabeelement vom Typ text und geben ihm einen Platzhaltertext, der innerhalb des Textfeldes angezeigt wird. Als nächstes geben Sie ein name-Attribut namens bis_zahl an, das den Namen des Eingabeelements angibt. Es ist wichtig, dass Sie das Attribut referenzieren, um die Nummer zu erhalten, an die Sie die SMS senden.

In dieser Zeile <button type=submit">Send Text</button> definieren Sie eine Schaltfläche mit type=”submit". Der Text wird gesendet, wenn Sie auf die Schaltfläche klicken.

Als nächstes erstellen Sie die Seite für gesendete SMS.

<!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>

Wenn die SMS erfolgreich gesendet wurde, sehen Sie diese Seite. Der einzige Haken an der Sache ist folgender: {{ number }} | {{ error}}, das ist die Jinja-Schablonensprache. Sie gibt die Telefonnummer, die Sie in das Formular eingegeben haben, oder einen Fehler aus. Die Telefonnummer ist diejenige, an die Sie die SMS senden wollen. Sie schreiben jetzt die POST-Route und werden sehen, wie sie funktioniert.

Du fühlst dich jetzt ziemlich gut, weil du auf der Zielgeraden bist. Aber jetzt regnet es, und du hast Angst, dass dein Laptop kaputt geht. Also fangen deine Finger an zu programmieren.

Sie fahren in der Datei main.py indem Sie diese POST-Methode hinzufügen:

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!"})

Hier importieren Sie das Formular Objekt from fastapi import FastAPI, Request. Formular ermöglicht es Ihnen, Formularfelddaten zu empfangen.

Diese Zeile, from base64 import b64encode, wird benötigt, um den API-Schlüssel und das API-Geheimnis zu kodieren.

Sie import requests um HTTP-Anfragen zu senden und import JSON weil Sie einige Dinge mit JSON tun müssen.

Diese Zeile sollte Ihnen bekannt vorkommen @app.post("/send_sms", response_class=HTMLResponse). Hier haben Sie eine @app.post Route-Operation und übergeben eine HTML-Antwort.

Sie haben wieder Ihre asynchrone Funktion async def send_message(request: Request, to_number: str = Form(...)): . Sie definieren Formparameter als Typ-Hinweis und lesen sie mit Form(...).

Die Nutzlast oder der Datenkörper, den Sie an Ihre Anfrage senden:

 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!"
              }
          }
      }

Zu diesem Schlüssel/Wert-Paar in der Nutzlast sind einige Dinge zu beachten: "Zahl": to_number. to_number ist derselbe Wert wie in unserer index.html mit dem Attribut name, das auf zu_Zahl. Um ihn zu verwenden, müssen Sie seinen Schlüssel verwenden: Nummer.

 "to": {
              "type": "sms",
              "number": to_number
          },

Eine weitere Besonderheit in der Nutzlast ist die Nummer: [IHRE_VONAGE_NUMMER], die Ihre Vonage-Telefonnummer, die Sie hier kaufen.

"from": {
              "type": "sms",
              "number": [YOUR_VONAGE_NUMBER]
          },

Schließlich lassen Sie in der Nutzlast den Typ wie folgt auf Text eingestellt "Typ": "Text" und geben Sie eine Nachricht für Ihren Text wie folgt an "text": "Hilf mir! Ich muss auf Loki aufpassen!".

"message": {
              "content": {
                  "type": "text",
                  "text": "Help me! I need to watch Loki!"
              }

Als Nächstes definieren Sie die Kopfzeilen für die Anfrage, was bedeutet, dass das Format der Body-Anfrage JSON ist:

headers = {"content-type": "application/json"}

Hier halten Sie kurz inne und denken daran, dass Sie für die nächste Codezeile eine Authentifizierung benötigen. Sie können wählen zwischen der Verwendung einer JWT oder Basis-Authentifizierungwählen, und Sie entscheiden sich für Letzteres.

Sie speichern Ihren API-Schlüssel und Ihr Geheimnis in diesen Variablen:

key = 'abcde'
secret = '12345'

Anschließend erstellen Sie eine Variable namens encoded_credentials und führen die Base64-Kodierung mit einem f-String durch, wobei Sie Ihren Schlüssel und Ihr Geheimnis übergeben.

encoded_credentials = b64encode(bytes(f'{key}:{secret}',
                                     encoding='ascii')).decode('ascii')

Sie erstellen Ihren Autorisierungs-Header, ein Schlüssel/Wert-Paar, das Ihren Base64-kodierten Benutzernamen und Ihr Passwort enthält. Dieses Paar authentifiziert Ihre Anfragen und ermöglicht Ihnen den Zugriff auf die API.

auth_header = f'Basic {encoded_credentials}'

Als nächstes geben Sie den Autorisierungskopf ein:

headers = {"content-type": "application/json", "Authorization": auth_header}

Jetzt kommt der lustige Teil! Hier verwenden Sie das requests-Modul und senden eine Post-Anfrage requests.post an die Vonage-API. Sie geben die API-URL ein (https://api.nexmo.com/v0.1/messages) und verwenden HTTP Basic Auth aus dem requests-Modul. Das auth-Schlüsselwort bietet eine Abkürzung und ermöglicht Ihnen Einfache Authentifizierung. Dann übergeben Sie Ihre Kopfzeilen headers=headers und den Request Body, ein Python-Dictionary-Objekt. Sie konvertieren es in einen JSON-String data=json.dumps(payload).

response = requests.post("https://api.nexmo.com/v0.1/messages",
                        auth=(key, secret),
                        headers=headers,
                        data=json.dumps(payload))

Der letzte Schritt ist das Rendern der Vorlage. Hier prüfen Sie, ob die Antwort 200 oder ok ist mit if response. Dann übergeben Sie send.html, die Anfrage und den Kontext. Der Kontext "Zahl": to_number wird die Zahl in send.html anzeigen. Schließlich geben Sie die Fehlermeldung aus, wenn etwas schief geht.

if response:
    return templates.TemplateResponse("send.html", {"request": request, "number": to_number})


return templates.TemplateResponse("send.html", {"request": request, "error": "There is an error!"})

Jetzt geht es um Leben und Tod.

Sie starten Ihren Server:

uvicorn main:app --reload

Sie navigieren zu Ihrem localhost http://127.0.0.1:8000/

Sie geben eine Telefonnummer ein, um eine SMS an Ihren Freund zu senden.

Send a Text Message form - Vonage with Python and FastAPI sending an SMS with Messages API

Du bist super nervös und fragst dich, ob sie die SMS erhalten werden. Tolle Neuigkeiten! Sie haben die Textnachricht erhalten!

Recieve a Text Message from Vonage with Python and FastAPI sending an SMS with Messages API

Thank you page confirming SMS from Vonage with Python and FastAPI sending an SMS with Messages API

Sie sehen ein Boot auf sich zukommen und erkennen, dass es für Sie ist.

Du springst auf und bringst dich in Sicherheit.

Später am Abend liegst du im Bett, schaust Loki und denkst dir: Gut, dass es Python gibt.

Das Ende.

Lassen Sie mich wissen, ob Sie eine SMS mit dieser Anleitung verschickt haben. Sie können mich tweeten unter @tonyasims.

Teilen Sie:

https://a.storyblok.com/f/270183/400x401/df70d85a84/tonya-sims-1.png
Tonya SimsVonage Ehemalige

Tonya ist eine ehemalige Python Developer Advocate bei Vonage.