+1

Enviando Emails Autenticados com o Protocolo SMTP

criado por Carlos Sica em 19/08/2005 9:11am
Índice
1 - Conceitos Iniciais
2 - Verbos SMTP
3 - Código Fonte do Script
4 - Informações Complementares e Conclusão


O que é SMTP?
Em principio, é um servidor para enviar email, mas como o nome SMTP, que vem do inglês "Simple Mail Transfer Protocol" diz, é um Protocolo Simples de Transferência de Mensagens, eletrônicas, naturalmente.

O que é protocolo?
Protocolo é um conjunto de regras utilizadas para se estabelecer uma comunicação entre dois sistemas, neste caso, entre o cliente com o servidor.

Os protocolos trabalham através de requerimentos (requisições ou perguntas) e respostas, ou seja, o servidor emite uma resposta para cada requerimento. Em geral, os requerimentos são compostos por uma linha texto, contendo um comando que pode exigir parâmetros ou não. Já a resposta pode conter uma ou mais linhas texto, mas todas elas contém um código que pode ser de acerto ou de erro.

Como é o protocolo SMTP?
Em primeiro lugar é necessário estabelecer um canal de comunicação com o servidor. Muitas linguagens de programação oferecem alguma função que permite o estabelecimento de comunicação entre o computador cliente e o servidor. Em PHP esta função e a fsockopen() que espera como principal parâmetro, o nome do servidor para criar um socket entre o cliente e o servidor.

O que é socket?
Pense numa tomada de energia que liga o aparelho de som na rede elétrica, é essa a idéia. O computador cliente vai se conectar ao computador servidor através de uma ligação lógica para comunicação bidirecional. Esta ligação é chamada socket.

Como são os requerimentos e as respostas nesse protocolo?
Um requerimento é uma string de bytes que contém um comando, chamado na literatura técnica de verbo, que pode receber parâmetros ou não. Ao final de cada comando (e parâmetros) deve vir uma quebra de linha, pois, o próximo comando deve iniciar em uma nova linha. Em PHP a quebra de linha é comandada pelas constantes \r\n.

Forma geral de um comando para o servidor SMTP.

VERBO parâmetro\r\n

As respostas são compostas por um número de três dígitos no formato de uma string ASCII, seguido por uma mensagem explicativa. Este dois componentes podem estar separados por espaço, traço ou outro separador.

999 resposta exemplo
999-resposta exemplo

Comentários:

Mostrando 1 - 10 de 26 comentários
g disse:
ola eu tenho uma ferramenta administrativa que organiza os destinatarios entao uso uma classe que pega do banco os destinarios o assunto e envia o e-mail mais ele só esta enviando para e-mails com @bizplace.com.br para nenhum outro mais
gostaria que me desse uma luz ai vai o código:






<?
// Instancia os objetos
//require_once $path_classes."PEAR/Mail.php";
//require_once $path_classes."PEAR/Mail/mime.php";

//$mailobj =& Mail::factory($config->mail_opt["driver"], $config->mail_opt);
//$o_sql = new SQL();

// Includes
include("./templates/header.php");
include($path_classes."admin/config/config_tabela.php");
include($path_classes."admin/config/config_form.php");

$o_form = new Form();
$o_form = config_frm( $o_form );
$o_form->descricao = "&raquo; Newsletter &raquo; Enviar";
$o_form->print_desc();
$o_sql = new SQL();
$o_geral = new Geral();

echo $o_form->frm_prefix;

// Envia emails
// ----------------------------------------

IF ($tipo=="testar")
{
// Pega o destinatário (email do user logado)
$tupla = $o_sql->select("SELECT distinct(usu_e_mail) FROM usuario WHERE usu_codigo='".$_SESSION["dados"]["usu_codigo"]."'");
}
ELSE
{
// Pega os destinatários
$in = "";
for ( $ind=0; $ind<sizeof($gru_cod); $ind++)
{
$in .= $gru_cod[$ind];
IF ($ind<sizeof($gru_cod)-1)
$in .= ",";
}
if ($reman==1)
$and = " AND usu_enviad='0'";

if ($filtro!="")
{
$o_sql->execSql("update usuario set usu_enviad = '0' WHERE gru_codigo IN ($in) ".$filtro);
$tupla = $o_sql->select("SELECT distinct(usu_e_mail)
FROM usuario
WHERE gru_codigo IN ($in) "
.$filto.$and );
}
else
{
$o_sql->execSql("update usuario set usu_enviad = '0' WHERE gru_codigo IN ($in) AND usu_newsle='1'");
$tupla = $o_sql->select("SELECT distinct(usu_e_mail)
FROM usuario
WHERE gru_codigo IN ($in)
AND usu_newsle='1' ".$and );
}


}

if ($assunto=="")
{
list($ntx_codigo) = $_GET['ntx_codigo'];
// Pega o assunto da mensagem
$tupla2 = $o_sql->select("SELECT new_descri FROM newsletter WHERE new_codigo=$new_codigo");
$assunto = $tupla2[0]["new_descri"];
//echo "SELECT ntx_conteu FROM news_texto WHERE ntx_codigo=$ntx_codigo";
$vet = $o_sql->select("SELECT ntx_conteu FROM news_texto WHERE ntx_codigo='$ntx_codigo'");
$conteudo = $vet[0]["ntx_conteu"];
}

/*$mime =& new Mail_mime();
$mime->setHTMLBody($message);
$body = $mime->get();
*/$body = $message;
$headers = array();

//$headers['From'] = $config->nome_resp." <".$config->email_resp.">";
// $headers['To'] = "dud@bizplace.com.br";
$headers['Subject'] = $assunto;

$c1=0;
$sto=$msg="";

for ( $ind=0; $ind<sizeof($tupla); $ind++)
{
$sto.=$tupla[$ind]["usu_e_mail"];

if((sizeof($tupla)-1)>$ind) $sto.=",";

#if ($c1==$config->mail_fila_qtd)
$c1 = true;
if ($c1)
{
$to = $sto;
$tto = $to;

$bcc = "Bcc:".$tto;
// Envia Mensagem
#$retorno = $mailobj->send($to, $headers, $body);
echo "<pre>";
//print_r($bcc);
echo "</pre>";
#$eMail = mail("adler@bizplace.com.br,adlerdesigner@hotmail.com,","mensagem teste","MENSAGEM TESTE");
#if($eMail) { echo "enviado"; } else { echo "nao enviado"; }
#echo "headers:::::: <pre>";
#print_r($headers);
#echo "</pre>";
#$headers[MIME-Version] . $headers[Content-Type] .
#$headers[Content-Transfer-Encoding] . $headers[From] . $headers[Subject];
#echo "<br>";
$subject = $headers[Subject];
#echo "<br>";
$from = "Goedert <goedert@bizplace.com.br>";
#echo "<br>";
// Cabeçalhos que definem o e-mail como sendo em formato HTML
$cabeca = "MIME-Version: 1.0\n";
$cabeca .= "Content-type: text/html; charset=iso-8859-1\n";
#$cabeca .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$cabeca .= "From: ".$from."\n";
$cabeca .= "Return-Path: Goedert <goedert@bizplace.com.br>\n";
#$cabeca .= "Bcc: ".$tto."\n";
#$cabeca .= "To: <$tto>\n";

#$headers = "From: ".$email."\r\n" .
#"MIME-Version: 1.0\r\n" .
#"Content-Type: text/html; charset=windows-1252\r\n" .
#"Content-Transfer-Encoding: 8bit\r\n\r\n";

$corpo = $conteudo;
$corpo .= "<center><a href='http://goedert.bizwork.com.br/news_cancelar.php?email={$tupla[$ind]['usu_e_mail']}'><img src='http://goedert.bizwork.com.br/imagens/b_cancelar.jpg&#039; border=0></a></center>";
//echo $corpo;
//$retorno = mail("adler@bizplace.com.br,adlerdesigner@hotmail.com,adlerdesigner@gmail.com", "TESTE", $corpo, $cabeca); // retorna todos os emails
//echo $o_geral->alert();
$retorno = mail($tto, $subject, $corpo, $cabeca);

//$retorno = mail($emails, $subject, $corpo, $cabeca);


//$retorno = $mailobj->send($tto, $headers, $body);
//$retorno = TRUE;
IF ($retorno!==TRUE)
{
$msg = "<div align='left' valign='top' class='{$o_form->desc_class}'>Erro ao enviar e-mail!<br></div><br><br>";
break;
}
$c1 = 0;
$sto="";
}
$o_sql->execSql("update usuario set usu_enviad = '1' where usu_e_mail = '".$tupla[$ind]["usu_e_mail"]."'");
$c1++;
}

if ($sto<>"")
{
// Envia Mensagem
$sto.=$tupla[$ind]["usu_e_mail"].",";
if ($c1==$config->mail_fila_qtd)
{
$to = $sto;
$tto = $to;
$bcc = "Bcc:".$tto;
// Envia Mensagem
$subject = $headers[Subject];
$from = "Goedert <goedert@bizplace.com.br>";
// Cabeçalhos que definem o e-mail como sendo em formato HTML
$cabeca = "MIME-Version: 1.0\n";
$cabeca .= "Content-type: text/html; charset=iso-8859-1\n";
#$cabeca .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$cabeca .= "From: ".$from."\n";
$cabeca .= "Return-Path: Goedert <goedert@bizplace.com.br>\n";
//$cabeca .= "Bcc: ".$tto."\n";
#$cabeca .= "To: <$tto>\n";

#$headers = "From: ".$email."\r\n" .
#"MIME-Version: 1.0\r\n" .
#"Content-Type: text/html; charset=windows-1252\r\n" .
#"Content-Transfer-Encoding: 8bit\r\n\r\n";
$corpo = $conteudo;
$corpo .= "<center><a href='http://goedert.bizwork.com.br/news_cancelar.php?email={$tupla[$ind]['usu_e_mail']}'><img src='http://goedert.bizwork.com.br/imagens/b_cancelar.jpg&#039; border=0></a> </center>";

//echo $to;

$retorno = mail($to, $subject, $corpo, $cabeca);
//echo $cabeca;
//$retorno = TRUE;
IF ($retorno!==TRUE)
{
$msg = "<div align='left' valign='top' class='{$o_form->desc_class}'>Erro ao enviar e-mail!<br></div><br><br>";
break;
}
$c1 = 0;
$sto="";
}
$o_sql->execSql("update usuario set usu_enviad = '1' where usu_e_mail = '".$tupla[$ind]["usu_e_mail"]."'");
$c1++;

}

// Mensagem de OK...
IF ( $msg!=="" )
$ind = $ind-$config->mail_fila_qtd;

// Mensagem de OK...
echo "<div align='left' valign='top' class='{$o_form->desc_class}'>&nbsp;{$ind}&nbsp;Mensagens Enviadas&nbsp;</div><br><br>";
IF ( $msg!=="" )
echo $msg;
echo "<a href='news_enviar.php' class='titulo4'&laquo;>&laquo; Voltar</a>";

echo $o_form->frm_sufix;

include("./templates/footer.php");
?>
05/05/2010 12:04pm (~4 anos atrás)

Diego Campos disse:
esse script aki dah Connection refused mas tenho certeza do servidor e da porta pois a mesma configuração no outlook conecta no smtp e envia ok
Já tentei com mais de um servidor diferente SMTP o local, alguns pagos outros grátis, sempre da Connection refused
alguém sabe pq?
16/08/2008 7:32pm (~6 anos atrás)

pela disse:
ERRATA: O TÍTULO SERIA:

"Máquina trava e a página >>NÃO<< é exibida"

Até mais!
10/05/2007 2:13pm (~7 anos atrás)

pela disse:
Máquina trava e a página é exibida

SOLUÇÃO:
substituir da linha 41 à 44 por:

//modificado ----------------
$i=0;
do
{
$i++;
$buffer=fgets($conexao, 512);
print($i." - loop: ".$buffer."<br>");
if(substr($buffer , 4, 8)=='8BITMIME')
break;
}
while ($buffer);
// fim -------------- modificado

Até mais!
10/05/2007 2:11pm (~7 anos atrás)

Bem pessoal...
o meu fica assim:
conectou com: Resource id #1
conexão:
loop:
loop:
loop:
loop:
loop:
loop:
loop:
Loop infinitamente :S

alguem poderia me ajudar?
obrigado!
19/04/2007 1:44pm (~7 anos atrás)

Carlos, ótimo artigo!
Meus parabéns mesmo, muito didático e funcional.
Junto à observação do Flavio Vargas eis um script muito bom.

Abraço,

Líbene Fernandes
27/09/2006 6:54am (~7 anos atrás)

Carlos estou escrevendo para elogiar seu script e tb a sua iniciativa de compartilhar com os amigos do forum esse script senssacional !!!
27/06/2006 9:21pm (~8 anos atrás)

Aproveitando que você criou esse artigo super interessante você poderia também fazer alguns comentarios a respeito de segurança que envolve esse método, etc.
Até mais!
18/04/2006 8:30am (~8 anos atrás)

Meu velho, estou tendo problemas com esse código, não funciona comigo, aparece isso pra mim!

conectou com: Resource id #1
conexão: 220 mail1.salvador.ba.gov.br ESMTP
loop: 250-mail1.salvador.ba.gov.br
loop: 250-PIPELINING
loop: 250-SIZE 10000000
loop: 250-DATAZ
loop: 250-STARTTLS
loop: 250-AUTH LOGIN PLAIN
loop: 250 8BITMIME

Fatal error: Maximum execution time of 30 seconds exceeded in c:\inetpub

Já mudei o tempo do timeout e nada.

O que tá errado?
Abraços!
Anderson
24/03/2006 7:56am (~8 anos atrás)

Tiago Felipe disse:
Olá, você esqueceu de publicar para a galera como que envia vários emails ao mesmo tempo em uma única conexão...
14/02/2006 1:55pm (~8 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)