https://d226lax1qjow5r.cloudfront.net/blog/blogposts/sending-sms-templates-python-dr/Sending-SMS-templates-with-Jinja2-and-Python.png

Envoi de modèles de SMS avec Jinja2 et Python

Publié le May 11, 2021

Temps de lecture : 2 minutes

Vous avez besoin d'envoyer un message à plusieurs personnes à la fois ? Vous voulez le personnaliser pour qu'il ne paraisse pas si impersonnel ? Vous ne pouvez pas envoyer un message groupé car vous ne voulez pas que votre mère voie que vous avez envoyé le même message à toutes vos relations et pas seulement à elle ? Nous allons voir comment créer un client SMS capable d'envoyer des messages groupés et des modèles de personnalisation.

Pour commencer

Vous aurez besoin d'un peu d'expérience avec Python pour exécuter le CLI, et au moins Python 3.6 car nous allons utiliser des chaînes f.

  1. Cloner la source depuis GitHub

  2. Installez les dépendances dans votre environnement virtuel ; je recommande l'utilisation de pipenv et d'installer le paquet en mode édition : pipenv install -e .

  3. Créez les variables environnementales suivantes ; NEXMO_KEY, NEXMO_SECRETet MY_NUMBER les deux premières sont disponibles dans votre tableau de bord Nexmo. MY_NUMBER est votre numéro de téléphone mobile au format international E.164.

Gestion des contacts SMS

Creating a new contact via the CLICreating a new contact via the CLI

Notre application aura besoin de d'un CRM de base pour contenir nos contacts. Nous allons utiliser tinydb pour notre couche de persistance car nous n'avons pas besoin de quelque chose de trop compliqué et, en prime, il stocke les données sous forme de fichier JSON, ce qui rend les sauvegardes et les modifications manuelles des données très simples.

Outre le nom et le numéro de téléphone du contact, nous collectons quelques valeurs à choix multiples.

@contact.command("create")
def contact_create():
    """Creates a new contact"""
    questions = [
        {"type": "input", "name": "name", "message": "Contact name"},
        {
            "type": "input",
            "name": "phonenumber",
            "message": "Contact phone number (E.164 international format)",
        },
        {
            "type": "checkbox",
            "qmark": "?",
            "message": "Select diminutives (select at least 1)",
            "name": "diminutive",
            "choices": [
                Separator("= The Bros ="),
                {"name": "Bro"},
                {"name": "Buddy"},
                {"name": "Dude"},
                {"name": "Matey"},
                {"name": "Pal"},
                Separator("= The Sweethearts ="),
                {"name": "Baby"},
                {"name": "Bae"},
                {"name": "Darling"},
                {"name": "Sweetheart"},
                {"name": "Sugar"},
                Separator("= The Scots/Irish/Aussies ="),
                {"name": "████"},
                {"name": "Eejit"},
                {"name": "█████████"},
                {"name": "Numpty"},
            ],
            "validate": lambda answer: "You must choose at least one diminutive."
            if len(answer) == 0
            else True,
        },
        {
            "type": "checkbox",
            "qmark": "?",
            "message": "Select greetings (select at least 1)",
            "name": "greeting",
            "choices": [
                {"name": "Alright"},
                {"name": "Greetings"},
                {"name": "Hello"},
                {"name": "Hey"},
                {"name": "Hi"},
                {"name": "Oi"},
                {"name": "Wasssssup"},
                {"name": "Yo"},
            ],
            "validate": lambda answer: "You must choose at least one greeting."
            if len(answer) == 0
            else True,
        },
        {
            "type": "checkbox",
            "qmark": "?",
            "message": "Select valediction (select at least 1)",
            "name": "valediction",
            "choices": [
                {"name": "Bye"},
                {"name": "Cya"},
                {"name": "Love you x"},
                {"name": "Peace"},
                {"name": "xox"},
            ],
            "validate": lambda answer: "You must choose at least one valediction."
            if len(answer) == 0
            else True,
        },
    ]

    answers = prompt(questions, style=questions_style)
    contacts_db.insert(answers)

    click.secho(
        f"New contact {answers['name']} created", fg="black", bg="cyan", bold=True
    )

Lorsque nous rendons le modèle d'un message, nous fournissons une valeur aléatoire de ces listes dans le contexte, ce qui donne aux messages une certaine variation.

Gestion de nos modèles de SMS

Nos modèles seront rendus à l'aide de Jinja2, ce qui nous permettra d'accéder à tous les filtres et fonctionnalités intégrés de Jinja. En outre, nous fournir des informations sur chaque contact dans le contexte lors du rendu du modèle.

Creating a new template via the CLICreating a new template via the CLI

J'ai fait un usage intensif du filtre Jinja random de Jinja pour qu'il y ait une certaine variation dans mes messages, même si je renvoie plusieurs fois le même message à la même personne, on devrait avoir l'impression que j'ai pris le temps de l'écrire personnellement à chaque fois. Pour plus d'authenticité, vous pouvez ajouter des fautes de frappe de temps en temps.

{{ greeting }} {{ diminutive }} {{ ["gah", "sorry", "I suck", "soz"]|random }}, I'm {{ ["running", "runnin", "runing"]|random }} about {{ range(5,25)|random }} {{ ["mins", "minutes", "mintes"]|random }} late. {{ valediction }}

Screenshot of phone with multiple SMSScreenshot of phone with multiple SMS

Le reste de code de gestion des modèles est très similaire à celui des contacts, bien que nous disposions d'une fonction d'exploration/expansion rudimentaire permettant de visualiser rapidement le contenu du modèle.

@template.command("list")
def template_list():
    """View all templates"""
    viewing_templates = True
    all_templates = templates_db.all()

    while viewing_templates:
        questions = [
            {
                "type": "list",
                "message": "View template",
                "name": "template",
                "choices": [
                    {"name": f"{template['name']}", "value": template}
                    for template in all_templates
                ],
            }
        ]

        answers = prompt(questions, style=questions_style)

        click.echo(answers["template"]["name"])
        click.echo("---")
        click.echo(answers["template"]["template"])

        if not click.confirm("View another template?"):
            viewing_templates = False

Envoi de plusieurs SMS avec Python

Sending multiple/bulk SMS via the CLISending multiple/bulk SMS via the CLI

Avec le Nexmo Python Client l'envoi d'un SMS est un un seul appel de fonction; la majeure partie de notre code d'envoi de SMS consiste à permettre à l'utilisateur de sélectionner les numéros qui vont recevoir le message, et le modèle que nous devons utiliser.

@click.command()
def send():
    """Send SMS"""

    questions = [
        {
            "type": "checkbox",
            "qmark": "?",
            "message": "Select contacts to message",
            "name": "contacts",
            "choices": [
                {
                    "name": f"{contact['name']} - {contact['phonenumber']}",
                    "value": contact,
                }
                for contact in contacts_db.all()
            ],
            "validate": lambda answer: "You must choose at least one contact."
            if len(answer) == 0
            else True,
        },
        {
            "type": "list",
            "message": "Select template",
            "name": "template",
            "choices": [
                {"name": f"{template['name']}", "value": template["template"]}
                for template in templates_db.all()
            ],
        },
    ]

    answers = prompt(questions, style=questions_style)
    template = Template(answers["template"])

    with click.progressbar(answers["contacts"], label="Sending messages") as contacts:
        for contact in contacts:
            message = template.render(
                name=contact["name"],
                phonenumber=contact["phonenumber"],
                diminutive=random.choice(contact["diminutive"]),
                greeting=random.choice(contact["greeting"]),
                valediction=random.choice(contact["valediction"]),
            )

            nexmo_client.send_message(
                {
                    "from": os.environ["MY_NUMBER"],
                    "to": contact["phonenumber"],
                    "text": message,
                }
            )

J'ai modifié le code ci-dessus pour enregistrer les résultats de mon message de Noël afin que vous puissiez voir le type de variation qu'il produit entre les différents contacts.

Multiple messages output from bulk SMS CLI in PythonMultiple messages output from bulk SMS CLI in Python

Partager:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Aaron BassettAnciens de Vonage

Aaron était défenseur des développeurs chez Nexmo. Ingénieur logiciel chevronné et artiste numérique en herbe, Aaron est souvent amené à créer des choses avec du code ou de l'électronique, parfois les deux. On peut généralement savoir qu'il travaille sur quelque chose de nouveau grâce à l'odeur de composants brûlés qui flotte dans l'air.