163 lines
6 KiB
JavaScript
163 lines
6 KiB
JavaScript
#!/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);
|
||
}
|
||
})();
|