Nous allons voir comment envoyer un email à partir d’un site Gatsby en utilisant Twilio Serverless Functions et Sendgrid.
Avant de parler de Gatsby, il est nécessaire de commencer par l’architecture JAMstack pour JavaScript, APIs et Markup.
Traditionnellement, les web apps génèrent dynamiquement du HTML à partir de templates quand le serveur reçoit une requête. Les sites JAMstack utilisent des générateurs pour transformer des templates en HTML quand le site est déployé et non quand une requête arrive.
Cette manière de faire apporte un énorme boost de performance et d’autant plus si vous utilisez un CDN mais il y a des limites en matière de complexité d’UI que les sites statiques peuvent supporter.
Gatsby fait le pont entre les sites statiques JAMstack et les webapps traditionnelles. Vous allez écrire des composants React qui compilent vers du HTML avec un petit peu de JavaScript pour apporter de l’interactivité.
Gatsby est totalement open source et est hébergé par une fondation. Il est pourvu également de tout un éco-système de plugins, thèmes et starters.
Pour réaliser ce tuto vous allez avoir besoin :
Twilio Serverless Functions et Sendgrid propose de généreux free tiers donc aucune inquiétude à ce niveau-là.
Il va falloir commencer par installer le CLI Gatsby. Pour cela, ouvrez un terminal et exécutez la commande suivante :
$ npm install -g gatsby-cli
Le flag -g
permet de rendre accessible le CLI Gatsby de n’importe où.
Testez ensuite votre installation avec la commande suivante :
$ gatsby --version
Si tout est correct, vous devriez obtenir la version du CLI Gatsby d’installer.
Pour générer notre site Gatsby, nous allons utiliser un starter
. Un starter
est une base d’un site Gatsby complet que vous allez pouvoir cloner et ensuite vous servir comme base.
À partir du terminal, lancez la commande suivante :
$ gatsby new gatsby-default https://github.com/gatsbyjs/gatsby-starter-default
Ouvrez le dossier gatsby-default
. Puis exécutez les commandes suivantes pour développer :
$ cd gatsby-default$ gatsby develop
Au bout d’un moment, vous allez voir dans votre terminal quelque chose comme ça :
You can now view gatsby-default in the browser.http://localhost:8000
Rendez-vous à l’URL http://localhost:8000
et vous allez voir votre site Gatsby en action.
Nous allons maintenant ajouter un formulaire. Comme un projet Gatsby est également une application React, il est courant d’utiliser le même genre d’organisation.
A l’intérieur du dossier src/components
, créer un nouveau fichier contactForm.js
. Puis ajouter le code ci-dessous :
import React from "react"class ContactForm extends React.Component {constructor(props) {super(props)this.state = {buttonDisabled: true,message: { fromEmail: "", subject: "", body: "" },submitting: false,error: null,}}onChange = event => {const name = event.target.getAttribute("name")this.setState({message: { ...this.state.message, [name]: event.target.value },})}render() {return (<><div>{this.state.error}</div><formstyle={{display: `flex`,flexDirection: `column`,maxWidth: `500px`,}}method="post"><label htmlFor="fromEmail">Your email address:</label><inputtype="email"name="fromEmail"id="fromEmail"value={this.state.message.fromEmail}onChange={this.onChange}></input><label htmlFor="subject">Subject:</label><inputtype="text"name="subject"id="subject"value={this.state.message.subject}onChange={this.onChange}/><label htmlFor="body">Message:</label><textareastyle={{height: `150px`,}}name="body"id="body"value={this.state.message.body}onChange={this.onChange}/><buttonstyle={{marginTop: `7px`,}}type="submit"disabled={this.state.submitting}onClick={this.onClick}>Send message</button></form></>)}}export default ContactForm
Le formulaire demande l’email à re-contacter, le sujet et le contenu du message. Le composant contactForm
gère ses données via React state. Le formulaire a également quelques status pour désactiver le bouton submit lorsque le formulaire est soumis ou bien afficher le texte d’erreur si nécessaire.
Pour afficher le formulaire, ouvrez le fichier pages/index.js
et modifiez le pour qu’il ressemble à celui ci-dessous :
import * as React from "react"import { StaticImage } from "gatsby-plugin-image"import Layout from "../components/layout"import Seo from "../components/seo"import ContactForm from "../components/contactForm"import * as styles from "../components/index.module.css"const IndexPage = () => (<Layout><Seo title="Home" /><div className={styles.textCenter}><StaticImagesrc="../images/example.png"loading="eager"width={64}quality={100}formats={["auto", "webp", "avif"]}alt=""style={{ marginBottom: `var(--space-3)` }}/><h1>Welcome to <b>Gatsby!</b></h1><ContactForm></ContactForm></div></Layout>)/*** Head export to define metadata for the page** See: https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/*/export const Head = () => <Seo title="Home" />export default IndexPage
Nous avons commencé par retirer pas mal de contenu de la page pour y voir plus clair. Puis, nous avons ajouté l’import de notre formulaire via import ContactForm from "../components/contactForm"
et nous l’avons injecté dans la page via <ContactForm></ContactForm>
.
Dès la sauvegarde du fichier, le navigateur va recharger la page et vous devriez voir apparaître notre formulaire.
Commencez par créer un compte si vous n’en avez pas déjà un.
Il va falloir ensuite vérifier une identité d’expéditeur. Pour cela, allez dans la rubrique “Settings” puis cliquez sur “Sender Authentication”. Dans la section “Single Sender Verification”, cliquez sur “Get Started”. Remplissez le formulaire, puis validez le profil en cliquant sur le lien dans le mail reçu.
Allez ensuite dans la rubrique “Settings” puis cliquez sur “API Keys”. Cliquez sur “Create API Key”, donnez lui un nom comme “gatsby-contact-form-test”. Au niveau des permissions, sélectionnez “Restricted Access” puis donnez lui l’accès au droit “Mail Send”.
Enfin, cliquez sur “Save” et conservez de côté l’API Key généré.
Pour le moment, notre formulaire ne fait rien du tout. Il a besoin d’un backend quelque part pour exécuter la logique de réception des données du formulaire et l’envoi de l’email via SendGrid. Pour faire cela nous allons utiliser Twilio Serverless Function.
Créez-vous un compte sur Twilio si ce n’est pas déjà fait. Nous allons commencer par aller dans “Functions and Assets” puis “Services”. Cliquez ensuite sur “Create Service” et donnez un nom à votre service comme “gatsby-site-service” puis cliquez sur “Next”.
Vous allez arriver sur un éditeur de fonction.
Dans la partie Settings, cliquez sur “Environment Variables”. Dans le panel de droite, mettez “SENDGRID_APIKEY” en key et l’ApiKey que vous avez généré un peu plus tôt puis cliquez sur “Add”.
Cliquez maintenant sur “Dependencies” toujours dans la partie Settings. Dans le panel de droite, nous allons ajouter le module sendgrid pour pouvoir interagir avec. Pour cela saisissez @sendgrid/mail
en nom de module et 7.7.0
en version puis cliquez sur “Add”.
Au moment du déploiement de la fonction, Twilio va injecter automatiquement d’autres modules utilitaires. Cela n’a pas d’incidence pour nous.
Il ne nous reste plus qu’à créer notre fonction. Pour cela cliquez sur le bouton “Add +” et sélectionnez “Add Function”.
Votre fonction va nécessiter un path, saisissez /send-email
, puis appuyer sur “entrée”.
Le panel de votre fonction s’ouvre avec un boilerplate. Remplacez-le par celui-ci :
const sendgrid = require('@sendgrid/mail')exports.handler = async function handler(context, event, callback) {sendgrid.setApiKey(context.SENDGRID_APIKEY)const response = new Twilio.Response()response.setHeaders({'Access-Control-Allow-Origin': 'http://localhost:8000','Content-Type': 'application/json',})const text = `from: ${event.fromEmail}body: ${event.body}`;const message = {to: '', // replace this with your email addressfrom: '', // replace this with your email addresssubject: event.subject,text,}try {await sendgrid.send(message)response.setBody({})response.setStatusCode(200)} catch (error) {response.setBody({ error: error.message })response.setStatusCode(error.code)}callback(null, response)}
Remplacez le to
et from
avec l’adresse email que vous avez vérifié auprès de SendGrid. Il n’est pas possible d’envoyer à partir d’un email non vérifié, cela rendrait l’usurpation d’identité bien trop facile.
Cette fonction récupère le contenu du formulaire qui se trouve dans l’objet event
, construit le mail et l’envoi via SendGrid. A noter que comme nous appelons depuis localhost:8000
vers un nom de domaine différent, nous devons configurer le header CORS dans la réponse de notre fonction ou bien l’appel échouera.
Il ne vous reste plus qu’à appuyer sur “Save”.
Avant de déployer notre fonction, passez la en “Public” pour qu’elle soit accessible de l’extérieur. Une fois fait cliquez sur “Deploy All” pour déployer votre code sur l’infrastructure de Twilio.
Copiez enfin l’URL de votre fonction et gardez la de côté.
Retournez maintenant sur votre projet Gatsby et modifiez le ContactForm
pour réaliser l’appel à la fonction.
import React from "react"const functionURL = "" // replace this with your function URLclass ContactForm extends React.Component {constructor(props) {super(props)this.state = {buttonDisabled: true,message: { fromEmail: "", subject: "", body: "" },submitting: false,error: null,}}onClick = async event => {event.preventDefault()this.setState({ submitting: true })const { fromEmail, subject, body } = this.state.messageconst response = await fetch(functionURL, {method: "post",headers: {"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",},body: new URLSearchParams({ fromEmail, subject, body }).toString(),})if (response.status === 200) {this.setState({error: null,submitting: false,message: {fromEmail: "",subject: "",body: "",},})} else {const json = await response.json()this.setState({error: json.error,submitting: false,})}}onChange = event => {const name = event.target.getAttribute("name")this.setState({message: { ...this.state.message, [name]: event.target.value },})}render() {return (<><div>{this.state.error}</div><formstyle={{display: `flex`,flexDirection: `column`,maxWidth: `500px`,}}method="post"action={functionURL}><label htmlFor="fromEmail">Your email address:</label><inputtype="email"name="fromEmail"id="fromEmail"value={this.state.message.fromEmail}onChange={this.onChange}></input><label htmlFor="subject">Subject:</label><inputtype="text"name="subject"id="subject"value={this.state.message.subject}onChange={this.onChange}/><label htmlFor="body">Message:</label><textareastyle={{height: `125px`,}}name="body"id="body"value={this.state.message.body}onChange={this.onChange}/><buttonstyle={{marginTop: `7px`,}}type="submit"disabled={this.state.submitting}onClick={this.onClick}>Send message</button></form></>)}}export default ContactForm
Nous avons ajouter un click handler sur le bouton de soumission du formulaire.
Il ne nous reste plus qu’à tester notre formulaire.
Si tout se passe bien l’envoi du formulaire va déclencher la fonction serverless sur Twilio qui va construire le mail et l’envoyer via SendGrid.
Le serverless et la coordination de service entre eux sont à la base de beaucoup de système aujourd’hui. N’hésitez pas à me contacter si vous rencontrez des difficultés dans sa compréhension ou sa mise en oeuvre.
Sélectionnez les meilleures technologies compte tenu des besoins et de la taille de votre société peut-être une tâche difficile.
N’hésitez pas à me contacter pour que je vous apporte les meilleurs conseils.