https://d226lax1qjow5r.cloudfront.net/blog/blogposts/throttling-bulk-sms-campaigns-with-python-and-vonage-sms-api/python_sms-throttling_1200x600.png

Restriction des campagnes de SMS en masse avec Python et l'API SMS de Vonage

Publié le August 18, 2021

Temps de lecture : 7 minutes

Introduction

Les SMS en nombre sont très utiles lorsque les équipes de marketing doivent mener des campagnes de promotion. Les organisations peuvent également les déployer pour transmettre des informations à un grand groupe de personnes.

Des problèmes peuvent survenir lorsque vous envoyez une campagne de SMS en masse destinée à générer des réponses à un large public. Par exemple, la réception de milliers de réponses en une seule fois pourrait submerger votre équipe. L'une des solutions à ce problème consiste à utiliser la limitation. Par exemple, vous pouvez concevoir une campagne pour envoyer les messages par lots, à des périodes spécifiques, ou les deux.

Cet article vous apprendra à mettre en œuvre la limitation des SMS en masse en Python en utilisant le cadre REST de Django et l'API Messages de Vonage. L'application web que nous construirons dans ce tutoriel vous permettra d'envoyer des messages à plusieurs utilisateurs par lots à des intervalles de temps spécifiés.

L'API Vonage Messages API permet aux développeurs de développer des applications basées sur les SMS et de mettre en œuvre des fonctionnalités de messagerie dans leurs apps pour SMS, WhatsApp, Messenger, etc. Django est un framework Python utilisé pour la création d'applications web. Le cadre REST de Django permet aux développeurs de créer des API RESTful avec Django.

Conditions préalables

  1. Un compte API Vonage gratuit

  2. Une application Vonage. Vous pouvez suivre ce guide pour créer une application sur votre tableau de bord Vonage.

  3. Python (version 3.6 ou ultérieure). Vous pouvez télécharger Python sur le site officiel.

  4. Le gestionnaire de paquets Python pip. Vous trouverez les instructions d'installation de pip ici.

  5. L'outil Python virtualenv pour créer des environnements virtuels virtuels isolés pour les projets Python.

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Configuration et installation

Vous commencerez par configurer les dépendances du projet et installer les modules dont vous avez besoin avec pip. Ensuite, vous créerez le projet Django pour le tutoriel.

Installer les dépendances

Créez d'abord un nouveau répertoire et un environnement virtuel. Ensuite, activez l'environnement virtuel nouvellement créé :

mkdir test_project && cd test_project
python -m venv env
source env/bin/activate

Les commandes ci-dessus ont installé les paquets suivants :

  1. Django: le paquetage du framework Django.

  2. djangorestframework: le framework REST de Django pour créer des API dans Django.

  3. django-cors-headers: Cela permet à notre API d'effectuer des requêtes cross-origin vers d'autres serveurs.

  4. vonage: le SDK du serveur Python de Vonage.

Créer un projet Django

Maintenant, utilisez l'utilitaire django-admin pour créer un projet Django appelé vonage_project:

django-admin startproject vonage_project

Ensuite, vous devez configurer le Django-cors-headers pour l'application. De cette façon, d'autres origines et applications frontales peuvent faire une demande à votre application Django. Allez à la section MIDDLEWARE dans le fichier settings.py et ajoutez les classes d'intergiciel suivantes :

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

Ensuite, créez une application Django appelée myapp pour héberger notre fonctionnalité de SMS en masse :

cd vonage
django-admin startapp myapp

Créer une fonctionnalité de SMS en masse

Dans cette section, vous configurerez la fonction de SMS en masse avec l'API SMS de Vonage. Vous mettrez également en place une fonction d'étranglement.

Initialiser la bibliothèque Vonage

Normalement, vous devez initialiser la bibliothèque Vonage pour utiliser l'API Vonage pour l'envoi de messages. Cependant, la nouvelle API Messages de Vonage est en version bêta et Python n'est pas encore pris en charge. Cependant, nous pouvons toujours utiliser l'API Messages.

Tout d'abord, ajoutez le code suivant au fichier views.py le code suivant :

import base64

vonageCredentials = 'API_KEY:API_SECRET'
encodedData = vonageCredentials.encode("utf-8")
b64value = b64encode(encodedData).decode("ascii")

Dans le code ci-dessus, remplacez les éléments API_KEY et API_SECRET par les valeurs de votre tableau de bord Vonage. La variable vonageCredentials prend vos informations d'identification Vonage : votre clé API et votre clé secrète sous la forme 'API_KEY: API_SECRET.' Vous encodez et décodez ensuite la chaîne contenant vos informations d'identification sous la forme base64 pour les transmettre en tant que caractères ASCII standard.

Créer une vue pour envoyer un message SMS

Maintenant, créez une vue pour l'envoi des SMS dans views.py comme ceci :

from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import parser_classes
from rest_framework.parsers import JSONParser
import json
import requests
import base64
import time
from django.http.response import JsonResponse

vonageCredentials = 'API_KEY:API_SECRET'
encodedData = vonageCredentials.encode("utf-8")
b64value = base64.b64encode(encodedData).decode("ascii")

@ csrf_exempt
@ parser_classes(\[JSONParser])
def sendMessage(self, request):
    pass

Dans le code ci-dessus, vous avez importé les éléments csrf_exempt, parser_classes, et JSONParser afin de pouvoir définir des décorateurs pour la vue. Vous avez également importé la classe json, JsonResponseet d'autres modules dont vous aurez besoin dans votre application web. Vous avez ensuite créé la fonction sendMessage dans laquelle vous placerez la logique d'envoi du message.

Ensuite, vous ajouterez du code à l'intérieur de la vue sendMessage pour accepter les demandes et les entrées de l'utilisateur. Modifiez view.py comme suit :

def sendMessage(self, request):
    if request.method == 'POST':
        body_unicode = request.body.decode('utf-8')
        body_data = json.loads(body_unicode)

        sender = body_data['sender']
        recipients = body_data['recipients']
        message_string = body_data['message_string']
        batch_size = body_data['batch_size']
        delay_period = body_data['delay_period']

Dans le code ci-dessus, vous avez spécifié que la vue accepte les requêtes POST dans la ligne : request.method == 'POST'. Ensuite, vous avez décodé le corps de la requête au format JSON. Ensuite, vous avez réduit le corps de la requête aux éléments qu'il contient. Ces éléments sont les entrées suivantes reçues de l'utilisateur :

  1. sender: une variable qui contient les informations sur l'expéditeur du message.

  2. recipients: liste des numéros de téléphone des destinataires du SMS.

  3. message_string: le texte que vous allez envoyer dans la campagne de SMS en masse.

  4. batch_size: stipule le nombre de destinataires à qui envoyer un SMS en une seule fois.

  5. delay_period: le délai entre deux envois de lots de SMS (mesuré en secondes).

Vous allez maintenant créer une fonction pour diviser la liste des numéros de téléphone des destinataires en lots. Ajoutez le code suivant à l'extérieur de la fonction sendMessage dans le fichier views.py à l'extérieur de la fonction :

def batch(recipients, batch_size=1):
    for i in range(0, len(recipients), batch_size):
        yield recipients[i:min(i + batch_size, len(recipients))]

Vous avez défini une fonction appelée batch. Elle accepte deux paramètres : la recipients et l'entier batch_size qui représente le nombre de destinataires auxquels vous souhaitez envoyer un message en une seule fois. Vous utilisez une boucle for et le mot-clé yield pour créer un lot de numéros de téléphone. Si cela n'est pas clair, vous pouvez en savoir plus sur la méthode plage et yield fonctionnent.

Vous allez maintenant mettre en œuvre la logique permettant d'envoyer des messages. Modifiez la vue sendMessage comme indiqué ci-dessous :

@ csrf_exempt
@ parser_classes([JSONParser])
def sendMessage(request):
    if request.method == 'POST':
        body_unicode = request.body.decode('utf-8')
        body_data = json.loads(body_unicode)

        sender = body_data['sender']
        recipients = body_data['recipients']
        message_string = body_data['message_string']
        batch_size = body_data['batch_size']
        delay_period = body_data['delay_period']

        for eachBatch in batch(recipients, batch_size):
            for number in eachBatch:
                response = requests.post('https://api.nexmo.com/v0.1/messages',
                     headers={
                         "Authorization": "Basic %s" % b64value,
                         "Content-type": "application/json",
                         "Accept": "application/json"},
                     json={
                         "to": {
                             "type": "sms",
                             "number": number
                         },
                         "from": {
                             "type": "sms",
                             "number": sender
                         },
                         "message": {
                             "content": {
                                 "type": "text",
                                 "text": message_string
                             }
                         }
                     })
                print("message sent to ", number)
            time.sleep(delay_period)
        try:
            return JsonResponse("OK", status=200, safe=False)

        except Exception as e:
            return JsonResponse({'the error is': str(e)}, status=403)

Il y a deux boucles for à l'intérieur de la fonction sendSmsMessage sont présentes à l'intérieur de la fonction L'instruction externe for parcourt les lots de numéros de téléphone à l'aide de la fonction batch que vous avez définie plus tôt dans cet article. Vous divisez les numéros de téléphone des destinataires en lots en utilisant `batch_size' de la requête POST.

Ensuite, vous avez une boucle interne qui prend chaque numéro de chaque lot et fait une demande POST à l'API Messages de Vonage au point de terminaison https://api.nexmo.com/v0.1/messages. L'en-tête de la requête contient les informations d'identification codées en base64 que vous avez créées plus tôt en tant que "b64value", ainsi qu'une charge utile JSON à transmettre à l'API Messages. La charge utile JSON contient les informations suivantes :

  • sender: une variable qui contient les informations sur l'expéditeur du message.

  • recipients: liste des numéros de téléphone des destinataires du SMS.

  • message_string: le texte qui doit être contenu dans le SMS en masse.

  • batch_size: le nombre de destinataires auxquels un message doit être envoyé en une seule fois.

  • delay_period: le délai entre les lots de SMS à envoyer.

Lorsque la requête au point de terminaison de l'API Messages aboutit, le SMS est envoyé au destinataire et le code imprime un message sur votre terminal pour vous avertir de l'envoi du message. Ensuite, votre code travaille à l'envoi du lot suivant.

Après avoir envoyé un message à tous les destinataires d'un lot, la boucle for parent s'exécute après la période de délai que vous avez définie à l'aide de la commande time.sleep(delay_period).

Lorsque vous avez fini d'envoyer les SMS, votre code renvoie un 200 - OK JsonResponse.

Le code complet views.py est le suivant :

from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import parser_classes
from rest_framework.parsers import JSONParser
import json
import requests
import base64
import time
from django.http.response import JsonResponse


# Create your views here.
vonageCredentials = 'ba779f8e:fFImpyBSezdXV1Nd'
encodedData = vonageCredentials.encode("utf-8")
b64value = base64.b64encode(encodedData).decode("ascii")
print(b64value)


@ csrf_exempt
@ parser_classes([JSONParser])
def sendMessage(request):
    if request.method == 'POST':
        body_unicode = request.body.decode('utf-8')
        body_data = json.loads(body_unicode)

        sender = body_data['sender']
        recipients = body_data['recipients']
        message_string = body_data['message_string']
        batch_size = body_data['batch_size']
        delay_period = body_data['delay_period']

        for eachBatch in batch(recipients, batch_size):
            for number in eachBatch:
                response = requests.post('https://api.nexmo.com/v0.1/messages',
                     headers={
                         "Authorization": "Basic %s" % b64value,
                         "Content-type": "application/json",
                         "Accept": "application/json"},
                     json={
                         "to": {
                             "type": "sms",
                             "number": number
                         },
                         "from": {
                             "type": "sms",
                             "number": sender
                         },
                         "message": {
                             "content": {
                                 "type": "text",
                                 "text": message_string
                             }
                         }
                     })
                print("message sent to ", number)
            time.sleep(delay_period)
        try:
            return JsonResponse("OK", status=200, safe=False)

        except Exception as e:
            return JsonResponse({'the error is': str(e)}, status=403)


def batch(recipients, batch_size=1):
    for i in range(0, len(recipients), batch_size):
        yield recipients[i:min(i + batch_size, len(recipients))]

Définir un chemin URL

Puisque vous avez créé une vue pour recevoir des demandes, vous aurez besoin d'une URL correspondante pour que les utilisateurs puissent accéder à la vue et faire des demandes. Par conséquent, vous ajouterez un chemin d'accès à l'URL urlpatterns dans le fichier urls.py du projet. Naviguez jusqu'au sous-répertoire du projet et ajoutez le code suivant :

from django.urls import path
from myapp.views import sendMessage

urlpatterns = [
   ...
    path('message/', sendMessage),
]

Comme indiqué ci-dessus, vous avez importé path et la vue sendMessage vue. Ensuite, vous avez ajouté un chemin avec l'URL message/ à la liste des urlpatterns.

Test de l'API de l'application

Vous pouvez tester la fonctionnalité construite ci-dessus avec le programme Postman qui permet de simuler et de documenter les API. Vous pouvez vous inscrire pour obtenir un Account Postman gratuit.

Pour exécuter ce test, vous devez également démarrer le serveur de test de Django comme suit :

Python manage.py runserver

Supposons que vous ayez l'intention d'utiliser les informations suivantes pour votre campagne de SMS en masse.

{
    "sender": "Your Vonage number.",
    "recipients": ["First number to send to.", "Second number to send to"],
    "message_string": "Hello, World!",
    "batch_size": 3,
    "delay_period": 3600
}

Vous pouvez saisir les détails ci-dessus dans le corps d'une requête Postman sous forme de JSON, comme le montre l'image suivante :

A Postman screenshot

Veillez à remplacer les "recipients" les numéros de téléphone par de vrais numéros et remplacez "sender" par votre numéro Vonage avant d'envoyer la demande. Ensuite, les messages seront livrés à vos destinataires.

Conclusion

Dans cet article, vous avez mis en œuvre l'étranglement des SMS en masse en utilisant Vonage dans une API REST Django. Vous pouvez maintenant intégrer cette solution dans vos projets et construire d'autres solutions avec Vonage. Vous pouvez consulter notre guide d'authentification pour mieux comprendre l'authentification avec les API de Vonage.

Partager:

https://a.storyblok.com/f/270183/400x397/505bfb0eb9/jekayinoluwa-olabemiwo.png
Jekayinoluwa Olabemiwo

Jẹ́káyinOlúwa is a software craftsman and product manager passionate about technology and its impact on people. He works on product management, backend development, DevOps, technical writing, and community strategy. He enjoys dealing in the intersection of software, design, and human interaction. He likes reading and music.