Envio duplicado de e-mail

33 views
Skip to first unread message

Gustavo Almeida

unread,
Aug 2, 2019, 9:49:20 AM8/2/19
to list...@googlegroups.com
Amigos,

Estou com um problema que não estou conseguindo achar solução. Tenho um
script rodando no CRON do servidor a cada 1 minuto.

Esse script lê uma tabela com uma fila de e-mails no banco de dados e
faz o envio.

Ocorre que os e-mails estão sendo enviados 2 ou 3 vezes para vários
destinatários.

E já revirei o código e definitivamente não há loop em lugar nenhum que
faça o envio duas vezes.

E também já conferi na fila do banco e não tem linha duplicada na tabela.


O código é o seguinte:

$tabela = $conexao->prepare ("SELECT id_mensagem, nome, email, mensagem,
assunto FROM emails WHERE enviado=0 limit 0, 300");
    $tabela->execute ();
    $tabela->bind_result ($id_mensagem, $nome, $email, $mensagem,
$assunto);
    $tabela->store_result();

    $i = 0;
    while ( $tabela->fetch () ) {
        $i = $i+1;

        $mail->Subject = $assunto;
        $mail->Body    = $mensagem;
        $mail->addAddress($email, $nome);

        if (!$mail->Send()){
            mail("con...@diligenciaexpressa.com.br","Erro enviando
e-mail #" . $id_mensagem, $mail->ErrorInfo);
            mysqli_query($conexao, "update emails set enviado=99,
dia='" . date("Y-m-d") . "' where id_mensagem=" . $id_mensagem);
            $erro = $erro + 1;
        }else{
            mysqli_query($conexao, "update emails set enviado=1, dia='"
. date("Y-m-d") . "' where id_mensagem=" . $id_mensagem);
            $sucesso = $sucesso + 1;
        }

        $mail->clearAddresses();
        if ($i==20){
            sleep(1);
            $i = 0;
        }
    }


Alguém tem alguma luz??????


---
Este email foi escaneado pelo Avast antivírus.
https://www.avast.com/antivirus

Diogo Alexsander Cavilha

unread,
Aug 2, 2019, 9:54:23 AM8/2/19
to list...@googlegroups.com
Bom dia, amigo.

Pode enviar como está a configuração da cron?
Você já debugou o while pra verificar as linhas que o fetch() tá retornando?

Abraço.

Diogo Alexsander Cavilha. 
Skype: diogocavilha


--
--
============================================================
JQUERY MAGAZINE > http://www.jquerymagazine.com.br
--
PHP MAGAZINE > http://www.phpmagazine.com.br
--
LISTA NODE.JS > https://groups.google.com/group/lista-nodejs?hl=pt-br
--
AJAX-BRASIL > http://groups.google.com/group/ajax-brasil
--
PYTHON-GOOGLE > http://groups.google.com.br/group/python-google
--
DOTNET-BRASIL > http://groups.google.com.br/group/dotnet_br
============================================================

---
Você está recebendo esta mensagem porque se inscreveu no grupo "LISTA PHP" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para listaphp+u...@googlegroups.com.
Para ver esta discussão na web, acesse https://groups.google.com/d/msgid/listaphp/ea3ef1a1-1043-d8fe-3fb8-65d109773620%40gmasoftwares.com.br.

Cassiano Ricardo Mourão

unread,
Aug 2, 2019, 9:56:57 AM8/2/19
to list...@googlegroups.com
Simples:

1) O envio total pode demorar mais de 1 minuto e no segundo processamento os mesmos endereços são coletados;
2) Existe outro cron configurado (ou em outro servidor).


Gustavo Almeida

unread,
Aug 2, 2019, 10:02:01 AM8/2/19
to list...@googlegroups.com

O Cron está configurada para executar a cada minuto:

* * * * * php -q /home/caminho/do/aquivo.php

Sobre o fetch(), ele tá retornando as linhas perfeitamente, uma por uma, sem duplicidade.

A impressão que eu tenho é o seguinte:
Meu script pega os registro da fila que estão com "enviado = 0" e faz o envio e executa um update para enviado=1.

É como se esse "update" estivesse com um delay e no minuto seguinte, quando o script roda de novo, o enviado dos registros ainda estivessem com 0.

E já verifiquei se o script não está demorando mais do que 1 minuto pra terminar a execução (o que encavalaria uma execução por cima da outra) e não é o caso.
Por conta do sleep() no meio do código ele leva uns 30 segundos pra executar.
Você recebeu essa mensagem porque está inscrito no grupo "LISTA PHP" dos Grupos do Google.

Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para listaphp+u...@googlegroups.com.

Renato de Freitas Freire

unread,
Aug 2, 2019, 10:09:18 AM8/2/19
to list...@googlegroups.com
Roda seu script com o flock... assim vc não depende da sorte pra evitar q um script rode por cima do outro...

/usr/bin/flock -n /tmp/nomedoseu.lockfile php /var/www/html/seuscript.php > /var/log/seuarquivode.log

-n lockfile -> define um lockfile que é criado no inicio do script e removido no final da execução
O flock sempre vai verificar se já existe um lockfile.. se existir, ele não executa o script.. se não existir, cria o lockfile e executa o script...

Pode não ser o seu problema (apesar de quase certeza que é), mas é uma boa prática rodar scripts no cron dessa forma...

--
Renato



Gustavo Almeida

unread,
Aug 2, 2019, 10:20:02 AM8/2/19
to list...@googlegroups.com

Não conhecia esse comando.

Vou tentar aqui e ver se resolve! Obrigado!

Marcos Bernardo

unread,
Aug 2, 2019, 10:30:11 AM8/2/19
to list...@googlegroups.com
Cara trabalhei com filas e um solução logica seria... Na sua flag Enviado qndo vc selecionar vc faz um update para enviado = 1 e depois q vc envio vc faz update  para enviado = 2... Assim qndo for selecionar vc faz o select so em enviados = 0....caso de algum problema vc sabe o que foi enviado e o q não pela flag...

Espero ter ajudado abraço

Samuel Aiala

unread,
Aug 16, 2019, 7:28:48 AM8/16/19
to list...@googlegroups.com
Também acho que seja isso ... fica meu comentário aqui só pelo flock que eu não conhecia, valeu a dica! 

----------------------------------------------------------------------
Samuel Aiala Ferreira

sam...@samuca.com
31-8449-8313


João Paulo (littleoak)

unread,
Sep 14, 2019, 5:01:08 PM9/14/19
to Listaphp
1 - Você está enviando emails sem autenticação?
Por que o correto era php mailer e não a função mail() que sendo ela básica vai simplesmente deixar o envio cair 100% em spam, sem contar outras coisas.
2 - Provavelmente seu retorno de emails pode estar rodando com tudo e simplesmente não terminou. Eu sempre uso + 1 tabela no BD com algo como "campanhas", id, disparo e statusfinal, se não estiver como finished o último ele não dispara :).
Flock é do caramba mesmo, bem lembrado pelo companheiro lá em cima.




Mailtrack Sender notified by
Mailtrack 14/09/19 17:57:33



--
--------------------------------
"O que vale é a intensidade do fôlego que se toma para grandes realizações!"
Thanks God.

DGmike

unread,
Sep 16, 2019, 8:22:23 AM9/16/19
to LISTA PHP
Estou sentindo falta de alguns logs na sua aplicação para facilitar o entendimento do processo.

Experimenta colocar algum log em arquivo ou coisa parecida... Tipo, horário que começou a executar, horário que terminou, a query executada... talvez isso te ajude a dar uma luz.

Ah, não precisa ser algo complexo com biblioteca e talz... faz uma função log simples...

<?php

function logMessage($logFile, $message) {
  $message = '[' . date('Y-m-d\TH:i:sP') . '] ' . $message . PHP_EOL; // particularmente, prefiro usar sprintf
  file_put_contents($logFile, $message);
}

$logFile = 'logs/log-cron-' . date('Y-m-d\TH:i:sP') . '.log';

logMessage($logFile, 'Iniciando o cron');
logMessage($logFile, 'Finalizando o cron');

Rubens Takiguti Ribeiro

unread,
Sep 16, 2019, 7:37:33 PM9/16/19
to list...@googlegroups.com
Você está usando o banco de dados como fila. Se puder trocar por uma fila de verdade, seria melhor.

Mas se não der, é possível garantir que os registros não sejam pegos e atualizados em processos paralelos usando transações de bancos de dados, com o nível de isolamento de transações apropriado.

Pro banco simular uma fila, precisaria ler um registro por vez, até acabar, e atualizar o bd antes de enviar o email, para que a transação falhe caso outro processo tenha pego o mesmo registro. Caso o envio do email falhe, você precisa fazer um rollback manual.

Dê uma olhada nesse artigo sobre isolamento de transações:

O PDO do PHP tem métodos próprios para iniciar/terminar/reverter transações. Dê uma olhada também.

Colocar um log também ajuda, como meu amigo Michael comentou.

--
--
============================================================
JQUERY MAGAZINE > http://www.jquerymagazine.com.br
--
PHP MAGAZINE > http://www.phpmagazine.com.br
--
LISTA NODE.JS > https://groups.google.com/group/lista-nodejs?hl=pt-br
--
AJAX-BRASIL > http://groups.google.com/group/ajax-brasil
--
PYTHON-GOOGLE > http://groups.google.com.br/group/python-google
--
DOTNET-BRASIL > http://groups.google.com.br/group/dotnet_br
============================================================

---
Você recebeu essa mensagem porque está inscrito no grupo "LISTA PHP" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para listaphp+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages