Como enviar e-mails para vários destinatários

Pelo título, aposto que você pensou “basta utilizar ‘com cópia’ (Cc) ou ‘com cópia oculta’ (CCO)”. Isso pode ser feito através de qualquer e-mail, porém vamos observar como fazer isso através de quatro maneiras diferentes: (1) importando-se uma lista de contatos de uma tabela MySQL e criando um grupo para o envio desse e-mail; (2) utilizando-se um conjunto de funções do PHPMailer rodando em um servidor LAMP; (3 e 4) rodar rotina em python com alguns módulos; (5) via terminal Linux usando shell script e o programa mutt; (6) via terminal, com o Sendemail.

caixa-de-correios-lotada

1 – Gmail

No Gmail, existe a possibilidade de criar um grupo e importar os contatos de um arquivo “.csv”. Para isso, entre no MySQL (supondo que seus contatos estejam lá), selecione a base de dados e digite a seguinte linha de comando para criar o arquivo:

SELECT nome, sobrenome, email FROM nome_da_tabela INTO OUTFILE '/tmp/contatos.csv' FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

Escolhi gravar na pasta de temporários por causa de permissões de leitura (copie o arquivo para uma outra pasta); os campos a serem gravados estão na ordem apresentada (nome, sobrenome, email) e serão delimitados por vírgula. Abra o arquivo para edição e coloque na primeira linha o cabeçalho. Nesse caso, deixei “Name,Family Name,E-mail 1 – Value” para corresponder aos campos disponíveis no arquivo.

Vá para o Gmail, clique em Gmail no canto superior esquerdo da página e depois em Contatos. Clique no botão Mais, acima da lista de contatos, e selecione Importar. Escolha o arquivo e pronto (mais detalhes no site do Google). Ou importe/copie o arquivo no google drive, clique em Ferramentas -> Galeria de Scripts, busque por “mail merge” e escolha um.

2 – PHPMailer

Por medida de segurança contra spam e abusos, alguns servidores de e-mail desativam sua conta temporariamente se você enviar mensagens para mais de x destinatários (no caso do Gmail, esse x é de 500 pessoas) ou enviar uma grande quantidade de mensagens devolvidas. Nesse caso, utilizaremos a clássica instalação LAMP (Linux, Apache, MySQL e PHP) e o PHPMailer.

O PHPMailer é uma classe pronta para envio de e-mails através do PHP via conexão SMTP ou POP3. Seu método de envio é largamente recomendado e é bem melhor do que o envio do mail(), que é a função padrão do PHP (a não ser que queira configurar um servidor de e-mails na sua máquina). Baixe os arquivos class.phpmailer.php e class.smtp.php (ou class.pop3.php, se for o caso) do zip disponível no site do github PHPMailer e coloque-os em um diretório.

O script para envio de e-mails contém um while para ler os campos ‘nome’, ‘sobrenome’ e ‘email’ da tabela usuarios, contida na base de dados cadastro do MySQL, e envio de cada e-mail. No final, imprime uma linha com os dados do e-mail enviado, se foi enviado com sucesso (não quer dizer que foi recebido ou lido) e o comando sleep. A função sleep atrasa a execução de um código, de acordo com a quantidade de segundos informados no parâmetro seconds da função. É muitas vezes necessário porque grande parte dos provedores de hospedagem limitam a quantidade de envio de e-mails, geralmente em 300 por hora.

<?php
// Inclui o arquivo class.phpmailer.php localizado na pasta PHPMailer
require('PHPMailer/class.phpmailer.php');
// Conexão com banco de dados MySQL
define('BD_USER', 'usuario');
define('BD_PASS', 'senha');
define('BD_NAME', 'base_de_dados');
mysql_connect('IP_ou_localhost', BD_USER, BD_PASS);
mysql_select_db(BD_NAME);
// Define busca a ser realizada no MySQL
$query= 'SELECT nome, sobrenome, email FROM usuarios;';
$resultado = mysql_query($query);
while ($linha = mysql_fetch_array($resultado, MYSQL_BOTH)) {
// Seleciona os campos, para cada linha
$nome=$linha['nome'];
$sobrenome=$linha['sobrenome'];
$email=$linha['email']; // Variáveis com assunto e mensagem
$subject = "\"Assunto da mensagem\"";
$mensagem = " Caro $nome $sobrenome, Aqui está a mensagem, Atenciosamente, Spammer "; // Inicia a classe PHPMailer
$mail=new PHPMailer(); // Define os dados do servidor e tipo de conexão
$mail->IsSMTP(); // Define que a mensagem será SMTP
$mail->SMTPAuth=true; // Usa autenticação SMTP? (obrigatório para alguns servidores, como o gmail)
$mail->Port=465;
$mail->SMTPSecure = "ssl";
$mail->Host='smtp_do_servidor';
$mail->Username='seu_e-mail'; // Usuário do servidor SMTP
$mail->Password='senha'; // Senha do servidor SMTP
// Define o remetente
$mail->SetFrom('seu_e-mail','seu_nome');
// Define os destinatário(s)
$mail->AddAddress($email,$nome.' '.$sobrenome);
//$mail->AddBCC('seu_e-mail', 'seu_nome'); // Cópia Oculta
// Define os dados técnicos da Mensagem
//$mail->IsHTML(true); // Define que o e-mail será enviado como HTML
//$mail->CharSet = 'UTF-8'; // Charset da mensagem (opcional)
$mail->Subject=$subject;
$mail->Body=$mensagem;
//$mail->AltBody = "Este é o corpo da mensagem de teste, em Texto Plano!";
//$mail->AddAttachment("/temp/documento.pdf", "novo_nome.pdf");  // Insere um anexo
// Cria e imprime variável de controle
$imprime=$nome." ".$sobrenome." ".$email."
";
// Exibe uma mensagem de resultado
echo $imprime;
if($mail->Send()){// Envia o e-mail
echo 'E-mail enviado com sucesso!';
}else{
echo 'Erro ao enviar e-mail: '.$mail->ErrorInfo;
}
sleep(10);
}
?>

Deixei comentado alguns itens opcionais, como texto plano, anexo e cópia oculta. Assim que conseguir configurar uma maneira de deixar mais apresentável o código acima eu arrumo.

3 – Python

Segue um script em python para envio de e-mail. Caso o servidor de e-mails seja local, só precisa mudar remetente, destinatário e assunto/mensagem. Porém, é possível também utilizar algum outro servidor SMTP, como o Gmail. Nesse caso, este servidor de e-mail requer conexão segura e por isso deve-se o comando “starttls”, além da identificação (duas vezes) com o comando “ehlo” e o login.

#!/usr/bin/python
#encoding: utf-8
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

sender = "E-MAIL_REMETENTE"
receivers = "DESTINATARIO_1, DESTINATARIO_2"
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = receivers
msg['Subject'] = "Teste de e-mail"

body = "Esse e-mail é um teste."
msg.attach(MIMEText(body, 'plain'))

try:
   smtpObj = smtplib.SMTP('localhost')
   #smtpObj = smtplib.SMTP("smtp.gmail.com",587)
   #smtpObj.ehlo()
   #smtpObj.starttls()
   #smtpObj.ehlo()
   #smtpObj.login("LOGIN_USER", "SENHA")
   smtpObj.sendmail(sender, receivers, msg.as_string())
   print "Email enviado!"
except smtplib.SMTPException:
   print "Error: Ocorreu um erro ao enviar o email"

Importante: deve-se também ativar a opção “Acesso para aplicativos menos seguros” na conta do Gmail utilizada.

Essa outra função é um pouco mais completa. Ela permite também enviar anexos e mantém os destinatários como “cópia oculta”, para não aparecer o e-mail de todo mundo no campo de destinatários:

def send_mail(self, send_from, send_to, subject, textfile, files, server):
	from os.path import basename
	import smtplib
	from email.mime.multipart import MIMEMultipart
	from email.mime.text import MIMEText
	from email.mime.application import MIMEApplication
	from email.utils import COMMASPACE
	assert isinstance(send_to, list)
	
	msg = MIMEMultipart()
	msg['From'] = send_from
	msg['To'] = ''
	msg['Bcc'] = COMMASPACE.join(send_to)
	msg['Subject'] = subject
	# Include a text/plain message from file
	with open(textfile) as fp:
		msg.attach(MIMEText(fp.read()))

	for f in files or []:
		with open(f, "rb") as fil:
			part = MIMEApplication(fil.read(),Name=basename(f))
		# After the file is closed
		part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
		msg.attach(part)
	
	smtp = smtplib.SMTP(server)
	smtp.sendmail(send_from, send_to, msg.as_string())
	smtp.close()

Essa função recebe e-mail de quem vai enviar, uma lista com os nomes dos destinatários (pode ser uma lista com 1 item apenas), assunto, nome do arquivo com o corpo do e-mail, uma lista com os caminhos completos (com os nomes) dos arquivos anexos (pode ser uma lista com apenas 1 item ou também uma lista vazia, se não tiver anexos) e o endereço do servidor de e-mails (geralmente “localhost”).

4 – Python + Gmail com OAuth (incluído em setembro de 2021)

O pacote YagMail (instalado como “conda install -c conda-forge yagmail premailer”) é um cliente GMAIL/SMTP simples que permite facilitar o envio de e-mail para múltiplos destinatários. Para utilizá-lo, você pode usar um comando com e-mail e senha diretamente (linha comentada no código abaixo, necessitando autoriação de “acesso para aplicativos menos seguros”) ou usar permissão OAuth 2 (mais indicado).

No segundo caso, você deve criar um projeto no um projeto no Google Cloud Console e ativar a Google Workspace API (mais detalhes no link). Você também deverá criar credenciais para uso (GMAIL API opção “dados do usuário” e ID do cliente OAuth como “app para computador”). Usando a API como teste (sem publicar), você deverá também incluir o e-mail que for fazer os envios na lista de autorizados (mesmo que seja o próprio e-mail da conta) na “Tela de permissão OAuth”.

O script a seguir faz o envio do texto (variável “msg”) com o assunto (“subject”) e o arquivo em anexo (“att”) para os emails listados no arquivo “destinatarios.csv”, que está no formato “nome,empresa,e-mail” – “name” e “company” entram no corpo do texto.

#!/usr/bin/env python3.7.10
# -*- coding: utf-8 -*-

import csv
import yagmail

def send_mail(name, company, dest, subject, att):
    '''
    Mount and send e-mail
    '''
    yag = yagmail.SMTP('EMAIL@gmail.com', oauth2_file= 'credentials.json')
    #yag = yagmail.SMTP(user='EMAIL@gmail.com', password='SENHA')
    msg = f'Prezado(a) {name} do(a) {company},\n\n\
Esse é o corpo do e-mail.\n\n\
Atenciosamente,\n\
Monolito Nimbus'
    #print(msg)
    # Send e-mail
    yag.send(to=dest, subject=subject, contents=msg, attachments=att)

# Define e-mail subject
subject = 'Teste de e-mail'
# Define attachment file name - list for more than one
att = 'anexo.pdf'
# Read file with all e-mails (name,company,email)
with open('destinatarios.csv', encoding='utf8') as fname:
    info = csv.DictReader(fname, dialect='excel')
    for row in info:
        name = row['name']
        company = row['company']
        dest = row['email']
        print(f'Sending mail to {name} from {company} - {dest}')
        send_mail(name, company, dest, subject, att)

Você também pode inserir uma imagem entre textos configurando a variável ‘msg’ (argumento de entrada do corpo do e-mail) decompondo a mensagem em duas partes de texto com o método “inline” no meio, juntando tudo em uma lista, conforme segue:

msg = [msg1, yagmail.inline("path_to_file/imagem.jpg"), msg2]

Ao executar o script pela primeira vez, será solicitado e-mail e um código de verificação, fornecida por uma URL impressa na tela nesse momento. Essas informações serão salvas (e futuramente consultadas) no arquivo “credentials.json” – sobrescreve o arquivo originalmente baixado. Por padrão, a validade dessas credenciais é de 1 dia, então é preciso ir nas credenciais e clicar em “editar” o cliente para “redefinir secret”. Então você deve baixar o arquivo e repetir o procedimento. Veja mais no github: viniroger/send_email.

5 – Shell script com Mutt

Outra maneira é enviar e-mail pelo terminal com o mutt (clique no link para ver mais a respeito). Instale através do comando “sudo apt-get install mutt”, crie o arquivo “~/.muttrc” conforme indicado no link e envie o e-mail conforme comando que segue abaixo. O shell script a seguir lê os e-mails dos destinatários de uma lista no arquivo “destinatarios.txt” (somente um e-mail por linha) com o assunto indicado no parâmetro “-s”, “-c” indica os e-mails com cópia, “b” para cópia oculta e um arquivo anexo indicado por “-a”:

for mail in `cat destinatarios.txt`; do
	echo enviando $arq para $mail
	cat 'conteúdo do e-mail' | mutt -s "Assunto do e-mail" -a $arq -- $mail
done

Observe que após o nome do último arquivo a anexar deve-se colocar dois traços para depois informar o(s) destinatário(s).

Certas definições podem ser colocadas no arquivo de configuração “~/.muttrc” ou inseridas através da própria linha de comando, utilizando o parâmetro “-e” para executar um comando de configuração. Por exemplo:

  • -e ‘set realname=”Nome do Remetente”‘ # Especifica nome do remetente
  • -e ‘set from=‘ # Especifica e-mail do remetente
  • -e ‘set use_from=yes’ # Força uso do e-mail definido com o parâmetro acima
  • -e ‘my_hdr Reply-To:email1@…,email2@…’ # Define e-mails padrão para resposta
  • -e ‘set envelope_from=yes’

O “mutt” precisa mesmo de um servidor de e-mail (nesse caso, o postfix). Veja mais no manual e no wiki do Debian.

6 – Sendemail

Outra forma bem simples de envio de e-mails pelo terminal é através do programa sendemail. Instale-o pelo comando “apt-get install sendemail” e execute o comando “sendEmail” seguidos dos seguintes parâmetros para enviar o e-mail:

  • -f → e-mail do remetente
  • -t → e-mail(s) do(s) destinatário(s), separados por vírgula
  • -u → assunto
  • -m → mensagem
  • -s → endereço do servidor SMTP
  • -xu → nome de usuário
  • -xp → senha do e-mail
  • -a → caminho de arquivo anexo (opcional)

Veja um exemplo usando o gmail, com o assunto, mensagem e destinatários definidos em variáveis shell script:

sendEmail -u "$SUBJECT" -m "$MESSAGE" -f REMETENTE@gmail.com -t $SYSADMIN -s smtp.gmail.com:25 -xu REMETENTE -xp SENHA

As configurações dos servidores POP, IMAP e SMTP dos principais fornecedores de acesso à internet podem ser vistas acessando-se esse link. Veja mais detalhes no artigo Enviando e-mails pelo terminal – usando o sendEmail e alguns exemplos.

Postfix e Courier são servidores de e-mail, usados para o envio e recebimentos de mensagens, respectivamente, servidores SMTP e POP3. Sua instalação e configuração podem ser vistas nos slides do link.

Você pode verificar se o e-mail foi enviado (ou o erro, caso não tenha tido sucesso no envio) através do arquivo de log: /var/log/mail.log.

2 comments

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.