An open API service indexing awesome lists of open source software.

https://github.com/monicaquintal/app-send-mail

Aplicação desenvolvida na Seção 12: PHP e Orientação a Objetos, do Curso de Desenvolvimento Web Completo.
https://github.com/monicaquintal/app-send-mail

php

Last synced: 3 months ago
JSON representation

Aplicação desenvolvida na Seção 12: PHP e Orientação a Objetos, do Curso de Desenvolvimento Web Completo.

Awesome Lists containing this project

README

        


App Send Mail ✉🐘


Desenvolvimento Web Completo 2022


---


Objetivo 🎯

Estudo do conteúdo abordado na [Seção 12: PHP e Orientação a Objetos](https://github.com/monicaquintal/estudandoPHP-orientacao-a-objetos):

- Paradigma de Orientação a Objetos;
- Uso de recursos como namespaces e tratamento de erros com try/catch;
- Incorporar biblioteca phpmailer;
- Segurança do lado do back-end da aplicação, protegendo arquivos sigilosos.

O projeto 💭





Aplicação funcional, capaz de enviar e-mails através do serviço de SMTP do Gmail (muito utilizado em sites comerciais).

No front-end da aplicação, um formulário, onde serão inseridos email, assunto e mensagem. O back-end fará o processamento necessário para disparar a mensagem de sucesso (caso o usuário seja válido).

Aulas 📚

Aula 01: Introdução.

Aula 02: Iniciando o projeto.

Aula 03: Enviando dados do front-end para o back-end via método Post.

Aula 04: Criando e instanciando a Classe Mensagem.

Aula 05: Adicionando a biblioteca PHPMailer ao projeto.

Aula 06: Configurando o PHPMailer e envindo e-mails.

Aula 07: Enviando e-mails com base nos parâmetros do front-end.

Aula 08: Melhorando o feedback visual.

Aula 09: De olho na segurança do back-end



Aula 01: Introdução


Apresentação do projeto e seus objetivos.



Aula 02: Iniciando o projeto


Iniciando o projeto: criação do diretório app-send-mail, incluindo arquivo `index.php` e imagem `logo.png`.



Aula 03: Enviando dados do front-end para o back-end via método Post


- definindo o método de envio do formulário (`post`) e o arquivo de destino (`processa_envio.php` - back-end da aplicação).

- atribuindo names para os campos, para posteriormente explorá-lo individualmente.



Aula 04: Criando e instanciando a Classe Mensagem


- submeter os dados via POST para o back-end.

- criação da classe Mensagem, definição dos atributos e métodos propostos e instanciando um objeto.

~~~php
echo '

';

print_r($_POST);
echo '
';
echo '
';

class Mensagem {

private $para = null;
private $assunto = null;
private $mensagem = null;

public function __get($atributo) {
return $this->$atributo;
}

public function __set($atributo, $valor) {
$this->$atributo = $valor;
}

public function __mensagemValida() {
// implementaremos posteriormente
}
}

$mensagem = new Mensagem();
$mensagem->__set('para', $_POST[('para')]);
$mensagem->__set('assunto', $_POST[('assunto')]);
$mensagem->__set('mensagem', $_POST[('mensagem')]);

echo '

';

print_r($mensagem);
echo '
';
~~~

Com retorno:

~~~
Array
(
[para] => teste
[assunto] => teste
[mensagem] => teste

)

-------------------------------------

Mensagem Object
(
[para:Mensagem:private] => teste
[assunto:Mensagem:private] => teste
[mensagem:Mensagem:private] => teste

)
~~~

- verificar se os dados contidos no Objeto (mensagem) são válidos, para determinar se devemos ou não dar continuidade no processamento da lógica da aplicação.

~~~php
class Mensagem {

private $para = null;
private $assunto = null;
private $mensagem = null;

public function __get($atributo) {
return $this->$atributo;
}

public function __set($atributo, $valor) {
$this->$atributo = $valor;
}

public function mensagemValida() {
if (empty($this->para) || empty($this->assunto) || empty($this->mensagem)) {
return false;
}
return true;
}
}

$mensagem = new Mensagem();
$mensagem->__set('para', $_POST[('para')]);
$mensagem->__set('assunto', $_POST[('assunto')]);
$mensagem->__set('mensagem', $_POST[('mensagem')]);

if($mensagem->mensagemValida()) { // true
echo "A mensagem é válida!";
} else { // false
echo "Mensagem inválida!";
}
~~~



Aula 05: Adicionando a biblioteca PHPMailer ao projeto


- adicionando a biblioteca [PHPMailer](https://packagist.org/packages/phpmailer/phpmailer) no projeto, a partir do site [Packagist](https://packagist.org/), repositório por trás do Composer.

- acessando o repositório no GitHub do [PHPMailer](https://github.com/PHPMailer/PHPMailer), e fazendo o download da [versão 6.4.1](https://github.com/PHPMailer/PHPMailer/releases/tag/v6.4.1), que inclui atualizações que deixaram o pacote mais compatível com as versões 7 e 8 do PHP.

- baixar o arquivo compactado contendo a biblioteca, e adicionar ao diretório do projeto.

- para adicionar a lib:
- importar os arquivos PHPMailer no script processa_envio.php (`require`);

~~~php
require "./libs/PHPMailer/Exception.php";
require "./libs/PHPMailer/OAuth.php";
require "./libs/PHPMailer/PHPMailer.php";
require "./libs/PHPMailer/POP3.php";
require "./libs/PHPMailer/SMTP.php";
~~~

- importar os namespaces (`use`);

~~~php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
~~~

- copiar a instrução que produz uma instância em PHPMailer, bem como try/catch associado (alterando a lógica do operador e inserindo dentro do if/else):

~~~php
if(!$mensagem->mensagemValida()) {
echo "Mensagem inválida!";
die();
} // lógica

// ctrl c+ ctrl v do repositório:
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = 'smtp.example.com'; //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = '[email protected]'; //SMTP username
$mail->Password = 'secret'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
//Recipients
$mail->setFrom('[email protected]', 'Mailer');
$mail->addAddress('[email protected]', 'Joe User'); //Add a recipient
$mail->addAddress('[email protected]'); //Name is optional
$mail->addReplyTo('[email protected]', 'Information');
$mail->addCC('[email protected]');
$mail->addBCC('[email protected]');
//Attachments
$mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body in bold!';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Não foi possível enviar este e-mail! Por favor, tente novamente mais tarde.";
echo "Detalhes do erro: {$mail->ErrorInfo}";
}
~~~



Aula 06: Configurando o PHPMailer e envindo e-mails.


`Servidor SMTP` tem o funcionamento parecido com os Correios: despachamos uma determinada correspondência, e ele é responsável por receber essa correspondência e organizar a sua entrega.

Há diversos servidores SMTP disponíveis de fotma gratuita, como o próprio Gmail do Google.

### Entendendo a interação entre as partes da aplicação:

O front-end se comunica com o back-end através do protocolo HTTP, enquanto a aplicação implementa uma biblioteca que vai utilizar um serviço disponível na Internet.
Então, através da Internet, utilizando o protocolo SMTP, é feita uma autenticação no Gmail para, a partir da nossa aplicação, disparar um e-mail, sendo o Gmail o responsável por fazer essa entrega ao destinatário!

### Implementando na prática:

1. Criar uma conta no Gmail.

2. Inserir login e senha do e-mail no script `processa_envio.php`.

~~~php
$mail = new PHPMailer(true);
try {
<...>
$mail->Username = '[email protected]';
$mail->Password = 'senha';
<...>
} catch {
<...>
}
~~~

3. Informar o Host (servidor SMTP) que utilizaremos como gateway.

- acessar o artigo ["Enviar e-mails usando uma impressora, um scanner ou um app"](https://support.google.com/a/answer/176600?hl=pt);

- inserir o DNS (endereço): smtp-relay.gmail.com (conforme acesso em 01/02/2023).

~~~php
$mail->Host = 'smtp-relay.gmail.com';
~~~

- configurações de segurança (criptografia em tls) e porta (587).

- ajustando remetente e destinatários.

~~~php
//Recipients
$mail->setFrom('[email protected]', 'Mônica Remetente');
$mail->addAddress('[email protected]', 'Mônica Destinatário'); //Add a recipient
// $mail->addReplyTo('[email protected]', 'Information'); // encaminha sempre as respostas a esse destinatário
// $mail->addCC('[email protected]'); // com cópia
// $mail->addBCC('[email protected]'); // cópia oculta
~~~

- alterando demais parâmetros (de anexos, mensagem, etc).

~~~php
try {
<...>
//Attachments (anexos)
// $mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name

//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = 'Oi, eu sou o assunto!';
$mail->Body = 'Oi, eu sou o conteúdo do e-mail!';
$mail->AltBody = 'Oi, eu sou o conteúdo do e-mail!';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
~~~

4. Relizando um teste!

Neste caso, ocorrerá uma mensagem se erro, pois geralmente servidores SMTP são fechados para aplicações externas.

Portanto, é necessário autorizar previamente que apps externos ao domínio tenham acesso a realizar autenticação com aqueles usuários.

### IMPORTANTE:

Atualmente, a opção de "apps menos seguros" não está mais autorizada pelo Google! Agora precisamos gerar uma senha exclusiva para este fim.

Para configurar uma senha exclusiva para o projeto, acesse a conta de e-mail do Gmail que será utilizada em seu projeto e siga os passos:

1. Clique na opção "Gerenciar sua Conta do Google";
2. Clique na opção "Segurança";
3. Ative a opção de "Verificação em duas etapas";
4. Clique na opção "Senhas de app";
5. Clique na opção "Selecione o app e o dispositivo para o qual você quer gerar a senha de app" e escolha a opção "Outro";
6. Defina um nome (pode ser qualquer nome) e depois clique em "gerar";
7. A senha será gerada, basta copiá-la;
8. Utilize a senha copiada no passo 7 no arquivo de configuração de envio de e-mail (processa_envio.php);
9. Após realizar estes passos o envio de e-mails deve funcionar normalmente.



Aula 07: Enviando e-mails com base nos parâmetros do front-end.


Inserindo atributos recuperados através do método __get():

~~~php
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = 2;//SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = 'smtp.gmail.com'; //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = '[email protected]'; //SMTP username
$mail->Password = 'senha'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Enable implicit TLS encryption
$mail->Port = 587; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`

//Recipients
$mail->setFrom('[email protected]', 'Monica');
$mail->addAddress($mensagem->__get('para')); //Add a recipient
// $mail->addReplyTo('[email protected]', 'Information'); // encaminha sempre as respostas a esse destinatário
// $mail->addCC('[email protected]'); // com cópia
// $mail->addBCC('[email protected]'); // cópia oculta

//Attachments (anexos)
// $mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name

//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = $mensagem->__get('assunto');
$mail->Body = $mensagem->__get('mensagem');
$mail->AltBody = "É necessário utilizar um client que suporte HTML para ter acesso total ao conteúdo desta mensagem!";
$mail->send();
echo 'E-mail enviado com sucesso!';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
~~~



Aula 08: Melhorando o feedback visual.


1. Impedindo o usuário de acessar o script `provessa_envio.php` sem que passe pelo arquivo `index.php`.

- já tratado no if/else (com "die()");
- ao invés de "matar" a aplicação, redirecionar para index.php.

~~~php
if(!$mensagem->mensagemValida()) {
echo "Mensagem inválida!";
header('Location: ./index.php');
}
~~~

2. Criando atributo para exibição de erros:

~~~php
class Mensagem {
<...>
private $mensagem = null;
public $status = array('codigo_status' => null, 'descricao_status' => '');
<...>
}

try {
<...>
} catch {
<...>
$mensagem->status['codigo_status'] = 1;
$mensagem->status['descricao_status'] = 'E-mail enviado com sucesso!';
} catch (Exception $e) {
$mensagem->status['codigo_status'] = 2;
$mensagem->status['descricao_status'] = 'Não foi possível enviar este e-mail. Por favor, tente novamente mais tarde!' . $mail->ErrorInfo;
}
~~~

3. Configurando uma página HTML de retorno, no arquivo `processa_envio.php`.

~~~php


App Send Mail




Send Mail


Seu app de envio de e-mails particular!



status['codigo_status'] == 1) {
?>


Sucesso!


= $mensagem->status['descricao_status']?>


Voltar


status['codigo_status'] == 2) {
?>


Ops!


= $mensagem->status['descricao_status']?>


Voltar


~~~

4. Ocultando relatório debug: definir atributo "false".

~~~php
$mail->SMTPDebug = false;
~~~



Aula 09: De olho na segurança do back-end.


1. Retirar do diretório público do Apache tudo que é sigiloso (arquivo `processa_envio.php`)!

2. Acessar a página de processamento através de require.