In this article I will explain how to attach multiple files and send email like GMAIL in ASP.Net using jQuery Uploadify Plugin.
HTML Markup
Below is the HTML Markup which is nothing but a simple form to send email.
<tr><td>To:</td><td><asp:TextBox ID="txtTo" runat="server"></asp:TextBox></td></tr>
<tr><td>Subject:</td><td><asp:TextBox ID="txtSubject" runat="server"></asp:TextBox></td></tr>
<tr><td>Body:</td><td><asp:TextBox ID="txtBody" runat="server" TextMode="MultiLine"></asp:TextBox></td></tr>
<tr><td></td><td><asp:FileUpload ID="FileUpload1" runat="server"/></td></tr>
<tr><td></td><td><table id="attachedfiles"></table></td></tr>
<tr><td></td><td><asp:Button ID="btnSend" runat="server" Text="Send" OnClick="btnSend_Click"/></td></tr>
Generating the Unique Key for Cache
In the Page Load event of the Page a Unique Key for Cache is generated and is stored in a protected ViewState property
protected string Key
    get { return ViewState["Key"].ToString(); }
    set { ViewState["Key"] = value; }
protected void Page_Load(object sender, EventArgs e)
    if (!IsPostBack)
        this.Key = Guid.NewGuid().ToString();
        Cache[this.Key] = new List<HttpPostedFile>();
Protected Property Key() As String
        Return ViewState("Key").ToString()
    End Get
    Set(value As String)
        ViewState("Key") = value
    End Set
End Property
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If Not IsPostBack Then
        Me.Key = Guid.NewGuid().ToString()
        Cache(Me.Key) = New List(Of HttpPostedFile)()
    End If
End Sub
Initially this article was using Session variable, but due to some reason Uploadify does not retain Session in Firefox browser hence I had to change the functionality to make use of Cache instead. But since Cache is not user specific i.e. shared across all users, we will need to generate a unique GUID Key for each user so that the Files can be uniquely identified.
Uploading multiple files as email attachments
To allow select and upload multiple files, I have made use of Uploadify jQuery plugin
You will notice that I have used <% %> server side Tags <%=Key %> in the script, this is the ViewState protected Property (discussed earlier) which is used to pass the Cache Unique key to access the Cache variable during Upload and also during file removal.
<link rel="Stylesheet" type="text/css" href="CSS/uploadify.css" />
<script type="text/javascript" src="scripts/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="scripts/jquery.uploadify.js"></script>
<script type="text/javascript">
    $(function () {
            'uploader': 'scripts/uploader.swf',
            'cancelImg': 'images/cancel.png',
            'buttonText': 'Attach Files',
            'script': 'UploadCS.ashx',
            'folder': 'uploads',
            'multi': true,
            'auto': true,
            'scriptData': {key:'<%=Key %>'},
            'onSelect': function (event, ID, file) {
                $("#attachedfiles tr").each(function () {
                    if ($("td", this).eq(0).html() == {
                        alert( + " already uploaded.");
            'onComplete': function (event, ID, file, response, data) {
                $("#attachedfiles").append("<tr><td>" + + "</td><td><a href = 'javascript:;'>[x]</a></td></tr>");
The files are uploaded via Generic Handler Upload.ashx. I am storing the uploaded files in Cache. Also the uploaded files are dynamically displayed on the page.
The Cache Unique Key passed to the Handler via Uploadify Plugin is
<%@ WebHandler Language="C#" Class="UploadCS" %>
using System;
using System.Web;
using System.IO;
using System.Collections.Generic;
public class UploadCS : IHttpHandler {
    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        context.Response.Expires = -1;
            List<HttpPostedFile> files = (List<HttpPostedFile>)context.Cache[context.Request.QueryString["key"]];
            HttpPostedFile postedFile = context.Request.Files["Filedata"];
            string filename = postedFile.FileName;
            context.Response.StatusCode = 200;
        catch (Exception ex)
            context.Response.Write("Error: " + ex.Message);
    public bool IsReusable {
        get {
            return false;
<%@ WebHandler Language="VB" Class="UploadVB" %>
Imports System
Imports System.Web
Imports System.IO
Imports System.Collections.Generic
Public Class UploadVB : Implements IHttpHandler
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
            Dim files As List(Of HttpPostedFile) = DirectCast(context.Cache(context.Request.QueryString("key")), List(Of HttpPostedFile))
            Dim postedFile As HttpPostedFile = context.Request.Files("Filedata")
            Dim filename As String = postedFile.FileName
            context.Response.StatusCode = 200
        Catch ex As Exception
            context.Response.Write("Error: " + ex.Message)
        End Try
    End Sub
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
            Return False
        End Get
    End Property
End Class
Removing Attached files using jQuery AJAX
I have also added functionality to remove files like we have in GMAIL browser. To achieve this I have made use of jQuery AJAX and ASP.Net Page Methods
<script type="text/javascript">
    $("#attachedfiles a").live("click", function () {
        var row = $(this).closest("tr");
        var fileName = $("td", row).eq(0).html();
            type: "POST",
            url: "CS.aspx/RemoveFile",
            data: '{fileName: "' + fileName + '", key: "<%=Key %>" }',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function () { },
            failure: function (response) {
The above JavaScript function makes call to a WebMethod defined below which deletes the file from the Cache variable where it was stored.
public static void RemoveFile(string fileName, string key)
    List<HttpPostedFile> files = (List<HttpPostedFile>)HttpContext.Current.Cache[key];
    files.RemoveAll(f => f.FileName.ToLower().EndsWith(fileName.ToLower()));
<WebMethod()> _
Public Shared Sub RemoveFile(fileName As String, key As String)
    Dim files As List(Of HttpPostedFile) = DirectCast(HttpContext.Current.Cache(key), List(Of HttpPostedFile))
    files.RemoveAll(Function(f) f.FileName.ToLower().EndsWith(fileName.ToLower()))
End Sub
Sending the email with multiple attachment
Finally here’s the code to send email using GMAIL account.
protected void btnSend_Click(object sender, EventArgs e)
    using (MailMessage mailMessage = new MailMessage())
        mailMessage.From = new MailAddress("");
        mailMessage.Subject = txtSubject.Text.Trim();
        mailMessage.Body = txtBody.Text.Trim();
        mailMessage.IsBodyHtml = true;
        mailMessage.To.Add(new MailAddress(txtTo.Text.Trim()));
        List<HttpPostedFile> files = (List<HttpPostedFile>)Cache[this.Key];
        foreach (HttpPostedFile file in files)
            mailMessage.Attachments.Add(new Attachment(file.InputStream, Path.GetFileName(file.FileName), file.ContentType));
        SmtpClient smtp = new SmtpClient();
        smtp.Host = "";
        smtp.EnableSsl = true;
        System.Net.NetworkCredential NetworkCred = new System.Net.NetworkCredential();
        NetworkCred.UserName = mailMessage.From.Address;
        NetworkCred.Password = "<Password>";
        smtp.UseDefaultCredentials = true;
        smtp.Credentials = NetworkCred;
        smtp.Port = 587;
Protected Sub btnSend_Click(sender As Object, e As EventArgs)
    Using mailMessage As New MailMessage()
        mailMessage.From = New MailAddress("")
        mailMessage.Subject = txtSubject.Text.Trim()
        mailMessage.Body = txtBody.Text.Trim()
        mailMessage.IsBodyHtml = True
        mailMessage.[To].Add(New MailAddress(txtTo.Text.Trim()))
        Dim files As List(Of HttpPostedFile) = DirectCast(Cache(Me.Key), List(Of HttpPostedFile))
        For Each file As HttpPostedFile In files
            mailMessage.Attachments.Add(New Attachment(file.InputStream, Path.GetFileName(file.FileName), file.ContentType))
        Dim smtp As New SmtpClient()
        smtp.Host = ""
        smtp.EnableSsl = True
        Dim NetworkCred As New System.Net.NetworkCredential()
        NetworkCred.UserName = mailMessage.From.Address
        NetworkCred.Password = "<Password>"
        smtp.UseDefaultCredentials = True
        smtp.Credentials = NetworkCred
        smtp.Port = 587
    End Using
End Sub
Send email with multiple attachments like GMAIL in ASP.Net