PHP tiene una función nativa denominada mail
que nos permite enviar correos electrónicos de una manera muy sencilla. en este apartado veremos cómo enviar un correo electrónico con archivos adjuntos e incluir una estructura HTML que será útil para agregar algún tipo de presentación.
Plantilla HTML
Crearemos nuestra plantilla HTML con todos los medios necesarios, cabe mencionar que los estilos CSS deben ser inline (estilos en línea). por otro parte, se recomienda usar tablas para maquetar la estructura HTML, ya que los servicios de correo electrónico actuales aun no so portan las últimas especificaciones de CSS.
function layoutTemplate($contentHTML = '')
{
return '<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Email</title>
</head>
<body>
<div style=\'background: #FAFAFA; padding: 5rem 0; text-align: center;\'>
<div style=\'max-width:590px!important; width:590px; background: white;padding: 1rem;margin: auto;\'>
' . $contentHTML . '
</div>
</div>
</body>
</html>
';
}
Enviar correo electrónico
Crearemos una función reutilizable para enviar correos electrónicos desde cualquier parte de nuestro código PHP.
function sendEmail($to, $subject, $from, $senderName, $message, $files = array())
$to
: destinatario del correo electrónico.$subject
: asunto del correo electrónico.$from
: remitente del correo electrónico.$senderName
: nombre del remitente$message
: mensaje o contenido HTML del correo electrónico.$files
: matris de las rutas absolutas de los archivos a enviar (parámetro opcional).
Esta función se divide en cinco partes principales que detallaremos a continuación.
Declaracion de variables
Declararemos algunas variables que nos serán de utilidad más adelante.
$semiRand = md5(time());
$separator = "==Multipart_Boundary_x{$semiRand}x";
$eol = "\r\n";
$separator
: separador con un hash que es muy necesario para enviar contenido mixto.$eol
: retorno de carro de tipo (RFC).
Encabezados
En los encabezados del correo electrónico podremos indicar el origen, destinatario, copia y el tipo de contenido que se enviará al destinatario.
$headers = "From: {$senderName} <{$from}>" . $eol;
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"{$separator}\"" . $eol;
$headers .= "Content-Transfer-Encoding: 7bit" . $eol;
Mensaje y/o contenido HTML
Añadiremos el contenido HTML de nuestro mensaje al destinatario, usando la plantilla HTML que creamos anteriormente.
$body = "--{$separator}" . $eol;
$body .= "Content-Type: text/html; charset=\"UTF-8\"" . $eol;
$body .= "Content-Transfer-Encoding: 7bit" . $eol;
$body .= layoutTemplate($message) . $eol;
Archivos
Recorremos todos los archivos que deseamos enviar y por cada archivo extraemos el tipo de archivo, tamaño y nombre y lo codificamos en base64, de esta manera podremos enviar el archivo como una cadena de texto en base64.
for ($i = 0; $i < count($files); $i++) {
if (is_file($files[$i])) {
$fileName = basename($files[$i]);
$fileSize = filesize($files[$i]);
$fileType = mime_content_type($files[$i]);
$fileStream = fopen($files[$i], "rb");
$fileContent = fread($fileStream, $fileSize);
fclose($fileStream);
$fileContentEncoded = chunk_split(base64_encode($fileContent));
$body .= "--" . $separator . $eol;
$body .= "Content-Type: $fileType; name=\"" . $fileName . "\"" . $eol;
$body .= "Content-Transfer-Encoding: base64" . $eol;
$body .= "Content-Disposition: attachment; filename=\"" . $fileName . "\"" . $eol;
$body .= "X-Attachment-Id: " . rand(1000, 99999) . $eol . $eol;
$body .= $fileContentEncoded . $eol;
}
}
Enviar correo
Finalmente llamaremos la función nativa mail
de PHP al cual le pasaremos los parámetros necesarios que construimos anteriormente.
mail($to, $subject, $body, $headers);
Enviar correo de ejemplo
Este es un ejemplo de cómo usar la función que creamos para el envío de correo electrónico.
$respuesta = sendEmail('[email protected]', 'Hola mundo', '[email protected]', 'admin', 'hola mundo', [__DIR__, '/archivo.txt']);
if ($respuesta) {
echo 'El correo se envió exitosamente';
} else {
echo 'No se pudo enviar el correo electrónico.';
}
Versión final
function layoutTemplate($contentHTML = '')
{
return '<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Email</title>
</head>
<body>
<div style=\'background: #FAFAFA; padding: 5rem 0; text-align: center;\'>
<div style=\'max-width:590px!important; width:590px; background: white;padding: 1rem;margin: auto;\'>
' . $contentHTML . '
</div>
</div>
</body>
</html>
';
}
function sendEmail($to, $subject, $from, $senderName, $message, $files = array())
{
// Vars
$semiRand = md5(time());
$separator = "==Multipart_Boundary_x{$semiRand}x";
$eol = "\r\n";
// Header
$headers = "From: {$senderName} <{$from}>" . $eol;
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"{$separator}\"" . $eol;
$headers .= "Content-Transfer-Encoding: 7bit" . $eol;
// Message
$body = "--{$separator}" . $eol;
$body .= "Content-Type: text/html; charset=\"UTF-8\"" . $eol;
$body .= "Content-Transfer-Encoding: 7bit" . $eol;
$body .= layoutTemplate($message) . $eol;
// Attachment
for ($i = 0; $i < count($files); $i++) {
if (is_file($files[$i])) {
$fileName = basename($files[$i]);
$fileSize = filesize($files[$i]);
$fileType = mime_content_type($files[$i]);
$fileStream = fopen($files[$i], "rb");
$fileContent = fread($fileStream, $fileSize);
fclose($fileStream);
$fileContentEncoded = chunk_split(base64_encode($fileContent));
$body .= "--" . $separator . $eol;
$body .= "Content-Type: $fileType; name=\"" . $fileName . "\"" . $eol;
$body .= "Content-Transfer-Encoding: base64" . $eol;
$body .= "Content-Disposition: attachment; filename=\"" . $fileName . "\"" . $eol;
$body .= "X-Attachment-Id: " . rand(1000, 99999) . $eol . $eol;
$body .= $fileContentEncoded . $eol;
}
}
// $body .= "--{$separator}--";
// $returnpath = "-f" . $senderEmail;
return mail($to, $subject, $body, $headers);
}
$respuesta = sendEmail('[email protected]', 'Hola mundo', '[email protected]', 'admin', 'hola mundo', [__DIR__, '/archivo.txt']);
if ($respuesta) {
echo 'El correo se envió exitosamente';
} else {
echo 'No se pudo enviar el correo electrónico.';
}