如何在电子邮件正文中插入带有行图像按钮的网格视图

How to insert a gridview with a row image button into the email body

提问人:samsmuthu 提问时间:2/5/2023 最后编辑:James Zsamsmuthu 更新时间:2/6/2023 访问量:98

问:

我编写了一些代码来发送电子邮件并从 Gridview 插入一个表格单元格。

Protected Sub SendRequestMail()
    Dim tryCount As Integer = 5
    Dim failed As Boolean = False
    Do
        Try
            failed = False

            Dim ToMailIDs As String
            ToMailIDs = LblRecipients.Text

            Using sw As New StringWriter()
                Using hw As New HtmlTextWriter(sw)

                    GridView1.RenderControl(hw)
                    Dim sr As New StringReader(sw.ToString())

                    Dim smtpSection As SmtpSection = CType(ConfigurationManager.GetSection("system.net/mailSettings/smtp"), SmtpSection)
                    Dim mm As MailMessage = New MailMessage()

                    mm.From = New MailAddress(smtpSection.From, "Notification")
                    For i As Integer = 0 To ToMailIDs.Split(","c).Length - 1
                        mm.To.Add(New MailAddress(ToMailIDs.Split(","c)(i)))
                    Next

                    mm.ReplyTo = New MailAddress("[email protected]")

                    mm.Subject = LblMrNumFull.Text & " | " & LblMrDate1x.Text & " | " & LblStorsName1.Text & " - Approval"

                    mm.Body = LblMrNumFull.Text & " | " & LblMrDate1x.Text & " | " & LblStorsName1.Text
                  
                    mm.Body += sw.ToString()

                    mm.Body += "<br />"
                    mm.Body += "Thanking you" 
                    
                    mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
                    mm.DeliveryNotificationOptions = DeliveryNotificationOptions.Delay
                    mm.Headers.Add("Disposition-Notification-To", "[email protected]")

                    ' ----- webconfig mail start
                    mm.IsBodyHtml = True
                    Dim smtp As SmtpClient = New SmtpClient
                    smtp.Host = smtpSection.Network.Host
                    smtp.EnableSsl = smtpSection.Network.EnableSsl
                    Dim networkCred As NetworkCredential = New NetworkCredential(smtpSection.Network.UserName, smtpSection.Network.Password)
                    smtp.UseDefaultCredentials = smtpSection.Network.DefaultCredentials
                    smtp.Credentials = networkCred
                    smtp.Port = smtpSection.Network.Port
                    smtp.Send(mm)
                    ' ----- webconfig mail end

                End Using
            End Using

        Catch ex As Exception
            failed = True
            tryCount = tryCount - 1
        Finally
            Response.Redirect("~/abc/xyx.aspx?NewID=" & Request.QueryString("NewID"))
        End Try

    Loop While failed AndAlso tryCount > 0
End Sub

该代码有效,电子邮件已成功发送。 之后,我在 Gridview 的最后一列中添加了一个图像按钮:

enter image description here

然后停止发送电子邮件。请建议使用上述代码发送带有或不带有最后一列图像按钮的电子邮件。

尝试什么都没用

'To Export all pages.

GridView1.AllowPaging = False
Me.BindData_GridView1()

GridView1.HeaderRow.BackColor = Color.White
For Each cell As TableCell In GridView1.HeaderRow.Cells
    cell.BackColor = GridView1.HeaderStyle.BackColor
Next
For Each row As GridViewRow In GridView1.Rows
    row.BackColor = Color.White
    For Each cell As TableCell In row.Cells
        If row.RowIndex Mod 2 = 0 Then
            cell.BackColor = GridView1.AlternatingRowStyle.BackColor
        Else
            cell.BackColor = GridView1.RowStyle.BackColor
        End If
        cell.CssClass = "textmode"
    Next
Next
asp.net vb.net 电子邮件 网格视图

评论

0赞 Albert D. Kallal 2/5/2023
我没有看到任何关于你的gridview循环与发送电子邮件有太大关系。我会创建一个例程,比如 MySendMail(sTo, sCC, sBody),并传递该信息(这样你就有了一个可以从任何代码调用的例程。然后将 gv 文本添加到正文中,并确定它在哪个点上失败,但将图像添加到电子邮件本身就是一个又大又长又巨大且庞大的复杂主题。此类图像可以(应该)转换为 base64 图像字符串,并且它们需要保持较小,否则电子邮件发件人(和客户端)通常会拒绝。构建 MySendMail 例程并测试

答:

0赞 Albert D. Kallal 2/6/2023 #1

图像是由 URL 提供的吗?

您可以考虑将图像转换为内联“base64”字符串,因此 GV 的 html 渲染将不包含链接。

有可能(但尚未确定)您不希望将图像作为指向当然指向您网站的 URL 的“链接”。

换句话说,如果您尝试在该正文的 html 中添加/渲染/注入/拥有/使用/欣赏某些图像,请尝试使用“字符串”而不是图像的实际 URL。

所以,说这个例子简单的gv

<h3>Hotels</h3>
<asp:GridView ID="GridView1" runat="server" Width="40%"
    AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-striped">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
        <asp:BoundField DataField="LastName" HeaderText="LastName" />
        <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField>
            <ItemTemplate>
                <asp:ImageButton ID="cmdApprove" runat="server"
                    ImageUrl="~/Content/Pictures/check1.jpg"
                    Width="48"
                    OnClick="cmdApprove_Click" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

要加载的代码是这样的:

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

    If Not IsPostBack Then
        LoadGrid()
    End If

End Sub

Sub LoadGrid()

    GridView1.DataSource = Myrst("SELECT * FROM tblHotelsA ORDER BY Hotelname")
    GridView1.DataBind()

End Sub

我们现在有了这个:

enter image description here

但是,现在让我们按 f12 获取浏览器开发工具和元素,并检查该 ImageButton,我们发现/得到这个:

<input type="image" name="GridView1$ctl03$cmdApprove"
 id="GridView1_cmdApprove_1"
 src="../Content/Pictures/check1.jpg" 
 style="width:48px;">

好吧,我看不出网格视图将如何在电子邮件正文中呈现,因为您有指向网站的路径名和“URL”,更糟糕的是,它们是相对路径名,仅适用于当前给定的网站,并且仅适用于当前文件夹页面

请注意“../“作为路径名!如果您将该网页移动到其他文件夹,即使是简单的路径名也无法再起作用!!

因此,让我们从该 ImageButton 中删除 URL。

并让“流式传输”+将图片注入为嵌入的字节数组。

因此,我们的图像按钮现在变成了:

<ItemTemplate>
  <asp:ImageButton ID="cmdApprove" runat="server"
    Width="48"
    OnClick="cmdApprove_Click" />
</ItemTemplate>

所以,没有图像。

但是,现在,在行数据绑定事件中,我们这样做:

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound


    If e.Row.RowType = DataControlRowType.DataRow Then

        Dim ImageBtn As ImageButton = e.Row.FindControl("cmdApprove")

        ImageBtn.ImageUrl = gImageBytes("~/Content/Pictures/check1.jpg")

    End If

End Sub


Function gImageBytes(sFile As String) As String

    Dim sFileInternal As String =
        Server.MapPath(sFile)


    Dim iBytes As Byte() = File.ReadAllBytes(sFileInternal)
    Dim sMineType As String = MimeMapping.GetMimeMapping(sFileInternal)

    Return $"data:{sMineType};base64,{Convert.ToBase64String(iBytes, 0, iBytes.Length)}"


End Function

当我们运行时,gv 看起来是一样的。

但是,现在检查标记,我们得到/看到这个:

 <input type="image" name="GridView1$ctl02$cmdApprove"
 id="GridView1_cmdApprove_0" 
 src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAS etc." 
 style="width:48px;">

我“剪切”了图像的其余字节,但现在请注意,标记在 Web 服务器上没有指向某些图像的 URL 路径名 - 客户端电子邮件正文永远不会有。

因此,上述操作将/可能/将删除该网格中图像的路径名。

然而,甚至更好?

我会“隐藏”按钮(visible = false)意味着 html 不会在 gv 中呈现,因此您最终会 100% 删除按钮。因此,在行数据绑定中,隐藏按钮 - 它们的标记将不会呈现。

所以,这样说:

在页面类中,定义一个标志,如下所示:

Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound


    If e.Row.RowType = DataControlRowType.DataRow Then

        Dim ImageBtn As ImageButton = e.Row.FindControl("cmdApprove")

        ImageBtn.Visible = Not (bHideGridButtons)

        ImageBtn.ImageUrl = gImageBytes("~/Content/Pictures/check1.jpg")

    End If

End Sub

所以,现在 gv 变成这样:

enter image description here

或者,另一个想法?,然后创建第二个 GV,并将其用于电子邮件。

(无论如何,我看不出在某些电子邮件正文中包含按钮的意义!

因此,您可以尝试删除图像。

然而,在做任何事情之前?

创建一个单独的 100% 例程,这样说:

Call SendMailWeb(strTO, strSubject, 
      strBody, True, strCC, strBC, 
      FileAttachments, strReplyFromList)

或“随便”。

因此,使用单独的例程来调用,这将允许轻松编码,但也允许您根据上述想法制作一些测试网格,例如删除图像链接,并使用“流式处理”

我经常甚至显示图像,甚至为用户下载文件?

我不允许、提供、使用、允许任何公共或基于文件的“URL”路径名来自网站和标记。所有文件操作都是 100% 来自代码隐藏,因此我从不在任何时候将文件公开给网站上允许的公共 URL。(这样做是出于安全原因,也是为了让用户下载PDF文档,但该pdf文件夹不会公开为任何URL公共路径名。

代码隐藏 100% 忽略 IIS 安全设置,文件路径名是 100% 平面 jane 服务器路径(老式的 Windows 路径名)。因此,虽然这是一个简单的“图像”示例,但它确实表明某些图像的 URL 不一定是该图像要显示的有效且现有的 URL,而只是将文件读取为字节的代码,然后将图像作为 base 64 图像字符串进行蒸出。

因此,对于电子邮件正文中接近任何图像的几乎,图片的链接和路径名在某些客户端计算机上的电子邮件正文中不起作用,这些客户端计算机甚至可能根本没有您的网站 URL 到图片路径名称。

0赞 samsmuthu 2/6/2023 #2

我从另一个论坛得到了解决方案,所以我把它贴在下面。

[HTML全文]

<%@ Page Title="" Language="vb" AutoEventWireup="false"  EnableEventValidation="false" MasterPageFile="~/abc/xyz.Master" CodeBehind="aaaa1.aspx.vb" Inherits="aaaa.sss" %>

VB.NET

Protected Sub SendRequestMail()
Dim tryCount As Integer = 5
Dim failed As Boolean = False
Do
    Try
        failed = False
        Dim ToMailIDs As String
        ToMailIDs = LblRecipients.Text
        GridView1.Columns(GridView1.Columns.Count - 1).Visible = False
        Using sw As New StringWriter()
            Using hw As New HtmlTextWriter(sw)
                GridView1.RenderControl(hw)
                Dim sr As New StringReader(sw.ToString())
                Dim smtpSection As Net.Configuration.SmtpSection = CType(ConfigurationManager.GetSection("system.net/mailSettings/smtp"), SmtpSection)
                Dim mm As System.Web.Mail.MailMessage = New System.Web.Mail.MailMessage()
                mm.From = New MailAddress(smtpSection.From, "Notification")
                For i As Integer = 0 To ToMailIDs.Split(","c).Length - 1
                    mm.To.Add(New MailAddress(ToMailIDs.Split(","c)(i)))
                Next
                mm.ReplyTo = New MailAddress("[email protected]")
                mm.Subject = LblMrNumFull.Text & " | " & LblMrDate1x.Text & " | " & LblStorsName1.Text & " - Approval"
                mm.Body = LblMrNumFull.Text & " | " & LblMrDate1x.Text & " | " & LblStorsName1.Text
                mm.Body += sw.ToString()
                mm.Body += "<br />"
                mm.Body += "Thanking you"
                mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
                mm.DeliveryNotificationOptions = DeliveryNotificationOptions.Delay
                mm.Headers.Add("Disposition-Notification-To", "[email protected]")
                ' ----- webconfig mail start
                mm.IsBodyHtml = True
                Dim smtp As SmtpClient = New SmtpClient
                smtp.Host = smtpSection.Network.Host
                smtp.EnableSsl = smtpSection.Network.EnableSsl
                Dim networkCred As NetworkCredential = New NetworkCredential(smtpSection.Network.UserName, smtpSection.Network.Password)
                smtp.UseDefaultCredentials = smtpSection.Network.DefaultCredentials
                smtp.Credentials = networkCred
                smtp.Port = smtpSection.Network.Port
                smtp.Send(mm)
                ' ----- webconfig mail end
            End Using
        End Using
        GridView1.Columns(GridView1.Columns.Count - 1).Visible = True
    Catch ex As Exception
        failed = True
        tryCount = tryCount - 1
    Finally
        Response.Redirect("~/abc/xyx.aspx?NewID=" & Request.QueryString("NewID"))
    End Try
Loop While failed AndAlso tryCount > 0

结束子

Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control) End Sub

谢谢