Envoi d'email avec Flutter / Directus

Hello World !

actuellement en train de développer une application Flutter avec des Services Directus je me retrouve avec la problématique d’envoi d’emails.

Ayant l’habitude d’envoyer des emails avec des Services Java, je ne sais pas comment m’y prendre avec Flutter/Directus.

L’application est de type Workflow. C’est à dire, un envoi d’email automatique à chaque étape du processus (quand il y a une création ou une modification d’occurrence dans une table).

Du coup, je me retrouve avec deux possibilités : laquelle choisir … ?!?

1/ côté client :
appeler le service directus pour créer/modifier les occurrence en base
et, si tout se passe bien, envoyer, à partir du package flutter sendgrid_mailer, un email à l’utilisateur.

2/ côté serveur :
appeler le service directus pour créer/modifier les occurrence en base et, envoyer également un email à partir de directus.
Je ne sais pas encore comment m’y prendre (ce n’est pas détaillé dans le cours directus) mais je peux m’y pencher :slight_smile:

Pour l’envoi d’email, je comptais partir sur l’api SendGrid mais si vous avez d’autres pistes je suis preneur :slight_smile:

Merci beaucouppppppppppppppp

1 « J'aime »

Finalement, après une recherche approfondie, je suis parti sur cette solution :

Création d’une API Directus (endpoints) qui me servira uniquement pour l’envoi d’email à partir de Flutter.

En paramètre, j’envoi l’email et, en fonction de la route appelée, le type d’email est différent :

module.exports = function registerEndpoint(router, { services, exceptions }) {
          const { ItemsService } = services;
          const { ServiceUnavailableException } = exceptions;

          router.get('/workflowA', (req, res, next) => {
                  const sgMail = require('@sendgrid/mail')
                  sgMail.setApiKey(process.env.SENDGRID_API_KEY)
                  const msg = {
                            to: req.body.email,
                            from: '[email protected]',
                            subject: 'Workflow A',
                            text: 'Bienvenue dans le Workflow A',
                            html: '<strong>Vive Node.js</strong>',
                  }
                  sgMail
                    .send(msg)
                        .then((results) => res.json(results))
                        .catch((error) => {
                                        return next(new ServiceUnavailableException(error.message));
                                      });
                    });

          router.get('/workflowB', (req, res, next) => {
                  const sgMail = require('@sendgrid/mail')
                  sgMail.setApiKey(process.env.SENDGRID_API_KEY)
                  const msg = {
                            to: req.body.email,
                            from: '[email protected]',
                            subject: 'Workflow B',
                            text: 'Bienvenue dans le Workflow B',
                            html: '<strong>Vive Node.js</strong>',
                  }
                  sgMail
                    .send(msg)
                        .then((results) => res.json(results))
                        .catch((error) => {
                                        return next(new ServiceUnavailableException(error.message));
                                      });
                    });

};

prochaine mission … trouver un moyen de sécuriser cette api avec un token :slight_smile:

1 « J'aime »

Changement de programme :slight_smile:

j’avais prévu, à partir de Flutter :

  • d’appeler un service personnalisé directus qui appelerait l’api sendgrid

Finalement, je viens de tester une autre solution : qui m’évite de passer par une api « passe-plat » :

  • appeler, à partir de Flutter, directement l’api de Mailjet (entreprise française) :
    on peut même créer un template et l’appeler directement dans l’api :slight_smile:
    (je ne sais pas si sendgrid le fait également)
https://api.mailjet.com/v3.1/send
{
    "Messages":[
            {
                  "From": {
                           "Email": "[email protected]",
                           "Name": "Contact"
                  },
                  "To": [
                        {
                         "Email": "[email protected]",
                         "Name": "Pseudo"
                        }
                  ],
                  "TemplateID": xxxxxxx
              } 
         ] 
}

Seul problème :
dans la partie ‹ Authorization › de l’api, on renseigne les clés de l’Api et j’ai cru comprendre, dans le live d’hier de Maxime qu’une personne mal intentionnée, pouvait intercepter les trames de l’appel et récupérer les clés :frowning:

Du coup, avec un petit sujet sur la messagerie, j’ai pu apprendre plein de choses sur Directus qui me resserviront (Endpoints, Hooks…)

Encore un changement de programme :slight_smile:

comme vu plus haut, un appel de Flutter vers Directus pour mettre à jour la base de données et, un appel de Flutter vers l’api Mailjet pour envoyer un mail de confirmation à l’utilisateur.

A mon sens, ce n’est pas logique, et pas très sécurisé !

Du coup, je viens de tester une autre solution :

un hook dans directus pour intercepter les mises à jour de la base de données !
En fonction de la table et de l’action, je peux envoyer automatiquement un mail avec le template qui va bien :slight_smile:
et tout se passe côté serveur !

bon j’arrête de vous embêter avec mes problèmes :slight_smile:

Au contraire. C’est très intéressant de suivre la démarche !
Merci pour ton retour :slightly_smiling_face:

Merci @Mrt1 :slight_smile:

du coup, à force, j’apprends plein de choses :slight_smile:
utiliser Hook et EndPoints dans Directus…
utiliser une solution de messagerie

Et ce matin, je me suis mis à faire du TypeScript (comme Maxime) :slight_smile:

au lieu d’utiliser les répertoires extensions/hooks et endpoints générés par Directus, j’ai créé un projet npm :
npm init directus-extension

dans ce projet (répertoire src), je créé mon endpoints en typescript et je le build (npm run build)
ensuite je copie le fichier javascript généré dist/index.js dans mon répertoire endpoints de directus
(je ne sais pas si c’est la bonne facon de faire mais ca marche)

et la … vous êtes censés vous poser la question … pourquoi être passé en typescript ?!?
PARCEQUE … en JS je n’arrive pas à faire fonctionner mon endpoints Mailjet et … en TS non plus :frowning:
Dans les deux cas, le mail arrive à destination (c’est déjà beaucoup) mais je n’obtiens aucune réponse du Service : Could not send request au bout de plusieurs secondes :frowning:

avec la solution sendgrid, j’obtenais une réponse en appel direct et dans mon endpoints
avec la solution mailjet, j’obtiens une réponse en appel direct mais pas dans mon endpoints (JS et TS) :frowning:
je ne comprends pas :frowning:

une idée ?
:slight_smile:

import { defineEndpoint } from '@directus/extensions-sdk';
import Mailjet, { SendEmailV3_1 } from 'node-mailjet'

export default defineEndpoint((router) => {
        router.get('/', (_req, res) =>

                  const mailjet = new Mailjet({
                              apiKey: process.env.MJ_APIKEY_PUBLIC,
                                  apiSecret: process.env.MJ_APIKEY_PRIVATE
                  });
                  (async () => {
                            const data: SendEmailV3_1.IBody = {
                                        Messages: [
                                              {
                                              From: {
                                               Email: '[email protected]',
                                        },
                                                To: [
                                          {
                                              Email: '[email protected]',
                                                        },
                                                        ],
Subject: 'Your email flight plan!',
HTMLPart: '<h3>Dear passenger, welcome to Mailjet!</h3><br />May the delivery force be with you!',
TextPart: 'Dear passenger, welcome to Mailjet! May the delivery force be with you!',
},
 ],
   };
     const result = await mailjet
         .post('send', { version: 'v3.1' })
             .request<SendEmailV3_1.IResponse>(data);
               const { Status } = result.body.Messages[0];
                  })();
                  );
});

Hello world !

absent pendant plusieurs jours, je vous donne la solution que j’ai choisie … après moulte réflexions et diverses embuches :slight_smile:

SUJET CLOS !!! :slight_smile:

Création d’une API Directus qui appelle l’api Mailjet :
elle fonctionne et me répond correctement :slight_smile:

module.exports = function registerEndpoint(router, context) {
   router.post('/', (req, res, next) => {
      const payload = req.body;
      const Mailjet = require ('node-mailjet');
      const mailjet = Mailjet.apiConnect(process.env.MJ_APIKEY_PUBLIC, process.env.MJ_APIKEY_PRIVATE);
      
      const request = mailjet
         .post("send", {'version': 'v3.1'})
         .request({
            "Messages":[{
                 "From": {
                       "Email": "[email protected]",
                       "Name": "xxxxx"
                  },
           "To": [{
                "Email": payload.email,
            }],
            "TemplateID": 4093508,}]})
         .then((resultat) => {console.log(resultat.response.status);

         res.status(resultat.response.status).end()})
   });
};
2 « J'aime »