Skip to main content

Overview

The Restaurant Reservation System uses a comprehensive email notification system to keep both customers and business owners informed about reservation activities. All notifications are sent automatically using Firebase’s Trigger Email Extension.

Email Service Architecture

Implementation

The ServicioEmail class handles all email operations:
class ServicioEmail {
  // Email templates and sending logic
}
Implementation: source/lib/adaptadores/servicio_email.dart

Firebase Integration

Emails are sent through Firebase Firestore triggers:
1

Add to Firestore

Email data is written to the mail collection
2

Extension triggers

Firebase Trigger Email Extension detects new document
3

SMTP delivery

Extension sends email via configured SMTP provider
4

Status update

Delivery status is written back to Firestore document
await FirebaseFirestore.instance.collection('mail').add({
  'to': [recipientEmail],
  'message': {
    'subject': emailSubject,
    'html': htmlContent,
  },
  'createdAt': FieldValue.serverTimestamp(),
});
Implementation reference: source/lib/adaptadores/servicio_email.dart:368-398
The Firebase Trigger Email Extension must be installed and configured for emails to be delivered. See the Email Configuration Guide.

Customer Notifications

Customers receive automated emails for all reservation activities.

Reservation Confirmed

Sent when a customer successfully creates a reservation:
await servicioEmail.enviarReservaConfirmada(
  emailCliente: '[email protected]',
  nombreCliente: 'John Doe',
  nombreNegocio: 'La Cocina',
  fechaHora: DateTime(2026, 3, 15, 19, 0),
  nombreMesa: 'Mesa 5',
  numeroPersonas: 4,
);
Email includes:
  • ✅ Confirmation badge with green styling
  • 📋 Complete reservation details table
  • 💡 Important reminders:
    • Arrive 10 minutes early
    • Cancellation policy (2 hours advance notice)
    • Save email for reference
  • 📧 Restaurant contact information
Implementation reference: source/lib/adaptadores/servicio_email.dart:18-72

Customer Cancellation Confirmation

Sent when a customer cancels their own reservation:
await servicioEmail.enviarReservaCanceladaPorCliente(
  emailCliente: '[email protected]',
  nombreCliente: 'John Doe',
  nombreNegocio: 'La Cocina',
  fechaHora: DateTime(2026, 3, 15, 19, 0),
  nombreMesa: 'Mesa 5',
  numeroPersonas: 4,
);
Email includes:
  • ❌ Cancellation confirmation with red accent
  • 📋 Cancelled reservation details
  • 🔄 Invitation to book again
Implementation reference: source/lib/adaptadores/servicio_email.dart:75-116

Restaurant Cancellation Notice

Sent when the restaurant cancels a customer’s reservation:
await servicioEmail.enviarReservaCanceladaPorRestaurante(
  emailCliente: '[email protected]',
  nombreCliente: 'John Doe',
  nombreNegocio: 'La Cocina',
  fechaHora: DateTime(2026, 3, 15, 19, 0),
  nombreMesa: 'Mesa 5',
  numeroPersonas: 4,
  motivo: 'Table unavailable due to unexpected maintenance',
);
Email includes:
  • ⚠️ Cancellation notice with warning styling
  • 📋 Original reservation details
  • 📝 Reason for cancellation (if provided)
  • 🙏 Apology for inconvenience
  • 🔄 Invitation to rebook
Implementation reference: source/lib/adaptadores/servicio_email.dart:119-175
Always provide a clear, professional reason when cancelling customer reservations. This helps maintain customer trust and goodwill.

Business Owner Notifications

Restaurant owners receive notifications for customer reservation activities.

New Reservation Alert

Sent when a customer creates a new reservation:
await servicioEmail.enviarNuevaReservaAlDueno(
  emailDueno: '[email protected]',
  nombreCliente: 'John Doe',
  emailCliente: '[email protected]',
  telefonoCliente: '+54 9 261 123-4567',
  fechaHora: DateTime(2026, 3, 15, 19, 0),
  nombreMesa: 'Mesa 5',
  numeroPersonas: 4,
  nombreNegocio: 'La Cocina',
);
Email includes:
  • 📋 “Nueva Reserva Recibida” header
  • 👤 Customer contact information (email and phone)
  • 📅 Complete reservation details
  • 🏪 Restaurant name
Implementation reference: source/lib/adaptadores/servicio_email.dart:182-222

Customer Cancellation Alert

Sent when a customer cancels their reservation:
await servicioEmail.enviarCancelacionClienteAlDueno(
  emailDueno: '[email protected]',
  nombreCliente: 'John Doe',
  fechaHora: DateTime(2026, 3, 15, 19, 0),
  nombreMesa: 'Mesa 5',
  numeroPersonas: 4,
  nombreNegocio: 'La Cocina',
);
Email includes:
  • ❌ “Un cliente ha cancelado su reserva” header
  • 📋 Cancelled reservation details
  • ℹ️ Note that table is now available
Implementation reference: source/lib/adaptadores/servicio_email.dart:225-258
Business owners do NOT receive email notifications when they cancel reservations themselves, as they performed the action directly.

Email Templates

All emails use a consistent HTML template with responsive design.

Template Structure

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="font-family: Arial, sans-serif; background-color: #f5f5f5;">
  <div style="max-width: 600px; margin: 0 auto; background-color: white;">
    
    <!-- Header -->
    <div style="background-color: #27AE60; padding: 30px; text-align: center;">
      <h1 style="color: white; margin: 0;">✅ Reserva Confirmada</h1>
    </div>

    <!-- Content -->
    <div style="padding: 30px;">
      <!-- Email content here -->
    </div>

    <!-- Footer -->
    <div style="background-color: #f5f5f5; padding: 20px; text-align: center;">
      <p style="color: #666; font-size: 12px;">
        © 2026 Sistema de Reservas
      </p>
      <p style="color: #999; font-size: 11px;">
        Este es un email automático, por favor no respondas a este mensaje.
      </p>
    </div>

  </div>
</body>
</html>
Implementation reference: source/lib/adaptadores/servicio_email.dart:401-436

Color Scheme

ColorUsageHex Code
GreenConfirmation, success#27AE60
RedCancellation#F44336
OrangeWarning, restaurant cancellation#FF9800
GrayNeutral information#666666

Reservation Details Table

All emails include a formatted details table:
<table style="width: 100%; border-collapse: collapse;">
  <tr>
    <td style="padding: 12px 0; color: #666;">👤 Nombre:</td>
    <td style="padding: 12px 0; font-weight: bold;">John Doe</td>
  </tr>
  <tr>
    <td style="color: #666;">🏪 Restaurante:</td>
    <td style="font-weight: bold;">La Cocina</td>
  </tr>
  <tr>
    <td style="color: #666;">📍 Mesa:</td>
    <td style="font-weight: bold;">Mesa 5</td>
  </tr>
  <tr>
    <td style="color: #666;">📅 Fecha:</td>
    <td style="font-weight: bold;">viernes 15 de marzo de 2026</td>
  </tr>
  <tr>
    <td style="color: #666;">🕐 Horario:</td>
    <td style="font-weight: bold;">19:00 hs</td>
  </tr>
  <tr>
    <td style="color: #666;">👥 Personas:</td>
    <td style="font-weight: bold;">4</td>
  </tr>
</table>
Implementation reference: source/lib/adaptadores/servicio_email.dart:439-498

Date and Time Formatting

Dates and times are formatted in Spanish:

Date Format

String _formatearFecha(DateTime fecha) {
  // "viernes 15 de marzo de 2026"
  final diaSemana = dias[fecha.weekday - 1];
  final dia = fecha.day;
  final mes = meses[fecha.month - 1];
  final anio = fecha.year;
  
  return '$diaSemana $dia de $mes de $anio';
}
Examples:
  • lunes 10 de marzo de 2026
  • viernes 15 de marzo de 2026
  • domingo 20 de diciembre de 2026
Implementation reference: source/lib/adaptadores/servicio_email.dart:501-532

Time Format

String _formatearHora(DateTime fecha) {
  // "19:00 hs"
  final hora = fecha.hour.toString().padLeft(2, '0');
  final minuto = fecha.minute.toString().padLeft(2, '0');
  return '$hora:$minuto hs';
}
Examples:
  • 12:00 hs
  • 19:30 hs
  • 21:45 hs
Implementation reference: source/lib/adaptadores/servicio_email.dart:534-538

Using Email Service

With Reserva Entity

Convenience methods accept Reserva objects directly:
final servicioEmail = ServicioEmail();

// Notify customer of confirmed reservation
await servicioEmail.notificarReservaConfirmada(
  reserva,
  nombreNegocio: 'La Cocina',
  nombreMesa: 'Mesa 5',
  emailDueno: '[email protected]',
);
This automatically:
  • Sends confirmation email to customer
  • Sends new reservation alert to owner
Implementation reference: source/lib/adaptadores/servicio_email.dart:265-300

Customer Cancellation

await servicioEmail.notificarReservaCanceladaPorCliente(
  reserva,
  nombreNegocio: 'La Cocina',
  nombreMesa: 'Mesa 5',
  emailDueno: '[email protected]',
);
This automatically:
  • Sends cancellation confirmation to customer
  • Sends cancellation alert to owner
Implementation reference: source/lib/adaptadores/servicio_email.dart:303-335

Restaurant Cancellation

await servicioEmail.notificarReservaCanceladaPorRestaurante(
  reserva,
  nombreNegocio: 'La Cocina',
  nombreMesa: 'Mesa 5',
  motivo: 'Unexpected maintenance required',
);
This sends cancellation notice to customer only. Implementation reference: source/lib/adaptadores/servicio_email.dart:338-359

Email Validation

The system validates email addresses before sending:
final email = reserva.contactoCliente;
if (email == null || !email.contains('@')) {
  print('⚠️ No se puede enviar email: contacto no es email válido');
  return;
}
If a customer’s contactoCliente field is missing or invalid, email notifications will not be sent. Always validate customer contact information.

Firestore Email Collection

Emails are stored in Firestore for tracking:
mail/
  {emailId}/
    to: ["[email protected]"]
    message:
      subject: "✅ Reserva confirmada - La Cocina"
      html: "<html>...</html>"
    createdAt: Timestamp(2026-03-15 18:45:00)
    delivery:
      state: "SUCCESS"  // or "ERROR", "PENDING"
      attempts: 1
      startTime: Timestamp(...)
      endTime: Timestamp(...)
      error: null

Delivery States

StateDescription
PENDINGEmail queued for delivery
PROCESSINGCurrently being sent
SUCCESSDelivered successfully
ERRORDelivery failed
You can monitor email delivery status in the Firebase Console under the mail collection.

Troubleshooting

Problem: Emails Not Being Sent

Possible causes:
  1. Firebase Trigger Email Extension not installed
  2. SMTP credentials not configured
  3. Email quota exceeded
  4. Invalid recipient email address
Solution:
1

Check Firebase Extensions

Verify Trigger Email Extension is installed in Firebase Console
2

Verify SMTP Configuration

Ensure SMTP credentials are correctly configured in extension settings
3

Check Firestore

Look for error messages in mail collection documents
4

Validate Email

Confirm customer email address is valid and contains ’@‘

Problem: Emails Going to Spam

Possible causes:
  • SMTP server reputation issues
  • Missing SPF/DKIM records
  • Generic “no-reply” sender address
Solution:
  • Configure SPF and DKIM records for your domain
  • Use a recognizable sender address
  • Include unsubscribe link (for marketing emails)
  • Test with multiple email providers

Problem: Duplicate Emails

Possible causes:
  • Multiple calls to email service
  • Retry logic triggering unnecessarily
Solution:
  • Add idempotency checks
  • Verify email service is called only once per event
  • Check for duplicate reservation confirmations

Best Practices

Always test emails before deploying:
  • Send test emails to yourself
  • Verify formatting on multiple devices
  • Check spam folder
  • Test all notification types
Regularly monitor email delivery:
  • Check Firebase Console for errors
  • Review mail collection delivery states
  • Track bounce rates
  • Monitor SMTP quota usage
Keep emails professional and useful:
  • Clear subject lines
  • Complete information
  • Professional tone
  • Mobile-responsive design
Handle customer data responsibly:
  • Only send relevant notifications
  • Secure email content
  • Don’t share customer emails
  • Comply with privacy regulations

Email Configuration

For detailed instructions on setting up the Firebase Trigger Email Extension and SMTP configuration, see:

Email Configuration Guide

Step-by-step guide to configure email delivery with Firebase

Next Steps

Reservation Management

Learn how reservation actions trigger email notifications

Business Configuration

Configure your restaurant settings

Build docs developers (and LLMs) love