Este artigo mostra como obter os e-mails recebidos por uma conta do GMail a partir de código PHP.
Primeiramente, é preciso configurar o GMail para aceitar conexão IMAP. Para isso, é preciso entrar na sua conta pelo web mail (mail.google.com), e acessar o link "Configurações", no canto superior direito da página. Isso deve abrir uma tela com várias abas de configurações, então acesse a aba "Encaminhamento e POP/IMAP". Nesta aba, ative o IMAP no campo mostrado pela imagem:
E não se esqueça de clicar em "Salvar alterações".
Também é necessário permitir o acesso por aplicações menos seguras nesse link Aplicativos menos seguros.
Agora é só montar o script. Para isso, será preciso usar o módulo imap do PHP. Ele pode ser instalado via PECL.
Abrindo a conexão:
// Configure com seu login/senha $login = 'teste'; $senha = '12345'; $str_conexao = '{imap.gmail.com:993/imap/ssl}'; if (!extension_loaded('imap')) { die('Modulo PHP/IMAP nao foi carregado'); } // Abrindo conexao $mailbox = imap_open($str_conexao, $login, $senha); if (!$mailbox) { die('Erro ao conectar: '.imap_last_error()); }
Obtendo dados básicos sobre a conta:
$check = imap_check($mailbox); // Ultima mensagem echo $check->Date; // Tipo de conexao echo $check->Driver; // Mailbox echo $check->Mailbox; // Numero de mensagens total echo $check->Nmsgs; // Numero de mensagens novas echo $check->Recent;
Obter os marcadores (ou diretórios) da conta:
$marcadores = imap_getmailboxes($mailbox, $str_conexao, '*'); if (is_array($marcadores)) { foreach ($marcadores as $marcador) { $nome = str_replace($str_conexao, '', $marcador->name); $pos = strpos($nome, $marcador->delimiter); if ($pos !== false) { $nome = substr($nome, $pos + 1); } echo $nome."\n"; } } else { echo imap_last_error(); }
Obtém um array com informações sobre a mensagem "1" (primeira mensagem da caixa de entrada):
$overview = imap_fetch_overview($mailbox, 1); $email = current($overview); // Assunto echo $email->subject; // Remetente echo $email->from; // Destinatarios echo $email->to; // Data echo $email->date; // Identificador da mensagem echo $email->message_id; // Identificador da mensagem de referencia echo $email->references; // Identificador da mensagem que gerou a resposta echo $email->in_reply_to; // Tamanho em bytes echo $email->size; // Identificador da mensagem na caixa de entrada echo $email->uid; // Numero sequencial da mensagem na caixa de entrada echo $email->msgno; // Possui marca de "recente" echo $email->recent; // Possui marca de "marcada" echo $email->flagged; // Possui marca de "respondida" echo $email->answered; // Possui marca de "pronta para ser apagada" echo $email->deleted; // Possui marca de "lida" echo $email->seen; // Possui marca de "rascunho" echo $email->draft;
Ler o cabeçalho da mensagem "1" (primeira mensagem da caixa de entrada):
$header = imap_header($mailbox, 1); // Data echo $header->Date; // Endereco do destinatario echo $header->toaddress; // Endereco do remetente echo $header->fromaddress; // Enderecos de copia echo $header->cc; // Endereco de resposta echo $header->reply_toaddress; // Tamanho da mensagem echo $header->Size; // Assunto da mensagem echo $header->Subject;
Obter o conteúdo da mensagem 1 (primeira mensagem):
$conteudo = imap_body($mailbox, 1);
Obtendo o conteúdo de texto (PLAIN e/ou HTML) das mensagens não lidas:
/** Funcao para decodificar o conteudo de uma mensagem */ function parse_encoding($body, $encoding) { switch ($encoding) { case ENCBASE64: return base64_decode($body); case ENCQUOTEDPRINTABLE: return imap_qprint($body); case ENC7BIT: return imap_mutf7_to_utf8($body); case ENC8BIT: case ENCBINARY: case ENCOTHER: return $body; } } // Obter os IDs dos e-mails nao lidos $unseen = imap_search($mailbox, 'UNSEEN'); foreach ($unseen as $id) { // Obter o conteudo cru da mensagem $body = imap_body($mailbox, $id); $structure = imap_fetchstructure($mailbox, $id); // Decodificando o conteudo das partes da mensagem $contents = array(); if ($structure->type == TYPEMULTIPART) { foreach ($structure->parts as $j => $part) { $body_part = imap_fetchbody($mailbox, $id, $j + 1); if ($part->type == TYPETEXT) { $contents[$part->subtype] = parse_encoding($body_part, $part->encoding); } } } else { $contents[$structure->subtype] = parse_encoding($body, $structure->encoding); } // Exibindo o conteudo de texto do e-mail var_dump($contents); }
Fechar a conexão IMAP:
imap_close($mailbox);
30 comentários
Não esqueça de incluir o @gmail.com ao final do nome de usuário.
Klawdyo, não precisa colocar o "@gmail.com" ao final. Mas se colocar, também funciona.
Olá, para obter o conteúdo da mensagem exatamente (de e-mail com anexo), você disse que é necessário utilizar um parser. como faço isso, teria com me ajudar?
Olá, Pancinha de Ouro
Existe uma extensão do PHP que faz isso. Dê uma olhada nesse link:
http://php.net/manual/en/book.mailparse.php
Olá rubS, como posso obter o tamanho total de espaço em disco utilizado por essa conta de e-mail?
pode ajudar?
Olá, Hotel,
Creio que não exista algo para determinar o tamanho em disco, mas você é capaz de calcular o tamanho total das mensagens de e-mail. Para isso, basta somar o valor de $overview['size'] de cada mensagem. Veja no exemplo de como obter um vetor com informações sobre uma mensagem.
Tem como usar numa intranet?
Pois testei e não funcionou.
Roberto, tem sim. Só precisa configurar adequadamente o servidor IMAP e ajustar a string de conexão com ele.
Da erro quando tento entrar no arquivo =(
Rubens, usamos o servidor do google mas com nosso proprio domínio, tem problema? Preciso usar o gmail.com?
Olá, Ednaldo
Não tenho certeza sobre qual é o comportamento do servidor imap do gmail respondendo por um domínio próprio.
Acredito que seja possível consultá-lo normalmente, mas precisaria informar o e-mail completo no lugar do "login" do exemplo do artigo (e-mail com o seu domínio próprio). É testar pra ver.
Se conseguir, por favor, comente aqui para ajudar outras pessoas.
Tem como pegar somente um diretorio ?
Luiz Filipe, para pegar as mensagens de um diretório, basta mudar a string de conexão colocando o nome do diretório (no caso do GMail, é o "marcador"). Por exemplo:
$str_conexao = '{imap.gmail.com:993/imap/ssl}[Gmail]/Com estrela';
Para obter direitinho o nome da string de conexão, você precisa conectar na raíz e obter os marcadores com a função "imap_getmailboxes", como mostrado no artigo.
Ola estou tentando fazer um script e gostaria da sua ajuda, seguinte eu recebi um e-mail com uma imagem com um link, daí quando clico nesta imagem vai pra um formulario que já preenche o e-mail automaticamente saberia me dizer como pegar o parametro e-mail.
Olá, Carlos
Se a URL possui o e-mail como parâmetro, basta usar a função parse_str sobre parte de "query string" da URL. Para mais detalhes, sugiro que leia este outro artigo e, se tiver dúvidas, é só perguntar:
http://rubsphp.blogspot.com.br/2012/04/manipulacao-de-url-uri-e-links.html
Olá Rubens, tudo bem? Possuo uma variável que recebe message_id do e-mail e gostaria de gravar em um banco mysql porem recebo o erro 1064 já tentei de diversas formas mas ainda não rolou, pode me auxiliar ;) ?
Olá, Anônimo.
Não ficou claro em que momento você recebe este erro. Você seguiu todos os passos descritos no artigo?
Segui sim Rubens, quanto ao que você passou acima tudo esta ok,porem quero gravar a id da mensagem em um banco mysql e neste momento que recebo o erro, a id esta neste formato <175228826.8.1412111715564.JavaMail.root@xxxdnn2594>, sistema@crmtel.com.br)
Entendido. Então o erro é na hora de inserir no banco. O erro 1064 do MySQL significa erro de sintaxe da sua query. Sugiro que dê uma revisada na query, para ver se não ficou faltando algum parênteses ou aspas. Recomendo que utilize o PDO para conectar ao MySQL, e capturar a exception se ocorrer algum erro. Seguem alguns artigos úteis:
http://rubsphp.blogspot.com.br/2010/09/pdo.html
http://rubsphp.blogspot.com.br/2010/11/modificando-o-controle-de-erros-do-pdo.html
Boa tarde, eu segui o procedimento e deu td certo até então, gostaria de informações a respeito se é possivel trazer somente as mensagens não lidas da caixa principal.
Oi, Jessica
Não conheço uma forma de obter apenas as mensagens não lidas de forma direta. A forma que eu conheço é percorrendo os e-mails e usando a função imap_fetch_overview para saber se cada um foi lido ou não (conforme mostrado no artigo).
Acredito que os clientes de e-mail façam um cache disso para não precisar consultar todos e-mail todas as vezes que são acessados.
Jessica, acabei descobrindo que tem a funcao imap_search que consegue buscar mensagens não lidas. Atualizei o artigo com essa informação.
O gmail está bloqueando meu acesso, mesmo colocando para utilizar app menos seguro. Alguma sugestão ?
estou utilizando o seu codigo acima mas é retornado este erro:
Erro ao conectar: Can not authenticate to IMAP server: [ALERT] Please log in via your web browser: https://support.google.com/mail/acco.
vc sabe o que pode estar errado??
Oi, Marcio
Se você habilitou o imap nas configurações do gmail e habilitou a autenticação de aplicativos menos seguros, como mostrado no artigo, então não sei.
Ola, precisava de um script para percorrer as mensagens da caixa de entrada do gmail e me retornar os endereços de email que devolveram as mensagens. Tenho como conseguir isso via php ou g-scripts?
Estou recebendo esse erro : imap_search() expects parameter 1 to be resource, null given nesta linha do seu código "$unseen = imap_search($mailbox, 'UNSEEN');"
Mensagens de erro :
Undefined property: stdClass::$references Na linha "echo $email->references;"
Undefined property: stdClass::$in_reply_to Na linha "echo $email->in_reply_to;"
Array to string conversion Na linha "echo $header->cc;"
Isso quer dizer que o primeiro parâmetro não foi construído corretamente ao se chamar a função imap_open.
Parabéns e muito obrigado! Ajudou bastante no meu projeto.
Abraço.
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com