Desarrollo y bases de datos

Generar informes CSV de correo y cron desde cPanel

Revisado el 8 min de lectura cpanel api reportes

Puedes utilizar UAPI para inventariar buzones, reenviadores y respuestas automáticas de tu cuenta. Los ejemplos siguientes se ejecutan con PHP 8 desde SSH; no son páginas para publicar en la web. Consulta antes la introducción a UAPI.

Preparar una carpeta privada

Guarda los scripts y sus resultados fuera de public_html y de las raíces de tus otros dominios, por ejemplo en /home/usuario_cpanel/reportes. Restringe el acceso a tu usuario: los informes contienen direcciones y pueden incluir comandos con información privada.

Antes de automatizar, ejecuta cada llamada de consulta en tu cuenta y confirma qué campos devuelve la versión instalada. Las funciones dependen de los servicios y permisos disponibles. Un informe vacío no demuestra que no existan cuentas si la llamada ha fallado.

Funciones comunes

Guarda este archivo como funciones.php en la carpeta privada. Comprueba que exec esté disponible en el PHP de la terminal. La función solo permite las consultas fijas utilizadas por estos ejemplos y comprueba tanto el proceso como el estado UAPI.

<?php

function ejecutar(string $comando): string
{
    $lineas = [];
    $codigo = 0;
    exec($comando, $lineas, $codigo);
    if ($codigo !== 0) {
        throw new RuntimeException('La consulta no terminó correctamente.');
    }
    return implode("\n", $lineas);
}

function uapi(string $funcion, array $parametros = []): array
{
    $permitidas = [
        'list_pops_with_disk', 'list_forwarders',
        'list_auto_responders', 'get_auto_responder',
    ];
    if (!in_array($funcion, $permitidas, true)) {
        throw new InvalidArgumentException('Función no admitida.');
    }
    $comando = '/usr/local/cpanel/bin/uapi --output=json Email '
        . escapeshellarg($funcion);
    foreach ($parametros as $clave => $valor) {
        if (!in_array($clave, ['domain', 'email'], true)) {
            throw new InvalidArgumentException('Parámetro no admitido.');
        }
        $comando .= ' ' . escapeshellarg($clave . '=' . $valor);
    }
    $respuesta = json_decode(ejecutar($comando), true, 512, JSON_THROW_ON_ERROR);
    $resultado = $respuesta['result'] ?? [];
    if ((int) ($resultado['status'] ?? 0) !== 1) {
        throw new RuntimeException('UAPI rechazó la consulta; revisa permisos y parámetros.');
    }
    if (!is_array($resultado['data'] ?? null)) {
        throw new RuntimeException('UAPI devolvió un formato de datos inesperado.');
    }
    return $resultado['data'];
}

function escribirCsv(array $filas): void
{
    foreach ($filas as $fila) {
        $valores = array_map(static function ($valor): string {
            $texto = (string) ($valor ?? '');
            // Evita que textos del informe se interpreten como fórmulas.
            if (preg_match('/^[\s]*[=+@-]/u', $texto)) {
                $texto = "'" . $texto;
            }
            return $texto;
        }, $fila);
        if (fputcsv(STDOUT, $valores, ';', '"', '') === false) {
            throw new RuntimeException('No se pudo escribir el CSV.');
        }
    }
}

fputcsv trata correctamente los delimitadores, comillas y saltos de línea. Importa además las columnas como texto en la hoja de cálculo cuando proceda; evita abrir informes de origen desconocido con fórmulas habilitadas.

Buzones y uso de espacio

Guarda como buzones.php:

<?php
require __DIR__ . '/funciones.php';

$filas = [['Email', 'Espacio usado', 'Cuota']];
foreach (uapi('list_pops_with_disk') as $cuenta) {
    $filas[] = [
        $cuenta['email'] ?? '',
        $cuenta['humandiskused'] ?? '',
        $cuenta['humandiskquota'] ?? '',
    ];
}
escribirCsv($filas);

Los campos de espacio están preparados para lectura humana y pueden incluir unidades o un valor de cuota ilimitada. No los sumes como si fueran números de bytes. Consulta los campos disponibles en list_pops_with_disk si necesitas otro formato.

Reenviadores de un dominio

Guarda como reenviadores.php y cambia el dominio:

<?php
require __DIR__ . '/funciones.php';

$filas = [['Origen', 'Destino']];
foreach (uapi('list_forwarders', ['domain' => 'example.com']) as $regla) {
    $filas[] = [$regla['dest'] ?? '', $regla['forward'] ?? ''];
}
escribirCsv($filas);

El ejemplo filtra expresamente un dominio. Repite la consulta para los dominios que quieras incluir y comprueba que no dupliques resultados. Una dirección de destino puede ser externa; el listado no acredita que esté entregando correo. Referencia: list_forwarders.

Respuestas automáticas

La lista por dominio identifica las respuestas configuradas. Guárdala como respuestas.php:

<?php
require __DIR__ . '/funciones.php';

$filas = [['Cuenta', 'Asunto']];
foreach (uapi('list_auto_responders', ['domain' => 'example.com']) as $respuesta) {
    $filas[] = [$respuesta['email'] ?? '', $respuesta['subject'] ?? ''];
}
escribirCsv($filas);

Consulta list_auto_responders para el formato de tu servidor. Si necesitas fechas, revisa también get_auto_responder: comprueba el identificador admitido y valida una respuesta conocida antes de repetir esa consulta para todas las cuentas. No recortes automáticamente el dominio de un email; podrías consultar otra identidad o no obtener el resultado previsto.

Los campos de inicio y fin pueden ser nulos. Si exportas marcas de tiempo Unix, conviértelas con una zona horaria explícita y refleja esa zona en la cabecera. Una respuesta configurada no implica que esté activa en el momento del informe.

Tareas cron

Puedes consultar las tareas del usuario con crontab -l. Conserva primero su salida original como referencia privada. Para generar un CSV de las líneas de programación habituales, guarda cron.php:

<?php
require __DIR__ . '/funciones.php';

$filas = [['Programación', 'Comando']];
foreach (explode("\n", ejecutar('crontab -l')) as $linea) {
    $linea = trim($linea);
    if ($linea === '' || str_starts_with($linea, '#')
        || preg_match('/^[A-Za-z_][A-Za-z0-9_]*\s*=/', $linea)) {
        continue;
    }
    if (preg_match('/^(@\S+)\s+(.+)$/', $linea, $partes)) {
        $filas[] = [$partes[1], $partes[2]];
    } else {
        $partes = preg_split('/\s+/', $linea, 6);
        if (count($partes) !== 6) {
            throw new RuntimeException('Hay una línea cron no reconocida.');
        }
        $filas[] = [implode(' ', array_slice($partes, 0, 5)), $partes[5]];
    }
}
escribirCsv($filas);

Si el usuario no tiene crontab, la orden puede terminar con error: comprueba el mensaje en la terminal antes de interpretar el resultado. Este CSV omite variables de entorno y comentarios; sirve para inventario, no para restaurar una programación completa. No representa las tareas de otros usuarios ni del sistema.

Generar y comprobar cada informe

Por ejemplo:

umask 077
php /home/usuario_cpanel/reportes/buzones.php > /home/usuario_cpanel/reportes/buzones.csv

Utiliza un nombre de salida nuevo y comprueba que el comando termine sin errores. No uses el archivo si ha fallado: la redirección puede dejar un CSV vacío o parcial. Revisa la cabecera, una fila conocida y el recuento antes de descargarlo. Borra las copias temporales cuando ya no sean necesarias.

También te puede ayudar

¿Algo no cuadra o ha cambiado? Cuéntanoslo y lo revisamos.