Envoyer des emails avec n8n

Lors du webinaire « Combiner Grist et n8n » du 12 décembre, nous avons présenté deux workflows créés avec l’outil d’automatisation n8n, et qui permettaient de :
1. Envoyer un email à une liste d’inscrits à un webinaire, lorsque le gestionnaire du document le décide.
2. Envoyer un email à chaque soumission du formulaire d’inscription au webinaire

Il est composé :

  • d’une table Webinaires avec le sujet du webinaire, le lien de connexion et une colonne Mail permettant de choisir entre plusieurs valeurs : « - », « à envoyer » et « envoyer »
  • d’une table Inscrits avec le nom et l’email de l’inscrit·e, le nom du webinaire (référence à la table Webinaires) et d’autres champs issus de la table Webinaires
  • d’un formulaire, basé sur la table Inscrits.
Tuto 1. Envoyer un email à une liste d'inscrits à un évènement

Objectif: Lors du choix de la valeur « à envoyer » dans la colonne Mail de la table Webinaires dans Grist, envoyer via n8n un e-mail personnalisé à tou·te·s les inscrit·e·s à ce webinaire.

Tuto:

  • Dans n8n, créer un nouveau projet
  • Ajoutez un premier noeud d’exécution de type « Test workflow » (servira à démarrer le workflow manuellement)
  • Ajoutez un noeud « Grist » avec la configuration suivante :
    Credential to connect with : “Create new credential”. La clé API peut être trouvée à [url_de_votre_instance/account]
    Operation : “Get Many Rows”
    Document ID : peut être trouvé dans Paramètres > ID du Document
    Table ID : nom de la table (remplacer les espaces par _), en cas de doute le nom de la table peut être trouvé dans « Vue du Code »
  • Cliquez Test step, voir que vous observez bien les données en sortie
  • Dans Additional options > Filter > Add filter, ajoutez un filtre sur la colonne d’intérêt, ici Mail2 avec Values = « à envoyer » (sans les guillemets)
  • Cliquez Test step, voir que vous observez bien les données filtrées en sortie
  • Ajoutez un noeud « Send Email ». Il devrait se connecter automatiquement au noeud Grist, sinon reliez-le manuellement. Lorsque vous vous trouvez dans la configuration du noeud, et qu’il est bien relié au noeud précédent, vous devez voir les données en entrée dans le panneau de gauche (les enregistrements obtenus depuis Grist). La configuration du noeud est la suivante :
    Credential to connect with : configurez votre authentification SMTP
    From Email : entrez l’email à partir duquel vous souhaitez envoyer les emails
    To Email : faites un glissé/déposé de la clé « Mail », à partir du panneau de gauche
    Subject: entrez le sujet du mail (ex: Webinaire + glissé/déposé de la clé « webinaire »)
    Email Format : choisissez HTML si vous souhaitez ajouter un lien au mail
    Dans le corps du mail, écrivez par exemple :
Bonjour,<br>
Vous êtes bien inscrit·e au webinaire '{{ $json.webinaire }}', le lien de connexion est : <br>
 <a href="">{{ $json.Lien }}</a>
 
<br> <br>
Hasta la vista
  • Cliquez sur « Test step » : vérifiez que vous avez bien reçu les emails :partying_face:

Nous souhaitons désormais que, dans Grist, la valeur de la colonne « Mail » soit passée à « bien envoyé ». Nous allons faire cela en 2 étapes (la première, pour lire la table Webinaire et récupérer l’identifiant de la ligne à modifier, la deuxième pour modifier la valeur souhaitée) :

  • Dans n8n, dupliquez le noeud Grist (au survol > 3 petits points > Duplicate)
  • Reliez ce noeud au premier noeud Grist
  • Modifier Table ID pour « Webinaires »
  • Dans Additional Options > Filter, choisir Column Name = Sujet et Values = glissé/déposé la clé « webinaire »
  • Cliquez sur Test step, voir que vous observez bien les données filtrées en sortie
  • Dupliquer à nouveau un noeud Grist
  • Relier ce noeud au second noeud Grist
  • Double-cliquer sur le noeud, et modifier Operation pour Update Row Table ID pour « Webinaires »
  • Dans Row ID, faire un glissé/déposé de la clé id
  • Dans Fields to Send, choisir Mail, et dans Field Value taper « bien envoyé » (sans les guillemets)
  • Cliquez sur Test step, vous devriez voir une réponse json de ce type :
[
{
"id": 2,
"Mail": "bien envoyé"
},
{
"id": 2,
"Mail": "bien envoyé"
}
]

Qui signifie que la même modification a été exécutée deux fois (c’est normal, il y avait deux éléments dans notre json en entrée). Pour éviter cela, cliquer sur Settings (deuxième onglet dans la configuration du noeud) > Execute once.

  • Cliquez sur Test step, voyez que cette fois-ci la requête ne s’est exécutée qu’une seule fois et vérifiez dans Grist que votre enregistrement « Mail » est bien passé à « bien envoyé » :v:
Tuto 2. Envoyer un email à chaque soumission du formulaire

Si vous utilisez Grist sur une instance de l’ANCT ou de la DINUM, les webhooks vers des url non connues sont bloquées pour raisons de sécurité - si vous auto-hébergez votre propre instance de n8n, il vous faudra contacter l’équipe (sur Tchap ou par mail donnees@anct.gouv.fr ou contact@grist.numerique.gouv.fr) en amont pour demander une validation de votre sous-domaine. Si vous hébergez sur un domaine .gouv.fr, il sera de facto autorisé.
Sur l’instance de l’ANCT, pour vous permettre de réaliser vos tests, nous avons autorisé les webhooks vers les instances cloud de n8n (n8n.cloud) et Activepieces (cloud.activepieces.com).

  • Dans n8n, dans un nouveau projet, ajouter un noeud de type « Webhook », choisir HTTP Method = POST et copier l’URL de test (qui s’affiche après POST)
    (vous pouvez modifier le chemin de l’url si nécessaire dans le champ Path)

  • Dans Grist, Paramètres > Points d'ancrage web, créez un nouveau webhook :
    Nom : champ libre
    Types d'événements : add
    Table : sélectionnez le nom de la table que vous souhaitez observer, ici « Inscrits »
    Filtrer les changements dans ces colonnes (facultatif) : spécifiez le nom de la colonne à observer (inutile ici)
    URL : collez l’URL de test de N8N
    Activé : ON

  • Dans n8n, cliquez sur Listen for test event

  • Dans Grist, ouvrez le formulaire, remplissez-le et validez

  • Dans N8N, voyez la requête réussie et le json ressemblant à :

[
  {
    "headers": {
     ...
    },
    "params": {},
    "query": {},
    "body": [
      {
        "id": 7,
        "manualSort": 7,
        "Nom": "aude",
        "Mail": "merrygristmas@mail.fr",
        "Session": 1,
        "gristHelper_Display2": "2024-12-12 - Combiner Grist et n8n",
        "webinaire": "Combiner Grist et n8n",
        "date": "2024-12-12",
        "Mail_d_annonce": "envoyer",
        "Lien": "www.webigrist.gouv.fr"
      }
    ],
    "webhookUrl": "https://aude.app.n8n.cloud/webhook-test/2961fc37-b9c9-413c-b636-61663eae17fa",
    "executionMode": "test"
  }
]

  • Ajoutez un noeud « Send Email »:
    Credential to connect with : configurez votre authentification SMTP
    From Email : entrez l’email à partir duquel vous souhaitez envoyer les emails
    To Email : faites un glissé/déposé de la clé « Mail », à partir du panneau de gauche
    Subject: entrez le sujet du mail (ex: Webinaire + glissé/déposé de la clé « webinaire »)
    Email Format : choisissez HTML si vous souhaitez ajouter un lien au mail
    Dans le corps du mail, écrivez votre texte et faites un glissé/déposé de la clé Lien. Par exemple :
    Ex:
Bonjour,
Voici le lien de connexion : {{ $json.body[0].Lien }}
  • CliquezTest step, vérifiez votre client de messagerie pour voir le nouvel e-mail reçu. Tests validés !
  • Dans n8n, ouvrez le noeud « Webhook », basculez sur Production URL et copiez l’url. Activez le workflow grâce au petit bouton switch au-dessus du canevas (obligatoire, sinon votre requête ne sera pas reçue !) et sauvegardez.
  • Dans Grist, dans la configuration du Webhook, dans le champ URL, remplacez l’url de test par l’url de production. En cas d’erreur visible dans le champ Statut, désactivez et réactivez le bouton Activé.
  • Soumettez à nouveau une réponse au formulaire, et vérifiez que vous avez bien reçu l’e-mail dans votre client mail :partying_face:

Le fichier json (à enregistrer en .json, il peut être importé directement dans n8n)
{
  "name": "Webinaires Mails",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -320,
        -80
      ],
      "id": "057e4ab0-8d50-498c-bdd7-4ff53aed1200",
      "name": "When clicking ‘Test workflow’"
    },
    {
      "parameters": {
        "docId": "5KssdVEEjGsav4ASnhLjMJ",
        "tableId": "Inscrits",
        "additionalOptions": {
          "filter": {
            "filterProperties": [
              {
                "field": "Mail_d_annonce",
                "values": "envoyer"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.grist",
      "typeVersion": 1,
      "position": [
        -80,
        -80
      ],
      "id": "47063939-71d9-41db-ba03-b4ff8c95d54d",
      "name": "Grist",
      "credentials": {
        "gristApi": {
          "id": "aaaaa",
          "name": "Grist account"
        }
      }
    },
    {
      "parameters": {
        "fromEmail": "merrygristmas@mail.fr",
        "toEmail": "={{ $json.Mail }}",
        "subject": "=Bientôt le webi {{ $json.webinaire }}",
        "html": "=Bonjour, <br>\nLe webinaire {{ $json.webinaire }} du {{ $json.date }} approche ! Le lien de co est : \n<a href=\"\"> {{ $json.Lien }}</a>\n\n<br><br>\nByebye\n",
        "options": {}
      },
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        160,
        -80
      ],
      "id": "0afb5c2c-6974-437d-9415-4389e833a2b0",
      "name": "Send Email",
      "credentials": {
        "smtp": {
          "id": "YuddTYCa",
          "name": "SMTP Merry Gristmas"
        }
      }
    },
    {
      "parameters": {
        "operation": "update",
        "docId": "5KssdVEEjGsav4ASnhLjMJ",
        "tableId": "Webinaires",
        "rowId": "={{ $json.id }}",
        "fieldsToSend": {
          "properties": [
            {
              "fieldId": "Mail_annonce",
              "fieldValue": "done!"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.grist",
      "typeVersion": 1,
      "position": [
        340,
        -340
      ],
      "id": "9282eabe-d45b-498a-8673-a62c9808eb51",
      "name": "Grist1",
      "credentials": {
        "gristApi": {
          "id": "xxxxx",
          "name": "Grist account"
        }
      }
    },
    {
      "parameters": {
        "docId": "5KssdVEEjGsav4ASnhLjMJ",
        "tableId": "Webinaires",
        "limit": 1,
        "additionalOptions": {
          "filter": {
            "filterProperties": [
              {
                "field": "Sujet",
                "values": "={{ $json.webinaire }}"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.grist",
      "typeVersion": 1,
      "position": [
        160,
        -340
      ],
      "id": "fb1ec292-9241-4d96-9af7-92e9e97b473f",
      "name": "Grist2",
      "executeOnce": true,
      "credentials": {
        "gristApi": {
          "id": "XXXX",
          "name": "Grist account"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "2961fc37-b9c9-413c-b636-61663eae17fa",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -280,
        280
      ],
      "id": "d765df9c-a587-49a5-9f9b-f3a56b87f7c0",
      "name": "Webhook",
      "webhookId": "2961fc37-b9c9-41ddd17fa"
    },
    {
      "parameters": {
        "fromEmail": "merrygristmas@mail.fr",
        "toEmail": "={{ $json.body[0].Mail }}",
        "subject": "=Bien inscrit·e au webi \"{{ $json.body[0].webinaire }}\"",
        "html": "=hi ! \n\nlien de co : {{ $json.body[0].Lien }}",
        "options": {}
      },
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        20,
        280
      ],
      "id": "45a15793-6fb2-4981-a4e8-732a03060015",
      "name": "Send Email1",
      "credentials": {
        "smtp": {
          "id": "YudddCa",
          "name": "SMTP Merry Gristmas"
        }
      }
    },
    {
      "parameters": {
        "content": "## Envoyer un email à une liste d'inscrits à un évènement\n\n",
        "height": 580,
        "width": 1320
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -500,
        -440
      ],
      "id": "ef93ff74-ca6a-419f-8e0c-f3dca3b38fff",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## Envoyer un email à chaque soumission du formulaire de participation",
        "height": 360,
        "width": 1320,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -500,
        180
      ],
      "id": "a30de224-e583-408b-bcc2-c8ce50a41fc4",
      "name": "Sticky Note1"
    }
  ],
  "pinData": {},
  "connections": {
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Grist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Grist": {
      "main": [
        [
          {
            "node": "Send Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Grist2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Grist2": {
      "main": [
        [
          {
            "node": "Grist1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Send Email1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "27ddd9-b0c0-c2956ab5f29c",
  "meta": {
    "instanceId": "8b084edd77c023e3d131c2cae3feb821f7"
  },
  "id": "yddEtyg8Kw",
  "tags": []
}

Si vous utilisez les instances DINUM ou ANCT, pour la connexion API il faut mettre l’url :
https://grist.incubateur.anct.gouv.fr/o/anct/
ou
https://grist.numerique.gouv.fr/o/dinum

Détails authentification

Vous pouvez créer l’authentification avec :

https://grist.incubateur.anct.gouv.fr/o/nom-de-l-espace-d-equipe

2 « J'aime »

Pour information : Il pourrait bientôt être possible de modifier l’en-tête et le corps des requêtes directement depuis la configuration d’un point d’ancrage dans Grist, ce qui signifie…la possibilité de se connecter directement à d’autres applications, sans passer par n8n ou autre outil d’automatisation !

Cela couvrirait la plupart des cas d’usage - comme la connexion à une application d’envoi d’email de masse type Brevo ou Mailjet. Et demanderait juste un peu de travail pour définir les paramètres des requêtes à la main.

Si vous souhaitez soutenir cette idée, n’hésitez-pas à mettre un :+1: ou un :heart: sur GitHub : Custom HTTP queries for webhooks · Issue #827 · gristlabs/grist-core · GitHub

confirmez-vous qu’il n’est toujours pas possible de créer des Webhooks sortant dans Grist ? En effet, l’interface Webhooks de Grist demande à chaque fois de spécifier une URL de point d’ancrage externe

Hello,

Merci pour la question et bienvenue sur le forum :blush: Il est tout à fait possible de créer des webhooks dans Grist, pour communiquer avec d’autres applications - il existe par contre des limitations sur les domaines accessibles. C’était l’occasion de faire un post pour détailler le fonctionnement des points d’ancrage et fournir une explication complète, mais n’hésitez-pas à me relancer si ça ne répond pas à votre question !

Bonjour, j’ai bien suiv le webinaire, merci. La clé API est la suivante : https://grist.numerique.gouv.fr/o/eafcbdx mais elle ne marche pas. Y a t’il un réglage à faire pour autoriser ?