Enviando emails autenticados do Gmail com PHP usando Swift Mailer

O Swift Mailer é uma biblioteca para envio de emails, usando PHP5. Conheci a biblioteca inicialmente no framework Symfony, pois a mesma é responsável pela tarefa de enviar emails no framework, pois seu uso é muito simples e a biblioteca é muito poderosa.

Tenho notado que muitas empresas estão adotando cada vez mais o uso do Google Apps como serviço de webmail, dada a facilidade de uso e configuração do sistema. O primeiro exemplo mostra como enviar emails autenticados a partir de uma conta de email do Google (Gmail ou Apps) e os outros tratam do envio de mensagens com anexo. Usei a versão 4.0.6 para o exemplo.

Enviando emails com autenticação no Gmail (incluindo Google Apps)

require('lib/swift_required.php');

$transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl')
	->setUsername('usuario@gmail.com')
	->setPassword('senha');

$mailer = Swift_Mailer::newInstance($transport);

$message = Swift_Message::newInstance('Assunto')
	->setFrom(array('seuemail@dominio.com.br' => 'Seu Nome'))
	->setTo(array('fulano@teste.com.br'))
	->setReplyTo('seuemail@dominio.com.br')
	->setBody('Conteudo da mensagem');

if ($mailer->send($message)){
	echo 'Mensagem enviada com sucesso';
}
else{
	echo 'Problema ao enviar mensagem. Tente novamente mais tarde';
}


Enviando emails com imagens embutidas (inline)

Útil para enviar emails com imagens que não serão bloqueadas pelos softwares leitores de email, já que estão embutidas no código e não em servidores remotos.

require('lib/swift_required.php');

$transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl')
	->setUsername('usuario@gmail.com')
	->setPassword('senha');

$mailer = Swift_Mailer::newInstance($transport);

$message = Swift_Message::newInstance('Assunto')
	->setFrom(array('seuemail@dominio.com.br' => 'Seu Nome'))
	->setTo(array('fulano@teste.com.br'))
	->setReplyTo('seuemail@dominio.com.br');

$imagem_inline = $message->embed(Swift_Image::fromPath('logotipo.png'));

$message->setBody(
	'<html>'.
	' <head></head>'.
	' <body>' .
	'  <img src="'.$imagem_inline.'" alt="Imagem embutida na mensagem" />'.
	'  <br /><br />Texto da mensagem'.
	' </body>'.
	'</html>',
  'text/html' //Definimos o tipo da mensagem para text/html, ao invés de texto puro
);

if ($mailer->send($message)){
	echo 'Mensagem enviada com sucesso';
}
else{
	echo 'Problema ao enviar mensagem. Tente novamente mais tarde';
}


Enviando emails com anexo

require_once 'lib/swift_required.php';

$transport = Swift_SmtpTransport::newInstance('smtp.seudominio.com', 25)
	->setUsername('seuemail@dominio.com')
	->setPassword('senha');

$mailer = Swift_Mailer::newInstance($transport);

$message = Swift_Message::newInstance()
	->setSubject('Email com PDF anexado')
	->setFrom(array('seuemail@seudominio.com' => 'Seu nome'))
	->setTo(array('contato1@teste.org', 'contato2@teste.org'))
	->setBody('Leia a apostila em anexo')
	->attach(Swift_Attachment::fromPath('apostilas/apostila_inicial.pdf'));

if ( ! $mailer->send($message)){
	echo 'Erro ao enviar email';
}

Bom, esses foram alguns exemplos bem básicos do uso da biblioteca Swift Mailer. Consulte a documentação oficial para mais informações e um guia de referência completo.

Abraço e até a próxima!

Validadores do Doctrine (validators)

Neste post mostrarei os validadores presentes no Doctrine (usei a versão 1.2.3). O Doctrine facilita a validação dos dados, bastando apenas definir os validadores para cada atributo ao invés de fazer vários malabarismos com funções do PHP e expressões regulares. Você pode definir os validadores na classe que estende a classe base. Dessa maneira, você pode gerar o model novamente e suas alterações não serão perdidas. Primeiro listarei os validadores e ao final mostrarei alguns exemplos. Vamos lá.

Importante
Para que seus dados sejam validados, cheque se seu “bootstrap.php” contém a diretiva abaixo. Caso contrário, seus dados não serão validados.

$manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);

notnull
Garante que o valor não seja nulo na aplicação e no banco de dados.

// models/SuaClasse.php

class SuaClasse extends BaseSuaClasse
{
    // ...

	public function setTableDefinition(){
		parent::setTableDefinition();

		// ...

		$this->hasColumn('nome', 'string', 70, array(
				'notnull' => true
			)
		);
	}
}

Válido: teste, jonnas
Inválido: valores nulos

email
Checa se o valor é um endereço de email válido.

	$this->hasColumn('email', 'string', 100, array(
				'email' => true
			)
	);

Válido: contato@fonini.net
Inválido: fulano!#@server

notblank
Este validador é semelhante ao validador notnull, exceto que além de não validar valores nulos, também não valida strings vazias.

	$this->hasColumn('nome', 'string', 100, array(
				'notblank' => true
			)
	);

Válido: teste, jonnas
Inválido: valores nulos, ”

nospace
Checa se o valor não contém espaços.

	$this->hasColumn('campo_sem_espacos', 'string', 100, array(
				'nospace' => true
			)
	);

Válido: JonnasFonini
Inválido: Jonnas Fonini

past
Checa se o valor é uma data que já ocorreu, o dia de ontem, por exemplo.

	$this->hasColumn('data', 'timestamp', null, array(
				'past' => true
			)
	);

Válido: Sendo hoje 14/09/2010, 01/01/2010 é válida
Inválido: Sendo hoje 14/09/2010, a mesma e posteriores são inválidas

future
Checa se o valor é uma data que ainda não aconteceu, amanhã, por exemplo.

	$this->hasColumn('data', 'timestamp', null, array(
				'future' => true
			)
	);

Válido: Sendo hoje 14/09/2010, 15/09/2010 é válida
Inválido: Sendo hoje 14/09/2010, a mesma e anteriores são inválidas

minlength
Checa se o valor passado tem o tamanho mínimo necessário.

	$this->hasColumn('senha', 'string', 32, array(
				'minlength' => 6
			)
	);

Válido: abcdef, abcdefg
Inválido: abc

ip
Checa se o valor passado é um endereço IP válido.

	$this->hasColumn('endereco_ip', 'string', 15, array(
				'ip' => true
			)
	);

Válido: 192.168.250.222, 201.10.34.21
Inválido: 345.10.10.290

htmlcolor
Checa se o valor passado é uma cor HTML em hexadecimal.

	$this->hasColumn('cor', 'string', 7, array(
				'htmlcolor' => true
			)
	);

Válido: #000FFF, FF0000
Inválido: #GGG111, #FFF (cores abreviadas são inválidas)

range
Checa se o valor numérico está contido no intervalo especificado.

	$this->hasColumn('idade', 'integer', null, array(
				'range' => array(18, 70)
			)
	);

Válido: 19, 50, 69
Inválido: 10, 18, 70

unique
Checa se o valor já existe no banco de dados.

	$this->hasColumn('rg', 'string', 15, array(
				'unique' => true
			)
	);

regexp
Checa se o valor casa com a expressão regular passada.

	$this->hasColumn('somente_letras', 'string', 15, array(
				'regexp' => '/^[a-zA-Z]+$/'
			)
	);

Válido: flex
Inválido: flex4

creditcard
Checa se o valor é um número de cartão de crédito válido.

	$this->hasColumn('cartao', 'integer', 16, array(
				'creditcard' => true
			)
	);

Válido: Cartões Visa, Master Card, American Express, Discover e Diners
Inválido: Outras bandeiras, exceto as citadas acima

readonly
Evita que o valor de uma coluna da tabela seja alterado.

	$this->hasColumn('coluna_que_nao_pode_ser_alterada', 'string', 25, array(
				'readonly' => true
			)
	);

unsigned
Checa se o valor númerico passado possui sinal, de menos, por exemplo.

	$this->hasColumn('idade', 'integer', 3, array(
				'unsigned' => true
			)
	);

Válido: 70, 100
Inválido: -20

usstate
Checa se a string passada é a sigla válida de um estado americano. Confira a lista completa aqui.

	$this->hasColumn('estado_americano', 'string', 2, array(
				'usstate' => true
			)
	);

Válido: AL, CA
Inválido: QW

country
Checa se a string passada é a sigla válida de um país. Confira a lista completa aqui.

	$this->hasColumn('pais', 'string', 2, array(
				'country' => true
			)
	);

Válido: br, BR, ar
Inválido: xx

No próximo post mostrarei como fazer um validador de estados brasileiros e outro de CEP’s.

Grande abraço e até a próxima!

Tutorial de Doctrine, um ORM para PHP

O Doctrine é um mapeador objeto-relacional (ORM) para PHP, aos moldes do Hibernate para Java. Este ORM elimina a tarefa de escrever consultas SQL básicas, além de facilitar a conexão com o banco de dados, através da extensão PDO. O Doctrine permite que você crie seu model escrevendo suas classes em PHP (seguindo alguns padrões pré-definidos), através de arquivos YAML ou ele se encarrega da geração do model através das tabelas já criadas no banco de dados. Uma vez que o model está criado, você pode definir validadores para campos específicos da tabela realizando essas alterações na classe gerada que estende cada model. Dessa forma, seu model fica preservado, você apenas altera a classe estendida, tornando fácil desfazer modificações.

Instalação

Baixe a última versão estável no site do projeto. No momento em que escrevo este post, a última versão estável é a 1.2.3. A versão 2 escontra-se em fase beta. Quem sabe quando ela for lançada sai mais um post. Crie uma pasta para seu projeto no seu webserver e dentro dela crie uma pasta lib. Após criar a pasta, extraia o Doctrine para ela. A estrutura deverá ficar semelhante a esta:
seu_projeto/lib/Doctrine
seu_projeto/lib/vendor
seu_projeto/lib/Doctrine.php

Crie também uma pasta chamada “models” na raíz do projeto, dando permissão 777 a ela. Esta pasta irá conter o model da aplicação.
seu_projeto/models

Configuração

Crie um arquivo na pasta raíz do projeto chamado “bootstrap.php”. Esse arquivo irá conter as configurações e parâmetros de funcionamento do Doctrine. Abaixo está o arquivo que eu uso. Você pode definir outros parâmetros consultando a documentação oficial.

// seu_projeto/bootstrap.php

require_once(dirname(__FILE__) . '/lib/Doctrine.php');

spl_autoload_register(array('Doctrine', 'autoload'));
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));

$manager = Doctrine_Manager::getInstance();

// Configurações do banco de dados. O banco deve ser criado previamente.
$user = 'postgres';
$password = 'teste';
$host = 'localhost';
$dbname = 'testdoctrine';
$driver = 'pgsql';

$conn = Doctrine_Manager::connection($driver.'://'.$user.':'.$password.'@'.$host.'/'.$dbname);
$conn->setOption('username', $user);
$conn->setOption('password', $password);
$manager->setAttribute(Doctrine_Core::ATTR_EXPORT, Doctrine_Core::EXPORT_ALL);
$manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_CONSERVATIVE);
$manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
$manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);

// Permite o override dos metodos do model.
$manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);

// Formato das sequências (uso para PostgreSQL)
$manager->setAttribute(Doctrine_Core::ATTR_SEQNAME_FORMAT, '%s_seq');

// Carrega os models da pasta especificada, no caso "models"
Doctrine_Core::loadModels('models');

Criação dos models

Com seu projeto configurado, o próximo passo é criar o model. Vou mostrar as 3 formas disponíveis.

Gerando as classes através das tabelas já existentes

Crie um arquivo chamado “test.php” que será usado neste e nos próximos passos. Deverá ter o seguinte conteúdo:

require_once('bootstrap.php');

Agora, basta adicionar as linhas abaixo ao seu arquivo “test.php”. Comente-a após a geração, pois senão os models serão gerados novamente a cada execução.

// seu_projeto/test.php
require_once('bootstrap.php');

Doctrine_Core::generateModelsFromDb('models', array('doctrine'), array(
	'generateTableClasses' => true
	)
);

Você pode usar como exemplo as tabelas abaixo:

CREATE TABLE cidade (
    id bigint NOT NULL,
    nome character(500) NOT NULL,
    uf character(2) NOT NULL
);

CREATE TABLE pessoa (
    id bigint NOT NULL,
    nome character(500) NOT NULL,
    data_nasc date,
    id_cidade bigint
);

ALTER TABLE ONLY cidade ADD CONSTRAINT cidade_pkey PRIMARY KEY (id);
ALTER TABLE ONLY pessoa ADD CONSTRAINT pessoa_pkey PRIMARY KEY (id);
ALTER TABLE ONLY pessoa ADD CONSTRAINT 
pessoa_id_cidade_cidade_id FOREIGN KEY (id_cidade) REFERENCES cidade(id);

Gerando as classes através de um arquivo YAML

Um arquivo YAML (extensão .yml) é um arquivo semelhante a um arquivo XML e eu diria muito mais poderoso (minha opinião). Ao invés de tags, os dados são representados pela identação dos atributos e seus valores (o pessoal do Python ama isso). A identação deve ser feita com espaços e não com tabulações. Para mais informações, consulte a Wikipédia.
Esta forma permite representar seus models no arquivo YAML.
Se você ainda não tem classes definidas, crie o arquivo “schemas.yml” na raíz do projeto com o conteúdo abaixo:

Cidade:
  connection: 0
  tableName: cidade
  columns:
    id:
      fixed: false
      notnull: true
      primary: true
      autoincrement: true
      type: integer(8)
    nome:
      fixed: true
      notnull: true
      type: string(500)
    uf:
      fixed: true
      notnull: true
      type: string(2)
  relations:
    Pessoa:
      local: id
      foreign: id_cidade
      type: many
Pessoa:
  connection: 0
  tableName: pessoa
  columns:
    id:
      fixed: false
      notnull: true
      primary: true
      autoincrement: true
      type: integer(8)
    nome:
      fixed: true
      notnull: true
      type: string(500)
    data_nasc: date(25)
    id_cidade: integer(8)
  relations:
    Cidade:
      local: id_cidade
      foreign: id
      type: one

Caso você já tenha as classes definidas, basta remover o código de geração das classes do arquivo “test.php” e adicionar as linhas abaixo:

// seu_projeto/test.php
require_once('bootstrap.php');
Doctrine_Core::generateYamlFromModels('schema.yml', 'models');

Após executar o test.php, você verá um arquivo chamado “schema.yml” na pasta raíz, com a definição do model. Crie agora um arquivo chamado “generate.php” com o código abaixo. Esse arquivo será responsável por remover as tabelas do banco de dados (se existirem) e recriá-las com base no arquivo “schema.yml”, gerando também as classes PHP. Portanto, muito cuidado, só execute quando for estritamente necessário, sob a pena de perder os dados do banco.

// seu_projeto/generate.php
require_once('bootstrap.php');

//Remova as próximas 2 linhas caso não queira remover e criar seu banco a cada execução.
Doctrine_Core::dropDatabases();
Doctrine_Core::createDatabases();
Doctrine_Core::generateModelsFromYaml('schema.yml', 'models');
Doctrine_Core::createTablesFromModels('models');

Definindo manualmente suas classes PHP

Usarei como exemplo duas classes, Pessoa e Cidade, sendo que uma pessoa pertence a uma cidade. Basta criar dois arquivos na pasta “models”, Pessoa.php e Cidade.php, com o código abaixo:

// seu_projeto/models/Cidade.php

class Cidade extends Doctrine_Record{
	public function setTableDefinition(){
		$this->hasColumn('id', 'integer', null, array(
			'fixed' => false, 
			'notnull' => true, 
			'primary' => true, 
			'autoincrement' => true
			)
		);
		$this->hasColumn('nome', 'string', 500, array('fixed' => true, 'notnull' => true));
		$this->hasColumn('uf', 'string', 2, array('fixed' => true, 'notnull' =>; true));
	}
}
// seu_projeto/models/Pessoa.php

class Pessoa extends Doctrine_Record{
	public function setTableDefinition(){
		$this->hasColumn('id', 'integer', null, array(
			'fixed' => false, 
			'notnull' => true,
			'primary' => true, 
			'autoincrement' => true
			)
		);
		$this->hasColumn('nome', 'string', 500, array('fixed' => true, 'notnull' => true));
		$this->hasColumn('data_nasc', 'date');
		$this->hasColumn('id_cidade', 'integer');
	}

	public function setUp(){
		$this->hasOne('Cidade', array(
				'local' => 'id_cidade',
				'foreign' => 'id'
			)
		);
	}
}

Após a definição das classes, rode o arquivo “test.php” com a linha “Doctrine_Core::generateYamlFromModels(‘schema.yml’, ‘models’);”. Após rodar esse arquivo, execute o “generate.php”, que irá apagar o banco de dados, criá-lo novamente e criar as tabelas referentes as classes.

Realizando consultas

Com o model pronto, vamos realizar algumas consultas.

Inserindo pessoa com uma cidade associada a ela

$cidade = new Cidade();
$cidade->nome = 'Marau';
$cidade->uf = 'RS';
$cidade->save();

$pessoa = new Pessoa();
$pessoa->nome = "Jonnas Fonini";
$pessoa->data_nasc = date('1990-04-12');
$pessoa->id_cidade = $cidade;
$pessoa->save();

Consultando informações de uma pessoa

$pessoa = Doctrine_Core::getTable('Pessoa')->find(1);
echo 'Id: '.$pessoa->id.'<br />';
echo 'Nome: '.$pessoa->nome.'<br />';
echo 'Data Nasc.: '.$pessoa->data_nasc.'<br />';
echo 'Cidade: '.$pessoa->Cidade->nome;

Atualizando informações de uma pessoa

$pessoa = Doctrine_Core::getTable('Pessoa')->find(1);
$pessoa->data_nasc = date('Y-m-d');
$pessoa->save();

Removendo uma pessoa

$pessoa = Doctrine_Core::getTable('Pessoa')->find(1);
$pessoa->delete();

Download

Clique aqui para baixar o projeto já pronto. Mude as configurações do banco de dados no arquivo “bootstrap.php”.

Conclusão

O Doctrine facilita muito a manipulação do banco de dados em PHP, poupando a você o trabalho de escrever consultas SQL. Incremente ainda mais seus estudos estudando o framework Symfony, um dos mais completos da atualizade e que faz uso do Doctrine. Pretendo criar mais posts sobre o Doctrine em breve.
Grande abraço a todos e até a próxima.

#soudev