In this article I will explain with an example, how to read emails from POP3 mail server in ASP.Net using C# and VB.Net.
This article makes use of the free open-source library OpenPop.Net which provides easy API to access and read emails from the POP3 mail Servers.
 
 
Download OpenPop.Net
You can download OpenPop.Net using the download link below.
 
 
HTML Markup
The following HTML Markup consists of an ASP.Net GridView with two BoundField columns and two TemplateField columns.
The first TemplateField column consists of a LinkButton control while second TemplateField column consists of an ASP.Net Repeater.
The body of the email is set to the hidden HTML SPAN element which will later use jQuery Dialog to display the body when LinkButton is clicked.
The GridView has been assigned with OnRowDataBound event handler and the DataKeyNames property has been set.
<asp:GridView ID="gvEmails" runat="server" OnRowDataBound="OnRowDataBound" DataKeyNames="MessageNumber"
    AutoGenerateColumns="false">
    <Columns>
        <asp:BoundField HeaderText="From" DataField="From" HtmlEncode="false" />
        <asp:TemplateField HeaderText="Subject">
            <ItemTemplate>
                <asp:LinkButton ID="lnkView" runat="server" Text='<%# Eval("Subject") %>' />
                <span class="body" style="display: none">
                    <%# Eval("Body") %></span>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField HeaderText="Date" DataField="DateSent" />
        <asp:TemplateField ItemStyle-CssClass="Attachments">
            <ItemTemplate>
                <asp:Repeater ID="rptAttachments" runat="server">
                    <ItemTemplate>
                        <asp:LinkButton ID="lnkAttachment" runat="server" OnClick="Download" Text='<%# Eval("FileName") %>' />
                    </ItemTemplate>
                    <SeparatorTemplate>
                        <br />
                    </SeparatorTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<div id="dialog" style="display: none">
    <span id="body"></span>
    <br />
    <span id="attachments"></span>
</div>
 
 
Custom property class to hold the Email messages
The following two classes one for Email Message and one for Attachment created with custom properties which will be used to hold the fetched email messages.
Note: The classes are marked as Serializable to store the fetched email messages in a ViewState variable to retain data across PostBacks.
 
C#
[Serializable]
public class Email
{
    public Email()
    {
        this.Attachments = new List<Attachment>();
    }
    public int MessageNumber { get; set; }
    public string From { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
    public DateTime DateSent { get; set; }
    public List<Attachment> Attachments { get; set; }
}
 
[Serializable]
public class Attachment
{
    public string FileName { get; set; }
    public string ContentType { get; set; }
    public byte[] Content { get; set; }
}
 
VB.Net
<Serializable> _
Public Class Email
    Public Sub New()
        Me.Attachments = New List(Of Attachment)()
    End Sub
    Public Property MessageNumber As Integer
    Public Property From As String
    Public Property Subject As String
    Public Property Body As String
    Public Property DateSent As DateTime
    Public Property Attachments As List(Of Attachment)
End Class
 
<Serializable> _
Public Class Attachment
    Public Property FileName As String
    Public Property ContentType As String
    Public Property Content As Byte()
End Class
 
 
Namespaces
You will have to import the following namespaces.
C#
using OpenPop.Pop3;
using OpenPop.Mime;
using System.Linq;
 
VB.Net
Imports OpenPop.Pop3
Imports OpenPop.Mime
Imports System.Linq
 
 
Fetching the email messages from POP3 mail server and binding them to ASP.Net GridView
Inside the Page Load event, the GridView is populated with email messages by calling Read_Emails method.
Inside the Read_Emails method, first a connection is made to the GMAIL POP3 mail server using the UserName and Password.
Once the connection is successful, a loop will be executed over recent fetched email messages and properties are set fromMessage object to Email class and message body is set from MessagePart class.
Inside the loop, a check is performed to determine whether the email has any attachment and if found the attachments are added to Attachments property of the Email class.
Finally, the email is added to the ViewState property named Emails.
C#
protected List<Email> Emails
{
    get { return (List<Email>)ViewState["Emails"]; }
    set { ViewState["Emails"] = value; }
}
 
protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        this.Read_Emails();
    }
}
 
private void Read_Emails()
{
    Pop3Client pop3Client;
    if (Session["Pop3Client"] == null)
    {
        pop3Client = new Pop3Client();
        pop3Client.Connect("pop.gmail.com", 995, true);
        pop3Client.Authenticate("<Your Gmail Email>", "<Your Gmail Password>", AuthenticationMethod.TryBoth);
        Session["Pop3Client"] = pop3Client;
    }
    else
    {
        pop3Client = (Pop3Client)Session["Pop3Client"];
    }
    int count = pop3Client.GetMessageCount();
    this.Emails = new List<Email>();
    int counter = 0;
    for (int i = count; i >= 1; i--)
    {
        Message message = pop3Client.GetMessage(i);
        Email email = new Email()
        {
            MessageNumber = i,
            Subject = message.Headers.Subject,
            DateSent = message.Headers.DateSent,
            From = string.Format("<a href = 'mailto:{1}'>{0}</a>", message.Headers.From.DisplayName, message.Headers.From.Address),
        };
        MessagePart body = message.FindFirstHtmlVersion();
        if (body != null)
        {
            email.Body = body.GetBodyAsText();
        }
        else
        {
            body = message.FindFirstPlainTextVersion();
            if (body != null)
            {
                email.Body = body.GetBodyAsText();
            }
        }
        List<MessagePart> attachments = message.FindAllAttachments();
 
        foreach (MessagePart attachment in attachments)
        {
            email.Attachments.Add(new Attachment
            {
                FileName = attachment.FileName,
                ContentType = attachment.ContentType.MediaType,
                Content = attachment.Body
            });
        }
        this.Emails.Add(email);
        counter++;
        if (counter > 2)
        {
            break;
        }
    }
    gvEmails.DataSource = this.Emails;
    gvEmails.DataBind();
}
 
VB.Net
Protected Property Emails() As List(Of Email)
    Get
        Return DirectCast(ViewState("Emails"), List(Of Email))
    End Get
    Set(value As List(Of Email))
        ViewState("Emails") = value
    End Set
End Property
 
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If Not Me.IsPostBack Then
        Me.Read_Emails()
    End If
End Sub
 
Private Sub Read_Emails()
    Dim pop3Client As Pop3Client
    If Session("Pop3Client") Is Nothing Then
        pop3Client = New Pop3Client()
        pop3Client.Connect("pop.gmail.com", 995, True)
        pop3Client.Authenticate("<Your Gmail Email>", "<Your Gmail Password>", AuthenticationMethod.TryBoth)
        Session("Pop3Client") = pop3Client
    Else
        pop3Client = DirectCast(Session("Pop3Client"), Pop3Client)
    End If
    Dim count As Integer = pop3Client.GetMessageCount()
    Me.Emails = New List(Of Email)()
    Dim counter As Integer = 0
    For i As Integer = count To 1 Step -1
        Dim message As Message = pop3Client.GetMessage(i)
        Dim email As New Email()
        email.MessageNumber = i
        email.Subject = message.Headers.Subject
        email.DateSent = message.Headers.DateSent
        email.From = String.Format("<a href = 'mailto:{1}'>{0}</a>", message.Headers.From.DisplayName, message.Headers.From.Address)
 
        Dim body As MessagePart = message.FindFirstHtmlVersion()
        If body IsNot Nothing Then
            email.Body = body.GetBodyAsText()
        Else
            body = message.FindFirstPlainTextVersion()
            If body IsNot Nothing Then
                email.Body = body.GetBodyAsText()
            End If
        End If
        Dim attachments As List(Of MessagePart) = message.FindAllAttachments()
 
        For Each attachment As MessagePart In attachments
            Dim attachmentObj As New Attachment
            attachmentObj.FileName = attachment.FileName
            attachmentObj.ContentType = attachment.ContentType.MediaType
            attachmentObj.Content = attachment.Body
            email.Attachments.Add(attachmentObj)
        Next
        Me.Emails.Add(email)
        counter += 1
        If counter > 2 Then
            Exit For
        End If
    Next
    gvEmails.DataSource = Me.Emails
    gvEmails.DataBind()
End Sub
 
 
Binding the Email Attachments to the Repeater inside ASP.Net GridView
Inside the OnRowDataBound event handler, the Attachments are fetched from the Emails property with the help of DataKeyNames property.
Finally, the list of Attachments is used to populate the Repeater control.
C#
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        Repeater rptAttachments = (e.Row.FindControl("rptAttachments") as Repeater);
        List<Attachment> attachments = this.Emails.Where(email => email.MessageNumber == Convert.ToInt32(gvEmails.DataKeys[e.Row.RowIndex].Value)).FirstOrDefault().Attachments;
        rptAttachments.DataSource = attachments;
        rptAttachments.DataBind();
    }
}
 
VB.Net
Protected Sub OnRowDataBound(sender As Object, e As GridViewRowEventArgs)
    If e.Row.RowType = DataControlRowType.DataRow Then
        Dim rptAttachments As Repeater = TryCast(e.Row.FindControl("rptAttachments"), Repeater)
        Dim attachments As List(Of Attachment) = Me.Emails.Where(Function(email) email.MessageNumber = Convert.ToInt32(gvEmails.DataKeys(e.Row.RowIndex).Value)).FirstOrDefault().Attachments
        rptAttachments.DataSource = attachments
        rptAttachments.DataBind()
    End If
End Sub
 
 
Downloading the Email message Attachments
When the Download LinkButton is clicked, the attachment is fetched from the ViewState property named Emails and is sent to the Response for download using the BinaryWrite function.
C#
protected void Download(object sender, EventArgs e)
{
    LinkButton lnkAttachment = (sender as LinkButton);
    GridViewRow row = (lnkAttachment.Parent.Parent.NamingContainer as GridViewRow);
    List<Attachment> attachments = this.Emails.Where(email => email.MessageNumber == Convert.ToInt32(gvEmails.DataKeys[row.RowIndex].Value)).FirstOrDefault().Attachments;
    Attachment attachment = attachments.Where(a => a.FileName == lnkAttachment.Text).FirstOrDefault();
    Response.AddHeader("content-disposition", "attachment;filename=" + attachment.FileName);
    Response.ContentType = attachment.ContentType;
    Response.BinaryWrite(attachment.Content);
    Response.End();
}
 
VB.Net
Protected Sub Download(sender As Object, e As EventArgs)
    Dim lnkAttachment As LinkButton = TryCast(sender, LinkButton)
    Dim row As GridViewRow = TryCast(lnkAttachment.Parent.Parent.NamingContainer, GridViewRow)
    Dim attachments As List(Of Attachment) = Me.Emails.Where(Function(email) email.MessageNumber = Convert.ToInt32(gvEmails.DataKeys(row.RowIndex).Value)).FirstOrDefault().Attachments
    Dim attachment As Attachment = attachments.Where(Function(a) a.FileName = lnkAttachment.Text).FirstOrDefault()
    Response.AddHeader("content-disposition", "attachment;filename=" + attachment.FileName)
    Response.ContentType = attachment.ContentType
    Response.BinaryWrite(attachment.Content)
    Response.End()
End Sub
 
 
Viewing the Email Message body using jQuery UI Dialog
Inside the jQuery document.ready event handler, the every View LinkButton in the GridView has been assigned with a jQuery Click event handler.
When the View LinkButton is clicked, the email Subject, Body and Attachments are fetched from the GridView Row and displayed using the jQuery Dialog Modal Popup.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/themes/smoothness/jquery-ui.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js"></script>
<script type="text/javascript">
    $(function () {
        $("[id*=lnkView]").click(function () {
            var subject = $(this).text();
            var row = $(this).closest("tr");
            $("#body").html($(".body", row).html());
            $("#attachments").html($(".Attachments", row).html());
            $("#dialog").dialog({
                title: subject,
                width: 600,
                buttons: {
                    Ok: function () {
                        $(this).dialog('close');
                    }
                }
            });
            return false;
        });
    });
</script>
 
 
Errors
If you are getting following error when you try to access your Gmail Mailbox using Gmail credentials in your ASP.Net application, then please refer my article: GMAIL POP3 Error: ERR [AUTH] Application specific password required.
Fetch and read email messages with attachments from GMAIL POP3 mail server in ASP.Net
 
 
Screenshot
Fetch and read email messages with attachments from GMAIL POP3 mail server in ASP.Net
 
 
Downloads