Enviar e-mail em ASP.NET usando o GMail com conta no Google Apps

Um artigo bem simples que se encontra na net para envio de e-mail em C# é esse aqui. Um post bem simples e explicativo de como fazer o envio usando o SMTP do GMail. Mas não era bem isso que eu queria abordar (também) já que disponibilizei o link para o post ensinando como. Quem não conhece o Google Apps já deveria dar uma olhada pois é um conjunto de soluções empresariais que ajuda na redução de custos de TI dando uma maior produtividade. Uma delas é a criação de e-mails tendo um domínio externo. Vou dispensar explicações (nota: tem a versão free e paga)... vamos à "implementação". Suponhamos que eu tenha o domínio www.thiagomarcal.com.br e que esteja configurado para o Google Apps. Lá eu criei um e-mail contato@thiagomarcal.com.br e agora quero usá-lo para fazer o envio de e-mails. Basta eu seguir o post citado anteriormente que é possível fazer o envio com os seguintes dados:
  • SMTP: smtp.gmail.com
  • Sender: contato@thiagomarcal.com.br
  • Senha: 123456
  • Porta: 587
  • Ssl: true
Obviamente a senha é fictícia... apenas usando para fins didáticos, mas que realmente muita gente usa. Então, tudo certo! Faz-se um envio e dá o seguinte erro:

The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at

O servidor SMTP requer uma conexão segura ou o cliente não foi autenticado. A resposta do servidor foi: 5.5.1 Autenticação solicitada Saiba mais em

Se garantir que os dados estão todos certos e já testou com outra conta (e fez o envio corretamente) faça o seguinte: mude a senha! Senha fraca ou padrão (que nem 123456) o GMail bloqueia a autenticação e não deixa enviar.

Vulnerabilidade de Segurança no ASP.NET

Recentemente, em um congresso internacional, descobriu-se um problema de vulnerabilidade em sistemas ASP.NET através do web.config. O problema afeta todas as versões do framework... A matéria completa de como é o ataque e de como se proteger podem ser lidos nesses posts de Scott Guthrie:
  1. Important: ASP.NET Security Vulnerability
  2. Frequently Asked Questions about the ASP.NET Security Vulnerability
A priori, para impedir o ataque, proteja sua aplicação fazendo com que os erros não sejam exibidos para o cliente. No web.config adicione as seguintes tags:

<configuration>
   <system.web>
      <customErrors mode="On" defaultRedirect="~/Erro.aspx" />
   </system.web>
</configuration>

Assim, toda vez que ocorrer um erro, irá ser redirecionado para uma tela específica.

URL Rewriter - Escreva URL Amigáveis em ASP.NET

A URL Rewriter permite mascarar o endereço original por um novo endereço mais seguro e amigável. Se temos o endereço:

http://thiagomarcal.blogspot.com/noticas.aspx?id_noticia=123

Podemos re-escrevê-la da seguinte forma:

http://thiagomarcal.blogspot.com/noticias/123

Ou de outras formas conforme o mascaramento desejado. Para fazer o mascaramento é preciso do componente URL Rewriter instalado no IIS. Ele é gratuito e é instalado facilmente. Para cada web-site é configurado um mascaramento de endereços que automaticamente ele faz a conversão logo que requisitado.
Não vou entrar em detalhes do processo de instalação e configuração aqui pois no site oficial tem um vídeo (logo na Home), bastando seguir o passo-a-passo, que irá conseguir deixar conforme deseja. Também há disponível vários tutoriais que auxiliam no processo bem como funções avançadas. Clique aqui para visitar o site da Micrososft URL Rewriter.

PagSeguro com ASP.NET (C#)

O PagSeguro é uma das melhores soluções para pagamento on-line que já usei. Muito fácil de usá-la e integrá-la em qualquer sistema. Vantagens são inúmeras e facilidade bem além da conta. No site você encontra bastante informações de como utilizá-la bem como códigos-fonte. Teoni Valois mostra no vídeo abaixo como realizar a integração de forma muito fácil então dispensarei minhas explicações.


Nesse link aqui você obtêm o Framework, Loja-Exemplo e o Test Server. Para quem estiver com problema do retorno automático dando FALSO, siga os procedimentos desse post.

* Todos os links e vídeo aqui mostrado são de seus respectivos autores. Apenas estou divulgando seus artigos já que, se eu escrevesse, seria redundante ;)

Gerando relatórios com o Crystal Reports

O Crystal Reports é um componente que permite a criação de relatórios personalizados de alto nível. Em substituto de relatórios em HTML puro, ele fornece uma assistência inovadora desde a criação até exportação. Para quem utiliza Java, há também uma versão específica para a linguagem. Mostraremos abaixo como gerar um simples relatório buscando dados de uma tabela em banco usando C#.

Abra/Crie um projeto do tipo Web Site no Visual Studio e no Solution Explorer clique com o direito no diretório onde deseja criar o relatório. Escolha Add New Item e opte pelo template Crystal Reports (note que a extensão de relatório do Crystal é .rtp). Nessa primeira tela escolha a primeira opção conforme a figura abaixo:


Clique em OK. Expanda o nó do Create New Connection e novamente expanda o OLE DB (ADO) para configuração de conexão (essa é a primeira conexão com o banco para início, depois mostraremos como usar para outro banco). Na configuração do ADO, escolha o tipo de provider a ser utilizado (no caso optei pelo SQL Server, então SQL Native Client) e dê Next.


Agora, em Connection Information, informe os dados de conexão.


Clique em Next e na última tela revise os dados. Se estiver tudo certo, clique em Finish. Você voltará à tela anterior já com a configuração realizada e o banco estará apto a selecionar os objetos. Procure qual objeto irá ser manipulado e exibido seus dados, podendo ser: uma tabela, um schema, uma view ou stored procedure. Clique no objeto desejado e, em seguida, clique no botão com a seta para direita conforme figura abaixo:


Clique em Next. Agora informe quais campos irão ser exibidos e escolha Next.


Na próxima tela, se precisar agrupar alguns campos, informe quais são. Se não precisar dê apenas Next. Se o Crystal identificar que está trabalhando com números, ele cria um passo adicional que é a opção de inserir gráficos. Outra tela que é exibida é a de Filtros. Se for ter filtros, informe-os. Caso contrário dê apenas Next. Ou seja, as duas últimas telas são parâmetros opcionais logo, se não desejar configurá-los, dê Next duas vezes. O último passo é escolher o estilo. Opte pelo mais parecido que quer e dê Finish.


Basicamente seu relatório está pronto, bastando ajustes da posição dos campos, design, cabeçalho, etc. Em Field Explorer, contêm as principais funcionalidades para fórmulas e cálculos avançados bem como a adição de novos campos. Como estamos elaborando um relatório simples, vamos parar por aí. Para ver um preview de como estará seu relatório com os dados, clique em Main Report Preview. Agora vamos ver como chamar pelo ASP.NET (C#).
Adicione uma página Impressao.aspx e nele adicione um objeto CrystalReportViewer que automaticamente irá ser registrado o assembly na página (puxando do ToolBox ele insere automaticamente). Se preferível configure alguns atributos do objeto como remoção da logo da BO, tema, etc. No code-behind, adicione os seguintes namespaces:

using CrystalDecisions.ReportSource;
using CrystalDecisions.Shared;
using CrystalDecisions.CrystalReports.Engine;
 
E para exibir os dados do relatório utilize o seguinte código:
 
DataSet ds = new DataSet();
// Antes, faço uma consulta no banco e jogo no DataSet para ser usado logo abaixo
ReportDocument relatorio = new ReportDocument();
relatorio.Load(Server.MapPath("Relatorio.rpt"));
relatorio.Database.Tables[0].SetDataSource(ds.Tables[0]);
// Esse é Viewer que puxamos antes
CrystalReportViewerRelatorio.ReportSource = relatorio;
CrystalReportViewerRelatorio.DataBind();
 
Pronto! Seu relatório será exibido...
 
 
Agora vamos aos problemas:
 
1) Fiz todo o processo mas ao exibir o relatório está pedindo login e senha do SQL Server
 
Se estiver usando DataSet, veja que só pude passar uma tabela por vez usando ds.Tables[0] e não apenas ds. Se quiser passar várias tabelas crie um DataSet tipado no App_Code ou informe uma a uma no atributo Database.
 
2) As imagens dos botões do relatório não estão aparecendo e ao clicar não funciona nada
 
Ao ser colocado em produção, verifique se o Crystal Reports está instalado corretamente na máquina. Veja se a pasta wwwroot\aspnet_client\system_web\ contêm a pasta CrystalReportWebFormViewer (depois da pasta system_web vem a versão do framework - exemplo 2_0_50727 - e em seguida vem ela). Copie a pasta aspnet_client e adicione na raiz de sua aplicação.
 
3) Ao exibir o relatório está aparecendo o erro: Não foi possível carregar arquivo ou assembly 'System.Web.Extensions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ou uma de suas dependências. A definição do manifesto do assembly localizado não corresponde à referência do assembly. (Exceção de HRESULT: 0x80131040)
 
Faça os procedimentos informados nesse post.
 
4) Depois que é exibido o relatório, ao clicar no botão de imprimir ou exportar ou qualquer outro botão, não executa nenhum dos processos que deveria fazer
 
Se estiver usando ASP.NET AJAX e o CrystalReportViewer estiver dentro de um UpdatePanel, remova-o. Pois, ao clicar em desses botões, é feito um PostBack na página (além de tentar abrir uma janela pop-up) e o Crystal não funciona adequadamente quando utiliza o AJAX.
 
5) Ao tentar exibir o relatório, ocorre o seguinte erro: O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção
 
Reinstale o Crystal Reports ou tente as soluções sugeridas nesse post.
 
6) Minhas imagens e/ou gráficos não estão aparendo ao exibir o relatório (fica aquele X de imagem não carregada) ou ficam distorcidas/baixa resolução
 
Se for uma imagem que está sendo inserida do disco (que você tem no computador e está inserindo através de Insert > Picture) verifique o formato dessa imagem (preferível JPG ou BMP) e as cores utilizadas bem como efeitos (fundo transparente, camadas). Quanto mais simples a imagem for, melhor será sua visualização. Se apesar de tudo ainda não estiver aparecendo, verifique no web.config se há as seguintes entradas:
  1. Em system.web > httpHandlers:

    <add verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
    <add verb="*" path="GenerateImage.ashx" type="GenerateDynamicImage"/>
     
  2. E em system.webServer > handlers:

    <add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode"/>
7) Meu relatório tem mais de 2 páginas mas só fica exibindo 2/2+ quando clico em avançar

Coloque todo o processo de geração do relatório dentro de Page_Init ou invés de Page_Load.

8) Meu relatório não exibe, a princípio, a quantidade total de páginas. Fica exibindo 1/1+...

O Crystal faz isso para não ter de renderizar todo o relatório e sobrecarregar, então faça o seguinte artifício depois de dar o Bind():

CrystalReportViewerRelatorio.ShowLastPage();
CrystalReportViewerRelatorio.ShowFirstPage();

Ou seja, vou rapidamente para a última página e volto apenas para o Crystal renderizar a última página e saber quantas temos ao todo.

Exportar Banco de Dados (BAK ou MDF) do SQL Server 2008 para o 2005

A forma mais fácil de transferir um banco para outro é fazer um BAK dele e depois recuperar do outro lado. Do 2005 para o 2008 é possível realizar a recuperação, mas do 2008 para o 2005 não é possível realizar o downgrade. Qual a solução? Gerar o script geral do banco e executá-lo no banco de destino. Mas se meu banco é muito grande, como fazer? A dica está no final do post, mas façamos tudo desde o início.
Abra o SQL Server Management Studio (ou Express) e conecte-se ao Server. Clique com o botão direito sobre a base de dados e siga em Task (Tarefas) e escolha Generate Scritps (Gerar Scripts). Na tela de seleção de base, marque a opção Script all objects in the selected database (Scritp de todos os objetos da base selecionada) e avance. Nessa próxima tela procure os itens abaixo e atribua os seguintes valores:
  1. Script for Server Version (Versão de Script do Server): SQL Server 2005
  2. Script Data (Script de Dados): True
  3. Script USE DATABASE: False
Demais opções fica a seu critério optar... Agora avance e na próxima tela escolha salvar o arquivo em disco com as opções Simples (Single file) e Unicode text. Avance, revise o que foi selecionado e finalize. Aguarde até que o processo seja finalizado. Quando terminado seu script já estará pronto para ser executado no destino.
O próximo passo é executar o script gerado na base de destino. Crie a base de destino vazia e agora temos duas opções:
  • Se o script gerado for pequeno (ou seja base pequena) podemos simplesmente abrir pelo próprio SQL Server Management e executar como se fosse Querys consecutivas;
  • Se o script for grande vamos usar um artifícío para isso.
Como a primeira opção é a mais simples (e também porque gosto de aventurar-me) vamos optar pela segunda (e que também é nossa realidade). No meu exemplo, o script gerado ficou em torno de 1,5Gb. Se desejar reduzir o tamanho um pouco, às vezes, reduzir o log ajuda (saiba como reduzir aqui) antes de gerar o script.
Abra o Prompt de Comando (emulador do DOS no Windows) e digite o seguinte comando:


sqlcmd -U thiago -P blog -S THIAGOMARCAL\SQLEXPRESS -d BaseBlog -i C:\ScriptSQL.sql -o C:\LogExecucao.txt

Explicando os atributos:
  • U: informa o nome do usuário que está conectando (no caso, o usuário thiago);
  • P: informa a senha do usuário (a senha é blog);
  • S: nome do servidor (como está na minha máquina a instância é THIAGOMARCAL\SQLEXPRESS);
  • d: nome da base nova que receberá o resultado do script (BaseBlog é o nome da nova base criada);
  • i: local onde salvei o script de dados e que usarei como entrada;
  • o: arquivo de texto contendo o resultado da operações (log para análise - opcional).
Dê ENTER e aguarde toda a operação ser executada. Para quaisquer tamanho do arquivo ele será processado sem problemas. Se tentasse abrir pelo SQL Server um arquivo muito grande daria erro de alocação de memória, ou demoraria e nem conseguiria executar exibindo alguns dos seguintes erros:
  • Cannot Open Datafile
  • Insufficient memory
  • Out of Memory Exception
Dessa forma é mais tranquilo...