Si has aterrizado aquí, probablemente programes usando PHP como lenguaje de programación y usarás Laravel como Framework, pero el tutorial que traemos hoy te puede resultar útil para otros lenguajes de programación y otros frameworks.

El escenario es el siguiente: Desde tu aplicación se envían correos electrónicos y el servidor SMTP de la dirección que los envía es de GMail. Hasta hace poco, esto no era ningún problema, configuramos el servidor SMTP de gmail y solucionado, pero desde que Google está dando pasos en la seguridad de Gmail, esto se está convirtiendo cada día en un nuevo reto.

La solución fácil hasta ahora era habilitar la autenticación para aplicaciones menos seguras en nuestra cuenta, una solución sencilla, pero que en muchos casos, hacía que nuestros correos fuesen a spam, errores de autenticación, etc.

Pues bien, en este post te contaremos cómo hemos afrontado en Bloonde este tema:

Habilitar API de GMail

El primer paso que tendremos que hacer es crearnos una cuenta de Google Cloud y habilitar la API de GMail:

  • Iremos a https://console.cloud.google.com y crearemos un nuevo proyecto si aún no lo hemos creado.
  • Haremos clic en habilitar APIs y servicios y seleccionaremos la api de GMail.
  • A continuación deberemos crear una credencial, (tan solo debemos dar acceso a los datos del usuario)
  • Como permisos elegiremos “Leer, redactar y enviar correos electrónicos desde tu Cuenta de Gmail”
  • Cómo tipo de aplicación: “Aplicación web”
  • Por último, descargamos el archivo .json con la credencial.

Código

Es hora de picar código.

Lo primero que haremos será preparar la credencial y variables de entorno, como es lógico, este archivo deberemos situarlo en un lugar que no sea accesible desde el exterior. nosotros hemos escogido en storage/app/gmail_credential.json

A continuación deberemos instalar el paquete google/apiclient con el comando:

composer require google/apiclient

A continuación, crearemos un provider al que llamaremos GmailApiServiceProvider

y lo añadiremos en el archivo config/app.php

Nuestro GmailApiServiceProvider tengrá el siguiente código:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Mail\TransportManager;

class GmailApiServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(\Google_Client::class, function ($app) {
            $client = new \Google_Client();
            $client->setApplicationName('Your App Name');
            $client->setScopes(\Google_Service_Gmail::GMAIL_SEND);
            $client->setAuthConfig(storage_path('app/credentials.json'));

            return $client;
        });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->extend('swift.transport', function (TransportManager $manager) {
            $manager->extend('gmail_api', function () {
                $client = $this->app->make(\Google_Client::class);
                return new \App\Mail\Transport\GmailApiTransport($client);
            });

            return $manager;
        });
    }
}

Sustituye ‘Your App Name’ por el nombre que le diste al crear la API. Si no lo recuerdas, puedes encontrarla en el archivo json. Sustituye la ruta del archivo con la credencial.

Ahora ha llegado el momento de incluir un concepto no muy habitual, puesto que deberemos de crear un "custom transport" en app/Mail/GmailApiTransport.php que nos permitirá que el envío de nuestros correos sea a través de la api y no por el sistema tradicional.

<?php


namespace App\Mail\Transport;


use Google_Client;
use Google_Service_Gmail;
use Swift_Mime_SimpleMessage;
use Swift_Transport;
use Swift_Events_EventListener;


class GmailApiTransport implements Swift_Transport
{
private $client;


public function __construct(Google_Client $client)
{
$this->client = $client;
}


public function isStarted()
{
return true;
}


public function start()
{
// Not needed for the Gmail API
}


public function stop()
{
// Not needed for the Gmail API
}


public function send(Swift_Mime_SimpleMessage $message, &$failedRecipients = null)
{
$gmail = new Google_Service_Gmail($this->client);


// Prepare the message in the format required by the Gmail API
$mimeMessage = rtrim(strtr(base64_encode($message->toString()), '+/', '-_'), '=');
$messagePayload = new Google_Service_Gmail_Message();
$messagePayload->setRaw($mimeMessage);


// Send the message using the Gmail API
$gmail->users_messages->send('me', $messagePayload);


return $message->getId();
}


// Add these stub methods:


public function ping()
{
return true;
}


public function registerPlugin(Swift_Events_EventListener $plugin)
{
// You can keep this empty if you don't need plugin functionality
}
}

Activar verificación en 2 pasos:

Ha llegado el momento de dar el paso, ya podremos activar la verificación en dos pasos de gmail.

Activación de verificación en dos pasos

Una vez hecho esto y desde la sección “verificación en dos pasos” bajaremos hasta abajo, donde encontraremos la sección “Contraseña de aplicaciones” desde donde se nos permitirá crear una contraseña de aplicación, la cual podremos cambiar en nuestro archivo de variables .env por el que tuviésemos en MAIL_PASSWORD.

Creación de contraseña de aplicaciones

Deberemos tener en cuenta que si restablecemos la contraseña general de nuestra cuenta de correo, esta cuenta desaparecerá, por lo que deberemos volver a crearla.

Finalización de la configuración

Para finalizar debemos hacer un último cambio que pasa por añadir la siguiente variable de entorno, que nos permitirá hacer uso de la nueva integración creada

MAIL_MAILER=gmail_api

Si estamos en producción deberemos ejecutar el comando artisan para limpiar la configuración php artisan config:clear y a continuación reiniciar supervisor. Hecho esto, ya estamos preparados para enviar correos electrónicos haciendo uso de la API de GMail.