feat(correo): SMTP desde la configuracion del panel, y fuera el proxy
Dos cambios que van juntos porque atacan el mismo fallo: en las webs de Forge no
salia ni un correo.
1. LOS CAMPOS DEL PANEL AHORA SIRVEN PARA ALGO
La tabla `configuracion` lleva desde siempre email_smtp, email_host,
email_port, email_secure, email_username, email_password, email_from y
email_from_name... y no los leia NADIE. Aparecian solo en el schema: el panel
te dejaba rellenarlos, se guardaban en la BD, y el envio seguia usando los
defaults de la clase —con la contrasena VACIA— o lo que hubiera a mano en
lib/variables.php. Un formulario decorativo.
`cargarSmtpDeConfiguracion()` los vuelca sobre la clase cuando el check
email_smtp esta marcado y email_host tiene valor. Se llama desde send() antes
de enviar, no solo desde send_email().
El schema de `configuracion` es PER-WEB y no todas tienen esas columnas
(villagrancanaria no las tiene): se lee con @ sobre el array, asi que una web
sin ellas se comporta exactamente igual que antes.
2. FUERA EL PROXY
send_email_coco_proxy() mandaba a cocosolution.com/?sendQuantumEmail=1. Se
quita por dos motivos medidos hoy:
- Ese endpoint RECHAZA TODO. Probados seis formatos (JSON crudo,
form-urlencoded, anidado, y el payload cifrado por tres vias) y siempre
contesta {"error":1,"message":"Need SMTP data and Params"}, incluso con
smtp_data completo. Es decir: ninguna web de Forge ha podido enviar por
ahi, y eso es anterior a los cambios de hoy.
- No hace falta. El container alcanza los SMTP por su cuenta: verificado
contra smtp.gmail.com:465 y :587 y smtp.ionos.es:465, con banner 220.
PHPMailer conecta solo cuando $smtp = true.
Se va con el encrypt(), que solo usaba el proxy y en una linea que ya estaba
comentada dentro de esa misma funcion. Cero llamadas a ambas fuera de la
clase, comprobado en los cuatro arboles.
Verificado en cdn-ecommerce: con el check marcado, la traza pasa de
"smtp=no host=smtp.gmail.com pass=VACIA" a "smtp=si host=<el del panel>", y
PHPMailer intenta la conexion. Falta solo poner credenciales de verdad.
OJO, queda pendiente: send_email() devuelve NULL siempre, tanto si entrega como
si no. Un fallo de envio es hoy indistinguible de un exito.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3615d85bc0
commit
e4ab0567df
@@ -163,35 +163,30 @@ class CocoEmail {
|
||||
|
||||
if (!$subject && $record) $subject = t($record, self::$field_subject);
|
||||
|
||||
// El correo sale por dos caminos segun el entorno, y esta era la unica
|
||||
// divergencia real entre el core de Forge y el de las webs legacy:
|
||||
// web-base mandaba SIEMPRE por el proxy y core_client SIEMPRE directo,
|
||||
// asi que el fichero no se podia unificar sin cambiarle el
|
||||
// comportamiento a media plataforma. Con la condicion delante, el mismo
|
||||
// fichero vale para los dos canales.
|
||||
//
|
||||
// En local/test hace falta el proxy: el envio directo no sale de ahi.
|
||||
// En produccion se mantiene el directo, que es lo que han hecho siempre
|
||||
// esas webs.
|
||||
//
|
||||
// Mismo criterio de deteccion que header.php:81 — un `.acai` en la raiz
|
||||
// de la web marca entorno local. Se comprueba en linea a proposito, sin
|
||||
// depender de que otro fichero haya definido nada (ver el commit
|
||||
// f81c5a2 de web-base, "el entorno se detecta en linea").
|
||||
// Desde cms/lib/classes/ la raiz esta tres niveles arriba.
|
||||
$esEntornoLocal = is_file(dirname(__FILE__) . '/../../../.acai');
|
||||
// Si la web tiene SMTP configurado (panel o variables.php), esas
|
||||
// credenciales mandan. Va aqui, antes del bucle, para que valga tanto si
|
||||
// se envia una vez como a varios destinatarios.
|
||||
self::cargarSmtpDeConfiguracion();
|
||||
|
||||
// Se devuelve array en los dos caminos. El directo no devolvia nada
|
||||
// (core_client) y el del proxy si (web-base): unificar hacia el array es
|
||||
// aditivo — quien ignoraba el retorno lo sigue ignorando.
|
||||
// Envio DIRECTO, siempre. Aqui hubo un proxy (send_email_coco_proxy, a
|
||||
// cocosolution.com/?sendQuantumEmail=1) que se quito el 2026-09-03 por
|
||||
// dos motivos comprobados:
|
||||
//
|
||||
// 1. Su endpoint rechaza TODO. Probados seis formatos —JSON crudo,
|
||||
// form-urlencoded, anidado, y el payload cifrado por tres vias
|
||||
// distintas— y siempre contesta {"error":1,"message":"Need SMTP
|
||||
// data and Params"}, incluso con smtp_data completo.
|
||||
// 2. No hacia falta: el container de las webs alcanza los servidores
|
||||
// SMTP por su cuenta (verificado contra smtp.gmail.com:465 y :587 y
|
||||
// smtp.ionos.es:465, con banner 220). PHPMailer conecta solo.
|
||||
//
|
||||
// Con $smtp = true y credenciales, PHPMailer habla SMTP directo y no
|
||||
// necesita MTA local. Sin credenciales cae a mail(), que en un hosting
|
||||
// normal entrega por su postfix y en el container de Forge NO puede
|
||||
// (no hay /usr/sbin/sendmail): ahi la unica salida es configurar el SMTP.
|
||||
$result = [];
|
||||
foreach ($to as $destinatario) {
|
||||
if ($esEntornoLocal) {
|
||||
$resultString = self::send_email_coco_proxy($destinatario, $subject, $content);
|
||||
$result[] = @json_decode($resultString,true) ?: ["success" => false, "message" => "Error decoding response", "raw_response" => $resultString];
|
||||
} else {
|
||||
$result[] = self::send_email($destinatario, $subject, $content);
|
||||
}
|
||||
$result[] = self::send_email($destinatario, $subject, $content);
|
||||
}
|
||||
self::$attach_files = [];
|
||||
return $result;
|
||||
@@ -282,50 +277,55 @@ class CocoEmail {
|
||||
}, array_change_key_case($arr));
|
||||
}
|
||||
|
||||
function encrypt($string, $key) {
|
||||
$result = '';
|
||||
for($i=0; $i<strlen($string); $i++) {
|
||||
$char = substr($string, $i, 1);
|
||||
$keychar = substr($key, ($i % strlen($key))-1, 1);
|
||||
$char = chr(ord($char)+ord($keychar));
|
||||
$result.=$char;
|
||||
|
||||
|
||||
/**
|
||||
* Vuelca las credenciales SMTP de la tabla `configuracion` sobre la clase.
|
||||
*
|
||||
* La tabla lleva desde siempre los campos email_smtp, email_host,
|
||||
* email_port, email_secure, email_username, email_password, email_from y
|
||||
* email_from_name... y NADIE los leia: estaban solo en el schema, o sea que
|
||||
* el panel te dejaba rellenarlos, se guardaban en la BD y el envio seguia
|
||||
* usando los defaults de esta clase (con la contrasena VACIA) o lo que
|
||||
* hubiera a mano en lib/variables.php. Un formulario decorativo.
|
||||
*
|
||||
* El check `email_smtp` es quien manda, que es como se lee la interfaz:
|
||||
* marcado -> SMTP con estas credenciales
|
||||
* sin marcar -> no se toca nada y el envio sale por mail() del sistema
|
||||
*
|
||||
* Se exige ADEMAS que email_host tenga valor: un check marcado con los
|
||||
* campos vacios dejaria a PHPMailer sin servidor, y fallar por una
|
||||
* configuracion a medias es peor que no aplicarla.
|
||||
*
|
||||
* OJO: el schema de `configuracion` es PER-WEB y no todas las webs tienen
|
||||
* estas columnas (villagrancanaria, por ejemplo, no las tiene). Por eso se
|
||||
* lee con @ sobre el array: si la columna no existe la clave no esta, el if
|
||||
* no entra y esa web se comporta igual que siempre.
|
||||
*
|
||||
* Se llama desde send() ANTES de elegir camino, no solo desde send_email():
|
||||
* en las webs de Forge el envio sale por el proxy y send_email() no llega a
|
||||
* ejecutarse nunca, asi que ponerlo solo alli dejaba fuera justo a las webs
|
||||
* que lo necesitan. El proxy tambien reenvia con este smtp_data.
|
||||
*/
|
||||
static function cargarSmtpDeConfiguracion() {
|
||||
global $configuracionRecord;
|
||||
|
||||
if (!isset($configuracionRecord)){
|
||||
$configuracionRecord = @CocoDB::get("configuracion","num != 0")[0];
|
||||
}
|
||||
return base64_encode($result);
|
||||
}
|
||||
|
||||
static function send_email_coco_proxy($destinatario="soporte@cocosolution.com", $asunto="Error al enviar correo", $contenido="", $respuesta="") {
|
||||
if (!@$configuracionRecord["email_smtp"] || !@$configuracionRecord["email_host"]) return;
|
||||
|
||||
$data = [
|
||||
"smtp_data" => self::$smtp_data,
|
||||
"mail_data" => self::$mail_data,
|
||||
"replyTo" => self::$replyTo,
|
||||
"send_copy_to" => self::$send_copy_to,
|
||||
"params" => [
|
||||
"to" => $destinatario,
|
||||
"subject" => $asunto,
|
||||
"body" => $contenido
|
||||
],
|
||||
"bloqued_emails" => self::$bloqued_emails,
|
||||
"encode_with_base64" => self::$encode_with_base64,
|
||||
"template" => self::$template,
|
||||
"styles" => self::$styles,
|
||||
"header" => self::$header,
|
||||
"footer" => self::$footer
|
||||
self::$smtp = true;
|
||||
self::$smtp_data = [
|
||||
"host" => $configuracionRecord["email_host"],
|
||||
"secure" => @$configuracionRecord["email_secure"] ?: "ssl",
|
||||
"port" => @$configuracionRecord["email_port"] ?: 465,
|
||||
"username" => @$configuracionRecord["email_username"],
|
||||
"password" => @$configuracionRecord["email_password"],
|
||||
"from" => @$configuracionRecord["email_from"] ?: @$configuracionRecord["email_username"],
|
||||
"from_name" => @$configuracionRecord["email_from_name"] ?: @$configuracionRecord["tienda_nombre_empresa"],
|
||||
];
|
||||
|
||||
//$encryptData = self::encrypt(json_encode($data), "Analiticaempresas17");
|
||||
|
||||
$opts = array('http' =>
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'header' => 'Content-Type: application/json',
|
||||
'content' => json_encode($data)
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$result = file_get_contents("https://cocosolution.com/?sendQuantumEmail=1", false, $context);
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function send_email($destinatario="soporte@cocosolution.com", $asunto="Error al enviar correo", $contenido="", $respuesta="") {
|
||||
@@ -337,6 +337,8 @@ class CocoEmail {
|
||||
$configuracionRecord = @CocoDB::get("configuracion","num != 0")[0];
|
||||
}
|
||||
|
||||
self::cargarSmtpDeConfiguracion();
|
||||
|
||||
require_once __DIR__ . '/../vendor/PHPMailer/PHPMailerAutoload.php';
|
||||
|
||||
/*$mensaje = "
|
||||
|
||||
Reference in New Issue
Block a user