ASP .NET - Enviando email a partir do GridView


Neste artigo veremos como enviar emails com os dados de um GridView em uma aplicação ASP .NET Web Forms.

O conceito usado neste exemplo consiste em gerar uma string HTML a partir de um controle GridView e então embutir a string HTML em uma seção body de um email e então enviar o email.

Ele usa o velho e bom ASP .NET Web Forms que

Recursos usados:

Criando a solução

Abra o Visual Studio Express 2012 for web ou o Visual Studio Community mais recente e clique em New Web Site;

Selecione a linguagem de sua escolha (vou usar Visual Basic) e o template ASP .NET Empty Web Site, informe o nome EnviandoEmails_GridView e clique em OK;

No menu WEBSITE clique em Add New Item e selecione o template Web Form e aceite o nome padrão Default.aspx para a página e clique em Add;

Selecione a página Default.aspx alterne para o modo Source e inclua entre as tags <div> um controle GridView(GridView1) e abaixo dele um controle Label (lblmsg) e a seguir um controle Button(btnEnviaEmail) a partir da ToolBox configurando os controles conforme o código abaixo:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>GridView - Enviando Emails </title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
        <asp:GridView ID="GridView1" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="Black"
            RowStyle-BackColor="#A1CCD2" AlternatingRowStyle-BackColor="White" AlternatingRowStyle-ForeColor="#000"
            runat="server" AutoGenerateColumns="false">
            <Columns>
                <asp:BoundField DataField="Id" HeaderText="Id" ItemStyle-Width="80" />
                <asp:BoundField DataField="Nome" HeaderText="Nome" ItemStyle-Width="150" />
                <asp:BoundField DataField="Email" HeaderText="Email" ItemStyle-Width="150" />
            </Columns>
        </asp:GridView>
        <asp:Label ID="lblmsg" runat="server" Text="Label"></asp:Label>
        <br />
        <asp:Button ID="btnEnviaEmail" runat="server" Text="Enviar Email" OnClick="EnviarEmail" />

    </div>
    </form>
</body>
</html>

A aparência da página deverá ser a seguinte:

No code-behind do arquivo Default.aspx.vb defina os seguintes namespaces no início do arquivo:

Imports System.IO
Imports System.Data
Imports System.Net.Mail

No evento Load da página Default.aspx vamos definir um DataTable com três colunas: Id, Nome e Email e definir alguns dados para preencher o controle GridView conforme a seguir: (Assim não dependemos de um banco de dados):

 Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load

        If Not Me.IsPostBack Then
            Dim dt As New DataTable()
            dt.Columns.AddRange(New DataColumn(2) {New DataColumn("Id"), New DataColumn("Nome"), New DataColumn("Email")})
            dt.Rows.Add(1, "Jose Carlos Macoratti", "macoratti@yahoo.com")
            dt.Rows.Add(2, "Janice Raquel Siqueira", "janjan@bol.dom.br")
            dt.Rows.Add(3, "Jefferson Ribeiro", "jeff@uol.com.br")
            dt.Rows.Add(4, "Yuri Santos", "yuris@net.com.br")
            dt.Rows.Add(5, "Jessica Bueno Lima", "jessbulim@uol.com.br")
            GridView1.DataSource = dt
            GridView1.DataBind()

        End If
    End Sub

Executando o projeto iremos obter a página Default.aspx conforme abaixo:

No evento Click do botão Enviar Email inclua o código abaixo que chama a rotina EnviarEmail():

Protected Sub EnviarEmail(sender As Object, e As EventArgs) Handles btnEnviaEmail.Click
     EnviarEmail()     
End Sub

Crie a rotina EnviarEmail com o código mostrado abaixo:

 Private Sub EnviarEmail()
        'Criamos um objeto do tipo StringWriter e um objeto HtmlTextWriter passando o conteúdo total do Gridview Renderizado.
        'Criamos uma string e atribuindo a ela o texto (código HTML) gerado na renderização.
        Using sw As New StringWriter()
            Using hw As New HtmlTextWriter(sw)
                GridView1.RenderControl(hw)
                Dim sr As New StringReader(sw.ToString())

                'cria uma instância de MailMessage
                Dim meuEmail As New MailMessage("macoratti@gmail.com", "alguem@gmail.com")
                meuEmail.Subject = "Email do GridView"
                meuEmail.Body = "GridView:<hr />" + sw.ToString()
                meuEmail.IsBodyHtml = True
                'Define a prioridade do E-mail
                meuEmail.Priority = MailPriority.High

                'cria uma instância da classe SmtpClient
                Dim smtp As New SmtpClient()
                smtp.Host = "smtp.gmail.com"
                smtp.EnableSsl = True
                Dim NetworkCred As New System.Net.NetworkCredential()
                NetworkCred.UserName = "macoratti@gmail.com"
                NetworkCred.Password = "<sua_senha_smtp>"
                smtp.UseDefaultCredentials = True
                smtp.Credentials = NetworkCred
                smtp.Port = 587
                Try
                    smtp.Send(meuEmail)
                    lblmsg.Text = "Email enviado com sucesso!!!"
                Catch ex As Exception
                    lblmsg.Text = "Falha ao Enviar o Email"
                End Try
            End Using
        End Using
    End Sub

Atenção !!!!

Esta rotina irá funcionar apenas se você estiver com o código no host onde existe um servidor SMTP configurado. Note que você tem que fornecer as suas credenciais.

Se você deseja enviar emails a partir da sua máquina local (127.0.0.1) terá que configurar no IIS o servidor SMTP.

Veja este artigo: Configurando o servidor SMTP no IIS - Macoratti.net

Um palavra final...

Clean Code

Note que a nossa rotina para enviar email tem muitas atribuições. Ela cuida da renderização do controle GridView, da instanciação da classe para enviar email e sua configuração e da instanciação da classe para enviar efetivamente o email.

O primeiro princípio SOLID, o princípio da responsabilidade única - SRP, declara que "Uma classe deve ter um, e somente um, motivo para mudar."

Portanto uma classe/rotina deve ser implementada tendo apenas um único objetivo.

Quando uma classe possui mais que um motivo para ser alterada é por que provavelmente ela esta fazendo mais coisas do que devia, ou seja, ela esta tendo mais de um objetivo.

Para corrigir este problema no código do artigo o correto seria criar uma classe para renderizar o conteúdo do GridView, outra para configurar o Email e outra para enviar o email.

O exemplo é funcional mas não é robusto e fere o princípio da responsabilidade única.

Que tal mostrar as suas habilidades e criar uma rotina genérica para enviar emails segundo as boas práticas ???

Pegue o projeto completo aqui: EnviandoEmails_GridView.zip

Mat 7:13 Entrai pela porta estreita; porque larga é a porta, e espaçoso o caminho que conduz à perdição, e muitos são os que entram por ela;

Mat 7:14 e porque estreita é a porta, e apertado o caminho que conduz à vida, e poucos são os que a encontram.

Referências:


José Carlos Macoratti