Como enviar e-mails em massa em PHP, dentro dos limites de utilização do serviço de e-mail?

Neste procedimento iremos entender como enviar e-mails em massa dentro de nossos limites permitidos.

Notas importantes

1. Criando o script PHP

Crie um arquivo chamado mail_lotes.php com o conteúdo abaixo:

<?php
/**
 * Exemplo de envio de e-mails autenticados em lote com PHPMailer
 */

require __DIR__.'/PHPMailer/Exception.php';
require __DIR__.'/PHPMailer/PHPMailer.php';
require __DIR__.'/PHPMailer/SMTP.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');

// Ativa exceções no PHPMailer
$mail = new PHPMailer(true);

// Corpo da mensagem
$body = 'Conteúdo do e-mail em HTML ou texto simples.';

// Configurações SMTP
$mail->isSMTP();
$mail->Host = 'smtp.seudominio.com.br';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; // Mantém a conexão aberta para reduzir overhead
$mail->Port = 587;
$mail->Username = 'conta@seudominio.com.br';
$mail->Password = 'suasenha';

// Remetente
$mail->setFrom('conta@seudominio.com.br', 'Gerenciador de Lista');

// Assunto
$mail->Subject = 'Teste de envio em lote com PHPMailer';

// Corpo em HTML e texto alternativo
$mail->msgHTML($body);
$mail->AltBody = 'Para visualizar esta mensagem, utilize um cliente de e-mail compatível com HTML.';

// Conexão com banco de dados
$mysql = mysqli_connect('mysql.seudominio.com.br', 'usuario', 'senha');
mysqli_select_db($mysql, 'banco');

$result = mysqli_query($mysql, "SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE");

foreach ($result as $row) {
    try {
        $mail->addAddress($row['email'], $row['full_name']);
    } catch (Exception $e) {
        echo 'Endereço inválido ignorado: ' . htmlspecialchars($row['email']) . '<br>';
        continue;
    }

    // Anexa foto caso exista no banco
    if (!empty($row['photo'])) {
        $mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
    }

    try {
        $mail->send();
        echo 'Mensagem enviada para: ' . htmlspecialchars($row['full_name']) . ' (' . htmlspecialchars($row['email']) . ')<br>';

        // Marca como enviada
        mysqli_query(
            $mysql,
            "UPDATE mailinglist SET sent = TRUE WHERE email = '" .
            mysqli_real_escape_string($mysql, $row['email']) . "'"
        );
    } catch (Exception $e) {
        echo 'Erro ao enviar para (' . htmlspecialchars($row['email']) . '): ' . $mail->ErrorInfo . '<br>';
        $mail->getSMTPInstance()->reset();
    }

    // Limpa destinatários e anexos para a próxima iteração
    $mail->clearAddresses();
    $mail->clearAttachments();
}

// Intervalo entre os envios
$seconds = 12;
echo("<meta http-equiv=\"refresh\" content=\"" . $seconds . "\">");
?>

2. Publicando o arquivo

Envie o arquivo mail_lotes.php para o seu servidor utilizando um cliente FTP.
Ele pode ser colocado na raiz do seu domínio ou em um diretório de sua preferência.

3. Observações finais

  • Este exemplo envia 10 e-mails a cada 12 segundos, reduzindo o risco de acúmulo de mensagens no serviço de e-mail.
  • Substitua os valores de exemplo:
    • conta@seudominio.com.br → pela sua conta de e-mail válida
    • mysql.seudominio.com.br → pelo endereço do banco de dados
    • usuario e senha → pelas credenciais corretas do MySQL

AVISO LEGAL: Os procedimentos descritos neste documento devem ser executados de acordo com o contexto de cada sistema, de forma a evitar impactos negativos à segurança, disponibilidade, integridade e privacidade de dados. A CentralServer se reserva o direito de modificar a qualquer tempo e sem aviso prévio as informações aqui apresentadas a fim de refletir o lançamento de novos serviços, atualizações físicas e operacionais, e evolução do estado-da-arte da tecnologia.