Você está mantendo sua senha de e-mail em um arquivo PHP como texto simples? Se o seu servidor estiver comprometido, o que acontecerá com seus e-mails? Este artigo é para você.
Quando as pessoas consultam para construir componentes de aplicativo para envio de e-mails, meu primeiro foco será a segurança. Claro, é um exemplo clássico em que os desenvolvedores de aplicativos devem cobrir a segurança.
Embora o PHP tenha uma função de e-mail embutida, mail (), procurei uma maneira melhor de fazer isso. Trata-se de garantir segurança confiável ao configurar os serviços de envio de e-mail no aplicativo de um cliente.
A biblioteca PHPMailer como um componente imbatível de envio de e-mails com recursos avançados. Usei o cliente Google OAuth para enviar e-mail via PHPMailer de forma segura.
Criei um exemplo básico simples aqui com este artigo para construir o script de envio de e-mail. Vamos coletar mais detalhes sobre como enviar um e-mail com PHPMailer via Gmail XOAUTH2.
O que há dentro?
- Sobre este exemplo
- Dependências e comandos de instalação
- Gerar chaves de API e token de atualização
- Modelo de IU e validação do lado do cliente
- O controlador PHP chama o script de envio de e-mail
- Diretivas configuráveis de aplicativo
- Serviço de correio usando PhpMailer e Gmail XOAUTH2
Sobre este exemplo
Este exemplo é para criar um serviço de correspondência para enviar e-mail via PHPMailer usando o cliente Google OAuth.
Mostra um formulário de contato para o usuário inserir os detalhes. A ação de envio do formulário envia o e-mail de contato ao destinatário. Se você deseja um componente de formulário de contato seguro, obtenha o Iris .
As dependências necessárias são instaladas por meio do composer e integradas neste exemplo para enviar um e-mail.
As configurações do aplicativo definem as chaves para solicitar autenticação baseada em tokens ao enviar e-mails.
Ele cobre não apenas o envio de e-mail, mas também um componente de formulário de contato ativo de ponta a ponta.
A imagem a seguir mostra a estrutura do arquivo deste exemplo. O diretório do fornecedor é expandido para exibir as dependências necessárias para este código.
Dependências e comandos de instalação
Como mencionamos na parte introdutória, este código usa PHPMailer e o Biblioteca de cliente OAuth.
As bibliotecas dependentes necessárias são baixadas automaticamente instalando essas duas páginas por meio de uma ferramenta de gerenciamento de pacotes como o composer .
O comando para instalar o PHPMailer via composer é,
composer require phpmailer/phpmailer
Para usar o Google OAuth, execute este comando para baixar as dependências mostradas na imagem da estrutura do arquivo.
composer require league/oauth2-google
Gerar chaves de API e atualizar token
Aqui estão as etapas para criar um projeto de API do Google e obter as chaves e o token. Essas chaves são os parâmetros para o processo de autenticação baseada em tokens.
- Faça login na conta do Google e vá para o console da plataforma em nuvem .
- No menu deslizante à esquerda, navegue em IAM e Admin-> Gerenciar recursos . Clique em CRIAR PROJETO e insira os detalhes.
- Vá para API e serviços-> Biblioteca e ative a API do Gmail .
- Vá para API e serviços-> Credenciais e clique em CRIAR CREDENCIAIS-> ID do cliente OAuth .
- Escolha o tipo de aplicativo e preencha outros detalhes para gerar as chaves.
Depois de obter as chaves, configure-o no seguinte arquivo que vem com o pacote PHPMailer . É para obter o token de atualização.
vendor/phpmailer/phpmailer/get_oauth_token.php
O código a seguir mostra onde definir o ID do cliente e as chaves secretas do cliente para obter o token de atualização.
php /** * PHPMailer-criação de e-mail PHP e classe de transporte. * PHP Versão 5.5 * @package PHPMailer * @ver https://github.com/PHPMailer/PHPMailer/O projeto PHPMailer GitHub * @author Marcus Bointon (Synchro/coolbru) * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (fundador original) * @copyright 2012-2020 Marcus Bointon * @copyright 2010-2012 Jim Jagielski * @copyright 2004-2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @note Este programa é distribuído na esperança de ser útil-SEM * QUALQUER GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou * ADEQUAÇÃO A UM DETERMINADO FIM. */ /** * Obtenha um token OAuth2 de um provedor OAuth2. * * Instale este script em seu servidor para que fique acessível * como [https/http]:////get_oauth_token.php * por exemplo: http://localhost/phpmailer/get_oauth_token.php * * Certifique-se de que as dependências sejam instaladas com'instalação do composer' * * Configure um aplicativo em sua conta Google/Yahoo/Microsoft * * Defina o endereço do script como o URL de redirecionamento do aplicativo * Se nenhum token de atualização for obtido ao executar este arquivo, * revogue o acesso ao seu aplicativo e execute o script novamente. */ namespace PHPMailer \ PHPMailer; /** * Aliases para Classes de Provedores de Liga * Certifique-se de que os adicionou ao composer.json e execute `composer install` * Muito por onde escolher: * @see http://oauth2-client.thephpleague.com/providers/thirdparty/ */
//@ veja https://github.com/thephpleague/oauth2-google
use League \ OAuth2 \ Client \ Provider \ Google;
//@ veja https://packagist.org/packages/hayageek/oauth2-yahoo
use Hayageek \ OAuth2 \ Client \ Provider \ Yahoo;
//@ veja https://github.com/stevenmaguire/oauth2-microsoft
use Stevenmaguire \ OAuth2 \ Client \ Provider \ Microsoft; if (! isset ($ _ GET ['code']) &&! isset ($ _ GET ['provider'])) { ?>
Selecione o provedor:
Google
Yahoo
Microsoft/Outlook/Hotmail/Live/Office365
php saída;
} require'vendor/autoload.php'; session_start (); $ providerName=''; if (array_key_exists ('provider', $ _GET)) { $ providerName=$ _GET ['provider']; $ _SESSION ['provedor']=$ providerName;
} elseif (array_key_exists ('provider', $ _SESSION)) { $ providerName=$ _SESSION ['provedor'];
}
if (! in_array ($ providerName, ['Google','Microsoft','Yahoo'])) { exit ('Apenas os provedores Google, Microsoft e Yahoo OAuth2 são atualmente suportados neste script.');
} //Esses detalhes são obtidos configurando um aplicativo no console do desenvolvedor do Google,
//ou qualquer provedor que você esteja usando.
$ clientId='RANDOMCHARS-----duv1n2.apps.googleusercontent.com';
$ clientSecret='RANDOMCHARS-----lGyjPcRtvP'; //Se este URL automático não funcionar, defina-o manualmente para o URL deste script
$ redirectUri=(isset ($ _ SERVER ['HTTPS'])?'https://':'http://'). $ _SERVER ['HTTP_HOST']. $ _SERVER ['PHP_SELF'];
//$ redirectUri='http://localhost/PHPMailer/redirect'; $ params=[ 'clientId'=> $ clientId, 'clientSecret'=> $ clientSecret, 'redirectUri'=> $ redirectUri, 'accessType'=>'offline'
]; $ options=[];
$ provedor=nulo; switch ($ providerName) { caso'Google': $ provedor=novo Google ($ params); $ options=[ 'escopo'=> [ 'https://mail.google.com/' ] ]; pausa; case'Yahoo': $ provedor=novo Yahoo ($ params); pausa; case'Microsoft': $ provedor=novo Microsoft ($ params); $ options=[ 'escopo'=> [ 'wl.imap', 'wl.offline_access' ] ]; pausa;
} if (null===$ provider) { exit ('Provedor ausente');
} if (! isset ($ _ GET ['code'])) { //Se não tivermos um código de autorização, obtenha um $ authUrl=$ provider-> getAuthorizationUrl ($ options); $ _SESSION ['oauth2state']=$ provider-> getState (); cabeçalho ('Localização:'. $ authUrl); saída; //Verifique o estado fornecido em relação ao previamente armazenado para mitigar o ataque CSRF
} elseif (empty ($ _ GET ['state']) || ($ _GET ['state']!==$ _SESSION ['oauth2state'])) { cancelar ($ _ SESSION ['oauth2state']); não definido ($ _ SESSION ['provedor']); saída ('estado inválido');
} senão { cancelar ($ _ SESSION ['provedor']); //Tente obter um token de acesso (usando a concessão do código de autorização) $ token=$ provider-> getAccessToken ( 'Código de autorização', [ 'code'=> $ _GET ['code'] ] ); //Use para interagir com uma API em nome dos usuários //Use para obter um novo token de acesso se o antigo expirar echo'Atualizar token:', $ token-> getRefreshToken ();
}
Modelo de IU e validação do lado do cliente
Este é um código HTML para um modelo de formulário de contato simples . Ele aciona a validação do formulário e o script de envio de email de back-end ao enviar o formulário.
É autoexplicativo com campos de formulário usuais e atributos semânticos.
index.php
Formulário de contato
As funções de validação do formulário restringem o envio do formulário até obter valores não vazios de todos os campos.
Ele valida os dados do campo de e-mail se corresponderem ao padrão regex especificado.
assets/js/validation.js
function validateContactForm () { var emailRegex=/^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9] {2,4}) + $/;
var userName=document.getElementById ("userName"). value;
var userEmail=document.getElementById ("userEmail"). value;
var subject=document.getElementById ("subject"). value;
var content=document.getElementById ("content"). value; var válido=verdadeiro;
if (userName=="") {
markAsInvalid ("userName","obrigatório");
document.getElementById ("userName"). classList.add ("campo de erro");
válido=falso;
} senão {
markAsValid ("userName");
document.getElementById ("userName"). classList.remove ("campo de erro");
} if (userEmail=="") {
markAsInvalid ("userEmail","obrigatório");
document.getElementById ("userEmail"). classList.add ("campo de erro");
válido=falso;
} else if (! emailRegex.test (userEmail)) {
markAsInvalid ("userEmail","endereço de e-mail inválido");
document.getElementById ("userEmail"). classList.add ("campo de erro");
válido=falso;
} senão {
markAsValid ("userEmail");
document.getElementById ("userEmail"). classList.remove ("campo de erro");
} if (assunto=="") {
markAsInvalid ("assunto","obrigatório");
document.getElementById ("assunto"). classList.add ("campo de erro");
válido=falso;
} senão {
markAsValid ("assunto");
document.getElementById ("assunto"). classList.remove ("campo de erro");
}
if (content=="") {
markAsInvalid ("userMessage","obrigatório");
document.getElementById ("conteúdo"). classList.add ("campo de erro");
válido=falso;
} senão {
markAsValid ("userMessage");
document.getElementById ("conteúdo"). classList.remove ("campo de erro");
} retorno válido;
} function markAsValid (id) {
document.getElementById (id +"-info"). style.display="none";
} function markAsInvalid (id, feedback) {
document.getElementById (id +"-info"). style.display="inline";
document.getElementById (id +"-info"). innerText=feedback;
}
O controlador PHP chama o script de envio de e-mail
Este script é adicionado no início do arquivo index.php acima do formulário de contato HTML.
Ele conecta o PHP MailService para enviar o e-mail de contato usando PHPMailer com XOAUTH2.
Ele captura a resposta do processo de envio de e-mail. Ele reconhece o usuário final para saber se a mensagem de contato foi recebida ou não.
Para enviar e-mails com PHPMailer usando GMail SMTP , o artigo vinculado tem o download com o código adequado.
index.php (código PHP para chamar o serviço de correio para enviar e-mail)
php namespace Phppot; require_once ("lib/MailService.php"); $ mailService=new MailService (); if (! empty ($ _ POST ['enviar'])) { $ response=$ mailService-> sendContactMail ($ _ POST); } ?>
Diretivas configuráveis de aplicativos
Este é o arquivo de configuração criado para este código de exemplo. Ele define as constantes do PHP para conter as chaves e tokens gerados anteriormente para autenticação.
Ele também define os endereços de e-mail do destinatário e o e-mail e os detalhes do usuário OAuth.
lib/Config.php
php /** * Copyright (C) Vincy-Todos os direitos reservados * A cópia não autorizada deste arquivo, por qualquer meio, é estritamente proibida * Confidenciais e proprietárias * Escrito por Vincy*/ namespace Phppot; /** * Esta classe contém as opções de configuração */ classe Config { const SENDER_NAME='Vincy'; const SENDER_EMAIL='[email protected]'; //você pode adicionar um ou mais e-mails separados por uma vírgula (,). const RECIPIENT_EMAIL='[email protected]'; const OAUTH_USER_EMAIL='[email protected]'; const OAUTH_CLIENT_ID=''; const OAUTH_SECRET_KEY=''; const REFRESH_TOKEN=''; const SMTP_HOST='smtp.gmail.com'; const SMTP_PORT=587; }
Serviço de e-mail usando PhpMailer e Gmail XOAUTH2
A função sendContactMail () define os detalhes do formulário de contato para construir o conteúdo do corpo do e-mail.
Ele cria a instância PHPMailer e define os atributos para autenticar as solicitações de envio de e-mail.
Ele define a instância do provedor Google OAuth com as chaves e token gerados e os detalhes do usuário OAuth.
Em seguida, ele adiciona os atributos de e-mail de rotina, o e-mail de destino, e-mail de, responder para e muito mais.
Ele constrói uma resposta JSON para retornar o resultado do processo de envio de e-mail.
lib/MailService.php
php namespace Phppot; use Phppot \ Config; use PHPMailer \ PHPMailer \ PHPMailer; use PHPMailer \ PHPMailer \ Exception; classe MailService { função sendContactMail ($ postValues) { $ name=$ postValues ["userName"]; $ email=$ postValues ["userEmail"]; $ subject=$ postValues ["assunto"]; $ content=$ postValues ["content"]; require_once __DIR__.'/Config.php'; $ receiverArray=explode (",", Config:: RECIPIENT_EMAIL); require_once __DIR__.'/../vendor/autoload.php'; $ mail=novo PHPMailer (verdadeiro); //Comente as seguintes linhas de código até $ mail-> Porta a enviar //email usando phpmail em vez de smtp. $ mail-> isSMTP (); //Habilitar depuração de SMTP //SMTP:: DEBUG_OFF=off (para uso em produção) //SMTP:: DEBUG_CLIENT=mensagens do cliente //SMTP:: DEBUG_SERVER=mensagens do cliente e do servidor $ mail-> SMTPDebug=SMTP:: DEBUG_OFF; //Defina o nome do host do servidor de e-mail $ mail-> Host=Config:: SMTP_HOST; //Defina o número da porta SMTP-587 para TLS autenticado, também conhecido como RFC4409 envio SMTP $ mail-> Port=Config:: SMTP_PORT; //Defina o mecanismo de criptografia a ser usado-STARTTLS ou SMTPS $ mail-> SMTPSecure=PHPMailer:: ENCRYPTION_STARTTLS; //Se deve usar autenticação SMTP $ mail-> SMTPAuth=true; //Defina AuthType para usar XOAUTH2 $ mail-> AuthType='XOAUTH2'; //Preencha os detalhes de autenticação aqui //O proprietário da conta do gmail ou o usuário que deu consentimento $ oauthUserEmail=Config:: OAUTH_USER_EMAIL; $ clientId=Config:: OAUTH_CLIENT_ID; $ clientSecret=Config:: OAUTH_SECRET_KEY; //Obtido configurando e executando get_oauth_token.php //depois de configurar um aplicativo no Google Developer Console. $ refreshToken=Config:: REFRESH_TOKEN; //Crie uma nova instância do provedor OAuth2 $ provider=novo Google ( [ 'clientId'=> $ clientId, 'clientSecret'=> $ clientSecret, ] ); //Passe a instância do provedor OAuth para PHPMailer $ mail-> setOAuth ( novo OAuth ( [ 'provedor'=> $ provedor, 'clientId'=> $ clientId, 'clientSecret'=> $ clientSecret, 'refreshToken'=> $ refreshToken, 'userName'=> $ oauthUserEmail, ] ) ); //Destinatários $ mail-> setFrom (Config:: SENDER_EMAIL, $ name); $ mail-> addReplyTo ($ email, $ name); $ mail-> addAddress (Config:: RECIPIENT_EMAIL, Config:: RECIPIENT_EMAIL); $ mail-> Assunto=$ assunto; $ mail-> CharSet=PHPMailer:: CHARSET_UTF8; $ mail-> msgHTML ($ mailBody); //Substitua o corpo do texto simples por um criado manualmente $ mail-> AltBody='Este é um corpo de mensagem de texto simples'; if (! $ mail-> send ()) { $ output=json_encode (array ('type'=>'error','text'=>''. $ from.' é inválido.')); $ output=json_encode (array ('type'=>'error','text'=>'Erro do servidor. Envie um e-mail [email protected]')); } senão { $ output=json_encode (array ('type'=>'message','text'=>'Obrigado, entrarei em contato em breve.')); } return $ output; } }
Esta fonte para download não está com os pacotes dependentes. Use o composer para baixar as dependências.
Download