import { getSecret } from "neo/secrets";
const CUSTOM_DOMAIN = "wallet.brand.com";
const TENANTID = "brand";
// Adobe IMS (identifiants client OAuth2)
// Votre runtime fournit un `fetch` personnalisé capable d’exécuter des flux OAuth d’identifiants client.
const IMS_TOKEN_URL = "https://ims-na1.adobelogin.com/ims/token/v3";
/**
* @typedef {Object} EmailData
* @property {string} Subject - Ligne d’objet rendue.
* @property {string} Body - Contenu du corps rendu.
*/
/**
* Envoie un e-mail en utilisant le nom de modèle et les données fournis.
* L’appelant fournit les cultures prises en charge et un callback
* pour construire le contenu de l’e-mail rendu.
*
* @param {string} recipient - Adresse e-mail cible.
* @param {string} emailTemplate - Nom du modèle à rendre.
* @param {Object.<string, any>} data - Données du modèle transmises au script.
* @param {string[]} cultures - Noms des cultures disponibles fournis par le fournisseur de cultures.
* @param {(templateName: string) => Promise<EmailData>} buildEmail
* Callback qui renvoie le contenu final de l’e-mail rendu.
*
* @returns {Promise<void>}
*/
async function sendEmail(recipient, emailTemplate, data, cultures, buildEmail) {
const email = recipient;
const countryCode = data["country"] || "fr";
const language = `${cultures[0]?.toLowerCase()?.substring(0, 2) || "fr"}_${countryCode.toLowerCase()}`;
const customerId = data["id.customerId"];
if (!customerId) {
throw new Error('Champ "id.customerId" manquant dans les données de l’e-mail.');
}
// URL sur laquelle le client doit cliquer pour télécharger sa Carte.
// Vous pouvez modifier le chemin pour l’adapter à votre disposition de distribution.
const url = `https://${CUSTOM_DOMAIN}/${TENANTID}/Carte?id.customerId=${encodeURIComponent(customerId)}`;
// Conservez éventuellement le rendu The Wallet Crew disponible.
// Si votre modèle AJO est entièrement géré dans Adobe, vous pouvez supprimer ceci.
const rendered = await buildEmail(emailTemplate);
// La configuration AJO doit être fournie sous forme de secrets.
// Utilisez une URL complète pour éviter de coder en dur des chemins propres au produit dans ce script.
// Exemple (varie selon la configuration) : "https://platform.adobe.io/journey/execute/<CAMPAIGN_OR_JOURNEY_ID>"
const ajoTriggerUrl = await getSecret("adobe-ajo-triggerUrl");
const orgId = await getSecret("adobe-orgId");
const sandboxName = await getSecret("adobe-sandboxName");
const clientId = await getSecret("adobe-clientId");
const clientSecret = await getSecret("adobe-clientSecret");
// Conservez la portée configurable. Les différentes configurations Adobe exigent des portées différentes.
// Exemples vus dans la pratique : "openid,AdobeID"
let scope = "openid,AdobeID";
try {
scope = (await getSecret("adobe-scope")) || scope;
} catch (e) {
// Secret facultatif. Conservez la portée par défaut.
}
// Votre `fetch` d’exécution gère les identifiants client OAuth et attache le jeton.
// Cela évite d’appeler IMS manuellement puis de transmettre le jeton Bearer.
const result = await fetch(ajoTriggerUrl, {
Method: "POST",
Authentication: {
mode: "OAuth2.0",
grantType: "clientCredentials",
sendCredentialsAsFormParams: true,
accessTokenUrl: IMS_TOKEN_URL,
clientId,
clientSecret,
scope,
},
Headers: {
"x-api-key": clientId,
"x-gw-ims-org-id": orgId,
"x-sandbox-name": sandboxName,
"Content-Type": "application/json",
},
Body: JSON.stringify({
// La forme exacte de la charge utile doit correspondre à la configuration de votre campagne/parcours AJO déclenché(e) par API.
// Gardez ce contrat stable entre votre script et votre actif AJO.
recipient: {
email,
language,
},
context: {
// Variable minimale pour un modèle géré par Adobe :
url,
// Variables optionnelles si vous souhaitez réutiliser le rendu The Wallet Crew dans Adobe :
subject: rendered.Subject,
body: rendered.Body,
// Métadonnées utiles pour le routage / le débogage :
template: emailTemplate,
customerId,
},
}),
ThrowOnError: false,
});
if (result.StatusCode < 200 || result.StatusCode >= 300) {
throw new Error(`L’appel du déclencheur AJO a échoué (${result.StatusCode}) : ${result.ResponseText}`);
}
}
export default function (context) {
context.register("runtime.scriptable.emailEngine", {
SendEmail: sendEmail,
});
}
Comment tester cela sans envoyer d’e-mails à de vrais clients ?
Utilisez un sandbox AJO lorsqu’il est disponible. Sinon, limitez les tests aux adresses internes et créez un parcours ou une campagne « test » dédié(e). Conservez le même contrat de charge utile que la production afin d’éviter les ruptures de schéma de dernière minute.