Skip to main content

Overview

Dashboard Dilemas sends automated emails for:
  • Completion certificates (participation and excellence awards)
  • Activity reminders for incomplete dilemmas
  • User notifications and alerts
The application supports SMTP email delivery through providers like Brevo, SendGrid, or Gmail, using WordPress’s PHPMailer library.

SMTP Configuration

Basic Setup

Configure SMTP settings in includes/config.php:
includes/config.php
define('SMTP_HOST', 'smtp-relay.brevo.com');
define('SMTP_USER', 'your-username');
define('SMTP_PASS', 'your-password');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls'); // 'tls' or 'ssl'
define('SMTP_FROM_EMAIL', '[email protected]');
define('SMTP_FROM_NAME', 'Dilemas Eticos');

Brevo

Free tier: 300 emails/dayHost: smtp-relay.brevo.comPort: 587 (TLS)

SendGrid

Free tier: 100 emails/dayHost: smtp.sendgrid.netPort: 587 (TLS)

Gmail

Requires App PasswordHost: smtp.gmail.comPort: 587 (TLS)

Provider-Specific Configuration

define('SMTP_HOST', 'smtp-relay.brevo.com');
define('SMTP_USER', '[email protected]');
define('SMTP_PASS', 'your-brevo-smtp-key');
define('SMTP_PORT', 587);
define('SMTP_SECURE', 'tls');
define('SMTP_FROM_EMAIL', '[email protected]');
define('SMTP_FROM_NAME', 'Your Company Name');
Gmail Users: You must generate an App Password instead of using your regular Gmail password. 2FA must be enabled on your account.

WordPress Integration

The email system requires WordPress’s PHPMailer library. Configure the WordPress path:
includes/config.php
define('WP_PATH', '/path/to/wordpress');
define('WP_SITE_URL', 'https://yourdomain.com');

PHPMailer Implementation

The application uses PHPMailer with SMTP authentication:
cron_email_reminders.php
function send_via_phpmailer(string $to, string $subject, string $body): bool
{
    try {
        require_once WP_PATH . '/wp-includes/class-phpmailer.php';
        require_once WP_PATH . '/wp-includes/class-smtp.php';
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host = SMTP_HOST;
        $mail->SMTPAuth = true;
        $mail->Username = SMTP_USER;
        $mail->Password = SMTP_PASS;
        $mail->SMTPSecure = SMTP_SECURE;
        $mail->Port = SMTP_PORT;
        $mail->setFrom(SMTP_FROM_EMAIL, SMTP_FROM_NAME);
        $mail->addAddress($to);
        $mail->isHTML(true);
        $mail->Subject = $subject;
        $mail->Body = $body;
        $mail->send();
        return true;
    } catch (Exception $e) {
        return false;
    }
}
If WordPress PHPMailer is not available, the system falls back to PHP’s native mail() function.

Email Types

Certificate Emails

Sent when users complete dilemmas, triggered by api_send_certificate.php.

Participation Certificate

POST /api_send_certificate.php
{
  "user_id": "u1",
  "game_id": "game_1",
  "type": "participation"
}
Email Preview:
  • Subject: ”📜 Tu Certificado de Participación - [Game Name]”
  • Content: Professional HTML template with download button
  • Certificate URL: SITE_URL/generate_certificate.php?user_id=X&game_id=Y&type=participation

Excellence Award Certificate

POST /api_send_certificate.php
{
  "user_id": "u1",
  "game_id": "game_1",
  "type": "award"
}
Email Preview:
  • Subject: ”🏆 ¡Felicidades! Tu Certificado de Excelencia - [Game Name]”
  • Content: Congratulatory message for outstanding performance

Reminder Emails

Automated reminders for users with incomplete dilemmas, sent via cron_email_reminders.php.

Configuration

Cron Setup
# Daily reminders at 9:00 AM
0 9 * * * curl -s "https://yourdomain.com/dashboard-dilemas/cron_email_reminders.php?secret=YOUR_SECRET"

Parameters

ParameterDefaultDescription
secret(required)Cron secret for authentication
days7Days of inactivity before reminder
dry_runfalseTest mode - logs without sending

Testing Reminders

# Test mode (no actual emails sent)
curl "http://localhost/dashboard-dilemas/cron_email_reminders.php?secret=YOUR_SECRET&dry_run=true"

# Send to users inactive for 3+ days
curl "http://localhost/dashboard-dilemas/cron_email_reminders.php?secret=YOUR_SECRET&days=3"

# Run from command line (development)
php cron_email_reminders.php
Reminder emails are limited to 50 recipients per execution to prevent SMTP throttling.

Email Templates

Certificate Email Template

The certificate email uses a responsive HTML template with gradient header:
api_send_certificate.php
$message = "
<div style='font-family: sans-serif; max-width: 600px; margin: 0 auto; 
     border: 1px solid #e5e7eb; border-radius: 20px; overflow: hidden; 
     box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);'>
    <div style='background: linear-gradient(to right, #2563eb, #4f46e5); 
         padding: 50px 40px; text-align: center; color: white;'>
        <div style='font-size: 32px; font-weight: 900; letter-spacing: -1px; 
             margin-bottom: 5px;'>DILEMAS ÉTICOS</div>
        <div style='font-size: 14px; text-transform: uppercase; 
             letter-spacing: 4px; opacity: 0.8;'>Certificaciones Digitales</div>
    </div>
    <!-- Email content -->
</div>
";

Reminder Email Template

Reminder emails feature a professional design encouraging completion:
cron_email_reminders.php
function build_reminder_email(string $name, string $gameName, string $url): string
{
    $year = date('Y');
    return <<<HTML
<!DOCTYPE html>
<html lang="es">
<body style="margin:0;padding:0;background:#f8fafc;font-family:'Segoe UI',Arial,sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#f8fafc;padding:40px 20px;">
  <tr><td align="center">
    <table width="580" cellpadding="0" cellspacing="0" 
           style="background:#fff;border-radius:16px;overflow:hidden;">
      <!-- Header with gradient -->
      <tr><td style="background:linear-gradient(135deg,#1d4ed8,#4f46e5);padding:40px;text-align:center;">
        <h1 style="color:#fff;margin:0;font-size:28px;font-weight:900;">FGE Dilemas Éticos</h1>
      </td></tr>
      <!-- Content -->
      <tr><td style="padding:40px;">
        <p>Hola, <strong>{$name}</strong>:</p>
        <p>Tienes el dilema <strong>{$gameName}</strong> pendiente de completar.</p>
        <div style="text-align:center;margin:32px 0;">
          <a href="{$url}" style="background:#2563eb;color:#fff;padding:16px 36px;
             border-radius:12px;font-weight:900;text-decoration:none;">Continuar Dilema →</a>
        </div>
      </td></tr>
    </table>
  </td></tr>
</table>
</body>
</html>
HTML;
}

Monitoring and Logging

Email Logs

Cron job execution logs are stored in:
dev/debug/cron_reminders.log
View recent activity:
tail -f dev/debug/cron_reminders.log

Log Format

[09:00:01] ═══ Cron Recordatorios iniciado — 2024-03-15 09:00:01 ═══
[09:00:01] Inactividad umbral: 7 días | Dry-run: NO
[09:00:02] Encontrados 12 usuarios con dilemas incompletos.
[09:00:03] ✓ Email enviado a [email protected]
[09:00:04] ✓ Email enviado a [email protected]
[09:00:05] ── Resumen: Enviados=12 | Errores=0 | Omitidos=0 ──

Certificate Sending Audit

Certificate emails are tracked in the database:
INSERT INTO de_app_funnel_events (game_id, user_id, event_type) 
VALUES (:gameId, :userId, 'cert_sent');
Query sent certificates:
SELECT user_id, game_id, created_at 
FROM de_app_funnel_events 
WHERE event_type = 'cert_sent' 
ORDER BY created_at DESC;

Troubleshooting

Symptoms: Emails not sending, SMTP errors in logs.Solutions:
  • Verify SMTP_USER and SMTP_PASS are correct
  • For Gmail, ensure you’re using an App Password, not your account password
  • Check that your SMTP provider hasn’t blocked your IP
  • Verify SMTP_PORT and SMTP_SECURE match your provider’s requirements
Symptoms: “WordPress not found at /path/to/wordpress” error.Solutions:
  • Update WP_PATH in includes/config.php to your actual WordPress directory
  • Ensure the path is absolute, not relative
  • Verify the web server has read permissions for that directory
  • Check that wp-includes/class-phpmailer.php exists in that path
Symptoms: Users not receiving emails, found in spam folder.Solutions:
  • Configure SPF and DKIM records for your domain
  • Use a verified sender email address
  • Ensure SMTP_FROM_EMAIL matches your domain
  • Avoid spam trigger words in subject lines
  • Use a reputable SMTP provider (Brevo, SendGrid)
Symptoms: No reminder emails sent, no new log entries.Solutions:
  • Verify cron job is properly configured in your server’s crontab
  • Test manually: curl "https://yourdomain.com/cron_email_reminders.php?secret=YOUR_SECRET"
  • Check that the secret parameter matches CRON_SECRET
  • Ensure the script has execute permissions
  • Check web server error logs for PHP errors
Symptoms: Some emails send, others fail after a certain number.Solutions:
  • Check your SMTP provider’s rate limits
  • Reduce MAX_EMAILS constant in cron_email_reminders.php (default: 50)
  • Upgrade to a paid tier for higher limits
  • Implement delays between emails if needed

Testing Email Configuration

Test Certificate Email

Send a test certificate to verify SMTP configuration:
curl -X POST http://localhost/dashboard-dilemas/api_send_certificate.php \
  -d "user_id=u1" \
  -d "game_id=game_1" \
  -d "type=participation"
Expected Response:
{"success": true}

Test Reminder Email (Dry Run)

Test reminder logic without sending actual emails:
curl "http://localhost/dashboard-dilemas/cron_email_reminders.php?secret=YOUR_SECRET&dry_run=true&days=1"
Expected Output:
[09:15:32] ═══ Cron Recordatorios iniciado — 2024-03-15 09:15:32 ═══
[09:15:32] Inactividad umbral: 1 días | Dry-run: SÍ
[09:15:32] Encontrados 5 usuarios con dilemas incompletos.
[09:15:32] [DRY-RUN] Sería enviado a: [email protected] — Dilema: Dilema del Puente
[09:15:32] [DRY-RUN] Sería enviado a: [email protected] — Dilema: Ética en la IA
[09:15:32] ── Resumen: Enviados=5 | Errores=0 | Omitidos=0 ──

Security Considerations

Important Security Practices:
  • Never commit SMTP credentials to version control
  • Use environment variables or secure config files for sensitive data
  • Implement rate limiting to prevent email abuse
  • Validate and sanitize email addresses before sending
  • Use CRON_SECRET to prevent unauthorized email sending
  • Enable SMTP authentication (never use open relay)

Secure Cron Secret

Generate a strong cron secret:
# Generate 32-byte random string
openssl rand -base64 32
Add to your configuration:
define('CRON_SECRET', getenv('CRON_SECRET') ?: 'your_generated_secret_here');

Next Steps

Database Configuration

Set up MySQL database schema

Environment Variables

Configure application settings

Build docs developers (and LLMs) love