espace-paie-odentas/scripts/send-test-email.js

163 lines
6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
const { readFileSync, writeFileSync, existsSync, mkdirSync } = require('fs');
const { join } = require('path');
const Handlebars = require('handlebars');
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses');
function parseArgs() {
const args = process.argv.slice(2);
const out = {};
for (let i = 0; i < args.length; i++) {
const a = args[i];
if (a === '--template' && args[i+1]) { out.template = args[++i]; }
else if (a === '--sample' && args[i+1]) { out.sample = args[++i]; }
else if (a === '--to' && args[i+1]) { out.to = args[++i]; }
else if (a === '--send') { out.send = true; }
else if (a === '--data' && args[i+1]) { out.dataFile = args[++i]; }
}
return out;
}
const opts = parseArgs();
const templateName = opts.template || 'universal-template.html';
const sampleType = opts.sample || 'annulation';
const toEmail = opts.to || process.env.TEST_TO_EMAIL || null;
const doSend = !!opts.send;
if (!toEmail && doSend) {
console.error('To send a real email you must pass --to <email> or set TEST_TO_EMAIL env var');
process.exit(1);
}
const templatePath = join(process.cwd(), 'templates-mails', templateName);
if (!existsSync(templatePath)) {
console.error('Template not found:', templatePath);
process.exit(1);
}
const templateSrc = readFileSync(templatePath, 'utf-8');
const template = Handlebars.compile(templateSrc);
const samples = {
annulation: {
subject: 'CDDU annulé',
preheaderText: 'CDDU annulé pour Jean Dupont · Réf CDD-123',
title: 'CDDU annulé',
mainMessage: 'Votre contrat CDDU a été annulé.',
closingMessage: "Pour votre sécurité, ne partagez jamais ce message.",
ctaText: "Accès à l'Espace Paie",
ctaUrl: 'https://example.com/contrat/123',
footerText: 'Vous recevez cet e-mail car vous êtes client de Odentas.',
logoUrl: 'https://newstaging.odentas.fr/wp-content/uploads/2025/08/Odentas-Logo-Bleu-Fond-Transparent-4-1.png',
contractReference: 'CDD-123',
employeeName: 'Jean Dupont',
profession: 'Développeur',
startDate: '2025-10-01',
showCard: true,
cardTitle: 'Détails du contrat',
cardRows: [
[ { label: 'Référence', value: 'CDD-123' } ],
[ { label: 'Salarié', value: 'Jean Dupont' } ],
[ { label: 'Poste', value: 'Développeur' } ],
[ { label: 'Date de début', value: '2025-10-01' } ]
],
showChips: false,
headerColor: '#efc543',
titleColor: '#0F172A',
buttonColor: '#efc543',
cardBorder: '1px solid #E5E7EB',
cardBackgroundColor: '#F8FAFC',
cardTitleColor: '#0F172A',
alertIndicatorColor: '#EF4444',
supportUrl: 'https://example.com/support',
userName: 'Jean Dupont',
companyName: 'Ma Structure',
employerCode: 'EMP-456',
productionName: 'Production A',
textFallback: 'CDDU annulé Réf CDD-123 pour Jean Dupont.'
}
};
let sampleData = samples[sampleType] || samples.annulation;
// allow loading a JSON data file with overrides
if (opts.dataFile) {
try {
const raw = readFileSync(join(process.cwd(), opts.dataFile), 'utf8');
const userData = JSON.parse(raw);
sampleData = { ...sampleData, ...userData };
} catch (err) {
console.warn('Unable to read/parse data file, ignoring:', opts.dataFile);
}
}
const rendered = template(sampleData);
// apply data-* attributes to inline styles (simple)
function applyDataAttrAsStyle(html, dataAttr, cssProp) {
// append to existing style
html = html.replace(new RegExp(`(<[^>]*?)${dataAttr}="([^"]*)"([^>]*style=\")([^"]*)(\"[^>]*>)`, 'g'), (_m, prefix, val, mid, styleValue, suffix) => {
return `${prefix}${mid}${styleValue} ${cssProp}:${val};${suffix}`;
});
// add style when missing
html = html.replace(new RegExp(`(<[^>]*?)${dataAttr}="([^"]*)"([^>]*?)>`, 'g'), (_m, prefix, val, suffix) => {
return `${prefix} style="${cssProp}:${val};"${suffix}>`;
});
html = html.replace(new RegExp(`${dataAttr}="[^"]*"`, 'g'), '');
return html;
}
let finalHtml = rendered;
['data-header-color','data-alert-indicator','data-title-color','data-card-border','data-card-bg','data-card-title-color','data-alert-title-color','data-alert-text-color','data-button-color'].forEach(attr => {
const css = {
'data-header-color':'background',
'data-alert-indicator':'background',
'data-title-color':'color',
'data-card-border':'border',
'data-card-bg':'background',
'data-card-title-color':'color',
'data-alert-title-color':'color',
'data-alert-text-color':'color',
'data-button-color':'background'
}[attr];
finalHtml = applyDataAttrAsStyle(finalHtml, attr, css);
});
if (!existsSync(join(process.cwd(), 'tmp'))) mkdirSync(join(process.cwd(), 'tmp'));
writeFileSync(join(process.cwd(), 'tmp', 'send-preview.html'), finalHtml, 'utf8');
console.log('Wrote preview to tmp/send-preview.html');
if (!doSend) {
console.log('Dry-run (not sending). To actually send, run with --send and set AWS env vars and --to <recipient>');
console.log('Env required for real send: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION (optional), FROM_EMAIL');
process.exit(0);
}
// Real send path
(async () => {
try {
const region = process.env.AWS_REGION || 'eu-west-3';
const ses = new SESClient({ region, credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
}});
const source = process.env.FROM_EMAIL || process.env.AWS_SES_FROM;
if (!source) throw new Error('Set FROM_EMAIL or AWS_SES_FROM env var to a verified sender');
const params = {
Source: source,
Destination: { ToAddresses: [toEmail] },
Message: {
Subject: { Data: sampleData.subject || 'Test email', Charset: 'UTF-8' },
Body: { Html: { Data: finalHtml, Charset: 'UTF-8' }, Text: { Data: sampleData.textFallback || '', Charset: 'UTF-8' } }
}
};
const cmd = new SendEmailCommand(params);
const res = await ses.send(cmd);
console.log('SES send response:', res);
} catch (err) {
console.error('Error sending via SES:', err);
process.exit(1);
}
})();