Una vez que ya tenemos la cuenta de servicio, ya podremos seguir con la programación. En este post veremos cómo enviar correos con Gmail y PHP.
Contenido
Para este mini proyecto usaremos lo siguiente:
- Docker
- Composer
- PHP
- Archivo JSON de las credenciales de Google (este ya lo debes tener).
Primero creamos la estructura de archivos y directorios:
touch Dockerfile
touch docker-compose.yml
mkdir app
touch app/index.php
Docker
Primero vamos a construir nuestra imagen con base en php 8.2
y Apache
.
Archivo Dockerfile
:
# Usar la imagen base de PHP con Apache
FROM php:8.2-apache
# Instalar OpenSSL y cualquier otra extensión necesaria
RUN apt-get update && apt-get install -y libssl-dev zip unzip git \
&& docker-php-ext-install mysqli \
&& a2enmod rewrite \
&& docker-php-ext-enable mysqli
# Instalar Composer dentro del contenedor (opcional si quieres usarlo aquí)
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Configurar el directorio raíz de Apache
ENV APACHE_DOCUMENT_ROOT /var/www/html/public
# Exponer el puerto 80
EXPOSE 80
Vamos a instalar algunas dependencias, incluyendo composer
y al final exponemos el puerto 80
, que corresponde al puerto de http
.
Ahora, para compilarlo, vamos a pasarle esto como parámetro a nuestro archivo docker-compose.yml
:
services:
php:
build:
context: .
dockerfile: Dockerfile
container_name: php_app
volumes:
- ./app:/var/www/html
ports:
- "8080:80"
environment:
- APACHE_DOCUMENT_ROOT=/var/www/html/public
working_dir: /var/www/html
networks:
- app-network
networks:
app-network:
driver: bridge
Con esto estamos creando un volume
para editar nuestros archivos en el directorio app
y vamos a exponer el puerto 80
de nuestra imagen al 8080
, que es el que vamos a acceder.
Ejecutamos nuestro container:
docker compose up
Instalación de librerías en composer
Conectarnos a nuestro container para usar composer
e instalar las librerías que nos sirven.
Conectar al contenedor mediante bash
para usar composer
.
docker exec -it <nombre-del-contenedor-o-id-del-contenedor> bash
Instalar librerías:
composer require google/apiclient
composer require phpmailer/phpmailer
Una vez instaladas esas dos, podemos salir del contenedor para usar sus clases.
Script para enviar correos con Gmail y PHP
Una vez que se ha instalado todo, iremos a nuestro archivo app/index.php
.
Encabezado
Iremos por partes. Primero vamos a cargar la información con autoload
y llamar las clases que vamos usar:
<?php
require "vendor/autoload.php";
use Google\Client;
use Google\Service\Gmail;
use Google\Service\Gmail\Message;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$account = "[email protected]";
$fromName = "El nombre de mi empresa";
$toEmail = "[email protected]";
$toName = "Manuel Hernandez";
$jsonConfig = "gmail.json";
Además asignamos los valores de from
y to
, así como el archivo JSON que descargamos cuando creamos la cuenta de servicio en Google.
PHP Mailer
PHP Mailer es la librería que nos permitirá generar el formato correcto para que las clases de Google puedan tomar el valor y enviarlo mediante sus funciones.
...
$mail = new PHPMailer();
$mail->isSMTP();
$mail->CharSet = PHPMailer::CHARSET_UTF8;
$mail->setFrom($account, $fromName);
$mail->addAddress($toEmail, $toName);
$mail->Subject = "Mi asunto";
$mail->Body = "Este es un mensaje HTML";
$mail->AltBody = "Texto plano para cuando no soporten HTML";
if (!$mail->preSend()) {
throw new Exception("Mailer Error: " . $mail->ErrorInfo);
}
$mimeMessage = $mail->getSentMIMEMessage();
OJO: aquí no usamos PHP Mailer para enviar nada, solo construimos todo el mensaje y al final obtener el formato correcto con
getSentMIMEMessage()
. Podemos hacerlo sin esto, pero pa’ qué batallamos.
Cliente de Google
Ahora, con el texto ya formateado para poderlo enviar, necesitamos empezar a configurar el cliente de Google de PHP para enviar el correo.
...
$client = new Client();
$client->setAuthConfig($jsonConfig);
// scope list on vendor/google/apiclient-services/src/Gmail.php
$client->setScopes(Gmail::GMAIL_SEND);
$client->setSubject($account);
$service = new Gmail($client);
$encodedMessage = base64_encode($mimeMessage);
$encodedMessage = str_replace(["+", "/", "="], ["-", "_", ""], $encodedMessage);
$message = new Message();
$message->setRaw($encodedMessage);
try {
$service->users_messages->send($account, $message);
echo "Message sent successfully";
} catch (Google\Service\Exception $e) {
echo "An error occurred: " . $e->getMessage();
} catch (Exception $e) {
echo "An error occurred: " . $e->getMessage();
}
Claves:
- Primero creamos un
Client
de Google para poder enviar las credenciales JSON y enviarle los scopes autorizados (esto se crea en la consola de administración de Google en la delegación de autoridad de dominio). Con esto lo que hacemos es decirle a Google que tenemos todo en regla para poder comunicarnos. - Luego creamos un cliente de
Gmail
y enviamos nuestro cliente creado y autorizado. - Luego en
$encodedMessage
guardamos una versión en “Base64 URL-safe”, reemplazando los caracteres “+”, “/” e “=”. - Creamos una instancia de
Message
que está dentro deGmail
(asegúrate de esto). Le enviamos nuestro mensaje codificado.
Script completo
Aquí tienes el script completo para enviar correos con Gmail y PHP.
<?php
require "vendor/autoload.php";
use Google\Client;
use Google\Service\Gmail;
use Google\Service\Gmail\Message;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$account = "[email protected]";
$fromName = "El nombre de mi empresa";
$toEmail = "[email protected]";
$toName = "Manuel Hernandez";
$jsonConfig = "gmail.json";
// ====================> PHP MAILER <====================
$mail = new PHPMailer();
$mail->isSMTP();
$mail->CharSet = PHPMailer::CHARSET_UTF8;
$mail->setFrom($account, $fromName);
$mail->addAddress($toEmail, $toName);
$mail->Subject = "Mi asunto";
$mail->Body = "Este es un mensaje HTML";
$mail->AltBody = "Texto plano para cuando no soporten HTML";
if (!$mail->preSend()) {
throw new Exception("Mailer Error: " . $mail->ErrorInfo);
}
$mimeMessage = $mail->getSentMIMEMessage();
// ====================> GMAIL <====================
$client = new Client();
$client->setAuthConfig($jsonConfig);
$client->setScopes(Gmail::GMAIL_SEND); // scope list on vendor/google/apiclient-services/src/Gmail.php
$client->setSubject($account);
$service = new Gmail($client);
$encodedMessage = base64_encode($mimeMessage);
$encodedMessage = str_replace(["+", "/", "="], ["-", "_", ""], $encodedMessage);
$message = new Message();
$message->setRaw($encodedMessage);
try {
$service->users_messages->send($account, $message);
echo "Message sent successfully";
} catch (Google\Service\Exception $e) {
echo "An error occurred: " . $e->getMessage();
} catch (Exception $e) {
echo "An error occurred: " . $e->getMessage();
}
Puedes ver un hilo acá si tienes algunos problemas.
En otro post lo enviaremos con Go (Golang), pa’ que tengas variedad.
¡Gracias por leer!