[FIX] EmailService: aggiungi sendViaTemplate() (era mancante - Edit fallito in de09af6)
Il metodo sendViaTemplate() non era stato salvato (Edit silenziosamente fallito): requestOtp() del portale chiamava un metodo inesistente -> errore inghiottito dal try/catch -> OTP MAI inviato. Ora presente: POST /api/emails/send con template + data (campo canonico relay AgileHub) + alias vars, senza logEmail (OTP fuori da email_log). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ccea3ab7b7
commit
006f86387b
@ -118,6 +118,72 @@ class EmailService
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invia via TEMPLATE del relay AgileHub (POST /api/emails/send), NON send-raw.
|
||||
* A differenza di send()/sendViaRelay() NON chiama logEmail(): pensato per
|
||||
* messaggi che non devono lasciare traccia del contenuto a DB (es. OTP del
|
||||
* portale fornitore). Il corpo e' renderizzato lato relay da template+data.
|
||||
*
|
||||
* @param string $to destinatario
|
||||
* @param string $template slug template registrato sul relay (es. "supplier_otp")
|
||||
* @param array $vars variabili di sostituzione del template
|
||||
* @param string|null $brandName nome committente per branding (opzionale)
|
||||
* @return bool true se il relay ha accettato (HTTP 2xx + success)
|
||||
*/
|
||||
public function sendViaTemplate(string $to, string $template, array $vars, ?string $brandName = null): bool
|
||||
{
|
||||
$base = rtrim(self::env('EMAIL_MS_URL', 'https://agilehub.agile.software/api/emails'), '/');
|
||||
$key = self::env('INTERNAL_EMAIL_KEY', '');
|
||||
|
||||
if ($key === '') {
|
||||
error_log('[EmailService] INTERNAL_EMAIL_KEY non configurata: template "' . $template . '" saltato per ' . self::maskEmail($to));
|
||||
return false;
|
||||
}
|
||||
|
||||
$payload = json_encode([
|
||||
'to' => $to,
|
||||
'template' => $template,
|
||||
'data' => $vars, // campo canonico standard email-relay AgileHub (Handlebars)
|
||||
'vars' => $vars, // alias difensivo (alcune versioni del relay leggono "vars")
|
||||
'product' => 'nis2',
|
||||
'brand_name' => $brandName,
|
||||
'priority' => 'transactional',
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$ch = curl_init($base . '/send'); // endpoint TEMPLATE (NON /send-raw)
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $payload,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 10,
|
||||
CURLOPT_CONNECTTIMEOUT => 5,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-Type: application/json',
|
||||
'X-Internal-Key: ' . $key,
|
||||
],
|
||||
]);
|
||||
$body = curl_exec($ch);
|
||||
$errno = curl_errno($ch);
|
||||
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($errno !== 0) {
|
||||
error_log('[EmailService] relay template unreachable (' . curl_strerror($errno) . ') per ' . self::maskEmail($to));
|
||||
return false;
|
||||
}
|
||||
if ($httpCode < 200 || $httpCode >= 300) {
|
||||
error_log('[EmailService] relay template HTTP ' . $httpCode . ' per ' . self::maskEmail($to) . ': ' . substr((string) $body, 0, 200));
|
||||
return false;
|
||||
}
|
||||
$decoded = json_decode((string) $body, true);
|
||||
if (is_array($decoded) && array_key_exists('success', $decoded) && !$decoded['success']) {
|
||||
error_log('[EmailService] relay template success=false per ' . self::maskEmail($to) . ': ' . substr((string) $body, 0, 200));
|
||||
return false;
|
||||
}
|
||||
// NESSUN logEmail(): il contenuto (OTP) non deve finire in email_log.
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Maschera l'email per i log (GDPR): m***@dominio.it. */
|
||||
private static function maskEmail(string $email): string
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user