Cakephp 3: Como enviar correo electrónico utilizando Gmail
|Desde hace un par de días he venido luchando para configurar adecuadamente el envío de correo a través de Gmail pero cada intento me daba un error de certificados SSL que hizo que odiara la tecnología un poco más de lo usual.
Espero que esta guía ayude a aquellos que intenten realizar este tipo de tarea o a lo mejor resolver el error que yo tenía.
Lo primero es tener habilitado openssl en nuestro servidor, si utilizas Lampp (osea de Linux) este ya viene habilitado por defecto, si estas en Windows entonces debes ir a editar el archivo /xampp/php/php.ini y encontrar la linea con el texto: extension=php_openssl.dll, si ves un punto y coma (;) al inicio de esa línea quiere decir que esta comentado y no esta habilitado, debes eliminar ese punto y coma, guardar el archivo y reiniciar el servidor apache.
Lo segundo antes de ir al código es saber que Gmail posee una característica por defecto de no permitir el acceso a tu cuenta si la aplicación desde la que intentes conectarte no posee una conexión segura como un cerfiticado ssl, y lo mas probable es que en tu servidor local no contes con uno así que vamos a habilitar el acceso de aplicaciones inseguras.
Para habilitar dicha característica primero vas a entrar en tu cuenta de correo Gmail, en la esquina superior derecha vas a ver un cirtulo donde debería estar tu foto de perfil, haces clic ahí y luego en el botón Mi Cuenta.
Luego clic en el enlace Acceso y Seguridad.
Baja hasta ver la opción Permitir el acceso a aplicaciones menos seguras y haces clic en el botón para activarla.
Entrando en materia de código lo primero que voy a hacer es una plantilla, esta plantilla será la base del mensaje en mi correo electrónico.
/src/Template/Email/html/correo_plantilla.ctp y le voy a poner algo sencillo:
1 2 3 4 5 6 7 |
<p>Este es un correo de ejemplo para cakephp 3</p> <p>Imprimimos las variables enviadas desde el controlador:</p> <p><?= $var1; ?></p> <p><?= $var2; ?></p> <p><?= $var3; ?></p> |
Como verán tengo 3 variables que luego llenaré desde el controlador.
El siguiente es un controlador que se llama Usuarios y voy a utilizar la configuración de correo llamada configTransport, que es una configuración al vuelo.
/src/Controller/UsuariosController.php con el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php namespace App\Controller; use Cake\Network\Email\Email; // <-- Importante para utilizacion de correo electronico class UsuariosController extends AppController{ public function correo(){ /*Para este ejemplo no necesito de renderizar una vista por lo que autorender lo pongo a false */ $this->autoRender = false; /*configuramos las opciones para conectarnos al servidor smtp de Gmail */ Email::configTransport('mail', [ 'host' => 'ssl://smtp.gmail.com', //servidor smtp con encriptacion ssl 'port' => 465, //puerto de conexion //'tls' => true, //true en caso de usar encriptacion tls //cuenta de correo gmail completa desde donde enviaran el correo 'username' => 'correo@gmail.com', 'password' => 'contrasena', //contrasena //Establecemos que vamos a utilizar el envio de correo por smtp 'className' => 'Smtp', //evitar verificacion de certificado ssl ---IMPORTANTE--- /*'context' => [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ] ]*/ ]); /*fin configuracion de smtp*/ /*enviando el correo*/ $correo = new Email(); //instancia de correo $correo ->transport('mail') //nombre del configTrasnport que acabamos de configurar ->template('correo_plantilla') //plantilla a utilizar ->emailFormat('html') //formato de correo ->to('correo_para@gmail.com') //correo para ->from('correo@gmail.com') //correo de ->subject('Correo de prueba en cakephp3') //asunto ->viewVars([ //enviar variables a la plantilla 'var1' => 'Hugo', 'var2' => 'Kiuvox', 'var3' => 'http://blog.kiuvox.com' ]); if($correo->send()){ echo "Correo enviado"; }else{ echo "Ups error man"; } } } |
Esto es lo básico que podrían tener para el envío de correo electrónico, NO DEJES DE LEER QUE TENGO UNAS NOTAS IMPORTANTES.
Como verán en el configTransport he comentado la opción de tls, eso es porque ahorita utilizo ssl, pero si quisieran usar tls entonces debería modificar estas opciones:
1 2 3 |
'host' => 'smtp.gmail.com', 'port' => 587, 'tls' => true, |
Ahí hemos cambiado el host, le quitamos el ssl://, el puerto y activamos tls.
Segunda nota por mencionar, si prueban el código en este momento a la mayoría podría ocurrirle el siguiente error:
stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed stream_socket_client(): Failed to enable crypto stream_socket_client(): unable to connect to ssl://smtp.gmail.com:465 (Unknown error)
Esto es porque Openssl en php 5.6 verifica cada conexión encriptada por defecto, pero al no contar con un certificado en nuestro servidor de desarrollo presentará el siguiente inconveniente es por eso que en el configTransport he dejado una opción comentada que se llama context, si la descomentamos evitarémos dicha verificación que al menos en nuestro desarrollo o hasta que tengamos un certificado ssl es conveniente para que funcione, para descomentarla quita el /* al inicio y el */ al final para que se vea así:
1 2 3 4 5 6 7 8 |
//evitar verificacion de certificado ssl ---IMPORTANTE--- 'context' => [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ] ] |
Ahora si intentas el correo debería enviarse sin problema.
Si llegas a tener otro tipo de error como:
php_network_getaddresses: getaddrinfo failed: Fallo temporal en la resolución del nombre
Podría ser alguna restricción en tu red por parte de un router, firewall o proxy que deberías investigar por aparte.
Realmente espero que esta guía sea de ayuda para alguien porque el problema del ssl me tomo dos días encontrar como resolverlo y es algo que quiero compartir con todos.
En la web de Cakephp podes encontrar más información sobre el uso de Email.
Hasta luego gente!!
Excelente post! me sirvo mucho. Gracias!