diff --git a/src/eventos/forms.py b/src/eventos/forms.py index 4928cee..9e54ea5 100644 --- a/src/eventos/forms.py +++ b/src/eventos/forms.py @@ -21,5 +21,16 @@ class ListaEsperaForm(forms.ModelForm): class MensajeCorreoForm(forms.Form): - asunto = forms.CharField(label="Asunto", max_length=200, required=True, widget=forms.TextInput(attrs={'class': 'form-control'})) - mensaje = forms.CharField(label="Mensaje", widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}), required=True) \ No newline at end of file + asunto = forms.CharField( + label="Asunto", + max_length=200, + required=True, + widget=forms.TextInput(attrs={'class': 'form-control'}) + ) + + mensaje = forms.CharField( + label="Mensaje", + widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 16}), + required=True + ) + diff --git a/src/eventos/views.py b/src/eventos/views.py index 9173ada..0468eff 100644 --- a/src/eventos/views.py +++ b/src/eventos/views.py @@ -6,7 +6,13 @@ from django.conf import settings from django.template.loader import render_to_string from django.utils import timezone -from django.core.mail import send_mail +import logging + +from django.core.mail import send_mass_mail +from django.core.mail import BadHeaderError +from smtplib import SMTPException + +from django.http import HttpResponse from rest_framework.response import Response from rest_framework.decorators import api_view @@ -15,6 +21,8 @@ from .serializers import EventoSerializer, ReservaSerializer, ListaEsperaSeriali from .models import Evento, Reserva, ListaEspera, Noticia from .forms import ListaEsperaForm, EventoForm, MensajeCorreoForm +logger = logging.getLogger(__name__) + @login_required def reservar_evento(request, evento_id): @@ -300,6 +308,7 @@ def api_detalle_noticia(request, noticia_id): def es_admin(user): return user.is_staff + @user_passes_test(es_admin) # Solo administradores pueden acceder def enviar_correo_inscritos(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) @@ -307,31 +316,43 @@ def enviar_correo_inscritos(request, evento_id): if not inscritos: messages.warning(request, "No hay usuarios inscritos en este evento.") - return redirect('detalle_evento', evento_id=evento.id) + return redirect('eventos:detalle_evento', evento_id=evento.id) destinatarios = [reserva.usuario.email for reserva in inscritos if reserva.usuario.email] if not destinatarios: messages.warning(request, "No hay correos disponibles para los inscritos.") - return redirect('detalle_evento', evento_id=evento.id) + return redirect('eventos:detalle_evento', evento_id=evento.id) if request.method == "POST": form = MensajeCorreoForm(request.POST) if form.is_valid(): - asunto = form.cleaned_data['asunto'] - mensaje = form.cleaned_data['mensaje'] + asunto_usuario = form.cleaned_data['asunto'] + mensaje_usuario = form.cleaned_data['mensaje'] + + asunto = f"{asunto_usuario} - {evento.nombre}" - send_mail( - asunto, - mensaje, - settings.DEFAULT_FROM_EMAIL, - destinatarios, - fail_silently=False - ) + firma = "\n\n\nSaludos, \n\nPádel entre amigos" + mensaje = f"{mensaje_usuario}{firma}" + + mensaje_comun = (asunto, mensaje, settings.DEFAULT_FROM_EMAIL, destinatarios) + mensaje_final = [mensaje_comun] + + try: + send_mass_mail(mensaje_final, fail_silently=False) + except BadHeaderError: + return HttpResponse('Encabezado inválido encontrado.') + except SMTPException as e: + return HttpResponse(f'Error de SMTP: {e}') + except Exception as e: + return HttpResponse(f'Ocurrió un error: {e}') + + logger.debug('Correo enviado') messages.success(request, f"Correo enviado a {len(destinatarios)} inscritos.") - return redirect('detalle_evento', evento_id=evento.id) + return redirect('eventos:detalle_evento', evento_id=evento.id) else: form = MensajeCorreoForm() - return redirect('eventos:detalle_evento', evento_id=evento.id) \ No newline at end of file + return render(request, 'eventos/enviar_correo_inscritos.html', {'form': form, 'evento': evento}) + diff --git a/src/gestion_reservas/settings.py b/src/gestion_reservas/settings.py index 20eb0cc..a8ca541 100644 --- a/src/gestion_reservas/settings.py +++ b/src/gestion_reservas/settings.py @@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/5.1/ref/settings/ from pathlib import Path import os +import logging # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -171,3 +172,58 @@ ADMIN_EMAIL = '' # El tiempo de validez del enlace para resetear la contraseña (por defecto es de 3 días) PASSWORD_RESET_TIMEOUT = 86400 # 1 día en segundos + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '{levelname} {asctime} {module} {message}', + 'style': '{', + }, + 'simple': { + 'format': '{levelname} {message}', + 'style': '{', + }, + }, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + }, + 'file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': '/dev/null', + 'formatter': 'verbose', + }, + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['file'], + 'level': 'DEBUG', + 'propagate': True, + }, + 'eventos': { + 'handlers': ['console', 'file'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'gestion_reservas': { + 'handlers': ['console', 'file'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': False, + }, + }, +} + diff --git a/src/templates/eventos/enviar_correo_inscritos.html b/src/templates/eventos/enviar_correo_inscritos.html index 33213a3..d8c6e30 100644 --- a/src/templates/eventos/enviar_correo_inscritos.html +++ b/src/templates/eventos/enviar_correo_inscritos.html @@ -2,7 +2,7 @@ {% block content %}
-

Enviar correo a los inscritos en "{{ evento.titulo }}"

+

Enviar correo a los inscritos en "{{ evento.nombre }}"

{% csrf_token %}
@@ -14,7 +14,7 @@ {{ form.mensaje }}
- Cancelar + Volver a la lista de eventos
{% endblock %}