domingo, 12 de febrero de 2023

10.- Django. Formulario de contacto y envío de email con datos. Variables de Entorno.

En este capitulo crearemos un ejemplo de formulario de contacto, veremos el método POST y aprovecharemos para mostrar como enviar un email que nos informe que hay un nuevo usuario y nos envíe la información introducida.

Empezamos.

Para crear el formulario de contacto lo primero que debemos hacer es irnos a las vistas, al archivo views.py y al final crear una nueva vista. De momento lo único que va a hacer es devolvernos un renderizado de un archivo, que aun no hemos creado, pero que lo haremos luego (contacto.html)

gestionPedidos/views.py

...
def contacto(request):
    '''Vista para definir un formulario de contacto.'''
    return render(request, "contacto.html")

El siguiente paso es irnos a las urls para registrar la vista.

tiendaVirtual/urls.py

...
from django.contrib import admin
from django.urls import path
# Siempre hay que importar las vistas de la aplicación
from gestionPedidos import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('busqueda_juegos/', views.busqueda_juegos),
    path('buscar/', views.buscar),
    path('contacto/', views.contacto),
]
y lo que nos falta es crear en la carpeta "templates", el archivo html del formulario que será el siguiente:

gestionPedidosl/templates/contacto.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contáctanos</title>
</head>
<body>
    <h1>Contacta con nosotros.</h1>
    <form action="/contacto/" method="POST">
        {% csrf_token %}
        <!-- Cuadro de texto de entrada -->
        <p>Asunto <input type="text" name="asunto"> </p>
        <p>Email <input type="text" name="email"> </p>
        <p>Mensaje<p>
        <p></p><textarea name="mensaje" rows="15" cols="45"></textarea></p>
        <input type="submit" value="Enviar">
    </form>
</body>
</html>
Es importante dentro de la etiqueta del formulario añadir {% csrf_token %} para evitar un ataque malicioso llamado "Cross Site Request Forgery".  Permite validar que las peticiones son realizadas desde un sitio web autorizado y no desde otras fuentes. Si te interesa una mayor explicación puedes encontrar la información aquí.

Otro matiz importante es que cuando pulsemos el botón enviar usaremos como forma de envío el método "POST". La diferencia con el método "GET", que usamos en el capitulo anterior, es que mientras que este envía los datos usando la URL y por tanto los podemos ver su contenido en la barra de navegación, el método POST los envía de forma que no podamos verlos (en segundo plano y ocultos para el usuario). 

Luego definimos los elementos del formulario que tendrá la siguiente forma:


formulario de contacto


De momento el formulario no hace nada, pero podemos probarlo para ver que funciona correctamente.

Ahora, para comprobar que este formulario (que está utilizando el método "POST") funciona, vamos a hacer lo siguiente. Si al dar al botón enviar todo va bien, nos devolverá un renderizado indicándonos que la información se ha enviado correctamente. Volvemos al archivo de vistas views.py:

gestionPedidos/views.py

...
def contacto(request):
    '''Vista para definir un formulario de contacto.'''
    if request.method=="POST":
        return render(request, "gracias.html")
    else:
        return render(request, "contacto.html")

La explicación es la siguiente.

La primera vez que entramos en la página del formulario, no estamos utilizando el método "POST" sino el "GET" con lo que se renderizará el formulario de contacto. Ahora bien, cuando le damos al botón enviar, entonces la información se envía de nuevo a esta vista /contacto/ usando, ahora si, el método "POST", con lo que se renderizará la página html "gracias.html", que crearemos ahora y que nos servirá para confirmar el envío y que todo funciona correctamente.

gestionPedidos/templates/gracias.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enviado</title>
</head>
<body>
    <h3>Gracias por enviar la información.</h3>
</body>
</html>

Si entramos en la url /contacto/ y enviamos el formulario nos debería salir el mensaje de Enviado. (siempre que tengamos el servidor conectado, claro)


archivo gracias.html


Envío de Emails en Django.


Enviar correos con Django es muy sencillo. Para enviar correos con Django es necesario tener un servidor local de protocolo simple de transferencia de correo (SMTP), o poder acceder a un servidor SMTP externo, como tu proveedor de servicios de correo electrónico (Gmail, Yahoo, Outlook etc)

Para ello, vamos a utilizar la librería core.mail. Para poder enviar mails lo primero que tenemos es ir al archivo settings.py y configurar una serie de parámetros. En este archivo, al final del todo pondremos las siguientes instrucciones.

tiendaVirtual/settings.py

...
# Configuración de servidor de correo de django
EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = 'smtp.outlook.com' o 'smtp.gmail.com' etc
EMAIL_PORT = 587
EMAIL_HOST_USER = 'usuario@outlook.com' o 'usuario@gmail.com'
EMAIL_HOST_PASSWORD = 'la contraseña del correo'
EMAIL_USE_TLS = True
El EMAIL_HOST es el servidor de correo que vas a usar para enviar los correos. Como gmail siempre me ha dado problemas, yo personalmente utilizo outlook. Utilizaremos el método smtp para enviar los correos. El resto es buscar la configuración asociada al correo que utilices y que puedes buscar en Google. El valor por defecto sino se especifica nada el "localhost"

EMAIL_PORT es el puerto por el que se comunica el servicio SMTP, que es el protocolo que se utiliza para enviar el correo. Por defecto el puerto es el 25.
 
EMAIL_HOST_USER es tu usuario o cuenta de correo.

EMAIL_HOST_PASSWORD es la contraseña de tu correo electrónico. Si estas usando Gmail como servidor SMTP desde que implemento la verificación en dos pasos y otras medidas de seguridad, no puedes usar tu contraseña del correo directamente. En vez de ello, Google te permite crear una contraseña especifica para la aplicación desde tu cuenta.  Para ello ve al navegador y abre la siguiente dirección, https://myaccount.google.com/. En el menú de la izquierda haz click en Seguridad, verás una pantalla como esta:

The Signing in to Google page for Google accounts

En "como inicias sesión en Google", selecciona "Verificación en dos pasos". En la parte inferior de la página selecciona "Contraseñas de aplicación". Ahí introduce un nombre que te ayude a recordar dónde vas a utilizar la contraseña de la aplicación. Después selecciona "Generar". Para introducir la contraseña de aplicación, sigue las instrucciones que aparecen en pantalla. La contraseña de aplicación es el código de 16 caracteres que se genera en tu dispositivo. 

Si no puedes usar un servidor SMTP (Gmail, Outlook, yahoo o cualquier otro servicio de correo), puedes decirle a Django que envíe estos emails a la consola del sistema remplazando la entrada EMAIL_BACKEND de archivo settings.py por esta otra:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Al usar esta configuración, Django enviará los emails a la consola del sistema en lugar de enviarlos fuera de tu equipo. Este resulta bastante útil para probar la aplicación.

Para probar si la configuración funciona vamos a hacer una prueba desde consola. Nos vamos a la misma e introducimos el comando.

$ python manage.py shell

Lo primero es importar la librería core.mail y dentro de este la función sendmail(). Luego le pasamos los argumentos que nos pide. Puedes encontrar la documentación Django sobre como enviar email aqui. Quedaría algo como esto:

(miEntorno) chema@lenovo:~/Cursos/DJANGO/tiendaVirtual$ python manage.py shell
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.core.mail import send_mail
>>> send_mail(
... 'Aqui el asunto del correo',
... 'Aqui el mensaje',
... 'tu_usuario@outlook.com',
... ['correo_destino@gmail.com'],
... fail_silently=False,
... )
1
Entramos en la consola interactiva de Django e importamos la librería que comentamos previamente.
Luego rellenamos los campo de asunto, mensaje etc. 'desde_correo@outlook.com' es el correo que registramos previamente en el archivo settings.py, es decir el correo que utilizamos para enviar los mensajes. 

La opción fail_silently=False final sirve para que si algo falla nos muestre las trazas del error y poder tener una idea de lo que ocurre. 
El 1 final es que el correo se envió correctamente.

Una vez que vemos que los parámetros son correctos y que nos llegan los correos electrónicos ¿Cómo hacemos para que desde nuestro formulario de contacto, lo que el usuario haya tecleado cuando le de al botón enviar nos llegue a nuestro correo electrónico?

Pues tenemos que ir al archivo de vistas y concretamente a la vista contacto. Allí tenemos que adaptar lo que hemos visto para enviar un email con los contenidos de los campos del formulario.

Lo primero empezaremos importando del módulo django.core.mail el método send_mail y también settings para poder usar las propiedades que definimos antes. Luego es hacer lo mismo que realizamos por consola. El archivo views.py quedaría tal que así.

 gestionPedidos/views.py
from django.shortcuts import render
from django.http import HttpResponse
# Para poder usar el modelo Articulos de la base de datos
from gestionPedidos.models import Articulos
# Para poder enviar emails del formulario de contacto.
from django.core.mail import send_mail
from django.conf import settings

...
def contacto(request):
    '''Vista para definir un formulario de contacto.'''
    if request.method=="POST":

        asunto = request.POST['asunto']
        mensaje = request.POST['mensaje'] + " " + request.POST['email']
        email_from = settings.EMAIL_HOST_USER

        send_mail(
            asunto,
            mensaje,
            email_from,
            ['correo_destino@correo.com'],
            )

        return render(request, "gracias.html")
    else:
        return render(request, "contacto.html")
Las variable asunto coge su valor del formulario, a través del método POST. En el formulario también llamamos asunto a la casilla de texto que recogía la información. Lo mismo ocurre con mensaje que coge su valor del mensaje que el usuario tecleo en el formulario y después de un espacio en blanco le añado el email para que cuando lo recibamos podamos contestarle si queremos.

email_from coge su valor del archivo de configuración y recordad que este correo, es la cuenta de correo que hemos configurado para enviar los archivos. Luego en una lista pondremos el correo o correo de destino a donde queremos que llegue la información de ese formulario.

Por ultimo si se ha enviado correctamente se renderizará el archivo "gracias.html".

Usar Variables de entorno para preservar datos privados.


Para preservar información importante y confidencial en nuestros proyectos de Django es útil usar las variables de entorno. De forma esquemática el proceso es el siguiente:

1.- Instalamos el siguiente paquete.

pip install django-environ

2.- Cuando este instalado, creamos un archivo llamado .env en el mismo directorio en donde este el archivo settings.py. Su contenido esta formado por parejas de clave-valor y es muy importante que no haya espacios ni antes ni después del igual ya que sino no funcionará. Por ejemplo, para usar como variables de entorno el EMAIL_HOST_USER y EMAIL_HOST_PASSWORD pondríamos lo siguiente:

tiendaVirtual/.env

EMAIL_HOST_USER=usuario@outlook.com
EMAIL_HOST_PASSWORD=#ladificilcontraseña
En el directorio base o raíz, añadimos al archivo .gitignore (o lo creamos si no lo está) lo siguiente:

*.pyc
__pycache__
db.sqlite3
/env
*.env
.vscode
Esto es para que GIT el controlador de versiones que normalmente se usa en los proyectos no haga un seguimiento de estos archivos, ni de sus valores.

Por último en el archivo settings.py en la línea de importación añadimos

tiendaVirtual/settings.py

import environ
env = environ.Env()
environ.Env.read_env()
y ya podemos usar los valores de entorno en el archivo de configuración de la siguiente forma:

tiendaVirtual/settings.py

...

# Configuración de servidor de correo de django
EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = 'smtp.outlook.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
EMAIL_USE_TLS = True
Ahora bien, si en el archivo de vistas de la aplicación queremos usar para algo los valores de estas variables tendremos que importarlos desde el archivo settings.py, ya que se encuentran ahí. Lo podemos hacer usando:

from django.conf import settings
Por eso en el apartado anterior al definir las vistas usamos "email_from = settings.EMAIL_HOST_USER"





No hay comentarios:

Publicar un comentario