<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
<title>Stardeveloper</title>
<link>http://www.stardeveloper.com/</link>
<description>Learn web application development.</description>
<language>en-us</language>
<ttl>60</ttl>
<pubDate>Tue, 09 Mar 2010 13:10:59 GMT</pubDate><generator><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2008112101&page=1]]></generator><copyright>Copyright 1999 - 2010 Stardeveloper.com, All Rights Reserved.</copyright>
<lastBuildDate>Fri, 26 Feb 2010 06:51:00 GMT</lastBuildDate>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" /><feedburner:info uri="stardevelopercomarticleheadlines" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
<title>SPF Record Syntax</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/AWhpXjCDYCU/</link>
<description>&lt;p&gt;Sender Policy Framework prevents fraudulent abuse of your domain name in emails sent by others claiming to be sent from your domain name. This cuts down the spam which was originating from spammers who were using your domain name to bypass filters on other users' email addresses.&lt;/p&gt;

&lt;p&gt;A domain name which does not have an SPF record set in its DNS records is open to spammers to use the address of this domain name in the 'From' field of their emails. They can then send thousands of these unsolicited emails to end users. And by using the repute of that domain name, can entice users to click on links which lead to their products, and to  websites that fraudulently seek confidential and sensitive information (phishing attacks).&lt;/p&gt;

&lt;p&gt;It is thus very important that you understand &lt;a href="http://www.stardeveloper.com/articles/what-is-sender-policy-framework/" title="What is Sender Policy Framework?" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/spf-record-syntax : /articles/what-is-spf', 'article']);"&gt;what is Sender Policy Framework&lt;/a&gt; (SPF) and how it works.&lt;/p&gt;

&lt;p&gt;SPF works by making you explicitly declare a list of hosts and IP addresses from which legitimate emails can originate for your domain name. This is called creating a &lt;i&gt;white list&lt;/i&gt;. You can also create a &lt;i&gt;black list&lt;/i&gt; by explicitly declaring hosts and IP addresses which &lt;strong&gt;cannot&lt;/strong&gt; send emails for your domain name. Generally, only a white list is created. Any other host or IP address not present in the white list is set to fail or soft fail, as the case may be.&lt;/p&gt;

&lt;h2&gt;What should be included in an SPF record?&lt;/h2&gt;

&lt;p&gt;An SPF record should comprehensively list all the hosts and IP addresses from which your website or domain name sends emails. This generally means an &lt;code&gt;A&lt;/code&gt; record (IP address of your website), SMTP Servers, IP addresses from your company's network from which an email may originate, and any third party mailers, e.g., Google Apps, BlackBerry Internet Service, etc.&lt;/p&gt;

&lt;p&gt;When you have created such a list, you should use SPF record syntax to publish this list in the DNS records of your domain name.&lt;/p&gt;

&lt;h2&gt;Introduction to SPF record syntax&lt;/h2&gt;

&lt;p&gt;SPF record syntax follows standard DNS syntax to declare a &lt;i&gt;policy&lt;/i&gt; using a list of &lt;i&gt;mechanisms&lt;/i&gt;. &lt;em&gt;A mechanism is any &lt;i&gt;rule&lt;/i&gt; you specify as part of your SPF record to allow or disallow a host or IP address range&lt;/em&gt;. You can specify zero or more mechanisms, each delimited by white space. All of these mechanisms constitute a policy for your domain name. An SPF record always begins with &lt;code&gt;v=spf1&lt;/code&gt; and ends with &lt;code&gt;~all&lt;/code&gt;, as shown below:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;All DNS records including SPF are enclosed in double quotes. &lt;code&gt;v=spf1&lt;/code&gt; tells the SPF record validator that this is an SPF record and that it belongs to SPF version 1.&lt;/p&gt;

&lt;p&gt;For practical purposes, always start from an SPF record like above, and then add mechanisms, relating to your hosts and IP addresses, one by one.&lt;/p&gt;

&lt;h2 id="quantifiers"&gt;Quantifiers&lt;/h2&gt;

&lt;p&gt;Before we delve ourselves into mechanisms, let me touch a bit about quantifiers. If you remember the discussion above, I talked about white listing or black listing hosts and IP addresses. To allow (white list) a host or IP address, we append a '+' letter at its beginning e.g., &lt;code&gt;+a&lt;/code&gt;. To disallow (black list) a host or IP address range, we append a '-' letter at its beginning e.g., &lt;code&gt;-a&lt;/code&gt;. An &lt;code&gt;a&lt;/code&gt; mechanism in these examples references the &lt;code&gt;A&lt;/code&gt; record for this domain name. Between allowing and disallowing are two other quantifiers; '~' and '?'. An '~' quantifier (like the one at the beginning of &lt;code&gt;all&lt;/code&gt; mechanism in our first example of an SPF record) means &amp;quot;soft fail&amp;quot;. &lt;em&gt;Soft fail means to accept the emails but put them in the 'Spam' folder and not the user's inbox&lt;/em&gt;. Soft fail is most often used in combination with &lt;code&gt;all&lt;/code&gt; mechanism. An &lt;code&gt;all&lt;/code&gt; mechanism is very powerful as it catches all the hosts and IP addresses that have not been explicitly declared in the preceding mechanisms. Finally, a '?' quantifier tells the SPF record validator to make this mechanism &amp;quot;neutral&amp;quot;. A neutral mechanism is generally interpreted as allowance for that mechanism's host or IP address.&lt;/p&gt;

&lt;p&gt;For practical purposes, I'd suggest that you limit yourself to '+' and '-' to allow and disallow any host or IP address range, and use '~' for the &lt;code&gt;all&lt;/code&gt; mechanism.&lt;/p&gt;

&lt;p&gt;Here is the recap of quantifiers you can use with the mechanisms in your SPF record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'+' - pass&lt;/li&gt;
&lt;li&gt;'?' - neutral (generally means pass)&lt;/li&gt;
&lt;li&gt;'~' - soft fail (accept the email but put it in 'Spam' folder)&lt;/li&gt;
&lt;li&gt;'-' - fail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not necessary to append '+' (pass) quantifier with mechanisms as it is assumed that a mechanism with no explicit quantifier has a '+' letter prepended. For example, following two SPF records mean one and the same thing:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 a ~all&amp;quot;&lt;/pre&gt;
&lt;pre&gt;&amp;quot;v=spf1 +a ~all&amp;quot;&lt;/pre&gt;

&lt;h2 id="mechanisms"&gt;Mechanisms&lt;/h2&gt;

&lt;p&gt;A mechanism (rule) allows you to declare a single IPv4 or IPv6 IP address or an IP address range, a host, an SPF record from another host, an &lt;code&gt;a&lt;/code&gt; record, an &lt;code&gt;mx&lt;/code&gt; (Mail Exchanger) record, and a &lt;code&gt;ptr&lt;/code&gt; record.&lt;/p&gt;

&lt;p&gt;Following is the list of all mechanisms available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="#ip4-mechanism"&gt;&lt;code&gt;ip4&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ip6-mechanism"&gt;&lt;code&gt;ip6&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#a-mechanism"&gt;&lt;code&gt;a&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#mx-mechanism"&gt;&lt;code&gt;mx&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#include-mechanism"&gt;&lt;code&gt;include&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ptr-mechanism"&gt;&lt;code&gt;ptr&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#exists-mechanism"&gt;&lt;code&gt;exists&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#all-mechanism"&gt;&lt;code&gt;all&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will look at all of them, one by one.&lt;/p&gt;

&lt;h3 id="ip4-mechanism"&gt;ip4 mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;ip4&lt;/code&gt; mechanism is used to include an IPv4 address or network range in an SPF record. A network range is specified by first declaring the IPv4 network address and then after a slash ('/'), is declared the length of the network range. All &lt;code&gt;ip4&lt;/code&gt; mechanisms start with &amp;quot;ip4:&amp;quot;.&lt;/p&gt;

&lt;p&gt;For example, following SPF record declares a single IPv4 address:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ip4:127.0.0.1 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following SPF record declares an &lt;code&gt;ip4&lt;/code&gt; mechanism to include all IP addresses in the 127.0.0.1-127.0.0.255 range:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ip4:127.0.0.1/8 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following SPF record declares an &lt;code&gt;ip4&lt;/code&gt; mechanism to include all IP addresses in the 127.0.0.1-127.0.255.255 range:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ip4:127.0.0.1/16 ~all&amp;quot;&lt;/pre&gt;

&lt;div class="note"&gt;Since no quantifier was prepended with the &lt;code&gt;ip4&lt;/code&gt; mechanisms in the examples above; a '+' quantifier is assumed. This means that any email originating from these IP addresses should be allowed to &lt;i&gt;pass&lt;/i&gt; successfully.&lt;/div&gt;

&lt;h3 id="ip6-mechanism"&gt;ip6 mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;ip6&lt;/code&gt; mechanism is used to include an IPv6 address or network range in an SPF record. All &lt;code&gt;ip6&lt;/code&gt; mechanisms start with &amp;quot;ip6:&amp;quot;.&lt;/p&gt;

&lt;p&gt;Following SPF record declares a single IPv6 address:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ip6:2001:db8:85a3::8a2e:370:7334 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following SPF record declares an &lt;code&gt;ip6&lt;/code&gt; mechanism to include all IPv6 addresses in the 2001:db8:85a3::8a2e:0000:0000-2001:db8:85a3::8a2e:FFFF:FFFF range:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ip6:2001:db8:85a3::8a2e:370:7334/96 ~all&amp;quot;&lt;/pre&gt;

&lt;h3 id="a-mechanism"&gt;a mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;a&lt;/code&gt; mechanism allows us to reference (and include) the IP address(es) of the current domain for which this SPF record exists. Every domain name almost always has an &lt;code&gt;A&lt;/code&gt; record which resolves to the IP address it is hosted at. Larger websites have more than one IP address that an &lt;code&gt;A&lt;/code&gt; record can resolve to. By including and allowing an &lt;code&gt;a&lt;/code&gt; record in the SPF record of your domain name, you are basically allowing any email originating from your domain name to pass.&lt;/p&gt;

&lt;p&gt;For example, following SPF record includes an &lt;code&gt;A&lt;/code&gt; record to allow any emails originating from the IP address of this domain name to pass:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 a ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;If you have another domain name and want to include its &lt;code&gt;A&lt;/code&gt; record so that any email originating from the IP address of that domain name is also passed for your domain name, then use this syntax:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 a:anotherdomain.com ~all&amp;quot;&lt;/pre&gt;

&lt;h3 id="mx-mechanism"&gt;mx mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;mx&lt;/code&gt; mechanism allows us to include the MX (Mail Exchanger) servers of this domain name in the SPF record. An &lt;code&gt;MX&lt;/code&gt; record in the DNS records of a domain name points to one or more mail servers that are entitled to &lt;i&gt;receive&lt;/i&gt; emails for that domain name. For example, if a person sends an email to an address at Stardeveloper.com, he will most probably send it via an SMTP relay server. That SMTP relay server then fetches the MX record of Stardeveloper.com and resolves it to an IP address. Then it connects to that IP address on the port 25 to deliver that email for Stardeveloper.com. As the admin for Stardeveloper.com, I can change the MX records and point them to any mail server of my choosing which I have configured to receive emails for my domain name.&lt;/p&gt;

&lt;p&gt;Now that we know what an &lt;code&gt;MX&lt;/code&gt; record is, let us see how we declare an &lt;code&gt;mx&lt;/code&gt; mechanism to allow all mail servers who are registered to &lt;i&gt;receive&lt;/i&gt; emails for our domain names to also be given a pass so that if any outgoing email originates from them, it will be passed.&lt;/p&gt;

&lt;p&gt;Following SPF record includes an &lt;code&gt;mx&lt;/code&gt; mechanism to allow any emails originating from the &lt;code&gt;MX&lt;/code&gt; servers of this domain name to pass:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 mx ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;You can also include &lt;code&gt;MX&lt;/code&gt; records for another domain name like the syntax we saw earlier for &lt;code&gt;A&lt;/code&gt; record:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 mx:anotherdomain.com ~all&amp;quot;&lt;/pre&gt;

&lt;h3 id="include-mechanism"&gt;include mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;include&lt;/code&gt; mechanism is used to include a policy (SPF record) from another host or domain name. You will use this if your domain's emails also go through 3rd party SMTP servers over which you have no control. The 3rd party has its own policy (SPF record) for their SMTP servers/domain names. By including their SPF record in the SPF record of your domain name, you are allowing all emails to pass which are allowed to pass by that domain name. In other words, all emails originating from 3rd party's SMTP servers will be passed.&lt;/p&gt;

&lt;p&gt;Following SPF record includes a policy (SPF record) from a third party's domain name:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 include:anotherdomain.com ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following is a real World example of an &lt;code&gt;include&lt;/code&gt; mechanism to allow emails going through Google's SMTP servers to be passed:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 include:aspmx.googlemail.com ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;If you plan to use Google Apps with your domain name, then you must include this mechanism in the SPF record of your domain name: &lt;code&gt;include:aspmx.googlemail.com&lt;/code&gt;. Learn more about &lt;a href="http://www.stardeveloper.com/articles/what-is-sender-policy-framework/#example-spf-record" title="How Stardeveloper uses its SPF records to allow outgoing emails from Google Apps" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/spf-record-syntax : /articles/what-is-spf', 'article']);"&gt;how to setup SPF records for Google Apps&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id="ptr-mechanism"&gt;ptr mechanism&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;ptr&lt;/code&gt; mechanism allows you to include a &lt;code&gt;PTR&lt;/code&gt; (pointer) record for a domain name. A &lt;code&gt;PTR&lt;/code&gt; record is used in reverse DNS lookup. If your domain name has &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;PTR&lt;/code&gt; records set correctly, an &lt;code&gt;A&lt;/code&gt; record will resolve to an IP address, and that IP address can be &lt;i&gt;reverse looked up&lt;/i&gt; back to the original domain name using &lt;code&gt;PTR&lt;/code&gt; record.&lt;/p&gt;

&lt;p&gt;Following SPF record uses a &lt;code&gt;ptr&lt;/code&gt; mechanism to include a &lt;code&gt;PTR&lt;/code&gt; record for this domain name:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ptr ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;To include a &lt;code&gt;PTR&lt;/code&gt; record of another domain name, you will use this syntax:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ptr:anotherdomain.com ~all&amp;quot;&lt;/pre&gt;

&lt;div class="note"&gt;It is recommended that you do not unnecessarily use a &lt;code&gt;ptr&lt;/code&gt; mechanism unless you have to because it results in unnecessary DNS lookups.&lt;/div&gt;

&lt;h3 id="exists-mechanism"&gt;exists mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;exists&lt;/code&gt; mechanism is used for checking if an &lt;code&gt;A&lt;/code&gt; record &lt;i&gt;exists&lt;/i&gt; for a given domain name. And if it exists, the email is allowed to pass.&lt;/p&gt;

&lt;p&gt;It does not matter if the IP address of that domain name matches the originating IP address for this email or not. What matters is that, an &lt;code&gt;A&lt;/code&gt; record should &lt;i&gt;exist&lt;/i&gt; and that's all.&lt;/p&gt;

&lt;p&gt;Following SPF record includes an &lt;code&gt;exists&lt;/code&gt; mechanism for anotherdomain.com:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 exists:anotherdomain.com ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Personally, I am not sure why if an &lt;code&gt;A&lt;/code&gt; record exists for a domain name, you will allow this email to pass. But then, there must be some reason why this mechanism exists, no?&lt;/p&gt;

&lt;h3 id="all-mechanism"&gt;all mechanism&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;all&lt;/code&gt; mechanism is used to declare a rule for hosts and IP addresses that have &lt;i&gt;not&lt;/i&gt; matched with the preceding mechanisms. All SPF records almost always have an &lt;code&gt;all&lt;/code&gt; mechanism declared at the end of the SPF record.&lt;/p&gt;

&lt;p&gt;What you should do is to declare one or more mechanisms that if matched, will allow the email to pass (white list). At the end you should declare an &lt;code&gt;all&lt;/code&gt; mechanism which should be quantified with an '~' to soft fail the rest.&lt;/p&gt;

&lt;p&gt;Following SPF record declares an &lt;code&gt;all&lt;/code&gt; mechanism to soft fail all emails i.e., no legitimate emails can originate for this domain name:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following SPF record will fail all emails originating for this domain name:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 -all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Following SPF record will &lt;i&gt;pass&lt;/i&gt; all emails with this domain name in the 'From' address of the email, no matter from where it originted:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 all&amp;quot;&lt;/pre&gt;

&lt;div class="note"&gt;The example above to allow all emails to pass is for demonstration purposes only. You obviously will not be using this in real practice.&lt;/div&gt;

&lt;h2&gt;SPF record generating tips&lt;/h2&gt;

&lt;p&gt;First create a white list of hosts and IP addresses from which legitimate emails can originate for your domain name. You can always look at the example &lt;a href="http://www.stardeveloper.com/articles/what-is-sender-policy-framework/#example-spf-record" title="Details of the SPF record for Stardeveloper" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/spf-record-syntax : /articles/what-is-spf', 'article']);"&gt;SPF record of Stardeveloper.com&lt;/a&gt; to have a look.&lt;/p&gt;

&lt;p&gt;To create an SPF record for this list, start with a simple SPF record which soft fails every email like this:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 ~all&amp;quot;&lt;/pre&gt;

&lt;p&gt;Then go through the white list you created, one by one, and using the &lt;a href="#mechanisms"&gt;mechanisms'&lt;/a&gt; syntax we learned above, add the mechanisms to your SPF record.&lt;/p&gt;

&lt;p&gt;My advice is to always include the &lt;code&gt;A&lt;/code&gt; record in the SPF record for your domain name. Rest, you can decide.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this article, we learned the SPF record syntax. We learned about quantifiers and mechanisms which collectively formulate a policy for a domain name. I hope the information in this article will be sufficient to help you setup correct SPF record for your domain name.&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=AWhpXjCDYCU:Lwq80HmkT5w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=AWhpXjCDYCU:Lwq80HmkT5w:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/AWhpXjCDYCU" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/spf-record-syntax/]]></guid>
<author>Faisal Khan</author>
<pubDate>Fri, 26 Feb 2010 06:51:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/spf-record-syntax/</feedburner:origLink></item>
<item>
<title>What is Sender Policy Framework?</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/EQzbjw2kQTw/</link>
<description>&lt;p&gt;SPF stands for '&lt;em&gt;Sender Policy Framework&lt;/em&gt;' which is an open standard to prevent the abuse of your domain name by someone else pretending to be you by using your email address or domain name in the 'From' field of his email.&lt;/p&gt;

&lt;p&gt;How many times do you get bounced email back in your inbox for emails containing your email address in the 'From' field, selling products or containing links to indecent websites? You never sent these emails. Yet someone has picked your email or a fake email using your website's domain name to send spam to thousands of others users using your email address to bypass the filters on their inboxes and to use your repute and recognition to make the end-user give undeserved attention to their spam links.&lt;/p&gt;

&lt;h2&gt;How does SPF work?&lt;/h2&gt;

&lt;p&gt;SPF works by making use of a list of &lt;a href="http://www.stardeveloper.com/articles/convert-ip-address-to-long/" onclick="_gaq.push(['_trackEvent', 'external-movement', '/articles/what-is-spf : /articles/convert-ip-address-to-long', 'article']);" title="What is an IP address?"&gt;IP addresses&lt;/a&gt; that you specifically allow from which a legitimate email can originate for your domain name. For your website you have to make a list of IP addresses (or host names) from which legitimate emails can be sent for your domain name. This list should contain the IP addresses of your website (the A records) and the IP addresses of your SMTP servers (all of them). If you are using BlackBerry to send emails for your website or company, you will have to include their IP addresses in this list as well.&lt;/p&gt;

&lt;p&gt;Now it is not easy to know the IP addresses of all servers from where the legitimate emails can originate for your domain name, you can make use of &lt;a href="http://www.stardeveloper.com/articles/spf-record-syntax/" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/what-is-spf : /articles/spf-record-syntax', 'article']);" title="SPF Record Syntax"&gt;SPF record syntax&lt;/a&gt; to create a &lt;i&gt;policy&lt;/i&gt; to include IP addresses by using host names and domain names instead of plain IP addresses in your SPF record. You can also &lt;i&gt;include&lt;/i&gt; other domains' SPF records. The cool thing with SPF's syntax is that with very little effort you can comprehensively include all the servers without needing to hard code any single IP address at all.&lt;/p&gt;

&lt;p&gt;Once a list of IP addresses and host names has been setup for your domain name, then the next time an authorized person tries to send an email using the 'From' address of your domain name e.g., fakedname@yourwebsite.com, the MX (Mail Exchanger) server receiving this email will lookup SPF record for your domain by checking the DNS records of your domain name. When it finds an SPF record, it will go through the list of IP addresses and host names, one by one, to see if this email is originating from the &lt;i&gt;white list&lt;/i&gt; of IP addresses allowed to send email on your behalf or not. Since the originating email in this case did not originate from an authorized IP address, the receiving mail server will silently place this email in the 'Spam' folder, and not the user's 'Inbox'.&lt;/p&gt;

&lt;p&gt;This is how SPF prevents misuse of your domain name by unauthorized persons.&lt;/p&gt;

&lt;div class="note"&gt;This of course implies that you have to have your own domain name, for example, yourwebsite.com, and an email address like yourname@yourwebsite.com. If you are using Gmail or Yahoo and have email address like yourname@gmail.com, then you do not need to setup an SPF record; because it is already set by those email providers.&lt;/div&gt;

&lt;h2 id="example-spf-record"&gt;An example SPF record&lt;/h2&gt;

&lt;p&gt;The SPF record for &lt;a href="http://www.stardeveloper.com/" title="Stardeveloper.com" onclick="_gaq.push(['_trackEvent', 'internal-movement', 'what-is-spf : home-page', 'article']);"&gt;Stardeveloper&lt;/a&gt; looks like this:&lt;/p&gt;

&lt;pre&gt;&amp;quot;v=spf1 a include:aspmx.googlemail.com include:srs.bis.eu.blackberry.com ~all&amp;quot;&lt;/pre&gt;

&lt;h2&gt;Explanation&lt;/h2&gt;

&lt;pre&gt;v=spf1&lt;/pre&gt;

&lt;p&gt;An SPF record always begings with &lt;code&gt;v=spf1&lt;/code&gt;. This tells the SPF record validator that this SPF record's syntax belongs to version 1 of Sender Policy Framework.&lt;/p&gt;

&lt;pre&gt;a&lt;/pre&gt;

&lt;p&gt;Next, the SPF record contains an &lt;code&gt;a&lt;/code&gt; which means an 'A' record for the domain name. What this means is that legitimate email can originate for Stardeveloper.com from the IP address it is hosted at. Note: the IP address has not been hard coded for the domain name, instead an &lt;code&gt;a&lt;/code&gt; record has been specified using &lt;a href="http://www.stardeveloper.com/articles/spf-record-syntax/" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/what-is-spf : /articles/spf-record-syntax', 'article']);" title="SPF Record Syntax"&gt;SPF record syntax&lt;/a&gt;. If Stardeveloper is relocated to another IP address, the 'A' record will automatically point to the new IP address without requiring any change in the SPF record for this domain name.&lt;/p&gt;

&lt;pre&gt;include:aspmx.googlemail.com&lt;/pre&gt;

&lt;p&gt;Since, Stardeveloper is using Google Apps for email hosting, I have included Google Apps' SPF record as part of the SPF record of Stardeveloper.com to make sure that any email that is sent through Google's SMTP servers is marked as legitimate.&lt;/p&gt;

&lt;pre&gt;include:srs.bis.eu.blackberry.com&lt;/pre&gt;

&lt;p&gt;I am using &lt;a href="http://blog.stardeveloper.com/tagged/BlackBerry" title="Faisal's blog posts about BlackBerry handsets" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/what-is-spf : blog/blackberry', 'article']);"&gt;BlackBerry&lt;/a&gt; Bold 9700 as my mobile device. I use it to send and receive emails. To be able to mark all emails sent through my BlackBerry device that make use of BlackBerry's SMTP servers, I have included their SPF records from their domain name.&lt;/p&gt;

&lt;div class="tip"&gt;If you are based in North America, then you should change the 'eu' with 'na' to include BlackBerry's North American SMTP servers, that is, &lt;code&gt;include:srs.bis.na.blackberry.com&lt;/code&gt; .&lt;/div&gt;

&lt;pre&gt;~all&lt;/pre&gt;

&lt;p&gt;The final mechanism beginning with a tilde '~' suggests a 'soft fail' for emails &lt;strong&gt;not&lt;/strong&gt; being sent from authorized IP address. Soft fail means that emails originating from unauthorized IP addresses will be received by mail servers (MX) but will be placed in 'Spam' folders and not users' inbox. If this syntax had been &lt;code&gt;-all&lt;/code&gt;, it would have meant 'hard fail'. Hard fail means to reject all emails originating from unlisted IP addresses straight away. Since Google recommends a soft fail based SPF syntax, Stardeveloper uses this syntax and so should you (unless of course if you know what you are doing).&lt;/p&gt;

&lt;h2&gt;How to check the SPF record for a domain name?&lt;/h2&gt;

&lt;p&gt;You can use the &lt;a href="http://tools.bevhost.com/cgi-bin/dnslookup" title="SPF record viewer" onclick="_gaq.push(['_trackEvent', 'external-movement', '/articles/what-is-spf : tools.bevhost.com/spf-record-viewer', 'article']);"&gt;SPF record checking tool&lt;/a&gt; here. Just enter the domain name of your website (or any other to just have a look how they have setup their SPF records), and submit the form.&lt;/p&gt;

&lt;h2&gt;Should you have an SPF record for your website?&lt;/h2&gt;

&lt;p&gt;It is absolutely important for you to have an SPF record for your domain name. You must prevent the abuse of your domain name. You must not let your Uncle get an email from an unauthorized person claiming as you and suggesting your Uncle to visit his spam website. And this becomes even more important if you have a repute online.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In this article, we learned what is an SPF record and how it works. We looked at a sample SPF record and learned how simple the SPF record syntax can be to set one up for one's website.&lt;/p&gt;

&lt;h2&gt;Read Next&lt;/h2&gt;

&lt;p&gt;Now that you know what is SPF and how you can use it to protect your domain name from being used by spammers, move on to the next article in this series to learn about &lt;a href="http://www.stardeveloper.com/articles/spf-record-syntax/" title="SPF Record Syntax" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/what-is-spf : /articles/spf-record-syntax', 'article']);"&gt;SPF record syntax&lt;/a&gt; and to use this syntax to create an SPF record for your website.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=EQzbjw2kQTw:jHnCD3mXvpg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=EQzbjw2kQTw:jHnCD3mXvpg:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/EQzbjw2kQTw" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/what-is-sender-policy-framework/]]></guid>
<author>Faisal Khan</author>
<pubDate>Mon, 22 Feb 2010 09:19:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/what-is-sender-policy-framework/</feedburner:origLink></item>
<item>
<title>Convert IP Address to Long</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/5Sc1UWqoO34/</link>
<description>&lt;p&gt;An IP address is a numerical address that is assigned to your computer the moment it connects to a network. Whenever you access a website on internet, a request is sent from your computer containing IP address of your computer, the address to which the website's data should be sent back to. This IP address can be used for logging, tracking stats, allowing (white lists) or blocking (black lists) content, and for a variety of other reasons by the website administrator.&lt;/p&gt;

&lt;p&gt;ASP.NET makes it very easy to develop &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;amp;page=1" title="Introduction to Developing HTTP Modules" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/convert-ip-address-to-long : /articles/introduction-to-developing-http-modules', 'article']);"&gt;HTTP Modules&lt;/a&gt; and &lt;a href="http://www.stardeveloper.com/#ADO.NET" title="Articles on database application development" onclick="_gaq.push(['_trackEvent', 'internal-movement', '/articles/convert-ip-address-to-long : home-page', 'article']);"&gt;database driven web applications&lt;/a&gt; to analyze and store these IP addresses in the database. A convenient property made available to all ASP.NET applications as part of an HTTP request is &lt;code&gt;HttpRequest.UserHostAddress&lt;/code&gt; property which will return a &lt;code&gt;string&lt;/code&gt; representation of the user's IP address.&lt;/p&gt;

&lt;h2&gt;Do not store IP Addresses as strings&lt;/h2&gt;

&lt;p&gt;The problem here is that to analyze or store this IP address as &lt;code&gt;string&lt;/code&gt; is not the most efficient or recommended method. Not only does it take more space (as much as 15 bytes) to store data, sorting and indexing this data is inefficient.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It takes 15 bytes (&lt;code&gt;varchar(15)&lt;/code&gt;) to store an IP address like &amp;quot;255.255.255.255&amp;quot;.&lt;/li&gt;
&lt;li&gt;Sorting is inefficient because the values will be sorted as string literals.&lt;/li&gt;
&lt;li&gt;It is not possible to find an IP address e.g., &amp;quot;255.255.255.127&amp;quot; in a &lt;i&gt;block&lt;/i&gt; of IP addresses e.g., &amp;quot;255.255.255.0&amp;quot; - &amp;quot;255.255.255.255&amp;quot;. You will have to use inefficient SQL queries like:
&lt;pre&gt;&amp;quot;SELECT * FROM [IPAddresses] WHERE [IPAddress] LIKE '255.255.255.%'&amp;quot;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what should you do?&lt;/p&gt;

&lt;h2&gt;Solution: Convert IP Addresses to Long values&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;The solution is to &lt;i&gt;convert&lt;/i&gt; an IP address into an integer.&lt;/em&gt;. In most programming languages, the integer is declared as &lt;code&gt;long&lt;/code&gt; to provide 8 bytes of space to the variable. In C#, an 8 byte long value is declared using &lt;code&gt;long&lt;/code&gt; keyword. In T-SQL (i.e., for SQL Server), an 8 byte long value is declared as &lt;code&gt;bigint&lt;/code&gt;. Here is why storing IP addresses as &lt;code&gt;long&lt;/code&gt; (or &lt;code&gt;bigint&lt;/code&gt; in T-SQL) is more efficient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It takes only 8 bytes to store an IP address as &lt;code&gt;long&lt;/code&gt;. An IP address like &amp;quot;255.255.255.255&amp;quot; is stored as 4294967295. The code to do this conversion, both in C# and T-SQL, will be looked upon later in this tutorial.&lt;/li&gt;
&lt;li&gt;Sorting is extremely efficient as it is very easy to do the sorting on numerical data like 4294967295 than string literals like &amp;quot;255.255.255.255&amp;quot;.&lt;/li&gt;
&lt;li&gt;You can very easily find if a given IP address exists in a block of IP addresses using the query:
&lt;pre&gt;&amp;quot;SELECT * FROM [IPAddresses] WHERE
	[IPAddress] BETWEEN [IPAddressBlock1] AND [IPAddressBlock2]&amp;quot;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we will look at the code to convert a &lt;code&gt;string&lt;/code&gt; literal IP address (like &amp;quot;255.255.255.255&amp;quot;) to a numerical value (like 4294967295) and back.&lt;/p&gt;

&lt;h2&gt;Converting IP Addresses to Long Values and Back in C#&lt;/h2&gt;

&lt;p&gt;To convert a &lt;code&gt;string&lt;/code&gt; IP address to a long value, we will use the &lt;code&gt;ConvertIPToLong()&lt;/code&gt; method as shown below. We first convert the IP address &lt;code&gt;string&lt;/code&gt; literal to &lt;code&gt;System.Net.IPAddress&lt;/code&gt;. Then we convert this IP address to an array of 4 bytes by splitting this IP address using the dot (&amp;quot;.&amp;quot;) letter. It then converts the 4 bytes array to a single &lt;code&gt;long&lt;/code&gt; value.&lt;/p&gt;

&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Author: Faisal Khan (http://www.stardeveloper.com)
/// &amp;lt;/summary&amp;gt;
public static long ConvertIPToLong(string ipAddress)
{
	System.Net.IPAddress ip;

	if (System.Net.IPAddress.TryParse(ipAddress, out ip))
	{
		byte[] bytes = ip.GetAddressBytes();

		return (long)((bytes[0] &amp;lt;&amp;lt; 24) | (bytes[1] &amp;lt;&amp;lt; 16) |
			(bytes[2] &amp;lt;&amp;lt; 8) | bytes[3]);
	}
	else
		return 0;
}&lt;/pre&gt;

&lt;p&gt;Now to convert an IP address &lt;code&gt;long&lt;/code&gt; value back to its &lt;code&gt;string&lt;/code&gt; representation, we will use the &lt;code&gt;ConvertLongToIP()&lt;/code&gt; method as shown below:&lt;/p&gt;

&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Author: Faisal Khan (http://www.stardeveloper.com)
/// &amp;lt;/summary&amp;gt;
public static string ConvertLongToIP(long ipLong)
{
	StringBuilder b = new StringBuilder();
	long tempLong, temp;

	tempLong = ipLong;
	temp = tempLong / (256 * 256 * 256);
	tempLong = tempLong - (temp * 256 * 256 * 256);
	b.Append(Convert.ToString(temp)).Append(&amp;quot;.&amp;quot;);
	temp = tempLong / (256 * 256);
	tempLong = tempLong - (temp * 256 * 256);
	b.Append(Convert.ToString(temp)).Append(&amp;quot;.&amp;quot;);
	temp = tempLong / 256;
	tempLong = tempLong - (temp * 256);
	b.Append(Convert.ToString(temp)).Append(&amp;quot;.&amp;quot;);
	temp = tempLong;
	tempLong = tempLong - temp;
	b.Append(Convert.ToString(temp));

	return b.ToString().ToLower();
}&lt;/pre&gt;

&lt;h2&gt;Converting IP Addresses to Bigint Values and Back in T-SQL&lt;/h2&gt;

&lt;p&gt;We will use &lt;code&gt;ConvertIPToLong()&lt;/code&gt; function to convert &lt;code&gt;varchar(15)&lt;/code&gt; based IP address to a &lt;code&gt;bigint&lt;/code&gt; value as shown below:&lt;/p&gt;

&lt;pre&gt;
' Author: Faisal Khan (http://www.stardeveloper.com)
CREATE FUNCTION [dbo].[ConvertIPToLong](@IP varchar(15))
RETURNS bigint
AS
BEGIN
	DECLARE @Long bigint
	SET @Long = CONVERT(bigint, PARSENAME(@IP, 4)) * 256 * 256 * 256 +
		CONVERT(bigint, PARSENAME(@IP, 3)) * 256 * 256 +
		CONVERT(bigint, PARSENAME(@IP, 2)) * 256 +
		CONVERT(bigint, PARSENAME(@IP, 1))

	RETURN (@Long)
END&lt;/pre&gt;

&lt;p&gt;Now, to convert this &lt;code&gt;bigint&lt;/code&gt; value back to its &lt;code&gt;varchar(15)&lt;/code&gt; representation, we will use the &lt;code&gt;ConvertLongToIP()&lt;/code&gt; function as shown below:&lt;/p&gt;

&lt;pre&gt;
' Author: Faisal Khan (http://www.stardeveloper.com)
CREATE FUNCTION [dbo].[ConvertLongToIP](@Long bigint)
RETURNS varchar(15)
AS
BEGIN
	DECLARE @IP varchar(15)
	DECLARE @TempLong bigint
	DECLARE @Temp bigint

	SET @TempLong = @Long
	SET @Temp = @TempLong / (256 * 256 * 256)
	SET @TempLong = @TempLong - (@Temp * 256 * 256 * 256)
	SET @IP = CONVERT(varchar(3), @Temp) + '.'
	SET @Temp = @TempLong / (256 * 256)
	SET @TempLong = @TempLong - (@Temp * 256 * 256)
	SET @IP = @IP + CONVERT(varchar(3), @Temp) + '.'
	SET @Temp = @TempLong / 256
	SET @TempLong = @TempLong - (@Temp * 256)
	SET @IP = @IP + CONVERT(varchar(3), @Temp) + '.'
	SET @Temp = @TempLong
	SET @TempLong = @TempLong - @Temp
	SET @IP = @IP + CONVERT(varchar(3), @Temp)

	RETURN (@IP)
END &lt;/pre&gt;

&lt;p&gt;After you have created these functions in your database, you can run the following SQL code to test these functions:&lt;/p&gt;

&lt;pre&gt;SELECT [dbo].ConvertIPToLong('255.255.255.255'), [dbo].ConvertLongToIP(4294967295)&lt;/pre&gt;

&lt;p&gt;You should create these functions in your C# libraries and in SQL Server databases and use them whenever you want to store or use an IP address in your code or database.&lt;/p&gt;

&lt;h2&gt;Final Words&lt;/h2&gt;

&lt;p&gt;I have very succinctly described the code to convert an IP address from a &lt;code&gt;string&lt;/code&gt; value to &lt;code&gt;long&lt;/code&gt; and back. I hope this code will be useful to you in your web and database application development. Good luck!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=5Sc1UWqoO34:OH9tshaSVaw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=5Sc1UWqoO34:OH9tshaSVaw:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/5Sc1UWqoO34" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/convert-ip-address-to-long/]]></guid>
<author>Faisal Khan</author>
<pubDate>Sun, 27 Dec 2009 08:48:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/convert-ip-address-to-long/</feedburner:origLink></item>
<item>
<title>Introduction to Developing HTTP Modules in ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/gzdvaqfZZr4/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In ASP.NET, an HTTP Module is a class that implements the &lt;code&gt;IHttpModule&lt;/code&gt; interface. By doing that it can listen to and handle events in the web request handling pipeline. They are the equivalent of &amp;#39;ISAPI Filters&amp;#39; in IIS and &amp;#39;Filters&amp;#39; in JSP. They are used for multiple purposes from authenticating a request to modifying the response and logging the request. In this tutorial, we will learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Common uses of HTTP Modules&lt;/li&gt;
&lt;li&gt;Web Request Handling Pipeline&lt;/li&gt;
&lt;li&gt;Structure of an HTTP Module&lt;/li&gt;
&lt;li&gt;Creating your first HTTP Module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Common Uses of HTTP Modules&lt;/b&gt;&lt;br /&gt;
Following is a noncomprehensive list of common uses of HTTP Modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Authentication&lt;/b&gt; - To authenticate a user. For example, you can place a cookie in the user's browser once he has logged in. Next time when the user visits the website, his session will have timed out. An HTTP Module can fetch the cookie and log the user back in by retrieving and matching the cookie string against user data in the database, without the user having to enter his username/password on the website. This can provide a smooth experience to the user who will never come to know how he has been logged back in automatically.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Authorization&lt;/b&gt; - To protect access to restricted resources on the website. An HTTP Module can authenticate the user accessing the resource and if the user is not listed in the roles allowed to access this resource, then the user can be redirected back to a &amp;quot;login&amp;quot; page.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Protection against Denial of Service Attacks&lt;/b&gt; - An HTTP Module can maintain an internal list of &lt;a href="http://www.stardeveloper.com/articles/convert-ip-address-to-long/" title="What are IP addresses and how to convert an IP address to an integer value"&gt;IP addresses&lt;/a&gt; accessing the website along with the hits the website is receiving from each of them. When an IP address is noted to be sending too many requests &lt;em&gt;out of proportion&lt;/em&gt; to the rest of the IP addresses, that IP address can be temporarily blocked from accessing the website.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP Compression&lt;/b&gt; - To compress the text output of web pages using &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2007110401&amp;amp;page=1"&gt;&lt;code&gt;Gzip&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2007110401&amp;amp;page=1"&gt;&lt;code&gt;Deflate&lt;/code&gt;&lt;/a&gt; algorithms. Compression can not only substantially reduce the bandwidth usage of a website, it can also make the pages appear faster in the users' browsers because of smaller sizes of compressed pages that are sent over the internet.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Encryption&lt;/b&gt; - To encrypt an outgoing response into encrypted text.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Caching&lt;/b&gt; - To cache commonly accessed content into an in-memory cache. This can be applied to static as well as dynamic generated content. Again an internal list can be used to gather statistics first as to which content is accessed more often than others. Then the popular content can be cached.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Collecting User Information&lt;/b&gt; - To get the user IP address and match it against an internal database of IP addresses along with names of countries. The HTTP Module can then pass the fetched country name (or country code) silently to the request handlers which can then display it as a country flag to the user. This is useful for not only providing customized experience to the user, you can also use it to display different content (e.g., ads) to users from different countries.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Modifying Headers&lt;/b&gt; - To modify the outgoing headers. For example, you can use it to tell the client browser when the requested resource was last modified and so on. You can send the headers for static content to be cached in the client browser and intermediate proxy servers, more often than for example dynamic content.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Formatting Output&lt;/b&gt; - To transform XML files with XSL stylesheets on the fly. So when the user accesses an XML file on your website directly, he/she will be served an HTML transformation of the XML file, displaying the content in a more pleasant fashion.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Replacing Content&lt;/b&gt; - To use regular expressions to parse and replace content in the response generated by the request handler. For example, to &lt;em&gt;highlight&lt;/em&gt; words in the outgoing HTML content matching keywords that a user entered in the search engine e.g., Google, to visit your website. This will improve the experience of a person on your website who entered some keywords in Google and found your website among the ones that Google displayed. Now when he visited your website he sees his keywords highlighted within the text of that page.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Logging&lt;/b&gt; - To log requests in a file or a database. Some examples:-
	&lt;ul&gt;
	&lt;li&gt;To log hits that your website is getting every hour. An ASP.NET page can be used to display these hits in a chart to you providing you with a quick snapshot of the activity on your website.&lt;/li&gt;
	&lt;li&gt;To scan the &lt;code&gt;Status Code&lt;/code&gt; e.g., 500, generated by a resource downstream, and log it in the database. An ASP.NET page again can be used to view in the form of a chart, when and how many 500 HTTP errors were generated on the website and by which resource.&lt;/li&gt;
	&lt;li&gt;To log bandwidth that your website is using, day in and day out.&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; What you can do with HTTP Modules is only limited by your imagination. Soon when you are up to speed with HTTP Modules, you will be developing ones for needs you had never thought you &lt;i&gt;can&lt;/i&gt; be developing for, before.&lt;/div&gt;

&lt;p&gt;On the next page, we will look at the events in the &amp;#39;Web Request Handling Pipeline&amp;#39;.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Web Request Handling Pipeline&lt;/b&gt;&lt;br /&gt;
In ASP.NET, there is a series of events that is raised before a request is handed over to a &lt;b&gt;request handler&lt;/b&gt; to execute. And on its way back to the client, another series of events is raised. This model is what I refer to as the &amp;#39;&lt;em&gt;Web Request Handling Pipeline&lt;/em&gt;&amp;#39;. The list of these events, in the order that they are fired from the moment a request is received to the moment it is disposed, is given below with brief description:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;BeginRequest&lt;/code&gt; - Fired as the first event when ASP.NET responds to a request.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AuthenticateRequest&lt;/code&gt; - Occurs when the identity of the user is being established.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostAuthenticateRequest&lt;/code&gt; - Occurs when the identity of the user has been established.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AuthorizeRequest&lt;/code&gt; - Occurs when the request is being authorized for this user.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostAuthorizeRequest&lt;/code&gt; - Occurs when the request has been authorized for this user.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ResolveRequestCache&lt;/code&gt; - Occurs when the request is being examined for the fact that the requested resource be sent directly from the cache or not.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostResolveRequestCache&lt;/code&gt; - Occurs when the requested resource is being sent directly from the cache and the &lt;em&gt;request handler will not be called to process this request&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MapRequestHandler&lt;/code&gt; - Occurs when the request is being mapped to an appropriate request handler. This event is only raised in IIS 7.0 when it is run in &lt;b&gt;integrated mode&lt;/b&gt; with .NET Framework 3.0 or above.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostMapRequestHandler&lt;/code&gt; - Occurs when appropriate request handler has been mapped with the request.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AcquireRequestState&lt;/code&gt; - Occurs when state associated with the request is being acquired.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostAcquireRequestState&lt;/code&gt; - Occurs when state associated with the request has been acquired.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PreRequestHandlerExecute&lt;/code&gt; - Occurs just before request handler (e.g., an ASP.NET page) is handed over control for this request. In the tutorial on &amp;quot;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2007110401&amp;page=1"&gt;Enabling Gzip and Deflate HTTP Compression in ASP.NET pages&lt;/a&gt;&amp;quot;, this event is handled to enable HTTP Compression in ASP.NET pages.&lt;/li&gt;
	&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; &lt;em&gt;The Request Handler is now handed over the request.&lt;/em&gt;&lt;/div&gt;
&lt;li&gt;&lt;code&gt;PostRequestHandlerExecute&lt;/code&gt; - Occurs right after the request handler has been executed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ReleaseRequestState&lt;/code&gt; - Occurs when the state (e.g., session state associated with the request) associated with the request is being released.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostReleaseRequestState&lt;/code&gt; - Occurs when the state associated with the request has been released.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UpdateRequestCache&lt;/code&gt; - Occurs when request handler has executed the request. This event provides opportunity to HTTP Modules that want to cache the response generated by this request so that subesquent requests can be handled directly from the cache.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostUpdateRequestCache&lt;/code&gt; - Occurs when HTTP Modules that wanted to cache the response generated by this request have finished doing so.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LogRequest&lt;/code&gt; - Occurs when ASP.NET is logging this request. This event is supported by IIS 7.0 in &lt;b&gt;integrated mode&lt;/b&gt; with .NET Framework 3.0 or above.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostLogRequest&lt;/code&gt; - Occurs when ASP.NET has finished logging this request. Again, this event is only supported in IIS 7.0 in &lt;b&gt;integrated mode&lt;/b&gt; with .NET Framework 3.0 or above.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EndRequest&lt;/code&gt; - Finally, this is the last event in the chain of events in web request handling pipeline.&lt;/li&gt;
&lt;/ol&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; Above events are associated with &lt;code&gt;HttpApplication&lt;/code&gt; object, the reference of which is provided to all HTTP Modules when they are initialized so that they can subscribe to the events of their interest.&lt;/div&gt;

&lt;p&gt;We will now learn what an HTTP Module looks like in the code and how it can subscribe to and handle these events.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Structure of an HTTP Module&lt;/b&gt;&lt;br /&gt;
An HTTP Module is an ordinary class that implements &lt;code&gt;IHttpModule&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;IHttpModule&lt;/b&gt;&lt;br /&gt;
It is defined in the &lt;code&gt;System.Web&lt;/code&gt; namespace. This interface has just two methods to be implemented as described below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Init(HttpApplication application)&lt;/code&gt; - This method is called by ASP.NET to &lt;em&gt;initialize&lt;/em&gt; the HTTP Module. In this method, the HTTP Module can use the supplied argument of type, &lt;code&gt;HttpApplication&lt;/code&gt;, to subscribe to events it wishes to handle.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dispose()&lt;/code&gt; - This method is called by ASP.NET just before it wishes to &lt;em&gt;dispose&lt;/em&gt; the given &lt;em&gt;instance&lt;/em&gt; of an HTTP Module.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;HttpApplication Events&lt;/b&gt;&lt;br /&gt;
The &lt;code&gt;HttpApplication&lt;/code&gt; object passed as the argument in the &lt;code&gt;Init()&lt;/code&gt; method of the &lt;code&gt;IHttpModule&lt;/code&gt; interface can be used by the HTTP Module to subscribe to events of its choice. The list of the events available to the HTTP Module has already been given above.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; You should only handle the event(s) that is/are most appropriate for the task that you want to achieve with your HTTP Module.&lt;/div&gt;

&lt;p&gt;Now that you have seen &lt;code&gt;IHttpModule&lt;/code&gt; interface and are aware of the events that are made available to HTTP Modules, we will look at the code of an empty HTTP Module and later add some code to handle an event from the web request handling pipeline.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Creating your first HTTP Module&lt;/b&gt;&lt;br /&gt;
Following code shows how a class can implement the &lt;code&gt;IHttpModule&lt;/code&gt; interface:&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

namespace Stardeveloper.Modules
{
	public class SampleModule : IHttpModule
	{
		public void Init(HttpApplication application)
		{
		}

		public void Dispose()
		{
		}
	}
}&lt;/pre&gt;

&lt;p&gt;That wasn't too much of a code, was it? A class with the name of &lt;code&gt;SampleModule&lt;/code&gt; declared in the &lt;code&gt;Stardeveloper.Modules&lt;/code&gt; namespace implements the &lt;code&gt;IHttpModule&lt;/code&gt; interface. An empty implementation of the methods is shown above.&lt;/p&gt;

&lt;p&gt;To handle events in the web request handling pipeline, it subscribes to them as follows:&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;

namespace Stardeveloper.Modules
{
	public class SampleModule : IHttpModule
	{
		public void Init(HttpApplication application)
		{
			application.PreRequestHandlerExecute +=
				new EventHandler(application_PreRequestHandlerExecute);
			application.PostRequestHandlerExecute +=
				new EventHandler(application_PostRequestHandlerExecute);
		}

		protected void application_PreRequestHandlerExecute(object sender,
			EventArgs e)
		{
			HttpApplication application = sender as HttpApplication;
			application.Response.Write(&amp;quot;Welcome!&amp;quot;);
		}
		
		protected void application_PostRequestHandlerExecute(object sender,
			EventArgs e)
		{
			HttpApplication application = sender as HttpApplication;
			application.Response.Write(&amp;quot;Bye!&amp;quot;);
		}

		public void Dispose()
		{
		}
	}
}&lt;/pre&gt;&lt;p&gt;Same class now uses C#'s syntax of subscribing to events to subscribe to two events; &lt;code&gt;PreRequestHandlerExecute&lt;/code&gt; and &lt;code&gt;PostRequestHandlerExecute&lt;/code&gt;. In the body of the event handlers, it casts the reference from the &lt;code&gt;sender&lt;/code&gt; object to &lt;code&gt;HttpApplication&lt;/code&gt; object and uses its &lt;code&gt;Response&lt;/code&gt; property (which is of type &lt;code&gt;HttpResponse&lt;/code&gt;) to write some text in the response being sent to the client browser.&lt;/p&gt;

&lt;p&gt;To install this module in your ASP.NET web application, place this code in &lt;code&gt;SampleModule.cs&lt;/code&gt; file and put it in the &lt;code&gt;/App_Code&lt;/code&gt; folder of your ASP.NET web application. Then edit your &lt;code&gt;web.config&lt;/code&gt; file to add following line within the &amp;quot;&lt;code&gt;httpModules&lt;/code&gt;&amp;quot; section:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;configuration&amp;gt;
	&amp;lt;system.web&amp;gt;
		&amp;lt;httpModules&amp;gt;
			&amp;lt;add name=&amp;quot;SampleModule&amp;quot; type=&amp;quot;Stardeveloper.Modules.SampleModule&amp;quot;/&amp;gt;
		&amp;lt;/httpModules&amp;gt;
	&amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now, when you access any ASP.NET page within your ASP.NET web application, you will see all the text wrapped between &amp;quot;Welcome!&amp;quot; and &amp;quot;Bye!&amp;quot;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
In this tutorial, we were introduced with the concept of events in the web request handling pipeline. We also got a good idea of what HTTP Modules can do. We then looked at the &lt;code&gt;IHttpModule&lt;/code&gt; interface and &lt;code&gt;HttpApplication&lt;/code&gt; object. Finally, we created an empty HTTP Module, made it handle a couple of events from the web request handling pipeline, configure it in the &lt;code&gt;web.config&lt;/code&gt; file, and display some text to the user.&lt;/p&gt;

&lt;p&gt;In the next tutorial, we will look at a more real-World example of an HTTP Module in action.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=gzdvaqfZZr4:b2zLk2uX0-E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=gzdvaqfZZr4:b2zLk2uX0-E:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/gzdvaqfZZr4" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009071801&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Sat, 18 Jul 2009 09:00:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009071801&amp;page=1</feedburner:origLink></item>
<item>
<title>Displaying Emails from Mailbox on Gmail using POP3 and ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/XXDt3_os0mA/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will create the missing ASP.NET page, that was left in the previous tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009070801&amp;page=1"&gt;Connecting to Mailbox on Gmail and Fetching List of Emails using POP3 and ASP.NET&lt;/a&gt;), that takes an individual email's sort number on the POP3 server to retrieve and display it to the user after properly decoding content-transfer-encodings like &lt;code&gt;base64&lt;/code&gt; and &lt;code&gt;quoted-printable&lt;/code&gt;. You will learn how to access individual message parts in MIME encoded emails including fetching and enlisting attachments.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; It is mandatory that you read the previous tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009070801&amp;page=1"&gt;Connecting to Mailbox on Gmail and Fetching List of Emails using POP3 and ASP.NET&lt;/a&gt;) to download and place the essential &lt;code&gt;Pop3.cs&lt;/code&gt; file in the &lt;code&gt;/App_Code&lt;/code&gt; folder of your ASP.NET web application. Without this code, you will not be able to connect and retrieve emails using POP3.&lt;/div&gt;

&lt;p&gt;In the previous tutorial, we limited ourselves to only listing the emails in our mailbox on Gmail. That in itself was quite a bit of a job since we had to develop all the baseline code that connects, sends commands, receives data, parses and instantiates objects. The classes that we created like &lt;code&gt;Pop3Client&lt;/code&gt;, &lt;code&gt;Email&lt;/code&gt;, and &lt;code&gt;MessagePart&lt;/code&gt; made the task a lot more easier for us. Only few lines of code were needed to retrieve the list of emails in the mailbox and display it on the ASP.NET page. We will build on that base in this tutorial.&lt;/p&gt;

&lt;div style="font-family: 'Georgia'; font-size: 10pt; padding: 1em; border: dotted 1px #111"&gt;If you are looking for a production ready, stable, easy to use ASP.NET Newsletter application, then look no further: &lt;strong&gt;Faisal Khan (the author of this tutorial) has created a great &lt;a href="http://www.stardeveloper.com/newsletter/"&gt;Newsletter Application&lt;/a&gt; for you to download and start using today.&lt;/strong&gt; It is easy to install, lets your users subscribe using a subscription form, provides a simple administration interface to create and send newsletters, handles the task of sending newsletters in the background using thread queues on the server, and lets users unsubscribe if they wish so.&lt;/div&gt;

&lt;p&gt;Following is the screen shot of the ASP.NET page that we developed in the previous tutorial:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-listing-emails.gif" width="600" height="235" border="0" alt="Listing emails" /&gt;
&lt;/div&gt;

&lt;p&gt;If you followed previous tutorial and created &lt;code&gt;Pop3Client.aspx&lt;/code&gt; ASP.NET page that is listing the emails as shown in screen shot above, you'd have found out that the subject of the email is displayed as a link to &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; ASP.NET page. That ASP.NET page is what we will create in this tutorial.&lt;/p&gt;

&lt;p&gt;Following screen shots shows &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; ASP.NET page displaying a plain text email:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-asp.net-plain-text-email.gif" width="600" height="252" border="0" alt="A plain text email" /&gt;
&lt;/div&gt;

&lt;p&gt;Following screen shot shows &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; displaying an HTML email:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-asp.net-html-email.gif" width="600" height="344" border="0" alt="An HTML email" /&gt;
&lt;/div&gt;

&lt;p&gt;Following screen shot shows &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; listing attachments:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-asp.net-listing-attachments.gif" width="600" height="322" border="0" alt="An Email with attachments" /&gt;
&lt;/div&gt;

&lt;p&gt;Now that you know what &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; ASP.NET page that we will create in this tutorial will do, we will now go straight into its code.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;DisplayPop3Email.aspx&lt;/b&gt;&lt;br /&gt;
Open Notepad and copy following text in it. Then save it as &amp;quot;&lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt;&amp;quot; in your ASP.NET web application where you saved &lt;code&gt;Pop3Client.aspx&lt;/code&gt; ASP.NET page from the previous tutorial:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;

&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Pop3&amp;quot; %&amp;gt;

&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	public const string Host = &amp;quot;pop.gmail.com&amp;quot;;
	public const int Port = 995;
	public const string Email = &amp;quot;youremail@gmail.com&amp;quot;;
	public const string Password = &amp;quot;yourpassword&amp;quot;;

	protected static Regex CharsetRegex =
		new Regex(&amp;quot;charset=\&amp;quot;?(?&amp;lt;charset&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
		RegexOptions.IgnoreCase | RegexOptions.Compiled);
	protected static Regex QuotedPrintableRegex =
		new Regex(&amp;quot;=(?&amp;lt;hexchars&amp;gt;[0-9a-fA-F]{2,2})&amp;quot;,
		RegexOptions.IgnoreCase | RegexOptions.Compiled);
	protected static Regex UrlRegex =
		new Regex(&amp;quot;(?&amp;lt;url&amp;gt;https?://[^\\s\&amp;quot;]+)&amp;quot;,
		RegexOptions.IgnoreCase | RegexOptions.Compiled);
	protected static Regex FilenameRegex =
		new Regex(&amp;quot;filename=\&amp;quot;?(?&amp;lt;filename&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
		RegexOptions.IgnoreCase| RegexOptions.Compiled);
	protected static Regex NameRegex =
		new Regex(&amp;quot;name=\&amp;quot;?(?&amp;lt;filename&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
		RegexOptions.IgnoreCase | RegexOptions.Compiled);

	protected void Page_Load(object source, EventArgs e)
	{
		/* Setting email id */
		int emailId = -1;

		if (Request.QueryString[&amp;quot;emailId&amp;quot;] == null)
		{
			Response.Redirect(&amp;quot;Pop3Client.aspx&amp;quot;);
			Response.Flush();
			Response.End();
		}
		else
			emailId = Convert.ToInt32(
				Request.QueryString[&amp;quot;emailId&amp;quot;]);

		/* Creating Pop3Client object and accessing email data */
		Email email = null;
		List&amp;lt;MessagePart&amp;gt; msgParts = null;

		using (Pop3Client client = new Pop3Client(Host, Port,
			Email, Password, true))
		{
			client.Connect();

			// Fetching email headers
			email = client.FetchEmail(emailId);
			// Fetching email body
			msgParts = client.FetchMessageParts(emailId);
		}

		if (email == null || msgParts == null)
		{
			Response.Redirect(&amp;quot;Pop3Client.aspx&amp;quot;);
			Response.Flush();
			Response.End();
		}

		/* Selecting a message part to display to the user */
		MessagePart preferredMsgPart = FindMessagePart(msgParts, &amp;quot;text/html&amp;quot;);

		if (preferredMsgPart == null)
			preferredMsgPart = FindMessagePart(msgParts, &amp;quot;text/plain&amp;quot;);
		else if (preferredMsgPart == null &amp;amp;&amp;amp; msgParts.Count &amp;gt; 0)
			preferredMsgPart = msgParts[0];

		string contentType, charset, contentTransferEncoding, body = null;

		if (preferredMsgPart != null)
		{
			contentType = preferredMsgPart.Headers[&amp;quot;Content-Type&amp;quot;];
			charset = &amp;quot;us-ascii&amp;quot;; // default charset
			contentTransferEncoding =
				preferredMsgPart.Headers[&amp;quot;Content-Transfer-Encoding&amp;quot;];

			Match m = CharsetRegex.Match(contentType);

			if (m.Success)
				charset = m.Groups[&amp;quot;charset&amp;quot;].Value;

			HeadersLiteral.Text = contentType != null ? &amp;quot;Content-Type: &amp;quot; +
				contentType + &amp;quot;&amp;lt;br /&amp;gt;&amp;quot; : string.Empty;
			HeadersLiteral.Text += contentTransferEncoding != null ?
				&amp;quot;Content-Transfer-Encoding: &amp;quot; +
				contentTransferEncoding : string.Empty;

			/* Decoding base64 and quoted-printable encoded messages */
			if (contentTransferEncoding != null)
			{
				if (contentTransferEncoding.ToLower() == &amp;quot;base64&amp;quot;)
					body = DecodeBase64String(charset,
						preferredMsgPart.MessageText);
				else if (contentTransferEncoding.ToLower() ==
						&amp;quot;quoted-printable&amp;quot;)
					body = DecodeQuotedPrintableString(
						preferredMsgPart.MessageText);
				else
					body = preferredMsgPart.MessageText;
			}
			else
				body = preferredMsgPart.MessageText;
		}

		/* Displaying information to the user */
		EmailIdLiteral.Text = Convert.ToString(emailId);
		DateLiteral.Text = email.UtcDateTime.ToString(); ;
		FromLiteral.Text = email.From;
		SubjectLiteral.Text = email.Subject;
		BodyLiteral.Text = preferredMsgPart != null ? 
			(preferredMsgPart.Headers[&amp;quot;Content-Type&amp;quot;]
				.IndexOf(&amp;quot;text/plain&amp;quot;) != -1 ?
			&amp;quot;&amp;lt;pre&amp;gt;&amp;quot; + FormatUrls(body) + &amp;quot;&amp;lt;/pre&amp;gt;&amp;quot; : body) : null;

		ListAttachments(msgParts);
	}&lt;/pre&gt;

&lt;p&gt;The code continues on the next page.&lt;/p&gt;&lt;p&gt;The code continues from the previous page.&lt;/p&gt;

&lt;pre&gt;
	protected Decoder GetDecoder(string charset)
	{
		Decoder decoder;

		switch (charset.ToLower())
		{
			case &amp;quot;utf-7&amp;quot;:
				decoder = Encoding.UTF7.GetDecoder();
				break;
			case &amp;quot;utf-8&amp;quot;:
				decoder = Encoding.UTF8.GetDecoder();
				break;
			case &amp;quot;us-ascii&amp;quot;:
				decoder = Encoding.ASCII.GetDecoder();
				break;
			case &amp;quot;iso-8859-1&amp;quot;:
				decoder = Encoding.ASCII.GetDecoder();
				break;
			default:
				decoder = Encoding.ASCII.GetDecoder();
				break;
		}

		return decoder;
	}

	protected string DecodeBase64String(string charset, string encodedString)
	{
		Decoder decoder = GetDecoder(charset);

		byte[] buffer = Convert.FromBase64String(encodedString);
		char[] chararr = new char[decoder.GetCharCount(buffer,
			0, buffer.Length)];

		decoder.GetChars(buffer, 0, buffer.Length, chararr, 0);

		return new string(chararr);
	}

	protected string DecodeQuotedPrintableString(string encodedString)
	{
		StringBuilder b = new StringBuilder();
		int startIndx = 0;

		MatchCollection matches = QuotedPrintableRegex.Matches(encodedString);

		for (int i = 0; i &amp;lt; matches.Count; i++)
		{
			Match m = matches[i];
			string hexchars = m.Groups[&amp;quot;hexchars&amp;quot;].Value;
			int charcode = Convert.ToInt32(hexchars, 16);
			char c = (char)charcode;

			if (m.Index &amp;gt; 0)
				b.Append(encodedString.Substring(startIndx,
					(m.Index - startIndx)));

			b.Append(c);

			startIndx = m.Index + 3;
		}
		
		if (startIndx &amp;lt; encodedString.Length)
			b.Append(encodedString.Substring(startIndx));

		return Regex.Replace(b.ToString(), &amp;quot;=\r\n&amp;quot;, &amp;quot;&amp;quot;);
	}

	protected void ListAttachments(List&amp;lt;MessagePart&amp;gt; msgParts)
	{
		bool attachmentsFound = false;
		StringBuilder b = new StringBuilder();
		b.Append(&amp;quot;&amp;lt;ol&amp;gt;&amp;quot;);

		foreach (MessagePart p in msgParts)
		{
			string contentType = p.Headers[&amp;quot;Content-Type&amp;quot;];
			string contentDisposition = p.Headers[&amp;quot;Content-Disposition&amp;quot;];

			Match m;

			if (contentDisposition != null)
			{
				m = FilenameRegex.Match(contentDisposition);

				if (m.Success)
				{
					attachmentsFound = true;
					b.Append(&amp;quot;&amp;lt;li&amp;gt;&amp;quot;).
						Append(m.Groups[&amp;quot;filename&amp;quot;].
							Value).Append(&amp;quot;&amp;lt;/li&amp;gt;&amp;quot;);
				}
			}
			else if (contentType != null)
			{
				m = NameRegex.Match(contentType);

				if (m.Success)
				{
					attachmentsFound = true;
					b.Append(&amp;quot;&amp;lt;li&amp;gt;&amp;quot;).
						Append(m.Groups[&amp;quot;filename&amp;quot;].
							Value).Append(&amp;quot;&amp;lt;/li&amp;gt;&amp;quot;);
				}
			}
		}
			
		b.Append(&amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;);

		if (attachmentsFound)
			AttachmentsLiteral.Text = b.ToString();
		else
			AttachementsRow.Visible = false;
	}

	protected MessagePart FindMessagePart(List&amp;lt;MessagePart&amp;gt; msgParts,
		string contentType)
	{
		foreach (MessagePart p in msgParts)
			if (p.ContentType != null &amp;amp;&amp;amp;
					p.ContentType.IndexOf(contentType) != -1)
				return p;

		return null;
	}

	protected string FormatUrls(string plainText)
	{
		string replacementLink = &amp;quot;&amp;lt;a href=\&amp;quot;${url}\&amp;quot;&amp;gt;${url}&amp;lt;/a&amp;gt;&amp;quot;;

		return UrlRegex.Replace(plainText, replacementLink);
	}
&amp;lt;/script&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;
		.emails-table { width: 600px; border: solid 1px #444444; }
		.emails-table-header { font-family: &amp;quot;Trebuchet MS&amp;quot;; font-size: 9pt;
			background-color: #0099B9; font-weight: bold; color: white;
			text-align: center; border: solid 1px #444444; }
		.emails-table-header-cell { font-family: &amp;quot;Georgia&amp;quot;; font-size: 9pt;
			font-weight: bold; border: solid 1px #666666; padding: 6px; }
		.emails-table-cell { font-family: &amp;quot;Georgia&amp;quot;; font-size: 9pt;
			border: solid 1px #666666; padding: 6px; }
		.emails-table-footer { border: solid 1px #666666; padding: 3px;
			width: 50%; }
		.email-datetime { float: right; color: #666666; }
		
		a { font-family: &amp;quot;Lucida Sans Unicode&amp;quot;, &amp;quot;Trebuchet MS&amp;quot;; font-size: 9pt;
			color: #005B7F; }
		a:hover { color:red; }
		pre { font-family: &amp;quot;Georgia&amp;quot;; font-size: 9pt; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;asp:Literal ID=&amp;quot;DebugLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;
    
    &amp;lt;table class=&amp;quot;emails-table&amp;quot;&amp;gt;
    &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-header&amp;quot; colspan=&amp;quot;2&amp;quot;&amp;gt;
		Email #&amp;lt;asp:Literal ID=&amp;quot;EmailIdLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;Date &amp;amp;amp; Time&amp;lt;/td&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;DateLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;From&amp;lt;/td&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;FromLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;Subject&amp;lt;/td&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;SubjectLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;tr id=&amp;quot;AttachementsRow&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;Attachments&amp;lt;/td&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;AttachmentsLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
     &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot; colspan=&amp;quot;2&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;HeadersLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;tr&amp;gt;
		&amp;lt;td class=&amp;quot;emails-table-cell&amp;quot; colspan=&amp;quot;2&amp;quot;&amp;gt;
			&amp;lt;asp:Literal ID=&amp;quot;BodyLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/table&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
We will now dissect the code, bit by bit.&lt;/p&gt;

&lt;p&gt;The first thing we do is to use a &lt;code&gt;Page&lt;/code&gt; level declaration to tell the ASP.NET compiler that all the server-side code encountered in this document should, by default, be assumed to be of the language, C#.&lt;/p&gt;

&lt;pre&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Next, we import the necessary namespaces.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; We are importing the namespace &lt;code&gt;Stardeveloper.Pop3&lt;/code&gt; to make use of the code that we created in the previous tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009070801&amp;page=1"&gt;Connecting to Mailbox on Gmail and Fetching List of Emails using POP3 and ASP.NET&lt;/a&gt;). This will make available classes like &lt;code&gt;Pop3Client&lt;/code&gt;, &lt;code&gt;Email&lt;/code&gt; and &lt;code&gt;MessagePart&lt;/code&gt; to us.&lt;/div&gt;

&lt;pre&gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Pop3&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;All the server-side code is encapsulated between &lt;code&gt;script&lt;/code&gt; tags.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	...
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt; arguments required in the constructor of &lt;code&gt;Pop3Client&lt;/code&gt; class will be set using the following four constants.&lt;/p&gt;

&lt;pre&gt;
public const string Host = &amp;quot;pop.gmail.com&amp;quot;;
public const int Port = 995;
public const string Email = &amp;quot;youremail@gmail.com&amp;quot;;
public const string Password = &amp;quot;yourpassword&amp;quot;;&lt;/pre&gt;

&lt;p&gt;Regular expressions used in the code later have been created as &lt;code&gt;static&lt;/code&gt; objects. The &lt;code&gt;RegexOptions.Compiled&lt;/code&gt; bit is also set in the constructor of all the &lt;code&gt;Regex&lt;/code&gt; objects so that they are compiled the first time they are used and from there onwards, running these regular expressions will be super fast.&lt;/p&gt;

&lt;pre&gt;
protected static Regex CharsetRegex =
	new Regex(&amp;quot;charset=\&amp;quot;?(?&amp;lt;charset&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
	RegexOptions.IgnoreCase | RegexOptions.Compiled);
protected static Regex QuotedPrintableRegex =
	new Regex(&amp;quot;=(?&amp;lt;hexchars&amp;gt;[0-9a-fA-F]{2,2})&amp;quot;,
	RegexOptions.IgnoreCase | RegexOptions.Compiled);
protected static Regex UrlRegex =
	new Regex(&amp;quot;(?&amp;lt;url&amp;gt;https?://[^\\s\&amp;quot;]+)&amp;quot;,
	RegexOptions.IgnoreCase | RegexOptions.Compiled);
protected static Regex FilenameRegex =
	new Regex(&amp;quot;filename=\&amp;quot;?(?&amp;lt;filename&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
	RegexOptions.IgnoreCase| RegexOptions.Compiled);
protected static Regex NameRegex =
	new Regex(&amp;quot;name=\&amp;quot;?(?&amp;lt;filename&amp;gt;[^\\s\&amp;quot;]+)\&amp;quot;?&amp;quot;,
	RegexOptions.IgnoreCase | RegexOptions.Compiled);&lt;/pre&gt;

&lt;p&gt;Now we will dig into the &lt;code&gt;Page_Load()&lt;/code&gt; method which is called with every request our &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; receives.&lt;/p&gt;

&lt;pre&gt;
protected void Page_Load(object source, EventArgs e)
{
	...
}&lt;/pre&gt;

&lt;p&gt;We retrieve the &lt;code&gt;emailId&lt;/code&gt; value from the querystring and save it in a variable of the same name.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; &lt;code&gt;emailId&lt;/code&gt; is the sort number of the email in the list of emails on the POP3 server. You can determine the number of emails by sending the &lt;code&gt;STAT&lt;/code&gt; command. For instance, you have 324 emails in your POP3 server. In those 324 emails, the email #324 is the latest email that your mailbox has received and email #1 is oldest email among all your emails in your mailbox. This is how emails are sorted by the POP3 server. Now if you want to retrieve the email #324, you should call the &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; ASP.NET page with the querystring value of the variable &lt;code&gt;emailId&lt;/code&gt; set to 324 i.e., &lt;code&gt;DisplayPop3Email.aspx?emailId=324&lt;/code&gt;. I hope this wasn't too difficult for you to understand.&lt;/div&gt;

&lt;pre&gt;
/* Setting email id */
int emailId = -1;

if (Request.QueryString[&amp;quot;emailId&amp;quot;] == null)
{
	Response.Redirect(&amp;quot;Pop3Client.aspx&amp;quot;);
	Response.Flush();
	Response.End();
}
else
	emailId = Convert.ToInt32(
		Request.QueryString[&amp;quot;emailId&amp;quot;]);&lt;/pre&gt;

&lt;p&gt;Once we have created the &lt;code&gt;Pop3Client&lt;/code&gt; object, we quickly call its &lt;code&gt;Connect()&lt;/code&gt; method to connect with the POP3 server. Once there, we call &lt;code&gt;FetchEmail()&lt;/code&gt; and &lt;code&gt;FetchMessageParts()&lt;/code&gt; methods to retrieve the full email, including all headers and its body.&lt;/p&gt;

&lt;pre&gt;
/* Creating Pop3Client object and accessing email data */
Email email = null;
List&amp;lt;MessagePart&amp;gt; msgParts = null;

using (Pop3Client client = new Pop3Client(Host, Port,
	Email, Password, true))
{
	client.Connect();

	// Fetching email headers
	email = client.FetchEmail(emailId);
	// Fetching email body
	msgParts = client.FetchMessageParts(emailId);
}&lt;/pre&gt;

&lt;p&gt;If the email's sort number was invalid e.g., the POP3 server has 324 emails and you accessed email #325, null references will be created by the code segment above. In which case we redirect the user to the ASP.NET page listing all the emails.&lt;/p&gt;

&lt;pre&gt;
if (email == null || msgParts == null)
{
	Response.Redirect(&amp;quot;Pop3Client.aspx&amp;quot;);
	Response.Flush();
	Response.End();
}&lt;/pre&gt;

&lt;p&gt;We then try to iterate through all the &lt;code&gt;MessagePart&lt;/code&gt; objects retrieved from the email and find the one most appropriate to display on the page. We begin by finding an HTML version of the email. If we cannot find it, we search for a plain text version of the email. If there is still no one found, we select the first &lt;code&gt;MessagePart&lt;/code&gt; object we encounter in the list.&lt;/p&gt;

&lt;pre&gt;
/* Selecting a message part to display to the user */
MessagePart preferredMsgPart = FindMessagePart(msgParts, &amp;quot;text/html&amp;quot;);

if (preferredMsgPart == null)
	preferredMsgPart = FindMessagePart(msgParts, &amp;quot;text/plain&amp;quot;);
else if (preferredMsgPart == null &amp;amp;&amp;amp; msgParts.Count &amp;gt; 0)
	preferredMsgPart = msgParts[0];&lt;/pre&gt;

&lt;p&gt;One we have the &lt;code&gt;MessagePart&lt;/code&gt; object we want to display on the page, we use its &lt;code&gt;content-type&lt;/code&gt; and &lt;code&gt;content-transfer-encoding&lt;/code&gt; headers to determine if the message body needs to be decoded first. If the message's body was encoded using &lt;code&gt;base64&lt;/code&gt; or &lt;code&gt;quoted-printable&lt;/code&gt; transfer encodings, we decode the content first and then display it to the user.&lt;/p&gt;

&lt;pre&gt;
string contentType, charset, contentTransferEncoding, body = null;

if (preferredMsgPart != null)
{
	contentType = preferredMsgPart.Headers[&amp;quot;Content-Type&amp;quot;];
	charset = &amp;quot;us-ascii&amp;quot;; // default charset
	contentTransferEncoding =
		preferredMsgPart.Headers[&amp;quot;Content-Transfer-Encoding&amp;quot;];

	Match m = CharsetRegex.Match(contentType);

	if (m.Success)
		charset = m.Groups[&amp;quot;charset&amp;quot;].Value;

	HeadersLiteral.Text = contentType != null ? &amp;quot;Content-Type: &amp;quot; +
		contentType + &amp;quot;&amp;lt;br /&amp;gt;&amp;quot; : string.Empty;
	HeadersLiteral.Text += contentTransferEncoding != null ?
		&amp;quot;Content-Transfer-Encoding: &amp;quot; +
		contentTransferEncoding : string.Empty;

	/* Decoding base64 and quoted-printable encoded messages */
	if (contentTransferEncoding != null)
	{
		if (contentTransferEncoding.ToLower() == &amp;quot;base64&amp;quot;)
			body = DecodeBase64String(charset,
				preferredMsgPart.MessageText);
		else if (contentTransferEncoding.ToLower() ==
				&amp;quot;quoted-printable&amp;quot;)
			body = DecodeQuotedPrintableString(
				preferredMsgPart.MessageText);
		else
			body = preferredMsgPart.MessageText;
	}
	else
		body = preferredMsgPart.MessageText;
}&lt;/pre&gt;

&lt;p&gt;We set a few literals with information from the email to display on the page.&lt;/p&gt;

&lt;pre&gt;
/* Displaying information to the user */
EmailIdLiteral.Text = Convert.ToString(emailId);
DateLiteral.Text = email.UtcDateTime.ToString(); ;
FromLiteral.Text = email.From;
SubjectLiteral.Text = email.Subject;
BodyLiteral.Text = preferredMsgPart != null ? 
	(preferredMsgPart.Headers[&amp;quot;Content-Type&amp;quot;]
		.IndexOf(&amp;quot;text/plain&amp;quot;) != -1 ?
	&amp;quot;&amp;lt;pre&amp;gt;&amp;quot; + FormatUrls(body) + &amp;quot;&amp;lt;/pre&amp;gt;&amp;quot; : body) : null;

ListAttachments(msgParts);&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;GetDecoder()&lt;/code&gt; returns the appropriate decoder to decode the message text depending on the &lt;code&gt;charset&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;
protected Decoder GetDecoder(string charset)
{
	Decoder decoder;

	switch (charset.ToLower())
	{
		case &amp;quot;utf-7&amp;quot;:
			decoder = Encoding.UTF7.GetDecoder();
			break;
		case &amp;quot;utf-8&amp;quot;:
			decoder = Encoding.UTF8.GetDecoder();
			break;
		case &amp;quot;us-ascii&amp;quot;:
			decoder = Encoding.ASCII.GetDecoder();
			break;
		case &amp;quot;iso-8859-1&amp;quot;:
			decoder = Encoding.ASCII.GetDecoder();
			break;
		default:
			decoder = Encoding.ASCII.GetDecoder();
			break;
	}

	return decoder;
}&lt;/pre&gt;&lt;p&gt;&lt;code&gt;DecodeBase64String()&lt;/code&gt; decodes a &lt;code&gt;base64&lt;/code&gt; encoded message and returns the decoded text.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; Most of the &lt;code&gt;base64&lt;/code&gt; encodings that you will encounter in a MIME encoded email will be for binary attachments that have been &lt;code&gt;base64&lt;/code&gt; encoded so that they can be attached as text with an email. But when when I went about to view emails on my email account, I encountered normal plain text emails that were &lt;code&gt;base64&lt;/code&gt; encoded. So I had to write a &lt;code&gt;base64&lt;/code&gt; decoder to decode and properly present them on the ASP.NET page.&lt;/div&gt;

&lt;pre&gt;
protected string DecodeBase64String(string charset, string encodedString)
{
	Decoder decoder = GetDecoder(charset);

	byte[] buffer = Convert.FromBase64String(encodedString);
	char[] chararr = new char[decoder.GetCharCount(buffer,
		0, buffer.Length)];

	decoder.GetChars(buffer, 0, buffer.Length, chararr, 0);

	return new string(chararr);
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;DecodeQuotedPrintableString()&lt;/code&gt; method decodes a message whose body has been encoded with &lt;code&gt;quoted-printable&lt;/code&gt; encoding.&lt;/p&gt;

&lt;pre&gt;
protected string DecodeQuotedPrintableString(string encodedString)
{
	StringBuilder b = new StringBuilder();
	int startIndx = 0;

	MatchCollection matches = QuotedPrintableRegex.Matches(encodedString);

	for (int i = 0; i &amp;lt; matches.Count; i++)
	{
		Match m = matches[i];
		string hexchars = m.Groups[&amp;quot;hexchars&amp;quot;].Value;
		int charcode = Convert.ToInt32(hexchars, 16);
		char c = (char)charcode;

		if (m.Index &amp;gt; 0)
			b.Append(encodedString.Substring(startIndx,
				(m.Index - startIndx)));

		b.Append(c);

		startIndx = m.Index + 3;
	}
	
	if (startIndx &amp;lt; encodedString.Length)
		b.Append(encodedString.Substring(startIndx));

	return Regex.Replace(b.ToString(), &amp;quot;=\r\n&amp;quot;, &amp;quot;&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;ListAttachments()&lt;/code&gt; method scans all the &lt;code&gt;MessagePart&lt;/code&gt; objects to determine which of these is an attachment. It then displays the list of attachments on the page.&lt;/p&gt;

&lt;pre&gt;
protected void ListAttachments(List&amp;lt;MessagePart&amp;gt; msgParts)
{
	bool attachmentsFound = false;
	StringBuilder b = new StringBuilder();
	b.Append(&amp;quot;&amp;lt;ol&amp;gt;&amp;quot;);

	foreach (MessagePart p in msgParts)
	{
		string contentType = p.Headers[&amp;quot;Content-Type&amp;quot;];
		string contentDisposition = p.Headers[&amp;quot;Content-Disposition&amp;quot;];

		Match m;

		if (contentDisposition != null)
		{
			m = FilenameRegex.Match(contentDisposition);

			if (m.Success)
			{
				attachmentsFound = true;
				b.Append(&amp;quot;&amp;lt;li&amp;gt;&amp;quot;).
					Append(m.Groups[&amp;quot;filename&amp;quot;].
						Value).Append(&amp;quot;&amp;lt;/li&amp;gt;&amp;quot;);
			}
		}
		else if (contentType != null)
		{
			m = NameRegex.Match(contentType);

			if (m.Success)
			{
				attachmentsFound = true;
				b.Append(&amp;quot;&amp;lt;li&amp;gt;&amp;quot;).
					Append(m.Groups[&amp;quot;filename&amp;quot;].
						Value).Append(&amp;quot;&amp;lt;/li&amp;gt;&amp;quot;);
			}
		}
	}
		
	b.Append(&amp;quot;&amp;lt;/ol&amp;gt;&amp;quot;);

	if (attachmentsFound)
		AttachmentsLiteral.Text = b.ToString();
	else
		AttachementsRow.Visible = false;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FindMessagePart()&lt;/code&gt; scans all the &lt;code&gt;MessagePart&lt;/code&gt; objects to find the one whose &lt;code&gt;content-type&lt;/code&gt; matches the &lt;code&gt;contentType&lt;/code&gt; argument.&lt;/p&gt;

&lt;pre&gt;
protected MessagePart FindMessagePart(List&amp;lt;MessagePart&amp;gt; msgParts,
	string contentType)
{
	foreach (MessagePart p in msgParts)
		if (p.ContentType != null &amp;amp;&amp;amp;
				p.ContentType.IndexOf(contentType) != -1)
			return p;

	return null;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FormatUrls()&lt;/code&gt; formats URL strings for display on the page.&lt;/p&gt;

&lt;pre&gt;
protected string FormatUrls(string plainText)
{
	string replacementLink = &amp;quot;&amp;lt;a href=\&amp;quot;${url}\&amp;quot;&amp;gt;${url}&amp;lt;/a&amp;gt;&amp;quot;;

	return UrlRegex.Replace(plainText, replacementLink);
}&lt;/pre&gt;

&lt;p&gt;Now that we have looked at the code, we will run this ASP.NET page.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Running DisplayPop3Email.aspx&lt;/b&gt;&lt;br /&gt;
I placed &lt;code&gt;Pop3.cs&lt;/code&gt; in the &lt;code&gt;/App_Code&lt;/code&gt; folder, &lt;code&gt;Pop3Client.aspx&lt;/code&gt; and &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; in the root folder (&lt;code&gt;/&lt;/code&gt;). Then I started the ASP.NET web server and accessed &lt;code&gt;Pop3Client.aspx&lt;/code&gt; in the browser. From the emails' list that appeared, I clicked one email's subject and this brought me to the &lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt; ASP.NET page that we just created. Following screen shot shows the result of this request:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-listing-emails.gif" width="600" height="235" border="0" alt="Listing emails" /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
In this tutorial, we created an ASP.NET page that takes an email's sort number on the POP3 server and connects to, retrieves, and displays that email on the page. This ASP.NET page was the missing page that was left in the previous tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009070801&amp;page=1"&gt;Connecting to Mailbox on Gmail and Fetching List of Emails using POP3 and ASP.NET&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I hope you can expand and modify the source code of this application to suit the needs of your application or if you are a beginner, learn the network programming aspects of it.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=XXDt3_os0mA:p5a1Nz9GIZU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=XXDt3_os0mA:p5a1Nz9GIZU:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/XXDt3_os0mA" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009071001&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Fri, 10 Jul 2009 05:52:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009071001&amp;page=1</feedburner:origLink></item>
<item>
<title>Connecting to Mailbox on Gmail and Fetching List of Emails using POP3 and ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/ZHb7g3uF9Sk/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will learn about &lt;em&gt;Post Office Protocol (POP3)&lt;/em&gt;. It is a protocol (a set of commands) used by an email client to connect to and retrieve email(s) from the mailbox on the remote server. We will develop the code that connects to the POP3 server and sends commands to retrieve the list of emails on the server, and then later, using an ASP.NET page, displays the list to the user. &lt;em&gt;To demonstrate the code, we will be connecting to Gmail's POP3 server using SSL (Secure Sockets Layer)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To connect to your own POP3 mail server, you can either use the secure connection (SSL) if your mail server supports it or connect in unsecure mode. The code is simple to understand and by looking at it you will learn a lot about how network programming is done in the .NET environment.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; In this tutorial, we will limit ourselves to retrieving and displaying a list of emails from user's mailbox which the user can browse through using &amp;apos;Previous Page&amp;apos; and &amp;apos;Next Page&amp;apos; links. In the next tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009071001&amp;page=1"&gt;Displaying Emails from Mailbox on Gmail using POP3 and ASP.NET&lt;/a&gt;), we will learn how to retrieve and view an individual email.&lt;/div&gt;

&lt;p&gt;Following screen shot shows an ASP.NET page listing emails in my Gmail mailbox:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-listing-emails.gif" width="600" height="235" border="0" alt="Connecting to mailbox on Gmail using POP3 and displaying list of emails" /&gt;
&lt;/div&gt;

&lt;div style="font-family: 'Georgia'; font-size: 10pt; padding: 1em; margin-top: 20px; border: dotted 1px #111"&gt;If you are looking for a production ready, stable, easy to use ASP.NET Newsletter application, then look no further: &lt;strong&gt;Faisal Khan (the author of this tutorial) has created a great &lt;a href="http://www.stardeveloper.com/newsletter/"&gt;Newsletter Application&lt;/a&gt; for you to download and start using today.&lt;/strong&gt; It is easy to install, lets your users subscribe using a subscription form, provides a simple administration interface to create and send newsletters, handles the task of sending newsletters in the background using thread queues on the server, and lets users unsubscribe if they wish so.&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Basic POP3 Commands&lt;/b&gt;&lt;br /&gt;
Following is a list of commonly used POP3 commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;USER&lt;/code&gt; - Takes one argument i.e., the email address of the user trying to connect to his/her mailbox. Example usage:
&lt;pre&gt;
USER youremail@xyz.com&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PASS&lt;/code&gt; - Takes one argument i.e., the password of the user. Example usage:
&lt;pre&gt;
PASS yourpassword&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STAT&lt;/code&gt; - Returns the number of emails in the mailbox and the number of bytes all the emails are taking on the server. Example usage:
&lt;pre&gt;
STAT&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TOP&lt;/code&gt; - Takes two arguments i.e., the sort number of the email on the server and the number of lines of text to retrieve from the body of the email. Example usage:
&lt;pre&gt;
TOP 1 10&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RETR&lt;/code&gt; - Takes one argument i.e., the sort number of the email on the server and returns all the headers and lines from the body of the email. Example usage:
&lt;pre&gt;
RETR 1&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELE&lt;/code&gt; - Takes one argument i.e., the sort number of the email on the server and deletes it. Example usage:
&lt;pre&gt;
DELE 1&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RSET&lt;/code&gt; - Resets any &lt;code&gt;DELE&lt;/code&gt; commands given above. The emails marked to be deleted by &lt;code&gt;DELE&lt;/code&gt; command are unmarked. Example usage:
&lt;pre&gt;
RSET&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QUIT&lt;/code&gt; - Closes the user session with the server. Example usage:
&lt;pre&gt;
QUIT&lt;/pre&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; In the code that we will develop, we will not close the session with the remote server using &lt;code&gt;QUIT&lt;/code&gt; command. Because if we have issued &lt;code&gt;RETR&lt;/code&gt; command to retrieve any emails from the POP3 server, issuing &lt;code&gt;QUIT&lt;/code&gt; commands gives the wrong impression to the server that those emails have been downloaded safely on our system so the server can remove them from its list. Since we do not want to inadvertently remove or delete any emails from the POP3 server, we will not issue &lt;code&gt;QUIT&lt;/code&gt; command and simply close the connection.&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Developing the Code&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will develop C# classes that encapsulate all the code that is necessary to connect to and retrieve emails from Gmail's mailbox. We will place these classes in &amp;quot;&lt;code&gt;Pop3.cs&lt;/code&gt;&amp;quot; C# source file. These classes will provide an easy to use interface to access the mailbox. An ASP.NET page with the name of &amp;quot;&lt;code&gt;Pop3Client.aspx&lt;/code&gt;&amp;quot; will use these classes to list emails in the mailbox.&lt;/p&gt;

&lt;p&gt;Files that we will develop in this tutorial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Pop3.cs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pop3Client.aspx&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;b&gt;i. Pop3.cs&lt;/b&gt;&lt;br /&gt;
All right guys, open Notepad and copy following code in it. Then save this new document as &lt;code&gt;Pop3.cs&lt;/code&gt; in the &lt;code&gt;/App_Code&lt;/code&gt; folder of your ASP.NET web application:&lt;/p&gt;

&lt;pre&gt;
/* Author: Faisal Khan */
/* &amp;copy; Stardeveloper.com */

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

namespace Stardeveloper.Pop3
{
  public class Pop3Client : IDisposable
  {
    public string Host { get; protected set; }
    public int Port { get; protected set; }
    public string Email { get; protected set; }
    public string Password { get; protected set; }
    public bool IsSecure { get; protected set; }

    public TcpClient Client { get; protected set; }
    public Stream ClientStream { get; protected set; }

    public StreamWriter Writer { get; protected set; }
    public StreamReader Reader { get; protected set; }

    private bool disposed = false;

    public Pop3Client(string host, int port, string email,
      string password)
      : this(host, port, email, password, false)
    {
    }

    public Pop3Client(string host, int port, string email,
      string password, bool secure)
    {
      Host = host;
      Port = port;
      Email = email;
      Password = password;
      IsSecure = secure;
    }

    public void Connect()
    {
      if (Client == null)
        Client = new TcpClient();

      if (!Client.Connected)
        Client.Connect(Host, Port);

      if (IsSecure)
      {
        SslStream secureStream =
          new SslStream(Client.GetStream());
        secureStream.AuthenticateAsClient(Host);

        ClientStream = secureStream;
        secureStream = null;
      }
      else
        ClientStream = Client.GetStream();

      Writer = new StreamWriter(ClientStream);
      Reader = new StreamReader(ClientStream);

      ReadLine();
      Login();
    }

    public int GetEmailCount()
    {
      int count = 0;
      string response = SendCommand(&amp;quot;STAT&amp;quot;);

      if (IsResponseOk(response))
      {
        string[] arr = response.Substring(4).Split(&amp;apos; &amp;apos;);
        count = Convert.ToInt32(arr[0]);
      }
      else
        count = -1;

      return count;
    }

    public Email FetchEmail(int emailId)
    {
      if (IsResponseOk(SendCommand(&amp;quot;TOP &amp;quot; + emailId + &amp;quot; 0&amp;quot;)))
        return new Email(ReadLines());
      else
        return null;
    }

    public List&amp;lt;Email&amp;gt; FetchEmailList(int start, int count)
    {
      List&amp;lt;Email&amp;gt; emails = new List&amp;lt;Email&amp;gt;(count);

      for (int i = start; i &amp;lt; (start + count); i++)
      {
        Email email = FetchEmail(i);

        if (email != null)
          emails.Add(email);
      }

      return emails;
    }

    public List&amp;lt;MessagePart&amp;gt; FetchMessageParts(int emailId)
    {
      if (IsResponseOk(SendCommand(&amp;quot;RETR &amp;quot; + emailId)))
        return Util.ParseMessageParts(ReadLines());

      return null;
    }&lt;/pre&gt;

&lt;p&gt;The code continues on the next page.&lt;/p&gt;&lt;p&gt;The code is continuing from the previous page.&lt;/p&gt;

&lt;pre&gt;
public List&amp;lt;MessagePart&amp;gt; FetchMessageParts(int emailId)
    {
      if (IsResponseOk(SendCommand(&amp;quot;RETR &amp;quot; + emailId)))
        return Util.ParseMessageParts(ReadLines());

      return null;
    }

    public void Close()
    {
      if (Client != null)
      {
        if (Client.Connected)
          Logout();

        Client.Close();
        Client = null;
      }

      if (ClientStream != null)
      {
        ClientStream.Close();
        ClientStream = null;
      }

      if (Writer != null)
      {
        Writer.Close();
        Writer = null;
      }

      if (Reader != null)
      {
        Reader.Close();
        Reader = null;
      }

      disposed = true;
    }

    public void Dispose()
    {
      if (!disposed)
        Close();
    }

    protected void Login()
    {
      if (!IsResponseOk(SendCommand(&amp;quot;USER &amp;quot; + Email)) ||
        !IsResponseOk(SendCommand(&amp;quot;PASS &amp;quot; + Password)))
        throw new Exception(&amp;quot;User/password not accepted&amp;quot;);
    }

    protected void Logout()
    {
      SendCommand(&amp;quot;RSET&amp;quot;);
      //SendCommand(&amp;quot;QUIT&amp;quot;);
    }

    protected string SendCommand(string cmdtext)
    {
      Writer.WriteLine(cmdtext);
      Writer.Flush();

      return ReadLine();
    }

    protected string ReadLine()
    {
      return Reader.ReadLine() + &amp;quot;\r\n&amp;quot;;
    }

    protected string ReadLines()
    {
      StringBuilder b = new StringBuilder();

      while (true)
      {
        string temp = ReadLine();

        if (temp == &amp;quot;.\r\n&amp;quot; || temp.IndexOf(&amp;quot;-ERR&amp;quot;) != -1)
          break;

        b.Append(temp);
      }

      return b.ToString();
    }

    protected static bool IsResponseOk(string response)
    {
      if (response.StartsWith(&amp;quot;+OK&amp;quot;))
        return true;
      if (response.StartsWith(&amp;quot;-ERR&amp;quot;))
        return false;

      throw new Exception(&amp;quot;Cannot understand server response: &amp;quot; +
        response);
    }
  }

  public class Email
  {
    public NameValueCollection Headers { get; protected set; }

    public string ContentType { get; protected set; }
    public DateTime UtcDateTime { get; protected set; }
    public string From { get; protected set; }
    public string To { get; protected set; }
    public string Subject { get; protected set; }

    public Email(string emailText)
    {
      Headers = Util.ParseHeaders(emailText);

      ContentType = Headers[&amp;quot;Content-Type&amp;quot;];
      From = Headers[&amp;quot;From&amp;quot;];
      To = Headers[&amp;quot;To&amp;quot;];
      Subject = Headers[&amp;quot;Subject&amp;quot;];

      if (Headers[&amp;quot;Date&amp;quot;] != null)
        try
        {
        UtcDateTime =
          Util.ConvertStrToUtcDateTime(Headers[&amp;quot;Date&amp;quot;]);
        }
        catch (FormatException)
        {
          UtcDateTime = DateTime.MinValue;
        }
      else
        UtcDateTime = DateTime.MinValue;
    }
  }

  public class MessagePart
  {
    public NameValueCollection Headers { get; protected set; }

    public string ContentType { get; protected set; }
    public string MessageText { get; protected set; }

    public MessagePart(NameValueCollection headers, string messageText)
    {
      Headers = headers;
      ContentType = Headers[&amp;quot;Content-Type&amp;quot;];
      MessageText = messageText;
    }
  }

  public class Util
  {
    protected static Regex BoundaryRegex =
      new Regex(&amp;quot;Content-Type: multipart(?:/\\S+;)&amp;quot; +
      &amp;quot;\\s+[^\r\n]*boundary=\&amp;quot;?(?&amp;lt;boundary&amp;gt;&amp;quot; +
      &amp;quot;[^\&amp;quot;\r\n]+)\&amp;quot;?\r\n&amp;quot;, RegexOptions.IgnoreCase |
      RegexOptions.Compiled);
    protected static Regex UtcDateTimeRegex = new Regex(
      @&amp;quot;^(?:\w+,\s+)?(?&amp;lt;day&amp;gt;\d+)\s+(?&amp;lt;month&amp;gt;\w+)\s+(?&amp;lt;year&amp;gt;\d+)\s+(?&amp;lt;hour&amp;gt;\d{1,2})&amp;quot; +
      @&amp;quot;:(?&amp;lt;minute&amp;gt;\d{1,2}):(?&amp;lt;second&amp;gt;\d{1,2})\s+(?&amp;lt;offsetsign&amp;gt;\-|\+)(?&amp;lt;offsethours&amp;gt;&amp;quot; +
      @&amp;quot;\d{2,2})(?&amp;lt;offsetminutes&amp;gt;\d{2,2})(?:.*)$&amp;quot;,
      RegexOptions.IgnoreCase | RegexOptions.Compiled);

    public static NameValueCollection ParseHeaders(string headerText)
    {
      NameValueCollection headers = new NameValueCollection();
      StringReader reader = new StringReader(headerText);

      string line;
      string headerName = null, headerValue;
      int colonIndx;

      while ((line = reader.ReadLine()) != null)
      {
        if (line == &amp;quot;&amp;quot;)
          break;

        if (Char.IsLetterOrDigit(line[0]) &amp;amp;&amp;amp; (colonIndx = line.IndexOf(&amp;apos;:&amp;apos;)) != -1)
        {
          headerName = line.Substring(0, colonIndx);
          headerValue = line.Substring(colonIndx + 1).Trim();

          headers.Add(headerName, headerValue);
        }
        else if (headerName != null)
          headers[headerName] += &amp;quot; &amp;quot; + line.Trim();
        else
          throw new FormatException(&amp;quot;Could not parse headers&amp;quot;);
      }

      return headers;
    }

    public static List&amp;lt;MessagePart&amp;gt; ParseMessageParts(string emailText)
    {
      List&amp;lt;MessagePart&amp;gt; messageParts = new List&amp;lt;MessagePart&amp;gt;();
      int newLinesIndx = emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

      Match m = BoundaryRegex.Match(emailText);

      if (m.Index &amp;lt; emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;) &amp;amp;&amp;amp; m.Success)
      {
        string boundary = m.Groups[&amp;quot;boundary&amp;quot;].Value;
        string startingBoundary = &amp;quot;\r\n--&amp;quot; + boundary;

        int startingBoundaryIndx = -1;

        while (true)
        {
          if (startingBoundaryIndx == -1)
            startingBoundaryIndx = emailText.IndexOf(startingBoundary);

          if (startingBoundaryIndx != -1)
          {
            int nextBoundaryIndx = emailText.IndexOf(startingBoundary,
              startingBoundaryIndx + startingBoundary.Length);

            if (nextBoundaryIndx != -1 &amp;amp;&amp;amp; nextBoundaryIndx != startingBoundaryIndx)
            {
              string multipartMsg = emailText.Substring(startingBoundaryIndx +
                startingBoundary.Length,
                (nextBoundaryIndx - startingBoundaryIndx - startingBoundary.Length));

              int headersIndx = multipartMsg.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

              if (headersIndx == -1)
                throw new FormatException(&amp;quot;Incompatible multipart message format&amp;quot;);

              string bodyText = multipartMsg.Substring(headersIndx).Trim();

              NameValueCollection headers = Util.ParseHeaders(multipartMsg.Trim());
              messageParts.Add(new MessagePart(headers, bodyText));
            }
            else
              break;

            startingBoundaryIndx = nextBoundaryIndx;
          }
          else
            break;
        }

        if (newLinesIndx != -1)
        {
          string emailBodyText = emailText.Substring(newLinesIndx + 1);
        }
      }
      else
      {
        int headersIndx = emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

        if (headersIndx == -1)
          throw new FormatException(&amp;quot;Incompatible multipart message format&amp;quot;);

        string bodyText = emailText.Substring(headersIndx).Trim();

        NameValueCollection headers = Util.ParseHeaders(emailText);
        messageParts.Add(new MessagePart(headers, bodyText));
      }

      return messageParts;
    }&lt;/pre&gt;

&lt;p&gt;The code continues on the next page.&lt;/p&gt;&lt;p&gt;The code is continuing from the previous page.&lt;/p&gt;

&lt;pre&gt;
public static DateTime ConvertStrToUtcDateTime(string str)
    {
      Match m = UtcDateTimeRegex.Match(str);

      int day, month, year, hour, min, sec;

      if (m.Success)
      {
        day = Convert.ToInt32(m.Groups[&amp;quot;day&amp;quot;].Value);
        year = Convert.ToInt32(m.Groups[&amp;quot;year&amp;quot;].Value);
        hour = Convert.ToInt32(m.Groups[&amp;quot;hour&amp;quot;].Value);
        min = Convert.ToInt32(m.Groups[&amp;quot;minute&amp;quot;].Value);
        sec = Convert.ToInt32(m.Groups[&amp;quot;second&amp;quot;].Value);

        switch (m.Groups[&amp;quot;month&amp;quot;].Value)
        {
          case &amp;quot;Jan&amp;quot;:
            month = 1;
            break;
          case &amp;quot;Feb&amp;quot;:
            month = 2;
            break;
          case &amp;quot;Mar&amp;quot;:
            month = 3;
            break;
          case &amp;quot;Apr&amp;quot;:
            month = 4;
            break;
          case &amp;quot;May&amp;quot;:
            month = 5;
            break;
          case &amp;quot;Jun&amp;quot;:
            month = 6;
            break;
          case &amp;quot;Jul&amp;quot;:
            month = 7;
            break;
          case &amp;quot;Aug&amp;quot;:
            month = 8;
            break;
          case &amp;quot;Sep&amp;quot;:
            month = 9;
            break;
          case &amp;quot;Oct&amp;quot;:
            month = 10;
            break;
          case &amp;quot;Nov&amp;quot;:
            month = 11;
            break;
          case &amp;quot;Dec&amp;quot;:
            month = 12;
            break;
          default:
            throw new FormatException(&amp;quot;Unknown month.&amp;quot;);
        }

        string offsetSign = m.Groups[&amp;quot;offsetsign&amp;quot;].Value;
        int offsetHours = Convert.ToInt32(m.Groups[&amp;quot;offsethours&amp;quot;].Value);
        int offsetMinutes = Convert.ToInt32(m.Groups[&amp;quot;offsetminutes&amp;quot;].Value);

        DateTime dt = new DateTime(year, month, day, hour, min, sec);

        if (offsetSign == &amp;quot;+&amp;quot;)
        {
          dt.AddHours(offsetHours);
          dt.AddMinutes(offsetMinutes);
        }
        else if (offsetSign == &amp;quot;-&amp;quot;)
        {
          dt.AddHours(-offsetHours);
          dt.AddMinutes(-offsetMinutes);
        }

        return dt;
      }

      throw new FormatException(&amp;quot;Incompatible date/time string format&amp;quot;);
    }
  }
}&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
&lt;code&gt;Pop3.cs&lt;/code&gt; defines &lt;code&gt;Stardeveloper.Pop3&lt;/code&gt; namespace, which contains following 4 classes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Pop3Client&lt;/code&gt; - This class uses classes in the &lt;code&gt;System.Net&lt;/code&gt; and sub-namespaces to connect with the Pop3 server and send commands. It retrieves the data, and uses the &lt;code&gt;Util&lt;/code&gt; class to create &lt;code&gt;Email&lt;/code&gt; and &lt;code&gt;MessagePart&lt;/code&gt; objects from the received data.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Email&lt;/code&gt; - It represents an Email message on the server. It provides you access to the &amp;quot;&lt;em&gt;From&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;To&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;Subject&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;Date&lt;/em&gt;&amp;quot; and &amp;quot;&lt;em&gt;Content-Type&lt;/em&gt;&amp;quot; headers. It does not let you access the body of the email. The body of the email is represented by an array of &lt;code&gt;MessagePart&lt;/code&gt; objects which are retrieved separately by calling &lt;code&gt;Pop3Client.FetchMessageParts()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MessagePart&lt;/code&gt; - It represents a part of the body of the email. Since most of the emails are MIME encoded, which means that there can be more than one type (text/plain, text/html, etc.) of message part, and that there can be attached files, we represent the body of the email with an array of &lt;code&gt;MessagePart&lt;/code&gt; objects. This class lets you access the headers and body of a message part of the email. More on it, later.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Util&lt;/code&gt; - This class contains 3 &lt;code&gt;static&lt;/code&gt; methods to parse headers, message parts, and to convert UTC date/time string to &lt;code&gt;DateTime&lt;/code&gt; object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will now look at the code of each of these classes in detail.&lt;/p&gt;

&lt;p&gt;The first thing we do is to import the necessary namespaces.&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;Pop3Client&lt;/code&gt; class implements &lt;code&gt;IDisposable&lt;/code&gt; interface.&lt;/p&gt;

&lt;pre&gt;
public class Pop3Client : IDisposable
{
	...
}&lt;/pre&gt;

&lt;p&gt;Following properties provide access to the variables we set in the constructor of &lt;code&gt;Pop3Client&lt;/code&gt; class.&lt;/p&gt;

&lt;pre&gt;
public string Host { get; protected set; }
public int Port { get; protected set; }
public string Email { get; protected set; }
public string Password { get; protected set; }
public bool IsSecure { get; protected set; }&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;TcpClient&lt;/code&gt; object that is used internally by &lt;code&gt;Pop3Client&lt;/code&gt; class is exposed using &lt;code&gt;Client&lt;/code&gt; property. The &lt;code&gt;ClientStream&lt;/code&gt; property is either of the &lt;code&gt;SslStream&lt;/code&gt; type if SSL is used to connect to the Pop3 server, or it is of &lt;code&gt;NetworkStream&lt;/code&gt; type if the connection is unsecure.&lt;/p&gt;

&lt;pre&gt;
public TcpClient Client { get; protected set; }
public Stream ClientStream { get; protected set; } // SslStream or NetworkStream&lt;/pre&gt;

&lt;p&gt;Since &lt;em&gt;all POP3 commands sent by the client and responses received from the server end in the new-line characters (&amp;quot;\r\n&amp;quot;)&lt;/em&gt;, we use &lt;code&gt;StreamWriter&lt;/code&gt; and &lt;code&gt;StreamReader&lt;/code&gt; classes to simplify the job of sending and receiving the data for us. You will see plenty of calls to their &lt;code&gt;WriteLine()&lt;/code&gt; and &lt;code&gt;ReadLine()&lt;/code&gt; methods, respectively, later.&lt;/p&gt;

&lt;pre&gt;
public StreamWriter Writer { get; protected set; }
public StreamReader Reader { get; protected set; }&lt;/pre&gt;

&lt;p&gt;Lastly, a &lt;code&gt;private&lt;/code&gt; variable is used to set the disposed state for this object. Remember, &lt;code&gt;Pop3Client&lt;/code&gt; class implements &lt;code&gt;IDisposable&lt;/code&gt; interface to make it easy for you to wrap access to this class in a &lt;code&gt;using&lt;/code&gt; statement.&lt;/p&gt;

&lt;pre&gt;
private bool disposed = false;&lt;/pre&gt;

&lt;p&gt;The constructor of &lt;code&gt;Pop3Client&lt;/code&gt; class takes as its arguments the name of the host you want to connect to e.g. &amp;quot;pop.gmail.com&amp;quot;, the port of the server you want to connect to e.g., 995 for Gmail, email address and password of your account on that Pop3 server. By default, the constructor will create an unsecure connection to the server. To use SSL to connect to the server, you have to set the final and optional argument to the constructor to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;
public Pop3Client(string host, int port, string email, string password)
	: this(host, port, email, password, false)
{
}

public Pop3Client(string host, int port, string email,
	string password, bool secure)
{
	Host = host;
	Port = port;
	Email = email;
	Password = password;
	IsSecure = secure;
}&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;Connect()&lt;/code&gt; method instantiates necessary objects and connects to the POP3 server on the given host and port. If it was specified in the constructor to open a secure connection to the POP3 server, a &lt;code&gt;SslStream&lt;/code&gt; object is created which encapsulates the &lt;code&gt;NetworkStream&lt;/code&gt; returned from the &lt;code&gt;TcpClient.GetStream()&lt;/code&gt; method. Lastly, &lt;code&gt;StreamWriter&lt;/code&gt; and &lt;code&gt;StreamReader&lt;/code&gt; objects are instantiated, and &lt;code&gt;Login()&lt;/code&gt; method is called.&lt;/p&gt;

&lt;pre&gt;
public void Connect()
{
	if (Client == null)
		Client = new TcpClient();

	if (!Client.Connected)
		Client.Connect(Host, Port);

	if (IsSecure)
	{
		SslStream secureStream =
			new SslStream(Client.GetStream());
		secureStream.AuthenticateAsClient(Host);

		ClientStream = secureStream;
		secureStream = null;
	}
	else
		ClientStream = Client.GetStream();

	Writer = new StreamWriter(ClientStream);
	Reader = new StreamReader(ClientStream);

	ReadLine();
	Login();
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;Login()&lt;/code&gt; method sends the user email and password to the server. Each call to send the command with required argument is sent using &lt;code&gt;SendCommand()&lt;/code&gt; method, which internally uses &lt;code&gt;StreamWriter.WriteLine()&lt;/code&gt; method to send the command. The response of the server is parsed using &lt;code&gt;IsResponseOk()&lt;/code&gt; method to determine if the response was successfull i.e., it began with an &amp;quot;+OK&amp;quot; message or if it was an error i.e., it began with an &amp;quot;-ERR&amp;quot; message. If everything went fine, the method simply returns, otherwise an &lt;code&gt;Exception&lt;/code&gt; is thrown.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; All responses received from the server start with either &amp;quot;+OK&amp;quot;, if +ve response has been generated on the server, or with &amp;quot;-ERR&amp;quot;, if an error occurred.&lt;/div&gt;

&lt;pre&gt;
protected void Login()
{
	if (!IsResponseOk(SendCommand(&amp;quot;USER &amp;quot; + Email)) ||
		!IsResponseOk(SendCommand(&amp;quot;PASS &amp;quot; + Password)))
		throw new Exception(&amp;quot;User/password not accepted&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;As explained above, the &lt;code&gt;SendCommand()&lt;/code&gt; method uses &lt;code&gt;StreamWriter.WriteLine()&lt;/code&gt; to send the command to the server. We use &lt;code&gt;WriteLine()&lt;/code&gt; and not &lt;code&gt;Write()&lt;/code&gt; because each command to the server must end with new-line characters i.e., &amp;quot;\r\n&amp;quot;. Since &lt;code&gt;StreamWriter&lt;/code&gt; internally buffers the data we want sent to the server, we call its &lt;code&gt;Flush()&lt;/code&gt; method to make it send the command immediately. The response that is received from the server is fetched using &lt;code&gt;StreamReader.ReadLine()&lt;/code&gt; method and is returned to the calling code.&lt;/p&gt;

&lt;pre&gt;
protected string SendCommand(string cmdtext)
{
	Writer.WriteLine(cmdtext);
	Writer.Flush();

	return ReadLine();
}&lt;/pre&gt;

&lt;p&gt;As explained above, the &lt;code&gt;IsResponseOk()&lt;/code&gt; method parses the response received from the server and checks for the &amp;quot;+OK&amp;quot; and &amp;quot;-ERR&amp;quot; strings to determine if the response was ok or if an error has been returned.&lt;/p&gt;

&lt;pre&gt;
protected static bool IsResponseOk(string response)
{
	if (response.StartsWith(&amp;quot;+OK&amp;quot;))
		return true;
	if (response.StartsWith(&amp;quot;-ERR&amp;quot;))
		return false;

	throw new Exception(&amp;quot;Cannot understand server response: &amp;quot; +
		response);
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;GetEmailCount()&lt;/code&gt; returns the number of emails in the mailbox. It uses &amp;quot;&lt;code&gt;STAT&lt;/code&gt;&amp;quot; POP3 command to retrieve the number of emails. As you can see in the code below, the response of the server is parsed and the word containing number of emails is taken and converted to an &lt;code&gt;integer&lt;/code&gt;, which is then returned to the calling code.&lt;/p&gt;

&lt;pre&gt;
public int GetEmailCount()
{
	int count = 0;
	string response = SendCommand(&amp;quot;STAT&amp;quot;);

	if (IsResponseOk(response))
	{
		string[] arr = response.Substring(4).Split(&amp;apos; &amp;apos;);
		count = Convert.ToInt32(arr[0]);
	}
	else
		count = -1;

	return count;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FetchEmail()&lt;/code&gt; takes the sort number of the email as its argument and retrieves the headers for that email using &amp;quot;TOP&amp;quot; POP3 command. This command takes two parameters, the sort no of email and the number of lines of the body of email you want to fetch. We give this command the sort no of the email to fetch and 0 (zero) as the number of lines of text to retrieve from the body of the email. We set the second parameter to 0 because we only want to retrieve headers. The headers returned are used to instantiate &lt;code&gt;Email&lt;/code&gt; object and that is then returned to the calling code.&lt;/p&gt;

&lt;pre&gt;
public Email FetchEmail(int emailId)
{
	if (IsResponseOk(SendCommand(&amp;quot;TOP &amp;quot; + emailId + &amp;quot; 0&amp;quot;)))
		return new Email(ReadLines());
	else
		return null;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FetchEmailList()&lt;/code&gt; fetches the email headers, using &lt;code&gt;FetchEmail()&lt;/code&gt; method, of given number of emails starting from given sort number. For instance, you have 300 emails in your mailbox and want to now display a list of 10 emails from 150 to 160, you should call this method as: &lt;code&gt;FetchEmailList(151, 10)&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;
 public List&amp;lt;Email&amp;gt; FetchEmailList(int start, int count)
{
	List&amp;lt;Email&amp;gt; emails = new List&amp;lt;Email&amp;gt;(count);

	for (int i = start; i &amp;lt; (start + count); i++)
	{
		Email email = FetchEmail(i);

		if (email != null)
			emails.Add(email);
	}

	return emails;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;FetchMessageParts()&lt;/code&gt; retrieves an email from the server and then parses its body into an array of &lt;code&gt;MessagePart&lt;/code&gt; objects. Each &lt;code&gt;MessagePart&lt;/code&gt; object encapsulates one part of the body of the email and any attached files.&lt;/p&gt;

&lt;pre&gt;
public List&amp;lt;MessagePart&amp;gt; FetchMessageParts(int emailId)
{
	if (IsResponseOk(SendCommand(&amp;quot;RETR &amp;quot; + emailId)))
		return Util.ParseMessageParts(ReadLines());

	return null;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Close()&lt;/code&gt; logs out the user, closes the connection, and properly disposes all the &lt;code&gt;Stream&lt;/code&gt; objects in use.&lt;/p&gt;

&lt;pre&gt;
public void Close()
{
	if (Client != null)
	{
		if (Client.Connected)
			Logout();

		Client.Close();
		Client = null;
	}

	if (ClientStream != null)
	{
		ClientStream.Close();
		ClientStream = null;
	}

	if (Writer != null)
	{
		Writer.Close();
		Writer = null;
	}

	if (Reader != null)
	{
		Reader.Close();
		Reader = null;
	}

	disposed = true;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Dispose()&lt;/code&gt; method is implemented as part of the implementation of &lt;code&gt;IDisposable&lt;/code&gt; interface. It calls the &lt;code&gt;Close()&lt;/code&gt; method above if not already called.&lt;/p&gt;

&lt;pre&gt;
public void Dispose()
{
	if (!disposed)
		Close();
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Logout()&lt;/code&gt; method does nothing but to send the &amp;quot;&lt;code&gt;RSET&lt;/code&gt;&amp;quot; command to the server which resets the server meaning there by that if any emails were marked as deleted, they are unmarked. Although no part in our code marks the emails to be deleted, we call it anyway.&lt;/p&gt;

&lt;pre&gt;
protected void Logout()
{
	SendCommand(&amp;quot;RSET&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;We will now look at the code that constitutes the &lt;code&gt;Email&lt;/code&gt; class.&lt;/p&gt;

&lt;pre&gt;
public class Email
{
	...
}&lt;/pre&gt;

&lt;p&gt;An &lt;code&gt;Email&lt;/code&gt; object represents an email on the server minus its body. It contains all the headers contained in an email. It provides access to the headers' collection using &lt;code&gt;Headers&lt;/code&gt; property. Commonly used headers like &amp;quot;&lt;em&gt;From&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;To&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;Subject&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;Date&lt;/em&gt;&amp;quot;, &amp;quot;&lt;em&gt;Content-Type&lt;/em&gt;&amp;quot; can be accessed using properites like &lt;code&gt;From&lt;/code&gt;, &lt;code&gt;To&lt;/code&gt;, &lt;code&gt;Subject&lt;/code&gt;, &lt;code&gt;UtcDateTime&lt;/code&gt;, and &lt;code&gt;ContentType&lt;/code&gt;, respectively.&lt;/p&gt;&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; The purpose of properties mentioned above is only to provide easy access to header fields. For practical purposes code like &lt;code&gt;Email.Headers["From"]&lt;/code&gt; and &lt;code&gt;Email.From&lt;/code&gt; will yield the same value. And if any of these headers is not found in the email, the property will return &lt;code&gt;null&lt;/code&gt;.&lt;/div&gt;

&lt;pre&gt;
public NameValueCollection Headers { get; protected set; }

public string ContentType { get; protected set; }
public DateTime UtcDateTime { get; protected set; }
public string From { get; protected set; }
public string To { get; protected set; }
public string Subject { get; protected set; }&lt;/pre&gt;

&lt;p&gt;Within the constructor of &lt;code&gt;Email&lt;/code&gt; class, we retrieve header fields as &lt;code&gt; a NameValueCollection&lt;/code&gt; object using &lt;code&gt;Util.ParseHeaders()&lt;/code&gt; method. Once we have the collection, we set the properties to the values retrieved from the header fields.&lt;/p&gt;

&lt;p&gt;Unlike other properties, the property &lt;code&gt;Date&lt;/code&gt; is not of type &lt;code&gt;string&lt;/code&gt;. It is of type &lt;code&gt;DateTime&lt;/code&gt;. We parse the &lt;code&gt;Headers[&amp;quot;Date&amp;quot;]&lt;/code&gt; header string and convert it in to a &lt;code&gt;DateTime&lt;/code&gt; structure using &lt;code&gt;Util.ConvertStrToUtcDateTime()&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;
public Email(string emailText)
{
	Headers = Util.ParseHeaders(emailText);

	ContentType = Headers[&amp;quot;Content-Type&amp;quot;];
	From = Headers[&amp;quot;From&amp;quot;];
	To = Headers[&amp;quot;To&amp;quot;];
	Subject = Headers[&amp;quot;Subject&amp;quot;];

	if (Headers[&amp;quot;Date&amp;quot;] != null)
		try
		{
			UtcDateTime = Util.ConvertStrToUtcDateTime(Headers[&amp;quot;Date&amp;quot;]);
		}
		catch (FormatException)
		{
			UtcDateTime = DateTime.MinValue;
		}
	else
		UtcDateTime = DateTime.MinValue;
}&lt;/pre&gt;

&lt;p&gt;We will now look at the code of &lt;code&gt;MessagePart&lt;/code&gt; class.&lt;/p&gt;

&lt;pre&gt;
public class MessagePart
{
	...
}&lt;/pre&gt;

&lt;p&gt;A &lt;code&gt;MessagePart&lt;/code&gt; object represents just one component of the body of an email. Remember, that most emails are MIME compatible and have multiple parts that form the body of that email.&lt;/p&gt;

&lt;p&gt;For instance, you send an HTML email to a person. Just in case if the person is using an email client that cannot render HTML emails, either you or your email client also creates a plain text version of the email and appends it to the email. Now your email has two parts; one is of &lt;code&gt;text/html&lt;/code&gt; content-type and the other is of &lt;code&gt;text/plain&lt;/code&gt; content-type. The email client of the person you sent that email to will upon receiving that email try to find a plain text version of the email so that it can display that to the person without any difficulty. On searching through the MIME compatible email's message parts, it finds a version of &lt;code&gt;text/plain&lt;/code&gt; content-type. It parses and decodes (if needed) it and displays it to that person.&lt;/p&gt;

&lt;p&gt;Now if you had attached 2 files with that email, the total message parts would have become four:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;HTML version of the email - &lt;code&gt;text/html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Plain text version of the email - &lt;code&gt;text/plain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Attached File #1 - &lt;code&gt;base64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Attached File #2 - &lt;code&gt;base64&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now upon parsing this email using the code above, you'll have an array of four &lt;code&gt;MessagePart&lt;/code&gt; objects. I hope you understand now what &lt;code&gt;MessagePart&lt;/code&gt; represents.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; &lt;em&gt;&lt;code&gt;base64&lt;/code&gt; is a content-transfer-encoding for sending binary data like images files, in a text based email message.&lt;/em&gt;&lt;/div&gt;

&lt;p&gt;It has a &lt;code&gt;Headers&lt;/code&gt; property that makes available all the headers that this message part contains. The &lt;code&gt;ContentType&lt;/code&gt; property is there to easily access the &lt;code&gt;Headers[&amp;quot;Content-Type&amp;quot;]&lt;/code&gt; field. The &lt;code&gt;MessageText&lt;/code&gt; property makes available the content of the body of this message part.&lt;/p&gt;

&lt;pre&gt;
public NameValueCollection Headers { get; protected set; }

public string ContentType { get; protected set; }
public string MessageText { get; protected set; }&lt;/pre&gt;

&lt;p&gt;In the constructor, we set the properties.&lt;/p&gt;

&lt;pre&gt;
public MessagePart(NameValueCollection headers, string messageText)
{
	Headers = headers;
	ContentType = Headers[&amp;quot;Content-Type&amp;quot;];
	MessageText = messageText;
}&lt;/pre&gt;

&lt;p&gt;We will now look at the code of &lt;code&gt;Util&lt;/code&gt; class, which contains 3 &lt;code&gt;static&lt;/code&gt; methods.&lt;/p&gt;

&lt;pre&gt;
public class Util
{
	...
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;ParseHeaders()&lt;/code&gt; parses all the headers and converts them into easily accessible &lt;code&gt;NameValueCollection&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;
public static NameValueCollection ParseHeaders(string headerText)
{
	NameValueCollection headers = new NameValueCollection();
	StringReader reader = new StringReader(headerText);

	string line;
	string headerName = null, headerValue;
	int colonIndx;

	while ((line = reader.ReadLine()) != null)
	{
		if (line == &amp;quot;&amp;quot;)
			break;

		if (Char.IsLetterOrDigit(line[0]) &amp;amp;&amp;amp; (colonIndx = line.IndexOf(&amp;apos;:&amp;apos;)) != -1)
		{
			headerName = line.Substring(0, colonIndx);
			headerValue = line.Substring(colonIndx + 1).Trim();

			headers.Add(headerName, headerValue);
		}
		else if (headerName != null)
			headers[headerName] += &amp;quot; &amp;quot; + line.Trim();
		else
			throw new FormatException(&amp;quot;Could not parse headers&amp;quot;);
	}

	return headers;
}&lt;/pre&gt;&lt;p&gt;&lt;code&gt;ParseMessageParts()&lt;/code&gt; parses the body of an email and separates the body into separate message parts using the boundary header.&lt;/p&gt;

&lt;pre&gt;
public static List&amp;lt;MessagePart&amp;gt; ParseMessageParts(string emailText)
    {
      List&amp;lt;MessagePart&amp;gt; messageParts = new List&amp;lt;MessagePart&amp;gt;();
      int newLinesIndx = emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

      Match m = BoundaryRegex.Match(emailText);

      if (m.Index &amp;lt; emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;) &amp;amp;&amp;amp; m.Success)
      {
        string boundary = m.Groups[&amp;quot;boundary&amp;quot;].Value;
        string startingBoundary = &amp;quot;\r\n--&amp;quot; + boundary;

        int startingBoundaryIndx = -1;

        while (true)
        {
          if (startingBoundaryIndx == -1)
            startingBoundaryIndx = emailText.IndexOf(startingBoundary);

          if (startingBoundaryIndx != -1)
          {
            int nextBoundaryIndx = emailText.IndexOf(startingBoundary,
              startingBoundaryIndx + startingBoundary.Length);

            if (nextBoundaryIndx != -1 &amp;amp;&amp;amp; nextBoundaryIndx != startingBoundaryIndx)
            {
              string multipartMsg = emailText.Substring(startingBoundaryIndx +
                startingBoundary.Length,
                (nextBoundaryIndx - startingBoundaryIndx - startingBoundary.Length));

              int headersIndx = multipartMsg.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

              if (headersIndx == -1)
                throw new FormatException(&amp;quot;Incompatible multipart message format&amp;quot;);

              string bodyText = multipartMsg.Substring(headersIndx).Trim();

              NameValueCollection headers = Util.ParseHeaders(multipartMsg.Trim());
              messageParts.Add(new MessagePart(headers, bodyText));
            }
            else
              break;

            startingBoundaryIndx = nextBoundaryIndx;
          }
          else
            break;
        }

        if (newLinesIndx != -1)
        {
          string emailBodyText = emailText.Substring(newLinesIndx + 1);
        }
      }
      else
      {
        int headersIndx = emailText.IndexOf(&amp;quot;\r\n\r\n&amp;quot;);

        if (headersIndx == -1)
          throw new FormatException(&amp;quot;Incompatible multipart message format&amp;quot;);

        string bodyText = emailText.Substring(headersIndx).Trim();

        NameValueCollection headers = Util.ParseHeaders(emailText);
        messageParts.Add(new MessagePart(headers, bodyText));
      }

      return messageParts;
    }&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;ConvertStrToUtcDateTime()&lt;/code&gt; parses a date &amp;amp; time string and converts it into a &lt;code&gt;DateTime&lt;/code&gt; structure. It makes use of a regular expression to parse individual components from the date &amp;amp; time string.&lt;/p&gt;

&lt;pre&gt;
public static DateTime ConvertStrToUtcDateTime(string str)
{
	Match m = UtcDateTimeRegex.Match(str);

	int day, month, year, hour, min, sec;

	if (m.Success)
	{
		day = Convert.ToInt32(m.Groups[&amp;quot;day&amp;quot;].Value);
		year = Convert.ToInt32(m.Groups[&amp;quot;year&amp;quot;].Value);
		hour = Convert.ToInt32(m.Groups[&amp;quot;hour&amp;quot;].Value);
		min = Convert.ToInt32(m.Groups[&amp;quot;minute&amp;quot;].Value);
		sec = Convert.ToInt32(m.Groups[&amp;quot;second&amp;quot;].Value);

		switch (m.Groups[&amp;quot;month&amp;quot;].Value)
		{
			case &amp;quot;Jan&amp;quot;:
				month = 1;
				break;
			case &amp;quot;Feb&amp;quot;:
				month = 2;
				break;
			case &amp;quot;Mar&amp;quot;:
				month = 3;
				break;
			case &amp;quot;Apr&amp;quot;:
				month = 4;
				break;
			case &amp;quot;May&amp;quot;:
				month = 5;
				break;
			case &amp;quot;Jun&amp;quot;:
				month = 6;
				break;
			case &amp;quot;Jul&amp;quot;:
				month = 7;
				break;
			case &amp;quot;Aug&amp;quot;:
				month = 8;
				break;
			case &amp;quot;Sep&amp;quot;:
				month = 9;
				break;
			case &amp;quot;Oct&amp;quot;:
				month = 10;
				break;
			case &amp;quot;Nov&amp;quot;:
				month = 11;
				break;
			case &amp;quot;Dec&amp;quot;:
				month = 12;
				break;
			default:
				throw new FormatException(&amp;quot;Unknown month.&amp;quot;);
		}

		string offsetSign = m.Groups[&amp;quot;offsetsign&amp;quot;].Value;
		int offsetHours = Convert.ToInt32(m.Groups[&amp;quot;offsethours&amp;quot;].Value);
		int offsetMinutes = Convert.ToInt32(m.Groups[&amp;quot;offsetminutes&amp;quot;].Value);

		DateTime dt = new DateTime(year, month, day, hour, min, sec);

		if (offsetSign == &amp;quot;+&amp;quot;)
		{
			dt.AddHours(offsetHours);
			dt.AddMinutes(offsetMinutes);
		}
		else if (offsetSign == &amp;quot;-&amp;quot;)
		{
			dt.AddHours(-offsetHours);
			dt.AddMinutes(-offsetMinutes);
		}

		return dt;
	}

	throw new FormatException(&amp;quot;Incompatible date/time string format&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;Now that we have created the necessary classes, we will create the front-end ASP.NET page to display the list of emails to the user.&lt;/p&gt;&lt;p&gt;&lt;b&gt;ii. Pop3Client.aspx&lt;/b&gt;&lt;br /&gt;
Open Notepad and copy following text in it, and then save it as &amp;quot;Pop3Client.aspx&amp;quot; in your ASP.NET web application:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;

&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Pop3&amp;quot; %&amp;gt;

&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	public const string Host = &amp;quot;pop.gmail.com&amp;quot;;
	public const int Port = 995;
	public const string Email = &amp;quot;youremail@gmail.com&amp;quot;;
	public const string Password = &amp;quot;yourpassword&amp;quot;;

	public const int NoOfEmailsPerPage = 5;
	public const string SelfLink =
		&amp;quot;&amp;lt;a href=\&amp;quot;Pop3Client.aspx?page={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;
	public const string DisplayEmailLink =
		&amp;quot;&amp;lt;a href=\&amp;quot;DisplayPop3Email.aspx?emailId={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;

	protected void Page_Load(object source, EventArgs e)
	{
		/* Setting current page */
		int page = 1;

		if (Request.QueryString[&amp;quot;page&amp;quot;] == null)
		{
			Response.Redirect(&amp;quot;Pop3Client.aspx?page=1&amp;quot;);
			Response.Flush();
			Response.End();
		}
		else
			page = Convert.ToInt32(Request.QueryString[&amp;quot;page&amp;quot;]);

		/* Creating Pop3Client object and accessing email data */
		int totalEmails;
		List&amp;lt;Email&amp;gt; emails;
		string emailAddress;

		using(Pop3Client client = new Pop3Client(Host, Port, Email, Password, true))
		{
			emailAddress = client.Email;

			client.Connect();

			totalEmails = client.GetEmailCount();
			emails = client.FetchEmailList(((page - 1) *
				NoOfEmailsPerPage) + 1, NoOfEmailsPerPage);
		}

		/* Computing total pages */
		int totalPages;
		int mod = totalEmails % NoOfEmailsPerPage;

		if (mod == 0)
			totalPages = totalEmails / NoOfEmailsPerPage;
		else
			totalPages = ((totalEmails - mod) / NoOfEmailsPerPage) + 1;

		for (int i = 0; i &amp;lt; emails.Count; i++)
		{
			Email email = emails[i];

			/* Appending each email to an existing table */
			int emailId = ((page - 1) * NoOfEmailsPerPage) + i + 1;

			TableCell noCell = new TableCell();
			noCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
			noCell.Text = Convert.ToString(emailId);
			
			TableCell fromCell = new TableCell();
			fromCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
			fromCell.Text = email.From;
			
			TableCell subjectCell = new TableCell();
			subjectCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
			subjectCell.Style[&amp;quot;width&amp;quot;] = &amp;quot;300px&amp;quot;;
			subjectCell.Text = String.Format(DisplayEmailLink,
				emailId, email.Subject);

			//TableCell contentTypeCell = new TableCell();
			//contentTypeCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
			//contentTypeCell.Text = email.ContentType;
			
			TableCell dateCell = new TableCell();
			dateCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
			
			if (email.UtcDateTime != DateTime.MinValue)
				dateCell.Text = email.UtcDateTime.ToString();

			TableRow emailRow = new TableRow();
			emailRow.Cells.Add(noCell);
			emailRow.Cells.Add(fromCell);
			emailRow.Cells.Add(subjectCell);
			//emailRow.Cells.Add(contentTypeCell);
			emailRow.Cells.Add(dateCell);

			EmailsTable.Rows.AddAt(2 + i, emailRow);
		}

		/* Creating links to previous and next pages */
		if (totalPages &amp;gt; 1)
		{
			if (page &amp;gt; 1)
				PreviousPageLiteral.Text =
					String.Format(SelfLink, page - 1, &amp;quot;Previous Page&amp;quot;);

			if (page &amp;gt; 0 &amp;amp;&amp;amp; page &amp;lt; totalPages)
				NextPageLiteral.Text =
					String.Format(SelfLink, page + 1, &amp;quot;Next Page&amp;quot;);
		}

		/* Displaying information to the user */
		EmailFromLiteral.Text =
			Convert.ToString(((page - 1) * NoOfEmailsPerPage) + 1);
		EmailToLiteral.Text = Convert.ToString(page * NoOfEmailsPerPage);
		EmailTotalLiteral.Text = Convert.ToString(totalEmails);
		EmailLiteral.Text = emailAddress;
	}
&amp;lt;/script&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;
		.emails-table { width: 600px; border: solid 1px #444444; }
		.emails-table-header { font-family: &amp;quot;Trebuchet MS&amp;quot;; font-size: 9pt;
			background-color: #0099B9; color: white;
			border: solid 1px #444444; }
		.emails-table-header-cell { font-family: &amp;quot;Georgia&amp;quot;; font-size: 9pt;
			font-weight: bold; border: solid 1px #666666; padding: 6px; }
		.emails-table-cell { font-family: &amp;quot;Georgia&amp;quot;; font-size: 9pt;
			border: solid 1px #666666; padding: 6px; }
		.emails-table-footer { border: solid 1px #666666; padding: 3px;
			width: 50%; }
		.email-datetime { float: right; color: #666666; }
		
		a { font-family: &amp;quot;Lucida Sans Unicode&amp;quot;, &amp;quot;Trebuchet MS&amp;quot;; font-size: 9pt;
			color: #005B7F; }
		a:hover { color:red; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;div&amp;gt;
		&amp;lt;asp:Table ID=&amp;quot;EmailsTable&amp;quot; CssClass=&amp;quot;emails-table&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
		&amp;lt;asp:TableHeaderRow&amp;gt;
			&amp;lt;asp:TableHeaderCell CssClass=&amp;quot;emails-table-header&amp;quot;
				ColumnSpan=&amp;quot;4&amp;quot;&amp;gt;Listing emails 
			&amp;lt;asp:Literal ID=&amp;quot;EmailFromLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;-
			&amp;lt;asp:Literal ID=&amp;quot;EmailToLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; of 
			&amp;lt;asp:Literal ID=&amp;quot;EmailTotalLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; for 
			&amp;lt;asp:Literal ID=&amp;quot;EmailLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;
			&amp;lt;/asp:TableHeaderCell&amp;gt;
		&amp;lt;/asp:TableHeaderRow&amp;gt;
		&amp;lt;asp:TableRow&amp;gt;
			&amp;lt;asp:TableCell CssClass=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;
				#&amp;lt;/asp:TableCell&amp;gt;
			&amp;lt;asp:TableCell CssClass=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;
				From&amp;lt;/asp:TableCell&amp;gt;
			&amp;lt;asp:TableCell CssClass=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;
				Subject&amp;lt;/asp:TableCell&amp;gt;
			&amp;lt;asp:TableCell CssClass=&amp;quot;emails-table-header-cell&amp;quot;&amp;gt;
				Date &amp;amp;amp; Time&amp;lt;/asp:TableCell&amp;gt;
		&amp;lt;/asp:TableRow&amp;gt;
		&amp;lt;asp:TableFooterRow&amp;gt;
			&amp;lt;asp:TableCell CssClass=&amp;quot;emails-table-footer&amp;quot; ColumnSpan=&amp;quot;4&amp;quot;&amp;gt;
			&amp;lt;asp:Table ID=&amp;quot;FooterTable&amp;quot; Width=&amp;quot;100%&amp;quot;
				BorderWidth=&amp;quot;0&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
			&amp;lt;asp:TableRow&amp;gt;
			&amp;lt;asp:TableCell&amp;gt;
				&amp;lt;asp:Literal ID=&amp;quot;PreviousPageLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;
			&amp;lt;/asp:TableCell&amp;gt;
			&amp;lt;asp:TableCell HorizontalAlign=&amp;quot;Right&amp;quot;&amp;gt;
				&amp;lt;asp:Literal ID=&amp;quot;NextPageLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;
			&amp;lt;/asp:TableCell&amp;gt;
			&amp;lt;/asp:TableRow&amp;gt;
			&amp;lt;/asp:Table&amp;gt;
			&amp;lt;/asp:TableCell&amp;gt;
		&amp;lt;/asp:TableFooterRow&amp;gt;
		&amp;lt;/asp:Table&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
This ASP.NET page is responsible for using the &lt;code&gt;Pop3Client&lt;/code&gt; class we developed earlier to display list of emails in Gmail's mailbox, page by page. The user will be able to browse all the pages using &amp;apos;Next Page&amp;apos; and &amp;apos;Previous Page&amp;apos; links.&lt;/p&gt;

&lt;p&gt;The first thing we do is to declare a &lt;code&gt;Page&lt;/code&gt; level directive and tell the ASP.NET compiler that the language we are going to use on this page is &amp;quot;C#&amp;quot;.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;/pre&gt;&lt;p&gt;Next, we import the necessary namespaces.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Pop3&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;The server-side code is encapsulated between the &lt;code&gt;&amp;lt;script&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	...
&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;We declare a few constants. The first four are required to properly connect and login to the Gmail's POP3 server. The &lt;code&gt;Host&lt;/code&gt; and &lt;code&gt;Port&lt;/code&gt; constants can be changed to point to your email provider's POP3 server, if it is not Gmail. For the purpose of demonstration, we will connect to Gmail's POP3 server. &lt;em&gt;The &lt;code&gt;Email&lt;/code&gt; and &lt;code&gt;Password&lt;/code&gt; constants should be changed to your email address and password&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NoOfEmailsPerPage&lt;/code&gt; constant is used to declare how many emails we want to show per page. You can change it to &lt;code&gt;10&lt;/code&gt; or &lt;code&gt;20&lt;/code&gt; to suit the needs of your web application. &lt;code&gt;SelfLink&lt;/code&gt; and &lt;code&gt;DisplayLink&lt;/code&gt; constants contain strings for formatting links and to display the full email in the &amp;quot;&lt;code&gt;DisplayPop3Email.aspx&lt;/code&gt;&amp;quot; ASP.NET page, which we will create in the next tutorial.&lt;/p&gt;

&lt;pre&gt;
public const string Host = &amp;quot;pop.gmail.com&amp;quot;;
public const int Port = 995;
public const string Email = &amp;quot;youremail@gmail.com&amp;quot;;
public const string Password = &amp;quot;yourpassword&amp;quot;;

public const int NoOfEmailsPerPage = 5;
public const string SelfLink =
	&amp;quot;&amp;lt;a href=\&amp;quot;Pop3Client.aspx?page={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;
public const string DisplayEmailLink =
	&amp;quot;&amp;lt;a href=\&amp;quot;DisplayPop3Email.aspx?emailId={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;&lt;/pre&gt;

&lt;p&gt;Now we will dig into the all important code in the &lt;code&gt;Page_Load()&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;
protected void Page_Load(object source, EventArgs e)
{
	...
}&lt;/pre&gt;

&lt;p&gt;If you access &lt;code&gt;Pop3Client.aspx&lt;/code&gt; directly, it will redirect you to &lt;code&gt;Pop3Client.aspx?page=1&lt;/code&gt;. The current page is retrieved and saved in the &lt;code&gt;page&lt;/code&gt; variable.&lt;/p&gt;

&lt;pre&gt;
/* Setting current page */
int page = 1;

if (Request.QueryString[&amp;quot;page&amp;quot;] == null)
{
	Response.Redirect(&amp;quot;Pop3Client.aspx?page=1&amp;quot;);
	Response.Flush();
	Response.End();
}
else
	page = Convert.ToInt32(Request.QueryString[&amp;quot;page&amp;quot;]);&lt;/pre&gt;

&lt;p&gt;Now we create the &lt;code&gt;Pop3Client&lt;/code&gt; object. We create it within the &lt;code&gt;using&lt;/code&gt; statement so that we don't explicitly have to call the &lt;code&gt;Pop3Client.Close()&lt;/code&gt; method. Gorgeous!&lt;/p&gt;

&lt;p&gt;We call the &lt;code&gt;GetEmailCount()&lt;/code&gt; method to get the number of emails in the mailbox. Next, we retrieve the list of emails for the current page.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; The number of emails in the list will be a maximum of &lt;code&gt;NoOfEmailsPerPage&lt;/code&gt; i.e., &lt;code&gt;5&lt;/code&gt;. We do not retrieve all the emails in the mailbox. We retrieve only those that are required to be displayed on the &lt;em&gt;current&lt;/em&gt; page.&lt;/div&gt;

&lt;pre&gt;
/* Creating Pop3Client object and accessing email data */
int totalEmails;
List&amp;lt;Email&amp;gt; emails;
string emailAddress;

using(Pop3Client client = new Pop3Client(Host, Port, Email, Password, true))
{
	emailAddress = client.Email;

	client.Connect();

	totalEmails = client.GetEmailCount();
	emails = client.FetchEmailList(((page - 1) *
		NoOfEmailsPerPage) + 1, NoOfEmailsPerPage);
}&lt;/pre&gt;

&lt;p&gt;Next, we compute the total number of pages the user can browse through.&lt;/p&gt;

&lt;pre&gt;
/* Computing total pages */
int totalPages;
int mod = totalEmails % NoOfEmailsPerPage;

if (mod == 0)
	totalPages = totalEmails / NoOfEmailsPerPage;
else
	totalPages = ((totalEmails - mod) / NoOfEmailsPerPage) + 1;&lt;/pre&gt;

&lt;p&gt;Next, we iterate through the retrieved list of emails, one by one, and append their information to an HTML table which we will display to the user.&lt;/p&gt;

&lt;pre&gt;
for (int i = 0; i &amp;lt; emails.Count; i++)
{
	Email email = emails[i];

	/* Appending each email to an existing table */
	int emailId = ((page - 1) * NoOfEmailsPerPage) + i + 1;

	TableCell noCell = new TableCell();
	noCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
	noCell.Text = Convert.ToString(emailId);
	
	TableCell fromCell = new TableCell();
	fromCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
	fromCell.Text = email.From;
	
	TableCell subjectCell = new TableCell();
	subjectCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
	subjectCell.Style[&amp;quot;width&amp;quot;] = &amp;quot;300px&amp;quot;;
	subjectCell.Text = String.Format(DisplayEmailLink,
		emailId, email.Subject);

	//TableCell contentTypeCell = new TableCell();
	//contentTypeCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
	//contentTypeCell.Text = email.ContentType;
	
	TableCell dateCell = new TableCell();
	dateCell.CssClass = &amp;quot;emails-table-cell&amp;quot;;
	
	if (email.UtcDateTime != DateTime.MinValue)
		dateCell.Text = email.UtcDateTime.ToString();

	TableRow emailRow = new TableRow();
	emailRow.Cells.Add(noCell);
	emailRow.Cells.Add(fromCell);
	emailRow.Cells.Add(subjectCell);
	//emailRow.Cells.Add(contentTypeCell);
	emailRow.Cells.Add(dateCell);

	EmailsTable.Rows.AddAt(2 + i, emailRow);
}&lt;/pre&gt;

&lt;p&gt;Next, we create &amp;apos;Previous Page&amp;apos; and &amp;apos;Next Page&amp;apos; links.&lt;/p&gt;

&lt;pre&gt;
/* Creating links to previous and next pages */
if (totalPages &amp;gt; 1)
{
	if (page &amp;gt; 1)
		PreviousPageLiteral.Text =
			String.Format(SelfLink, page - 1, &amp;quot;Previous Page&amp;quot;);

	if (page &amp;gt; 0 &amp;amp;&amp;amp; page &amp;lt; totalPages)
		NextPageLiteral.Text =
			String.Format(SelfLink, page + 1, &amp;quot;Next Page&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;Lastly, we set a few literals to display on the page.&lt;/p&gt;

&lt;pre&gt;
/* Displaying information to the user */
EmailFromLiteral.Text =
	Convert.ToString(((page - 1) * NoOfEmailsPerPage) + 1);
EmailToLiteral.Text = Convert.ToString(page * NoOfEmailsPerPage);
EmailTotalLiteral.Text = Convert.ToString(totalEmails);
EmailLiteral.Text = emailAddress;&lt;/pre&gt;

&lt;p&gt;We are now all set to run this page on our ASP.NET web server. But before that, there is one final step left, and that is to &lt;em&gt;enable POP3 access for our mailbox on Gmail&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Enabling POP3 access on Gmail&lt;/b&gt;&lt;br /&gt;
Follow these steps to enable POP3 access for your email address on Gmail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to your account at Gmail.&lt;/li&gt;
&lt;li&gt;Click the &amp;quot;Settings&amp;quot; link on the top right.&lt;/li&gt;
&lt;li&gt;From the &amp;apos;Settings&amp;apos; panel, click the &amp;quot;Forwarding and POP/IMAP&amp;quot; tab.&lt;/li&gt;
&lt;li&gt;In the &amp;apos;POP Download&amp;apos; section, select the option &amp;quot;Enable POP for all mail (even mail that's already been downloaded)&amp;quot;&lt;/li&gt;
&lt;li&gt;Make sure &amp;apos;When messages are accessed with POP&amp;apos; is set to &amp;quot;keep Gmail's copy in the Inbox&amp;quot;. &lt;em&gt;This is always a safe bet to keep your emails in the Gmail's inbox and not have them deleted when you retrieve them from Gmail's POP3 server&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Now click &amp;apos;Save Changes&amp;apos; button to save the changes.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;b&gt;Running the Pop3Client.aspx Page&lt;/b&gt;&lt;br /&gt;
After placing &amp;quot;Pop3.cs&amp;quot; in the &lt;code&gt;/App_Code&lt;/code&gt; sub-folder and &lt;code&gt;Pop3Client.aspx&lt;/code&gt; in the &lt;code&gt;/&lt;/code&gt; folder of my ASP.NET web application, I ran the &lt;code&gt;Pop3Client.aspx&lt;/code&gt; page and got following result:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009071001_pop3-listing-emails.gif" width="600" height="235" border="0" alt="Listing emails" /&gt;
&lt;/div&gt;

&lt;p&gt;I hope you were also able to successfully connect to your email's mailbox on the remote server and were able to view the list of emails in it.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; It is recommended that you study the code in full to understand how we are connecting to, sending and receiving data over the network. If your POP3 server doesn't support secure access over SSL, you should set the &lt;code&gt;secure&lt;/code&gt; argument in the constructor of &lt;code&gt;Pop3Client&lt;/code&gt; class to &lt;code&gt;false&lt;/code&gt;.&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
In this tutorial, we developed code to connect to Gmail's secure POP3 server using SSL. We learned about &lt;code&gt;TcpClient&lt;/code&gt;, &lt;code&gt;NetworkStream&lt;/code&gt;, &lt;code&gt;SslStream&lt;/code&gt;, &lt;code&gt;StreamWriter&lt;/code&gt; and &lt;code&gt;StreamReader&lt;/code&gt; classes. Using these classes we created our own set of top level classes to make the task of communicating with the server, easier. An ASP.NET page in the end, using the code that we developed, successfully displayed the list of emails retrieved from the server.&lt;/p&gt;

&lt;p&gt;In the next tutorial (&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009071001&amp;page=1"&gt;Displaying Emails from Mailbox on Gmail using POP3 and ASP.NET&lt;/a&gt;), we will create an ASP.NET page that will retrieve the actual email from the POP3 server and display it to the user.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=ZHb7g3uF9Sk:Hi98PiesArA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=ZHb7g3uF9Sk:Hi98PiesArA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/ZHb7g3uF9Sk" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009070801&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Wed, 08 Jul 2009 10:13:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009070801&amp;page=1</feedburner:origLink></item>
<item>
<title>Displaying Twitter Updates in a Page by Page fashion with ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/WZHBIju0wR0/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will develop a technique to retrieve and display a page full of Twitter updates to the user, giving him the ability to move to the next page. The user will be able to browse all the pages using &amp;apos;Previous Page&amp;apos; and &amp;apos;Next Page&amp;apos; links. Our technique will be highly efficient as we will be retrieving only enough number of Twitter updates from a given screen name, to display on a single page. Only when the user browses to the next page will another set of Twitter updates be retrieved. At the same time we will cache the results, page by page, giving seamless and smooth performance to the end user.&lt;/p&gt;

&lt;p&gt;The code in this tutorial makes use of the code we developed in the previous tutorial: &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1"&gt;Retrieving Twitter Updates with ASP.NET&lt;/a&gt;. We will only be updating &lt;code&gt;TwitterClient.cs&lt;/code&gt; a little bit to enable retrieval of Twitter updates page by page. Rest of the files will remain the same. We will develop an ASP.NET page to demonstrate the technique.&lt;/p&gt;

&lt;p&gt;I advise that you read this series of tutorials from the beginning and create/place the files as advised in the previous tutorial.&lt;/p&gt;

&lt;p&gt;This tutorial is 3rd in the series of tutorials regarding Twitter and ASP.NET:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061401&amp;page=1"&gt;Introduction to Twitter for ASP.NET Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1"&gt;Retrieving Twitter Updates with ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Displaying Twitter Updates in a Page by Page fashion with ASP.NET&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Demonstration of Twitter Updates being Displayed Page by Page&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will develop an ASP.NET page that retrieves 5 status updates for a given screen name and displays them on a page. When 'Next Page' link is clicked, next 5 status updates are retrieved and displayed to the user.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; 5 is an arbitrary number. You can modify the code to display any number of status updates per page.&lt;/div&gt;

&lt;p&gt;Following screen shots show the ASP.NET page displaying Twitter status updates in a page by page fashion:&lt;/p&gt;

&lt;div align="center" style="margin-bottom: 20px"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009062001_stardeveloper-updates-page-1.gif" width="400" height="365" border="0" alt="Displaying Twitter Updates Page by Page" /&gt;
&lt;/div&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009062001_stardeveloper-updates-page-2.gif" width="400" height="222" border="0" alt="Displaying Twitter Updates Page by Page" /&gt;
&lt;/div&gt;

&lt;p&gt;Let us now go ahead and develop the necessary code.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Developing the Code&lt;/b&gt;&lt;br /&gt;
We need to update &lt;code&gt;TwitterClient.cs&lt;/code&gt; file to accomodate the retrieval of Twitter status updates  page by page.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; It is absolutely necessary to create and place the files as described in &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1"&gt;Retrieving Twitter Updates with ASP.NET&lt;/a&gt; tutorial. Without which you will not be able to make the changes as described below.&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Updated TwitterClient.cs&lt;/b&gt;&lt;br /&gt;
You should replace the code in &lt;code&gt;TwitterClient.cs&lt;/code&gt; with the code given below. The updated sections of the code have been highlighted.&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using Stardeveloper.Twitter;

namespace Stardeveloper.Twitter
{
	public class TwitterClient
	{
	public const string StatusesUserTimelineStr =
		&amp;quot;http://twitter.com/statuses/user_timeline.xml?&amp;quot; +
		&amp;quot;screen_name={0}&amp;amp;count={1}&amp;amp;page={2}&amp;quot;;

	public TwitterClient()
	{
	}

	protected virtual string FetchXmlFromUrl(string url)
	{
		using (WebClient client = new WebClient())
		using (Stream s = client.OpenRead(url))
		using (StreamReader sr = new StreamReader(s))
		{
			return sr.ReadToEnd();
		}
	}&lt;/pre&gt;

&lt;p&gt;The code continues on the next page.&lt;/p&gt;&lt;pre&gt;protected virtual List&amp;lt;Status&amp;gt;
		CreateStatusObjectsFromXml(string xml, int count)
	{
		List&amp;lt;Status&amp;gt; statuses = new List&amp;lt;Status&amp;gt;(count);

		XmlDocument xmldoc = new XmlDocument();
		xmldoc.LoadXml(xml);

		foreach (XmlNode status in xmldoc.DocumentElement)
		{
		// created_at
		string value = status.SelectSingleNode(&amp;quot;created_at&amp;quot;).InnerXml;
		DateTime statusCreatedAt = ConvertStrToUtcDateTime(value);

		// id
		value = status.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
		long statusId = Convert.ToInt64(value);

		// text
		string text = status.SelectSingleNode(&amp;quot;text&amp;quot;).InnerXml;

		// source
		string source = status.SelectSingleNode(&amp;quot;source&amp;quot;).InnerXml;

		// truncated
		value = status.SelectSingleNode(&amp;quot;truncated&amp;quot;).InnerXml;
		bool truncated = Convert.ToBoolean(value);

		// in_reply_to_status_id
		value = status.SelectSingleNode(&amp;quot;in_reply_to_status_id&amp;quot;).InnerXml;
		long inReplyToStatusId = value != &amp;quot;&amp;quot; ? Convert.ToInt64(value) : 0;

		// in_reply_to_user_id
		value = status.SelectSingleNode(&amp;quot;in_reply_to_user_id&amp;quot;).InnerXml;
		long inReplyToUserId = value != &amp;quot;&amp;quot; ? Convert.ToInt64(value) : 0;

		// favorited
		value = status.SelectSingleNode(&amp;quot;favorited&amp;quot;).InnerXml;
		bool favorited = Convert.ToBoolean(value);

		// in_reply_to_screen_name
		string inReplyToScreenName =
			status.SelectSingleNode(&amp;quot;in_reply_to_screen_name&amp;quot;).InnerXml;

		/* Getting into user element */
		XmlNode user = status.SelectSingleNode(&amp;quot;user&amp;quot;);

		// id
		value = user.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
		long userId = Convert.ToInt64(value);

		// name
		string name = user.SelectSingleNode(&amp;quot;name&amp;quot;).InnerXml;

		// screen_name
		string screenName = user.SelectSingleNode(&amp;quot;screen_name&amp;quot;).InnerXml;

		// location
		string location = user.SelectSingleNode(&amp;quot;location&amp;quot;).InnerXml;

		// description
		string description = user.SelectSingleNode(&amp;quot;description&amp;quot;).InnerXml;

		// profile_image_url
		string profileImageUrl =
			user.SelectSingleNode(&amp;quot;profile_image_url&amp;quot;).InnerXml;

		// url
		string url = user.SelectSingleNode(&amp;quot;url&amp;quot;).InnerXml;

		// protected
		value = user.SelectSingleNode(&amp;quot;protected&amp;quot;).InnerXml;
		bool protectedstr = Convert.ToBoolean(value);

		// followers_count
		value = user.SelectSingleNode(&amp;quot;followers_count&amp;quot;).InnerXml;
		long followersCount = Convert.ToInt64(value);

		// profile_background_color
		string profileBackgroundColor =
			user.SelectSingleNode(&amp;quot;profile_background_color&amp;quot;).InnerXml;

		// profile_text_color
		string profileTextColor =
			user.SelectSingleNode(&amp;quot;profile_text_color&amp;quot;).InnerXml;

		// profile_link_color
		string profileLinkColor =
			user.SelectSingleNode(&amp;quot;profile_link_color&amp;quot;).InnerXml;

		// profile_sidebar_fill_color
		string profileSidebarFillColor =
			user.SelectSingleNode(&amp;quot;profile_sidebar_fill_color&amp;quot;)
				.InnerXml;

		// profile_sidebar_border_color
		string profileSidebarBorderColor =
			user.SelectSingleNode(&amp;quot;profile_sidebar_border_color&amp;quot;)
				.InnerXml;

		// friends_count
		value = user.SelectSingleNode(&amp;quot;friends_count&amp;quot;).InnerXml;
		long friendsCount = Convert.ToInt64(value);

		// created_at
		value = user.SelectSingleNode(&amp;quot;created_at&amp;quot;).InnerXml;
		DateTime userCreatedAt = TwitterClient.ConvertStrToUtcDateTime(value);

		// favourites_count
		value = user.SelectSingleNode(&amp;quot;favourites_count&amp;quot;).InnerXml;
		long favouritesCount = Convert.ToInt64(value);

		// utc_offset
		value = user.SelectSingleNode(&amp;quot;utc_offset&amp;quot;).InnerXml;
		int utcOffset = Convert.ToInt32(value);

		// time_zone
		string timeZone = user.SelectSingleNode(&amp;quot;time_zone&amp;quot;).InnerXml;

		// profile_background_image_url
		string profileBackgroundImageUrl =
			user.SelectSingleNode(&amp;quot;profile_background_image_url&amp;quot;).InnerXml;

		// profile_background_tile
		value = user.SelectSingleNode(&amp;quot;profile_background_tile&amp;quot;).InnerXml;
		bool profileBackgroundTile = Convert.ToBoolean(value);

		// statuses_count
		value = user.SelectSingleNode(&amp;quot;statuses_count&amp;quot;).InnerXml;
		long statusesCount = Convert.ToInt64(value);

		// notifications
		string notifications = user.SelectSingleNode(&amp;quot;notifications&amp;quot;).InnerXml;

		// following
		string following = user.SelectSingleNode(&amp;quot;following&amp;quot;).InnerXml;

		/* Creating User object */
		User userobj = new User(userId, name, screenName, location,
			description, profileImageUrl, url, protectedstr,
			followersCount, profileBackgroundColor, profileTextColor,
			profileLinkColor, profileSidebarFillColor,
			profileSidebarBorderColor, friendsCount, userCreatedAt,
			favouritesCount, utcOffset, timeZone,
			profileBackgroundImageUrl, profileBackgroundTile,
			statusesCount, notifications, following);

		Status statusobj = new Status(statusCreatedAt, statusId,
			text, source, truncated, inReplyToStatusId, inReplyToUserId,
			favorited, inReplyToScreenName, userobj);

		statuses.Add(statusobj);
		}

		return statuses;
	}

	public Status GetLatestStatusUpdate(string screenName)
	{
		List&amp;lt;Status&amp;gt; statuses = GetStatusUpdates(screenName, 1);

		return statuses[0];
	}

	public List&amp;lt;Status&amp;gt; GetStatusUpdates(string screenName, int count)
	{
		return GetStatusUpdates(screenName, count, 1);
	}

	public List&amp;lt;Status&amp;gt; GetStatusUpdates(string screenName, int count,
		int page)
	{
		string url = String.Format(StatusesUserTimelineStr,
			screenName, count, page);
		string xml = FetchXmlFromUrl(url);

		return CreateStatusObjectsFromXml(xml, count);
	}

	public static DateTime ConvertStrToUtcDateTime(string str)
	{
		string[] arr = str.Split(&amp;apos; &amp;apos;);

		int day, month, year, hour, min, sec;

		switch (arr[1])
		{
			case &amp;quot;Jan&amp;quot;:
				month = 1;
				break;
			case &amp;quot;Feb&amp;quot;:
				month = 2;
				break;
			case &amp;quot;Mar&amp;quot;:
				month = 3;
				break;
			case &amp;quot;Apr&amp;quot;:
				month = 4;
				break;
			case &amp;quot;May&amp;quot;:
				month = 5;
				break;
			case &amp;quot;Jun&amp;quot;:
				month = 6;
				break;
			case &amp;quot;Jul&amp;quot;:
				month = 7;
				break;
			case &amp;quot;Aug&amp;quot;:
				month = 8;
				break;
			case &amp;quot;Sep&amp;quot;:
				month = 9;
				break;
			case &amp;quot;Oct&amp;quot;:
				month = 10;
				break;
			case &amp;quot;Nov&amp;quot;:
				month = 11;
				break;
			case &amp;quot;Dec&amp;quot;:
				month = 12;
				break;
			default:
				throw new FormatException(&amp;quot;Unknown month.&amp;quot;);
		}

		day = Convert.ToInt32(arr[2]);

		string[] arr1 = arr[3].Split(&amp;apos;:&amp;apos;);

		hour = Convert.ToInt32(arr1[0]);
		min = Convert.ToInt32(arr1[1]);
		sec = Convert.ToInt32(arr1[2]);

		string offsetSign = arr[4].Substring(0, 1);
		int offsetHours = Convert.ToInt32(arr[4].Substring(1, 2));
		int offsetMinutes = Convert.ToInt32(arr[4].Substring(3, 2));

		year = Convert.ToInt32(arr[5]);

		DateTime dt = new DateTime(year, month, day, hour, min, sec);

		if (offsetSign == &amp;quot;+&amp;quot;)
		{
			dt.AddHours(offsetHours);
			dt.AddMinutes(offsetMinutes);
		}
		else if (offsetSign == &amp;quot;-&amp;quot;)
		{
			dt.AddHours(-offsetHours);
			dt.AddMinutes(-offsetMinutes);
		}

		return dt;
	}
	}
}&lt;/pre&gt;

&lt;p&gt;Code is explained on the next page.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
The URL to retrieve Twitter status updates remains the same but we add an extra querystring parameter to tell Twitter which page we want to retrieve. The &lt;code&gt;screen_name&lt;/code&gt; should be set to the screen name of the user whose status updates we want to retrieve. The &lt;code&gt;count&lt;/code&gt; parameter should be set to a numeric value of number of status updates you want to show per page. The &lt;code&gt;page&lt;/code&gt; parameter should be set to a numeric value of the page whose status updates you want to retrieve, beginning from 1. You don't have to manually set these values. It is only for you to understand what is going on behind the scenes.&lt;/p&gt;

&lt;pre&gt;
public const string StatusesUserTimelineStr =
	&amp;quot;http://twitter.com/statuses/user_timeline.xml?&amp;quot; +
	&amp;quot;screen_name={0}&amp;amp;count={1}&amp;amp;page={2}&amp;quot;;&lt;/pre&gt;

&lt;p&gt;Next we add another &lt;code&gt;GetStatusUpdates()&lt;/code&gt; method with the extra option of specifying the page you want to retrieve status updates from.&lt;/p&gt;

&lt;pre&gt;
public List&amp;lt;Status&amp;gt; GetStatusUpdates(string screenName, int count,
	int page)
{
	string url = String.Format(StatusesUserTimelineStr,
		screenName, count, page);
	string xml = FetchXmlFromUrl(url);

	return CreateStatusObjectsFromXml(xml, count);
}&lt;/pre&gt;

&lt;p&gt;This is it as far as the changes in &lt;code&gt;TwitterClient.cs&lt;/code&gt; are concerned.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TwitterAllUpdates.aspx&lt;/b&gt;&lt;br /&gt;
The logic to pull the the right page and display the status updates properly is handled by this ASP.NET page. Open notepad and copy following code in it and then save it as &amp;quot;TwitterAllUpdates.aspx&amp;quot; in the main folder of your ASP.NET web application:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;

&amp;lt;%@ OutputCache VaryByParam=&amp;quot;page&amp;quot; Duration=&amp;quot;1200&amp;quot; %&amp;gt;

&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Twitter&amp;quot; %&amp;gt;

&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
public const int StatusUpdatesPerPage = 5;
public const string ScreenName = &amp;quot;Stardeveloper&amp;quot;;
public const string LinkText =
	&amp;quot;&amp;lt;a href=\&amp;quot;TwitterAllUpdates.aspx?page={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;

protected void Page_Load(object source, EventArgs e)
{
	/* Setting current page and total pages */
	int page = 1;
	int totalPages = -1;

	if (Request.QueryString[&amp;quot;page&amp;quot;] == null)
		Response.Redirect(&amp;quot;TwitterAllUpdates.aspx?page=1&amp;quot;);
	else
		page = Convert.ToInt32(Request.QueryString[&amp;quot;page&amp;quot;]);
	
	/* Retrieving status updates in real-time */
	TwitterClient client = new TwitterClient();
	List&amp;lt;Status&amp;gt; statuses = client.GetStatusUpdates(ScreenName,
		StatusUpdatesPerPage, page);

	foreach (Status status in statuses)
	{
		/* Appending each status to existing table */
		TableCell statusCell = new TableCell();
		statusCell.ColumnSpan = 2;
		statusCell.CssClass = &amp;quot;status-updates-table-cell&amp;quot;;

		StringBuilder statusBuilder = new StringBuilder();
		statusBuilder.Append(status.FormattedText);
		statusBuilder.Append(&amp;quot;&amp;lt;div class=\&amp;quot;status-datetime\&amp;quot;&amp;gt;&amp;quot;);
		statusBuilder.Append(status.CreatedAt.ToShortDateString());
		statusBuilder.Append(&amp;quot; &amp;quot;);
		statusBuilder.Append(status.CreatedAt.ToShortTimeString());
		statusBuilder.Append(&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;);
		
		statusCell.Text = statusBuilder.ToString();

		TableRow statusRow = new TableRow();
		statusRow.Cells.Add(statusCell);

		StatusUpdatesTable.Rows.Add(statusRow);

		/* Computing total possible pages */
		if (totalPages == -1)
		{
			int statusesCount =
				Convert.ToInt32(status.User.StatusesCount);
			int mod = statusesCount % StatusUpdatesPerPage;
			
			if (mod == 0)
				totalPages = statusesCount / StatusUpdatesPerPage;
			else
				totalPages = ((statusesCount - mod) /
					StatusUpdatesPerPage) + 1;
		}
	}

	/* Creating links to previous and next pages */
	if (totalPages &amp;gt; 1)
	{
		TableCell prevPageCell = new TableCell();
		TableCell nextPageCell = new TableCell();

		prevPageCell.CssClass = &amp;quot;status-updates-table-footer&amp;quot;;
		nextPageCell.CssClass = &amp;quot;status-updates-table-footer&amp;quot;;
		nextPageCell.Style[&amp;quot;text-align&amp;quot;] = &amp;quot;right&amp;quot;;

		if (page &amp;gt; 1)
			prevPageCell.Text = String.Format(LinkText, page - 1,
				&amp;quot;Previous Page&amp;quot;);

		if (page &amp;gt; 0 &amp;amp;&amp;amp; page &amp;lt; totalPages)
			nextPageCell.Text = String.Format(LinkText, page + 1,
				&amp;quot;Next Page&amp;quot;);

		TableFooterRow footerRow = new TableFooterRow();
		footerRow.Cells.Add(prevPageCell);
		footerRow.Cells.Add(nextPageCell);

		StatusUpdatesTable.Rows.Add(footerRow);
	}

	/* Setting some values to display to the user */
	ScreenNameLiteral.Text = ScreenName;
	PageLiteral.Text = Convert.ToString(page);
	TotalPagesLiteral.Text = Convert.ToString(totalPages);
}
&amp;lt;/script&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;
		.status-updates-table { width: 400px; border: solid 1px #444444; }
		.status-updates-table-header { font-family: &amp;quot;Trebuchet MS&amp;quot;;
			font-size: 9pt; background-color: #0099B9; color: white;
			border: solid 1px #444444; }
		.status-updates-table-cell { font-family: &amp;quot;Georgia&amp;quot;;
			font-size: 9pt; border: solid 1px #666666; padding: 6px; }
		.status-updates-table-footer { border: solid 1px #666666;
			padding: 3px; width: 50%; }
		.status-datetime { float: right; color: #666666; }
		
		a { font-family: &amp;quot;Lucida Sans Unicode&amp;quot;,
			&amp;quot;Trebuchet MS&amp;quot;; font-size: 9pt;
			color: #005B7F; }
		a:hover { color:red; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
	&amp;lt;asp:Table ID=&amp;quot;StatusUpdatesTable&amp;quot;
		CssClass=&amp;quot;status-updates-table&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
	&amp;lt;asp:TableHeaderRow&amp;gt;
		&amp;lt;asp:TableHeaderCell CssClass=&amp;quot;status-updates-table-header&amp;quot;
		ColumnSpan=&amp;quot;2&amp;quot;&amp;gt;
		&amp;lt;asp:Literal ID=&amp;quot;ScreenNameLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; Updates (page 
		&amp;lt;asp:Literal ID=&amp;quot;PageLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; of 
		&amp;lt;asp:Literal ID=&amp;quot;TotalPagesLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;)
		&amp;lt;/asp:TableHeaderCell&amp;gt;
	&amp;lt;/asp:TableHeaderRow&amp;gt;
	&amp;lt;/asp:Table&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
The first &lt;code&gt;Page&lt;/code&gt; level directive tells ASP.NET compiler that the default language in this page is going to be C#.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Next, an &lt;code&gt;OutputCache&lt;/code&gt; directive tells the ASP.NET runtime to cache the output of this page for 20 minutes (20 min x 60 sec = 1200 sec). The &lt;code&gt;VaryByParam&lt;/code&gt; attribute is set to &amp;quot;page&amp;quot; which makes sure that a new copy of the output of this page will be cached for each variation of &amp;quot;page&amp;quot; querystring parameter.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ OutputCache VaryByParam=&amp;quot;page&amp;quot; Duration=&amp;quot;1200&amp;quot; %&amp;gt;&lt;/pre&gt;&lt;p&gt;Necessary namespaces are imported. &lt;code&gt;System.Collections.Generic&lt;/code&gt; namespace is necessary because we want to use generic &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; class. &lt;code&gt;Stardeveloper.Twitter&lt;/code&gt; namespace is necessary because we want to make use of &lt;code&gt;TwitterClient&lt;/code&gt;, &lt;code&gt;Status&lt;/code&gt;, and &lt;code&gt;User&lt;/code&gt; classes, we developed earlier.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Collections.Generic&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Twitter&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;A server-side script tag tells the ASP.NET compiler that this segment is going to contain server-side code.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	...
&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;We define 3 page level constant variables. &lt;code&gt;StatusUpdatesPerPage&lt;/code&gt; variable is set to the number of status updates we want to display per page. You can change this value to suit the need of your web application. &lt;code&gt;ScreenName&lt;/code&gt; variable is set to the screen name of the user whose status updates you want to retrieve from Twitter. &lt;code&gt;LinkText&lt;/code&gt; contains string which contains placeholders which will be set by the code later. This variable will be used to create &amp;apos;Previous Page&amp;apos; and &amp;apos;Next Page&amp;apos; links, in the table, under the status updates, later.&lt;/p&gt;

&lt;pre&gt;
public const int StatusUpdatesPerPage = 5;
public const string ScreenName = &amp;quot;Stardeveloper&amp;quot;;
public const string LinkText =
	&amp;quot;&amp;lt;a href=\&amp;quot;TwitterAllUpdates.aspx?page={0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;;&lt;/pre&gt;

&lt;p&gt;Next, we place all of our important code in the &lt;code&gt;Page_Load()&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;
protected void Page_Load(object source, EventArgs e)
{
	...
}&lt;/pre&gt;

&lt;p&gt;Within the &lt;code&gt;Page_Load()&lt;/code&gt; method, we start by declaring two important variables. &lt;code&gt;page&lt;/code&gt; should be set to the page whose status updates we want to retrieve from Twitter and display to the user. &lt;code&gt;totalPages&lt;/code&gt; should be set to the total number of pages that are available for this screen name. If a user has 100 status updates at Twitter and we want to show 20 updates per page, then &lt;code&gt;totalPages&lt;/code&gt; should be set to 5.&lt;/p&gt;

&lt;p&gt;If the querystring parameter, &amp;quot;page&amp;quot;, is not set, the we set the querystring parameter and redirect the user to the same page. Otherwise, we fetch and set the &lt;code&gt;page&lt;/code&gt; variable's value to it.&lt;/p&gt;

&lt;pre&gt;
/* Setting current page and total pages */
int page = 1;
int totalPages = -1;

if (Request.QueryString[&amp;quot;page&amp;quot;] == null)
	Response.Redirect(&amp;quot;TwitterAllUpdates.aspx?page=1&amp;quot;);
else
	page = Convert.ToInt32(Request.QueryString[&amp;quot;page&amp;quot;]);&lt;/pre&gt;

&lt;p&gt;We then create &lt;code&gt;TwitterClient&lt;/code&gt; object and retrieve given status updates for a given page from Twitter. Once we have the list of status updates as &lt;code&gt;Status&lt;/code&gt; objects, we iterate through them, one by one, and populate our HTML table with its values.&lt;/p&gt;

&lt;pre&gt;
/* Retrieving status updates in real-time */
TwitterClient client = new TwitterClient();
List&amp;lt;Status&amp;gt; statuses = client.GetStatusUpdates(ScreenName,
	StatusUpdatesPerPage, page);

foreach (Status status in statuses)
{
	...
}&lt;/pre&gt;

&lt;p&gt;For each &lt;code&gt;Status&lt;/code&gt; object, we fetch formatted text by accessing the &lt;code&gt;Status.FormattedText&lt;/code&gt; property and append to it date &amp;amp; time of the status update. This text is then appended as an HTML row to an HTML table we have already placed as a user control in our ASP.NET page.&lt;/p&gt;

&lt;pre&gt;
/* Appending each status to existing table */
TableCell statusCell = new TableCell();
statusCell.ColumnSpan = 2;
statusCell.CssClass = &amp;quot;status-updates-table-cell&amp;quot;;

StringBuilder statusBuilder = new StringBuilder();
statusBuilder.Append(status.FormattedText);
statusBuilder.Append(&amp;quot;&amp;lt;div class=\&amp;quot;status-datetime\&amp;quot;&amp;gt;&amp;quot;);
statusBuilder.Append(status.CreatedAt.ToShortDateString());
statusBuilder.Append(&amp;quot; &amp;quot;);
statusBuilder.Append(status.CreatedAt.ToShortTimeString());
statusBuilder.Append(&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;);

statusCell.Text = statusBuilder.ToString();

TableRow statusRow = new TableRow();
statusRow.Cells.Add(statusCell);

StatusUpdatesTable.Rows.Add(statusRow);&lt;/pre&gt;

&lt;p&gt;Last bit of code checks and sets the &lt;code&gt;totalPages&lt;/code&gt; variable to total number of pages for this screen name using given status updates per page.&lt;/p&gt;

&lt;pre&gt;
/* Computing total possible pages */
if (totalPages == -1)
{
	int statusesCount =
		Convert.ToInt32(status.User.StatusesCount);
	int mod = statusesCount % StatusUpdatesPerPage;
	
	if (mod == 0)
		totalPages = statusesCount / StatusUpdatesPerPage;
	else
		totalPages = ((statusesCount - mod) /
			StatusUpdatesPerPage) + 1;
}&lt;/pre&gt;

&lt;p&gt;Once all &lt;code&gt;Status&lt;/code&gt; objects' formatted text has been appended to the HTML table in our ASP.NET page, we append &amp;apos;Previous Page&amp;apos; and &amp;apos;Next Page&amp;apos; links to the HTML table using the logic given below:&lt;/p&gt;

&lt;pre&gt;
/* Creating links to previous and next pages */
if (totalPages &amp;gt; 1)
{
	TableCell prevPageCell = new TableCell();
	TableCell nextPageCell = new TableCell();

	prevPageCell.CssClass = &amp;quot;status-updates-table-footer&amp;quot;;
	nextPageCell.CssClass = &amp;quot;status-updates-table-footer&amp;quot;;
	nextPageCell.Style[&amp;quot;text-align&amp;quot;] = &amp;quot;right&amp;quot;;

	if (page &amp;gt; 1)
		prevPageCell.Text = String.Format(LinkText, page - 1,
			&amp;quot;Previous Page&amp;quot;);

	if (page &amp;gt; 0 &amp;amp;&amp;amp; page &amp;lt; totalPages)
		nextPageCell.Text = String.Format(LinkText, page + 1,
			&amp;quot;Next Page&amp;quot;);

	TableFooterRow footerRow = new TableFooterRow();
	footerRow.Cells.Add(prevPageCell);
	footerRow.Cells.Add(nextPageCell);

	StatusUpdatesTable.Rows.Add(footerRow);
}&lt;/pre&gt;

&lt;p&gt;Lastly, 3 &lt;code&gt;Literal&lt;/code&gt; controls' values are set. These values will be displayed to the user.&lt;/p&gt;

&lt;pre&gt;
/* Setting some values to display to the user */
ScreenNameLiteral.Text = ScreenName;
PageLiteral.Text = Convert.ToString(page);
TotalPagesLiteral.Text = Convert.ToString(totalPages);&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;StatusUpdatesTable&lt;/code&gt; is the id of the HTML table that will display the Twitter status updates to the user in our ASP.NET page.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;asp:Table ID=&amp;quot;StatusUpdatesTable&amp;quot;
	CssClass=&amp;quot;status-updates-table&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
&amp;lt;asp:TableHeaderRow&amp;gt;
	&amp;lt;asp:TableHeaderCell CssClass=&amp;quot;status-updates-table-header&amp;quot;
	ColumnSpan=&amp;quot;2&amp;quot;&amp;gt;
	&amp;lt;asp:Literal ID=&amp;quot;ScreenNameLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; Updates (page 
	&amp;lt;asp:Literal ID=&amp;quot;PageLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; of 
	&amp;lt;asp:Literal ID=&amp;quot;TotalPagesLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;)
	&amp;lt;/asp:TableHeaderCell&amp;gt;
&amp;lt;/asp:TableHeaderRow&amp;gt;
&amp;lt;/asp:Table&amp;gt;&lt;/pre&gt;

&lt;p&gt;When this ASP.NET page was run on my computer, it produced following output:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009062001_stardeveloper-updates-page-1.gif" width="400" height="365" border="0" alt="TwitterAllUpdates.aspx" /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
In this tutorial, we updated the code to add paging ability in our ASP.NET web application. We demonstrated the code by developing an ASP.NET page which displayed Twitter status updates, page by page.&lt;/p&gt;

&lt;p&gt;In the next tutorial, we will learn how to display &amp;quot;followers' count&amp;quot; on our website for a given screen name.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=WZHBIju0wR0:2VjQwnoYvcs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=WZHBIju0wR0:2VjQwnoYvcs:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/WZHBIju0wR0" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009062001&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Sat, 20 Jun 2009 06:49:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009062001&amp;page=1</feedburner:origLink></item>
<item>
<title>Retrieving Twitter Updates with ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/HIxLqs0-2Fc/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will learn how to retrieve &lt;a href="http://twitter.com" target="_blank" rel="nofollow"&gt;Twitter&lt;/a&gt; status updates using Twitter API and ASP.NET. We will develop code that encapsulates calls to Twitter API and provides easy to use .NET classes to retrieve Twitter status updates, programmatically. We will demonstrate the code by developing an ASP.NET control that uses these .NET classes to retrieve and display Twitter status updates on our website.&lt;/p&gt;

&lt;p&gt;This tutorial is 2nd in the series of tutorials regarding Twitter and ASP.NET:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061401&amp;page=1"&gt;Introduction to Twitter for ASP.NET Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Retrieving Twitter Updates with ASP.NET&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009062001&amp;page=1"&gt;Displaying Twitter Updates in a Page by Page fashion with ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Things to know about Twitter API&lt;/b&gt;&lt;br /&gt;
Before getting started, it is prudent to know a few things about Twitter API.&lt;/p&gt;

&lt;p&gt;Twitter API is entirely HTTP based. This means that all you need to do to retrieve or post status updates is to make simple HTTP GET and POST calls, respectively, over the internet.&lt;/p&gt;

&lt;p&gt;Twitter API conforms to REST (Representational State Transfer) style of software architecture. You can use URL like &lt;code&gt;http://twitter.com/statuses/user_timeline.&lt;i&gt;format&lt;/i&gt;&lt;/code&gt; to retrieve status updates of a user. You can choose the desired format of the response by specifying the format in the URL. For instance, to retrieve the status updates in XML, the complete URL will be &lt;code&gt;http://twitter.com/statuses/user_timeline.xml&lt;/code&gt;. You have the option of choosing the format between XML, JSON, RSS and Atom.&lt;/p&gt;

&lt;p&gt;Twitter API is rate limited. You can only make 100 calls per hour. If you find that this limit is insufficient for the needs of your application, you can request &amp;quot;whitelisting&amp;quot; of your account. To do this you have to submit a request a manually using &lt;a href="http://twitter.com/help/request_whitelisting" target="_blank" rel="nofollow"&gt;Whitelisting request form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can learn more about the Twitter API on &lt;a href="http://apiwiki.twitter.com/" target="_blank" rel="nofollow"&gt;Twitter API Wiki&lt;/a&gt;. A good &amp;quot;Getting Started&amp;quot; guide for developers can be found on this link: &lt;a href="http://apiwiki.twitter.com/Things-Every-Developer-Should-Know" target="_blank" rel="nofollow"&gt;Things Every Developer Should Know&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Retrieving Twitter Status Updates&lt;/b&gt;&lt;br /&gt;
The URL to retrieve the status updates of a user on Twitter is: &lt;code&gt;http://twitter.com/statuses/user_timeline.xml&lt;/code&gt;. The documentation for what values this URL accepts as querystring parameters and what this URL returns, can be found on &lt;a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-user_timeline" target="_blank" rel="nofollow"&gt;Twitter REST API Method: statuses user_timeline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the purpose of this tutorial, there are only two querystring parameters of value to us. The first is &amp;quot;&lt;code&gt;screen_name&lt;/code&gt;&amp;quot;. Its value is the &amp;quot;Screen Name&amp;quot; (not the username) of the user whose status updates you want to retrieve. For instance, to retrieve the status updates of &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt;, we will be specifying &amp;quot;stardeveloper&amp;quot; as the &lt;code&gt;screen_name&lt;/code&gt;.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; &amp;quot;Screen Name&amp;quot; is the name after &lt;code&gt;http://twitter.com/&lt;/code&gt;, in the Twitter URL that you use to view status updates of a user. For example, in the URL &lt;code&gt;http://twitter.com/&lt;b&gt;stardeveloper&lt;/b&gt;&lt;/code&gt;, &lt;code&gt;stardeveloper&lt;/code&gt; is the screen name.&lt;/div&gt;

&lt;p&gt;The second paramater is &amp;quot;&lt;code&gt;count&lt;/code&gt;&amp;quot;, which accepts a numeric value stating how many status updates do we want to retrieve. For instance, if you want only to retrieve the latest status update, set its value to &amp;apos;1&amp;apos;.&lt;/p&gt;

&lt;p&gt;To view in your browser what XML string Twitter API will return for this URL, if we set the &lt;code&gt;screen_name&lt;/code&gt; to &amp;quot;stardeveloper&amp;quot; and &lt;code&gt;count&lt;/code&gt; to 1, click this link: &lt;a href="http://twitter.com/statuses/user_timeline.xml?screen_name=stardeveloper&amp;count=1" target="_blank" rel="nofollow"&gt;http://twitter.com/statuses/user_timeline.xml?screen_name=stardeveloper&amp;count=1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my browser, it returned following XML string:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;statuses type=&amp;quot;array&amp;quot;&amp;gt;
&amp;lt;status&amp;gt;
  &amp;lt;created_at&amp;gt;Sat Jun 13 19:58:29 +0000 2009&amp;lt;/created_at&amp;gt;
  &amp;lt;id&amp;gt;2157106641&amp;lt;/id&amp;gt;
  &amp;lt;text&amp;gt;New tutorial published: Introduction to Twitter for 
	ASP.NET Developers http://bit.ly/17mAhX&amp;lt;/text&amp;gt;
  &amp;lt;source&amp;gt;web&amp;lt;/source&amp;gt;
  &amp;lt;truncated&amp;gt;false&amp;lt;/truncated&amp;gt;

  &amp;lt;in_reply_to_status_id&amp;gt;&amp;lt;/in_reply_to_status_id&amp;gt;
  &amp;lt;in_reply_to_user_id&amp;gt;&amp;lt;/in_reply_to_user_id&amp;gt;
  &amp;lt;favorited&amp;gt;false&amp;lt;/favorited&amp;gt;
  &amp;lt;in_reply_to_screen_name&amp;gt;&amp;lt;/in_reply_to_screen_name&amp;gt;
  &amp;lt;user&amp;gt;
    &amp;lt;id&amp;gt;43659543&amp;lt;/id&amp;gt;
    &amp;lt;name&amp;gt;Faisal Khan&amp;lt;/name&amp;gt;

    &amp;lt;screen_name&amp;gt;Stardeveloper&amp;lt;/screen_name&amp;gt;
    &amp;lt;location&amp;gt;&amp;lt;/location&amp;gt;
    &amp;lt;description&amp;gt;Chief author and developer at 
		Stardeveloper.com.&amp;lt;/description&amp;gt;
    &amp;lt;profile_image_url&amp;gt;http://s3.amazonaws.com/
		twitter_production/profile_images/241256611/
		udh_normal.png&amp;lt;/profile_image_url&amp;gt;
    &amp;lt;url&amp;gt;http://www.stardeveloper.com&amp;lt;/url&amp;gt;
    &amp;lt;protected&amp;gt;false&amp;lt;/protected&amp;gt;

    &amp;lt;followers_count&amp;gt;3&amp;lt;/followers_count&amp;gt;
    &amp;lt;profile_background_color&amp;gt;0099B9&amp;lt;/profile_background_color&amp;gt;
    &amp;lt;profile_text_color&amp;gt;444444&amp;lt;/profile_text_color&amp;gt;
    &amp;lt;profile_link_color&amp;gt;006699&amp;lt;/profile_link_color&amp;gt;
    &amp;lt;profile_sidebar_fill_color&amp;gt;F5F1E5&amp;lt;/profile_sidebar_fill_color&amp;gt;
    &amp;lt;profile_sidebar_border_color&amp;gt;E2F0F4&amp;lt;/profile_sidebar_border_color&amp;gt;

    &amp;lt;friends_count&amp;gt;0&amp;lt;/friends_count&amp;gt;
    &amp;lt;created_at&amp;gt;Sun May 31 07:44:58 +0000 2009&amp;lt;/created_at&amp;gt;
    &amp;lt;favourites_count&amp;gt;0&amp;lt;/favourites_count&amp;gt;
    &amp;lt;utc_offset&amp;gt;18000&amp;lt;/utc_offset&amp;gt;
    &amp;lt;time_zone&amp;gt;Islamabad&amp;lt;/time_zone&amp;gt;
    &amp;lt;profile_background_image_url&amp;gt;http://static.twitter.com/
		images/themes/theme1/bg.gif&amp;lt;/profile_background_image_url&amp;gt;

    &amp;lt;profile_background_tile&amp;gt;false&amp;lt;/profile_background_tile&amp;gt;
    &amp;lt;statuses_count&amp;gt;7&amp;lt;/statuses_count&amp;gt;
    &amp;lt;notifications&amp;gt;&amp;lt;/notifications&amp;gt;
    &amp;lt;verified_profile&amp;gt;false&amp;lt;/verified_profile&amp;gt;
    &amp;lt;following&amp;gt;&amp;lt;/following&amp;gt;
  &amp;lt;/user&amp;gt;
&amp;lt;/status&amp;gt;&lt;/pre&gt;

&lt;p&gt;In the XML string that was returned, we can clearly see the latest status update at Stardeveloper.com. Twitter also returns lot more other information as XML elements.&lt;/p&gt;

&lt;p&gt;Now that we know what URL to send the HTTP GET request to from our code, what values to set in the querystring parameters, and what XML string to expect to be returned; we will be developing the code to do all of this for us programmatically and to display the latest status update on our website using an ASP.NET control which we will develop later.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Code to Retrieve the Twitter Update&lt;/b&gt;&lt;br /&gt;
The code that we will develop will do the job of retrieving status updates at Twitter in following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the XML string from the URL, &lt;code&gt;http://twitter.com/statuses/user_timeline.xml?screen_name=stardeveloper&amp;count=1&lt;/code&gt; using &lt;code&gt;System.Net.WebClient&lt;/code&gt; class. There will the option of sepcifying &lt;code&gt;screen_name&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt; querystring parameters, so that you can retrieve the status updates of the user of your choice. We will encapsulate all of this code in &lt;code&gt;TwitterClient&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;Develop separate classes to represent &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; elements in the XML file. The &lt;code&gt;Status&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; classes' properties will be named according to the names of their sub-elements in the XML string. For instance, to retrieve the status update from the XML string you will have to access the property of &lt;code&gt;Status&lt;/code&gt; object as: &lt;code&gt;Status.Text&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Convert the XML string to a list of &lt;code&gt;Status&lt;/code&gt; objects. Each &lt;code&gt;Status&lt;/code&gt; object will have a property with the name of &lt;code&gt;User&lt;/code&gt; which you can use to access the sub-elements of the &lt;code&gt;user&lt;/code&gt; element in the XML string. For instance to retrieve the &lt;code&gt;name&lt;/code&gt; of the &lt;code&gt;user&lt;/code&gt; element, the code to access is: &lt;code&gt;Status.User.Name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once we have the code that fetches the XML string and converts it into easily accessible objects, we will create an ASP.NET control with the name of &amp;quot;&lt;code&gt;TwitterControl&lt;/code&gt;&amp;quot; to display this status update on our website. This control will cache the result in memory for 20 mins. We do this so that we only have to access Twitter API not more than 3 times per hour. You will be provided the option of changing the cache duration to suit the needs of your web application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We should now get started with developing the code. We will first develop &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Status&lt;/code&gt; classes, because these classes are needed by the &lt;code&gt;TwitterClient&lt;/code&gt; class which we will develop later.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;User.cs&lt;/b&gt;&lt;br /&gt;
Open notepad and copy following text in it. Then save it as &amp;quot;User.cs&amp;quot; in the &lt;code&gt;/App_Code/&lt;/code&gt; sub-folder of your ASP.NET web application.&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

namespace Stardeveloper.Twitter
{
	public class User
	{
	public long Id { get; protected set; }
	public string Name { get; protected set; }
	public string ScreenName { get; protected set; }
	public string Location { get; protected set; }
	public string Description { get; protected set; }
	public string ProfileImageUrl { get; protected set; }
	public string Url { get; protected set; }
	public bool Protected { get; protected set; }
	public long FollowersCount { get; protected set; }
	public string ProfileBackgroundColor { get; protected set; }
	public string ProfileTextColor { get; protected set; }
	public string ProfileLinkColor { get; protected set; }
	public string ProfileSidebarFillColor { get; protected set; }
	public string ProfileSidebarBorderColor { get; protected set; }
	public long FriendsCount { get; protected set; }
	public DateTime CreatedAt { get; protected set; }
	public long FavouritesCount { get; protected set; }
	public int UtcOffset { get; protected set; }
	public string TimeZone { get; protected set; }
	public string ProfileBackgroundImageUrl { get; protected set; }
	public bool ProfileBackgroundTile { get; protected set; }
	public long StatusesCount { get; protected set; }
	public string Notifications { get; protected set; }
	public string Following { get; protected set; }

	public User(long id, string name, string screenName,
		string location, string description, string profileImageUrl,
		string url, bool protectedstr, long followersCount,
		string profileBackgroundColor, string profileTextColor,
		string profileLinkColor, string profileSidebarFillColor,
		string profileSidebarBorderColor, long friendsCount,
		DateTime createdAt, long favourtiesCount, int utcOffset,
		string timeZone, string profileBackgroundImageUrl,
		bool profileBackgroundTile, long statusesCount,
		string notifications, string following)
	{
		Id = id;
		Name = name;
		ScreenName = screenName;
		Location = location;
		Description = description;
		ProfileImageUrl = profileImageUrl;
		Url = url;
		Protected = protectedstr;
		FollowersCount = followersCount;
		ProfileBackgroundColor = profileBackgroundColor;
		ProfileTextColor = profileTextColor;
		ProfileLinkColor = profileLinkColor;
		ProfileSidebarFillColor = profileSidebarFillColor;
		ProfileSidebarBorderColor = profileSidebarBorderColor;
		FriendsCount = friendsCount;
		CreatedAt = createdAt;
		FavouritesCount = favourtiesCount;
		UtcOffset = utcOffset;
		TimeZone = timeZone;
		ProfileBackgroundImageUrl = profileBackgroundImageUrl;
		ProfileBackgroundTile = profileBackgroundTile;
		StatusesCount = statusesCount;
		Notifications = notifications;
		Following = following;
	}

	public override string ToString()
	{
		return Name;
	}
	}
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;User&lt;/code&gt; class does nothing more than to provide easy access to the sub-elements of &lt;code&gt;user&lt;/code&gt; element in the XML string.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Status.cs&lt;/b&gt;&lt;br /&gt;
Open notepad and copy following text in it. Then save it as &amp;quot;Status.cs&amp;quot; in the &lt;code&gt;/App_Code/&lt;/code&gt; sub-folder of your ASP.NET web application.&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using Stardeveloper.Twitter

namespace Stardeveloper.Twitter
{
	public class Status
	{
		protected static Regex UrlReplacement =
			new Regex(@&amp;quot;(https?://([\w-]+\.)+[\w-]+([^ ]*))&amp;quot;,
			RegexOptions.Compiled);
		protected static Regex UserNameReplacement =
			new Regex(@&amp;quot;@([\w_]+)&amp;quot;,
			RegexOptions.Compiled);

		public DateTime CreatedAt { get; protected set; }
		public long Id { get; protected set; }
		public string Text { get; protected set; }
		public string FormattedText { get; protected set; }
		public string Source { get; protected set; }
		public bool Truncated { get; protected set; }
		public long InReplyToStatusId { get; protected set; }
		public long InReplyToUserId { get; protected set; }
		public bool Favorited { get; protected set; }
		public string InReplyToScreenName { get; protected set; }
		public User User { get; protected set; }

		public Status(DateTime createdAt, long id, string text,
			string source, bool truncated, long inReplyToStatusId,
			long inReplyToUserId, bool favorited,
			string inReplyToScreenName, User user)
		{
			CreatedAt = createdAt;
			Id = id;
			Text = text;
			Source = source;
			Truncated = truncated;
			InReplyToStatusId = inReplyToStatusId;
			InReplyToUserId = inReplyToUserId;
			Favorited = favorited;
			InReplyToScreenName = inReplyToScreenName;
			User = user;

			FormattedText = UrlReplacement.Replace(text,
				&amp;quot;&amp;lt;a href=\&amp;quot;$1\&amp;quot;&amp;gt;$1&amp;lt;/a&amp;gt;&amp;quot;);
			FormattedText = UserNameReplacement.Replace(FormattedText,
				&amp;quot;@&amp;lt;a href=\&amp;quot;http://twitter.com/$1\&amp;quot;&amp;gt;$1&amp;lt;/a&amp;gt;&amp;quot;);

		}

		public override string ToString()
		{
			return Text;
		}
	}
}&lt;/pre&gt;&lt;p&gt;Apart from providing access to the sub-elements of &lt;code&gt;status&lt;/code&gt; element in the XML string, &lt;code&gt;Status&lt;/code&gt; class also lets you access the text of the status update in a formatted manner by accessing the &lt;code&gt;Status.FormattedText&lt;/code&gt; property. All the HTTP links and references to usernames are converted to clickable HTML links.&lt;/p&gt;

&lt;p&gt;For example, following status update is in plain text:&lt;/p&gt;

&lt;pre&gt;New tutorial published: Introduction to Twitter for 
	ASP.NET Developers http://bit.ly/17mAhX&lt;/pre&gt;

&lt;p&gt;It is formatted into following string:&lt;/p&gt;

&lt;pre&gt;New tutorial published: Introduction to Twitter for 
	ASP.NET Developers &lt;a href="http://bit.ly/17mAhX"&gt;http://bit.ly/17mAhX&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;Notice how the HTTP link was formatted to appear as a clickable link in your browser. This very useful property of &lt;code&gt;Status&lt;/code&gt; class will prove very handy when we'd want to display this status update on our website and will need all the links and references to be properly formatted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Status&lt;/code&gt; makes use of 2 regular expressions to convert the HTTP links and references to usernames, to clickable HTML links. These two regular expressions are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For HTTP links: @&amp;quot;&lt;code&gt;(https?://([\w-]+\.)+[\w-]+([^ ]*))&lt;/code&gt;&amp;quot;&lt;/li&gt;
&lt;li&gt;For references to usernames: @&amp;quot;&lt;code&gt;@([\w_]+)&lt;/code&gt;&amp;quot;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These regular expressions are statically compiled and will be executed at great speed on the server to format the text of the status update.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TwitterClient.cs&lt;/b&gt;&lt;br /&gt;
Open notepad and copy following text in it. Then save it as &amp;quot;TwitterClient.cs&amp;quot; in the &lt;code&gt;/App_Code/&lt;/code&gt; sub-folder of your ASP.NET web application.&lt;/p&gt;

&lt;pre&gt;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using Stardeveloper.Twitter;

namespace Stardeveloper.Twitter
{
	public class TwitterClient
	{
	public const string StatusesUserTimelineStr =
		&amp;quot;http://twitter.com/statuses/user_timeline.xml?&amp;quot; +
		&amp;quot;screen_name={0}&amp;amp;count={1}&amp;quot;;

	public TwitterClient()
	{
	}

	protected virtual string FetchXmlFromUrl(string url)
	{
		using (WebClient client = new WebClient())
		using (Stream s = client.OpenRead(url))
		using (StreamReader sr = new StreamReader(s))
		{
			return sr.ReadToEnd();
		}
	}

	protected virtual List&amp;lt;Status&amp;gt;
		CreateStatusObjectsFromXml(string xml, int count)
	{
		List&amp;lt;Status&amp;gt; statuses = new List&amp;lt;Status&amp;gt;(count);

		XmlDocument xmldoc = new XmlDocument();
		xmldoc.LoadXml(xml);

		foreach (XmlNode status in xmldoc.DocumentElement)
		{
		// created_at
		string value = status.SelectSingleNode(&amp;quot;created_at&amp;quot;).InnerXml;
		DateTime statusCreatedAt = ConvertStrToUtcDateTime(value);

		// id
		value = status.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
		long statusId = Convert.ToInt64(value);

		// text
		string text = status.SelectSingleNode(&amp;quot;text&amp;quot;).InnerXml;

		// source
		string source = status.SelectSingleNode(&amp;quot;source&amp;quot;).InnerXml;

		// truncated
		value = status.SelectSingleNode(&amp;quot;truncated&amp;quot;).InnerXml;
		bool truncated = Convert.ToBoolean(value);

		// in_reply_to_status_id
		value = status.SelectSingleNode(&amp;quot;in_reply_to_status_id&amp;quot;).InnerXml;
		long inReplyToStatusId = value != &amp;quot;&amp;quot; ? Convert.ToInt64(value) : 0;

		// in_reply_to_user_id
		value = status.SelectSingleNode(&amp;quot;in_reply_to_user_id&amp;quot;).InnerXml;
		long inReplyToUserId = value != &amp;quot;&amp;quot; ? Convert.ToInt64(value) : 0;

		// favorited
		value = status.SelectSingleNode(&amp;quot;favorited&amp;quot;).InnerXml;
		bool favorited = Convert.ToBoolean(value);

		// in_reply_to_screen_name
		string inReplyToScreenName =
			status.SelectSingleNode(&amp;quot;in_reply_to_screen_name&amp;quot;).InnerXml;

		/* Getting into user element */
		XmlNode user = status.SelectSingleNode(&amp;quot;user&amp;quot;);

		// id
		value = user.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
		long userId = Convert.ToInt64(value);

		// name
		string name = user.SelectSingleNode(&amp;quot;name&amp;quot;).InnerXml;

		// screen_name
		string screenName = user.SelectSingleNode(&amp;quot;screen_name&amp;quot;).InnerXml;

		// location
		string location = user.SelectSingleNode(&amp;quot;location&amp;quot;).InnerXml;

		// description
		string description = user.SelectSingleNode(&amp;quot;description&amp;quot;).InnerXml;

		// profile_image_url
		string profileImageUrl =
			user.SelectSingleNode(&amp;quot;profile_image_url&amp;quot;).InnerXml;

		// url
		string url = user.SelectSingleNode(&amp;quot;url&amp;quot;).InnerXml;

		// protected
		value = user.SelectSingleNode(&amp;quot;protected&amp;quot;).InnerXml;
		bool protectedstr = Convert.ToBoolean(value);

		// followers_count
		value = user.SelectSingleNode(&amp;quot;followers_count&amp;quot;).InnerXml;
		long followersCount = Convert.ToInt64(value);

		// profile_background_color
		string profileBackgroundColor =
			user.SelectSingleNode(&amp;quot;profile_background_color&amp;quot;).InnerXml;

		// profile_text_color
		string profileTextColor =
			user.SelectSingleNode(&amp;quot;profile_text_color&amp;quot;).InnerXml;

		// profile_link_color
		string profileLinkColor =
			user.SelectSingleNode(&amp;quot;profile_link_color&amp;quot;).InnerXml;

		// profile_sidebar_fill_color
		string profileSidebarFillColor =
			user.SelectSingleNode(&amp;quot;profile_sidebar_fill_color&amp;quot;).InnerXml;

		// profile_sidebar_border_color
		string profileSidebarBorderColor =
			user.SelectSingleNode(&amp;quot;profile_sidebar_border_color&amp;quot;)
				.InnerXml;

		// friends_count
		value = user.SelectSingleNode(&amp;quot;friends_count&amp;quot;).InnerXml;
		long friendsCount = Convert.ToInt64(value);

		// created_at
		value = user.SelectSingleNode(&amp;quot;created_at&amp;quot;).InnerXml;
		DateTime userCreatedAt = ConvertStrToUtcDateTime(value);

		// favourites_count
		value = user.SelectSingleNode(&amp;quot;favourites_count&amp;quot;).InnerXml;
		long favouritesCount = Convert.ToInt64(value);

		// utc_offset
		value = user.SelectSingleNode(&amp;quot;utc_offset&amp;quot;).InnerXml;
		int utcOffset = Convert.ToInt32(value);

		// time_zone
		string timeZone = user.SelectSingleNode(&amp;quot;time_zone&amp;quot;).InnerXml;

		// profile_background_image_url
		string profileBackgroundImageUrl =
			user.SelectSingleNode(&amp;quot;profile_background_image_url&amp;quot;)
				.InnerXml;

		// profile_background_tile
		value = user.SelectSingleNode(&amp;quot;profile_background_tile&amp;quot;).InnerXml;
		bool profileBackgroundTile = Convert.ToBoolean(value);

		// statuses_count
		value = user.SelectSingleNode(&amp;quot;statuses_count&amp;quot;).InnerXml;
		long statusesCount = Convert.ToInt64(value);

		// notifications
		string notifications =
			user.SelectSingleNode(&amp;quot;notifications&amp;quot;).InnerXml;

		// following
		string following = user.SelectSingleNode(&amp;quot;following&amp;quot;).InnerXml;

		/* Creating User object */
		User userobj = new User(userId, name, screenName, location,
			description, profileImageUrl, url, protectedstr,
			followersCount, profileBackgroundColor, profileTextColor,
			profileLinkColor, profileSidebarFillColor,
			profileSidebarBorderColor, friendsCount, userCreatedAt,
			favouritesCount, utcOffset, timeZone,
			profileBackgroundImageUrl, profileBackgroundTile,
			statusesCount, notifications, following);

		/* Creating Status object */
		Status statusobj = new Status(statusCreatedAt, statusId,
			text, source, truncated, inReplyToStatusId, inReplyToUserId,
			favorited, inReplyToScreenName, userobj);

		statuses.Add(statusobj);
		}

		return statuses;
	}&lt;pre&gt;
public Status GetLatestStatusUpdate(string screenName)
	{
		List&amp;lt;Status&amp;gt; statuses = GetStatusUpdates(screenName, 1);

		return statuses[0];
	}

	public List&amp;lt;Status&amp;gt; GetStatusUpdates(string screenName, int count)
	{
		string url = String.Format(StatusesUserTimelineStr, screenName,
			count);
		string xml = FetchXmlFromUrl(url);

		return CreateStatusObjectsFromXml(xml, count);
	}

	public static DateTime ConvertStrToUtcDateTime(string str)
	{
		string[] arr = str.Split(&amp;apos; &amp;apos;);

		int day, month, year, hour, min, sec;

		switch (arr[1])
		{
			case &amp;quot;Jan&amp;quot;:
				month = 1;
				break;
			case &amp;quot;Feb&amp;quot;:
				month = 2;
				break;
			case &amp;quot;Mar&amp;quot;:
				month = 3;
				break;
			case &amp;quot;Apr&amp;quot;:
				month = 4;
				break;
			case &amp;quot;May&amp;quot;:
				month = 5;
				break;
			case &amp;quot;Jun&amp;quot;:
				month = 6;
				break;
			case &amp;quot;Jul&amp;quot;:
				month = 7;
				break;
			case &amp;quot;Aug&amp;quot;:
				month = 8;
				break;
			case &amp;quot;Sep&amp;quot;:
				month = 9;
				break;
			case &amp;quot;Oct&amp;quot;:
				month = 10;
				break;
			case &amp;quot;Nov&amp;quot;:
				month = 11;
				break;
			case &amp;quot;Dec&amp;quot;:
				month = 12;
				break;
			default:
				throw new
					FormatException(&amp;quot;Unknown month.&amp;quot;);
		}

		day = Convert.ToInt32(arr[2]);

		string[] arr1 = arr[3].Split(&amp;apos;:&amp;apos;);

		hour = Convert.ToInt32(arr1[0]);
		min = Convert.ToInt32(arr1[1]);
		sec = Convert.ToInt32(arr1[2]);

		string offsetSign = arr[4].Substring(0, 1);
		int offsetHours = Convert.ToInt32(arr[4].Substring(1, 2));
		int offsetMinutes = Convert.ToInt32(arr[4].Substring(3, 2));

		year = Convert.ToInt32(arr[5]);

		DateTime dt = new DateTime(year, month, day, hour, min, sec);

		if (offsetSign == &amp;quot;+&amp;quot;)
		{
			dt.AddHours(offsetHours);
			dt.AddMinutes(offsetMinutes);
		}
		else if (offsetSign == &amp;quot;-&amp;quot;)
		{
			dt.AddHours(-offsetHours);
			dt.AddMinutes(-offsetMinutes);
		}

		return dt;
	}
	}
}&lt;/pre&gt;

&lt;p&gt;Don't be deterred by the length of the code in this class. The code is very simple to understand. The actual code that does the job of fetching the XML from the URL is this:&lt;/p&gt;

&lt;pre&gt;protected virtual string FetchXmlFromUrl(string url)
{
	using (WebClient client = new WebClient())
	using (Stream s = client.OpenRead(url))
	using (StreamReader sr = new StreamReader(s))
	{
		return sr.ReadToEnd();
	}
}&lt;/pre&gt;

&lt;p&gt;We create a &lt;code&gt;WebClient&lt;/code&gt; object and call its &lt;code&gt;OpenRead()&lt;/code&gt; method providing reference to the string containing the URL to send the HTTP GET request to. Once we have reference to the returned &lt;code&gt;Stream&lt;/code&gt; object, we create a new &lt;code&gt;StreamReader&lt;/code&gt; object to read this stream from beginning to end. By calling &lt;code&gt;StreamReader.ReadToEnd()&lt;/code&gt; method, we get the  &lt;code&gt;string&lt;/code&gt; object returned to us by Twitter API. This &lt;code&gt;string&lt;/code&gt; object actually is the XML string that we saw earlier in our browser. We will have to convert this raw XML string to &lt;code&gt;Status&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; objects to make use of it in our ASP.NET control later.&lt;/p&gt;

&lt;p&gt;The method that does the job of converting this raw XML string into &lt;code&gt;Status&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; objects is &lt;code&gt;CreateStatusObjectsFromXml()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
protected virtual List&lt;Status&gt;
	CreateStatusObjectsFromXml(string xml, int count)
{
	List&amp;lt;Status&amp;gt; statuses = new List&amp;lt;Status&amp;gt;(count);
	
	...
	
	return statuses;
}&lt;/pre&gt;

&lt;p&gt;It creates a list of &lt;code&gt;Status&lt;/code&gt; objects. Each &lt;code&gt;Status&lt;/code&gt; object corresponds to one &lt;code&gt;status&lt;/code&gt; element in the XML string i.e., to one status update on Twitter. Since there can be more than one &lt;code&gt;status&lt;/code&gt; elements returned, depending on the &lt;code&gt;count&lt;/code&gt; parameter, we create a list of &lt;code&gt;Status&lt;/code&gt; objects to incorporate as many &lt;code&gt;status&lt;/code&gt; elements as possible.&lt;/p&gt;

&lt;p&gt;Now that we need to access the values of elements from the returned XML string, we create an &lt;code&gt;XmlDocument&lt;/code&gt; object to make this task easy for us.&lt;/p&gt;

&lt;pre&gt;
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xml);

foreach (XmlNode status in xmldoc.DocumentElement)
{
	...
}&lt;/pre&gt;

&lt;p&gt;As shown in the code above, we then iterate through this XML string, one node at a time, i.e., one &lt;code&gt;status&lt;/code&gt; element at a time. In each iteration, we create a &lt;code&gt;User&lt;/code&gt; and a &lt;code&gt;Status&lt;/code&gt; object. We properly set the properties of these objects to the values fetched from their XML counterparts as shown below:&lt;/p&gt;

&lt;pre&gt;
foreach (XmlNode status in xmldoc.DocumentElement)
{
	// created_at
	string value = status.SelectSingleNode(&amp;quot;created_at&amp;quot;).InnerXml;
	DateTime statusCreatedAt = ConvertStrToUtcDateTime(value);

	// id
	value = status.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
	long statusId = Convert.ToInt64(value);

	...

	/* Getting into user element */
	XmlNode user = status.SelectSingleNode(&amp;quot;user&amp;quot;);

	// id
	value = user.SelectSingleNode(&amp;quot;id&amp;quot;).InnerXml;
	long userId = Convert.ToInt64(value);

	// name
	string name = user.SelectSingleNode(&amp;quot;name&amp;quot;).InnerXml;

	...

	/* Creating User object */
	User userobj = new User(userId, name, screenName, location,
		description, profileImageUrl, url, protectedstr,
		followersCount, profileBackgroundColor, profileTextColor,
		profileLinkColor, profileSidebarFillColor,
		profileSidebarBorderColor, friendsCount, userCreatedAt,
		favouritesCount, utcOffset, timeZone,
		profileBackgroundImageUrl, profileBackgroundTile,
		statusesCount, notifications, following);

	/* Creating Status object */
	Status statusobj = new Status(statusCreatedAt, statusId,
		text, source, truncated, inReplyToStatusId, inReplyToUserId,
		favorited, inReplyToScreenName, userobj);

	statuses.Add(statusobj);
}&lt;/pre&gt;

&lt;p&gt;Above segment of code is a stripped down version of the code that fetches the XML values, creates new &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Status&lt;/code&gt; objects, and sets the properties of these objects to fetched XML values. All of this code is run, again and again, for each iteration of the &lt;code&gt;status&lt;/code&gt; element in the returned XML string.&lt;/p&gt;

&lt;p&gt;All of the calls to previous methods are encapsulated in a very simple to call &lt;code&gt;public&lt;/code&gt; method of &lt;code&gt;TwitterClient&lt;/code&gt; object; &lt;code&gt;GetStatusUpdates()&lt;/code&gt;, which returns a list of &lt;code&gt;Status&lt;/code&gt; objects:&lt;/p&gt;

&lt;pre&gt;
public List&amp;lt;Status&amp;gt; GetStatusUpdates(string screenName, int count)
{
	string url = String.Format(StatusesUserTimelineStr, screenName,
		count);
	string xml = FetchXmlFromUrl(url);

	return CreateStatusObjectsFromXml(xml, count);
}&lt;/pre&gt;

&lt;p&gt;Another method is also provided if you only want to retrieve the latest status update:&lt;/p&gt;

&lt;pre&gt;
public Status GetLatestStatusUpdate(string screenName)
{
	List&amp;lt;Status&amp;gt; statuses = GetStatusUpdates(screenName, 1);

	return statuses[0];
}&lt;/pre&gt;

&lt;p&gt;Lastly, the code in the method &lt;code&gt;ConvertStrToUtcDateTime()&lt;/code&gt;, rips apart the date &amp;amp; time string in the parameter and creates a new &lt;code&gt;DateTime&lt;/code&gt; structure and properly sets its properties to the values fetched from the date &amp;amp; time string. This method is very handy in converting UTC date &amp;amp; time strings that Twitter API returns to UTC &lt;code&gt;DateTime&lt;/code&gt; objects that our ASP.NET code can understand.&lt;/p&gt;&lt;pre&gt;
public static DateTime ConvertStrToUtcDateTime(string str)
{
	...
}&lt;/pre&gt;

&lt;p&gt;Once we have properly placed all the 3 *.cs files and have understood the code, we should move on to create the ASP.NET control that accesses this code to display the status update on our website.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TwitterControl.ascx&lt;/b&gt;&lt;br /&gt;
Open notepad and copy following text in it. Then save it as &amp;quot;TwitterControl.ascx&amp;quot; in the main folder of your ASP.NET web application.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Control Language=&amp;quot;C#&amp;quot; ClassName=&amp;quot;TwitterControl&amp;quot; %&amp;gt;

&amp;lt;%@ OutputCache VaryByParam=&amp;quot;none&amp;quot; Duration=&amp;quot;1200&amp;quot; Shared=&amp;quot;true&amp;quot; %&amp;gt;

&amp;lt;%@ Import Namespace=&amp;quot;Stardeveloper.Twitter&amp;quot; %&amp;gt;

&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	protected void Page_Load(object source, EventArgs e)
	{
		TwitterClient client = new TwitterClient();
		Status status = client.GetLatestStatusUpdate(&amp;quot;stardeveloper&amp;quot;);

		// Setting Status Text
		TwitterLiteral.Text = status.FormattedText;
		
		// Setting Status Date
		DateTime createdAt = status.CreatedAt;
		DateTime utcNow = DateTime.UtcNow;

		if (createdAt.Year == utcNow.Year &amp;amp;&amp;amp;
			createdAt.Month == utcNow.Month &amp;amp;&amp;amp;
			createdAt.Day == utcNow.Day)
			TwitterDateLiteral.Text = &amp;quot;&amp;lt;b&amp;gt;Today&amp;lt;/b&amp;gt;&amp;quot;;
		else
			TwitterDateLiteral.Text = &amp;quot;on &amp;quot; +
				status.CreatedAt.ToShortDateString();
	}
&amp;lt;/script&amp;gt;

&amp;lt;div&amp;gt;Stardeveloper Update&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;
	&amp;lt;asp:Literal ID=&amp;quot;TwitterLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt; 
	(&amp;lt;asp:Literal ID=&amp;quot;TwitterDateLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;)
&amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;
	&amp;lt;a href=&amp;quot;http://twitter.com/stardeveloper&amp;quot;&amp;gt;See all updates&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;

&lt;p&gt;The code in the &lt;code&gt;TwitterControl.ascx&lt;/code&gt; control fetches the latest status update as a &lt;code&gt;Status&lt;/code&gt; object and then sets the text of one of the &lt;code&gt;Literal&lt;/code&gt; controls on the page to the value of the &lt;code&gt;Status.FormattedText&lt;/code&gt; property. The most important lines of the code have been highlighted above.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;TwitterUpdate.aspx&lt;/b&gt;&lt;br /&gt;
Open notepad and copy following text in it. Then save it as &amp;quot;TwitterUpdate.aspx&amp;quot; in the main folder of your ASP.NET web application.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;

&amp;lt;%@ Register TagPrefix=&amp;quot;sd&amp;quot; TagName=&amp;quot;Twitter&amp;quot; Src=&amp;quot;~/TwitterControl.ascx&amp;quot; %&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
    .twitter-update { font-family: &amp;quot;Georgia&amp;quot;; font-size: 8pt;
		width: 300px; padding: 20px; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;twitter-update&amp;quot;&amp;gt;
		&amp;lt;sd:Twitter runat=&amp;quot;server&amp;quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;We created a very simple ASP.NET page that uses the control we created earlier to display the latest status update of a user (which in this case is &lt;a href="http://twitter.com/stardeveloper" target="_blank"&gt;stardeveloper&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;When all files that we created above were placed at proper places and TwitterUpdate.aspx page was called, this is the result that I got in my browser:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009061701_twitter-update.gif" width="284" height="80" border="0" alt="Latest status update using TwitterUpdate.aspx" /&gt;
&lt;/div&gt;

&lt;p&gt;The same code is used at Stardeveloper.com to display the latest status update. After changing the CSS formatting a little bit, this is how it looks on Stardeveloper.com:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009061701_twitter-update-on-stardeveloper.gif" width="162" height="125" border="0" alt="Latest status update on Stardeveloper.com" /&gt;
&lt;/div&gt;

&lt;p&gt;This is it as far as the code to retrieve and display the latest status update from Twitter, was concerned.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; You should keep in mind that the code for all the classes that we created in this tutorial will change as we continue to add more code in the upcoming tutorials.&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
After &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061401&amp;page=1"&gt;introducing Twitter&lt;/a&gt; in the last article, we looked at the code to retrieve and display the latest status update of a user from Twitter, in this tutorial. Much of the code was quite simple. After creating the classes, all that is left to make use of them in ASP.NET controls and pages is nothing more than 2-3 lines of code.&lt;/p&gt;

&lt;p&gt;In the next tutorial, &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009062001&amp;page=1"&gt;Displaying Twitter Updates in a Page by Page fashion with ASP.NET&lt;/a&gt;, we will learn how to page through Twitter updates, an essential technique to learn if you are interested in displaying more than one status update to the user.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=HIxLqs0-2Fc:UCrfYlv5Nl4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=HIxLqs0-2Fc:UCrfYlv5Nl4:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/HIxLqs0-2Fc" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009061701&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Wed, 17 Jun 2009 07:33:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1</feedburner:origLink></item>
<item>
<title>Introduction to Twitter for ASP.NET Developers</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/dNWEEqvMyk4/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
Twitter is a free social networking service that lets its users communicate with each other through short text messages. There is a limit of 140 characters per message. Users can send messages using online website, mobile devices or by sending SMS from their cell phones. These messages, known as &amp;apos&lt;i&gt;tweets&lt;/i&gt;&amp;apos; are then delivered, by a variety of means, to the users who have subscribed to receive them; known as &amp;apos;&lt;i&gt;followers&lt;/i&gt;&amp;apos;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Guidelines for sending Messages&lt;/b&gt;&lt;br /&gt;
In text messages, username of the person you are replying to should start with &amp;apos@&amp;apos; (at) sign e.g., @Stardeveloper. Twitter will convert these usernames in the text messages to clickable links e.g., &amp;quot;Hello &lt;a href="http://twitter.com/stardeveloper"&gt;@Stardeveloper&lt;/a&gt;!&amp;quot;.&lt;/p&gt;


&lt;p&gt;This tutorial is 1st in the series of tutorials regarding Twitter and ASP.NET:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Twitter for ASP.NET Developers&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1"&gt;Retrieving Twitter Updates with ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009062001&amp;page=1"&gt;Displaying Twitter Updates in a Page by Page fashion with ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Connecting with your Audience&lt;/b&gt;&lt;br /&gt;
Twitter provides another opportunity for ASP.NET developers to connect with their website audience. ASP.NET developers can create accounts with screen names of their websites e.g., &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt; (Faisal Khan). This account can then be used as a micro-blog for the website. Not only should the status updates include important website updates, but should also focus on the interesting things you, as a developer, are working on or can benefit your audience. A link is placed on the website linking to the Twitter profile, giving users the opportunity to view the profile, and if he/she chooses so, to start following this account.&lt;/p&gt;

&lt;p&gt;Following image shows how a link to &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt;'s (Faisal Khan) profile is placed on Stardeveloper.com's home page:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;a href="http://twitter.com/Stardeveloper"&gt;&lt;img src="http://www.stardeveloper.com/images/articles/2009061401_follow-stardeveloper-at-twitter.gif" width="156" height="69" alt="Follow Stardeveloper at Twitter" border="0" /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;Following image shows how Twitter API is being used to pull the latest update from &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt;'s (Faisal Khan) profile:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;a href="http://twitter.com/Stardeveloper"&gt;&lt;img src="http://www.stardeveloper.com/images/articles/2009061401_stardeveloper-update.gif" width="178" height="200" alt="Stardeveloper Update" border="0" /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;We will learn how to use Twitter API in ASP.NET pages in upcoming tutorials.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;What is in it for ASP.NET Developers?&lt;/b&gt;&lt;br /&gt;
While much of this can be done by any developer or webmaster, doing it with ASP.NET allows us to harness the Twitter API and display those updates right on our own websites. We can even create a separate private Twitter account for things like logging website activity. Twitter API can be used to actually create status updates for website usage, errors, files missing, DOS attacks, etc. Then chosen users who work on our website can follow that account and be notified of things going on within the website. Thus separate Twitter accounts can be used for different purposes, all harnessing the Twitter API.&lt;/p&gt;

&lt;p&gt;Following is a small list of things you can do with Twitter API in your ASP.NET web application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Twitter account with status updated related to your website and interesting things you are working on or can benefit your audience e.g., @WebsiteName.&lt;/li&gt;
&lt;li&gt;Display status updates right on your website using .NET and the Twitter API.&lt;/li&gt;
&lt;li&gt;Create separate Twitter account which only your selected users can follow. You can use a screen name such as @WebsiteName-Development, to share and synchronize the development you are doing on your web application.&lt;/li&gt;
&lt;li&gt;Create separate Twitter account which only selected users can follow e.g., @WebsiteName-Log. You can use the Twitter API in your ASP.NET web application to log all the website activity in that Twitter account. You can log messages like memory cache size, articles cached, site stats, error messages, database activity, files not found, etc. Your own developers should follow this account to keep a tap on your web application.&lt;/li&gt;
&lt;li&gt;You can use your cell phone and control your website via SMS. Here is how you can do it: Create two separate Twitter accounts e.g., @WebsiteName-Acc1 and @WebsiteName-Acc2. You should develop code in your ASP.NET applicaton to follow (&lt;i&gt;listen&lt;/i&gt; for any messages in) @WebsiteName-Acc1 account. You should then send an SMS with text message like &amp;quot;STATS&amp;quot; to @WebsiteName-Acc1 account. Your ASP.NET code should wakeup every minute to check for new messages in this account. As soon as your SMS arrives, the code scans the text and finds the command. It then acts on the command and creates a new text message by retrieving web application stats from the database and sending this message to @WebsiteName-Acc2 Twitter account. Now you should be following this second account. As soon as ASP.NET application delivers a message to this second account, it gets delivered to your cell phone as an SMS with text like &amp;quot;Active Uses: 132, Total Users Today: 3,456, Page Views Today: 9,677&amp;quot;. You can add more commands to your liking and control your ASP.NET application from your SMS enabled cell phone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;The Twitter API&lt;/b&gt;&lt;br /&gt;
Twitter offers a comprehensive, yet simple, API to developers. It is based on simple HTTP GET and POST requests. As ASP.NET developers, we can create a .NET API on top of it to make tasks such as creating and retrieving updates even simpler. On ASP.NET pages, we can then use custom controls to display things like status updates, number of followers, etc. A control that displays the latest status update from &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt; has already been shown in the image above, we will study its code in next tutorial.&lt;/p&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Tip:&lt;/b&gt; You can follow the &lt;a href="http://twitter.com/stardeveloper"&gt;Stardeveloper&lt;/a&gt; account on Twitter or you can subscribe to my newsletter (at the top left of this page) to be notified of the latest tutorials, articles and updates at Stardeveloper.com.&lt;/div&gt;

&lt;p&gt;In the next tutorial, we will learn &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009061701&amp;page=1"&gt;how to use Twitter API to retrieve latest status updates in our ASP.NET application&lt;/a&gt;. Rest assured it will be simple, yet interesting. It will give you new ideas for your ASP.NET web application. In the mean time you should create your own Twitter account, if you don't have one, as the things are only going to get more interesting from here onwards. Good luck!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=dNWEEqvMyk4:78DEVjwozKo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=dNWEEqvMyk4:78DEVjwozKo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/dNWEEqvMyk4" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009061401&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Sat, 13 Jun 2009 12:49:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009061401&amp;page=1</feedburner:origLink></item>
<item>
<title>Validating an XML Document using DTD in ASP.NET</title>
<link>http://feeds.stardeveloper.com/~r/StardevelopercomArticleHeadlines/~3/AOnPbjy19qY/display.html</link>
<description>&lt;p&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;
In this tutorial, we will learn how to validate an &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009030101&amp;page=1"&gt;XML&lt;/a&gt; document using &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009052601&amp;page=1"&gt;DTD&lt;/a&gt;. We will develop an ASP.NET page to demonstrate the code. After you are finished reading this tutorial, you will be proficient in writing C# code that validates XML documents using DTD.&lt;/p&gt;

&lt;p&gt;Following topics will be covered in this tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="#xml-wellformedness-validation"&gt;Well-formedness vs Validation.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#xml-validation-dtd"&gt;Validating XML Document using DTD.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tutorial is 6th one in the series of tutorials about XML and ASP.NET:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009030101&amp;page=1"&gt;Introduction to XML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009030701&amp;page=1"&gt;Reading XML Files with ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009031001&amp;page=1"&gt;Introduction to XPath for ASP.NET Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009031901&amp;page=1"&gt;Creating new XML Document in ASP.NET Programmatically&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009052601&amp;page=1"&gt;Introduction to DTD (Document Type Definition)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Validating an XML Document using DTD in ASP.NET&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will first refresh ourselves with basic XML concepts of well-formedness and validation, and later develop the code to validate XML document using DTD.&lt;/p&gt;

&lt;a name="xml-wellformedness-validation"&gt;&lt;/a&gt;
&lt;p&gt;&lt;b&gt;Well-formedness vs Validation&lt;/b&gt;&lt;br /&gt;
Well-formedness means that an XML document obeys the rules that are necessary for an XML document to be, frankly, an XML document. What this means is that there should be an XML declaration, there should be a root element, the name of element in opening tag must match with the name in the closing tag, and so on. We covered a good part of it in the first article on &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009030101&amp;page=1"&gt;introduction to XML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Validation on the other hand is an entirely different thing. An XML document is &lt;em&gt;valid&lt;/em&gt; only if it conforms to the constraints declared in DTD. Put it simply, if the structure of an XML document is exactly as it is described in DTD, then that XML document is valid (in reference to that DTD), otherwise it is not.&lt;/p&gt;

&lt;a name="xml-validation-dtd"&gt;&lt;/a&gt;
&lt;p&gt;&lt;b&gt;Validating XML Document using DTD&lt;/b&gt;&lt;br /&gt;
We will use the sample XML document and DTD file from the article on &lt;a href="http://www.stardeveloper.com/articles/display.html?article=2009052601&amp;page=1"&gt;Document Type Definition&lt;/a&gt;. We will then write code to validate that XML document using that DTD.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Sample XML Document&lt;/b&gt;&lt;br /&gt;
Following is the XML document that we will be using for demonstration:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;

&amp;lt;!DOCTYPE article SYSTEM &amp;quot;article.dtd&amp;quot;&amp;gt;

&amp;lt;article&amp;gt;
	&amp;lt;title&amp;gt;Sample XML Document.&amp;lt;/title&amp;gt;
	&amp;lt;author email=&amp;quot;hidden@xyz.com&amp;quot;&amp;gt;Faisal Khan&amp;lt;/author&amp;gt;
	&amp;lt;body&amp;gt;This is a sample XML Document.&amp;lt;/body&amp;gt;
&amp;lt;/article&amp;gt;&lt;/pre&gt;

&lt;p&gt;Copy above code in a new text file and save it as &amp;quot;article.xml&amp;quot; in the /App_Data folder of your ASP.NET application.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Sample DTD File&lt;/b&gt;&lt;br /&gt;
Following is the DTD file that we will be using for demonstration:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;!ELEMENT article (title, author?, body)&amp;gt;
&amp;lt;!ELEMENT title (#PCDATA)&amp;gt;
&amp;lt;!ELEMENT author (#PCDATA)&amp;gt; 
&amp;lt;!ELEMENT body (#PCDATA)&amp;gt;

&amp;lt;!ATTLIST author email CDATA #REQUIRED&amp;gt;&lt;/pre&gt;

&lt;p&gt;Copy above code in a new text file and save it as &amp;quot;article.dtd&amp;quot; in the /App_Data folder of your ASP.NET application.&lt;/p&gt;

&lt;p&gt;If you look at the XML document and DTD file closely, you'll see that the XML document conforms to the constraints in the DTD file, and is thus, a &lt;em&gt;valid&lt;/em&gt; XML document with respect to that DTD file. To do this manual verfication programmatically, we'll have to write code. Luckily, in .NET, writing code that validates an XML document is quite simple.&lt;/p&gt;&lt;p&gt;&lt;b&gt;ASP.NET Page that Validates an XML Document using DTD&lt;/b&gt;&lt;br /&gt;
Copy following code in a new text file and save it as &amp;quot;ValidateXml.aspx&amp;quot; in your ASP.NET application:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;

&amp;lt;%@ Import Namespace=&amp;quot;System.Xml&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Xml.Schema&amp;quot; %&amp;gt;

&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	private bool valid = true;
	private StringBuilder msgs = new StringBuilder();

	protected void Page_Load(object source, EventArgs e)
	{
		string fullPathToXmlFile = Server.MapPath(&amp;quot;~/App_Data/article.xml&amp;quot;);

		XmlReaderSettings settings = new XmlReaderSettings();
		settings.ProhibitDtd = false;
		settings.ValidationType = ValidationType.DTD;
		settings.ValidationEventHandler +=
			new ValidationEventHandler(ValidationHandler);

		XmlReader reader = XmlReader.Create(fullPathToXmlFile, settings);

		while (reader.Read())
			;

		reader.Close();
		reader = null;

		if (valid == true)
			StatusLiteral.Text = &amp;quot;Is Valid&amp;quot;;
		else
			StatusLiteral.Text = &amp;quot;Is NOT Valid&amp;quot;;

		MessagesLiteral.Text = msgs.ToString();
	}

	protected void ValidationHandler(object sender, ValidationEventArgs args)
	{
		valid = false;

		msgs.Append(args.Message);
		msgs.Append(&amp;quot;&amp;lt;br /&amp;gt;&amp;quot;);
	}
&amp;lt;/script&amp;gt;

&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot;
	&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;
&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;
    &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;
    body { font-family: Verdana; font-size: 9pt; }
    pre { font-family: Lucida Console; font-size: 8pt; }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;
    &amp;lt;div&amp;gt;&amp;lt;asp:Label ID=&amp;quot;StatusLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;pre&amp;gt;&amp;lt;asp:Literal ID=&amp;quot;MessagesLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&amp;lt;/pre&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Explanation&lt;/b&gt;&lt;br /&gt;
Since our code is going to be in the language, C#, we declare it as the first line in our ASP.NET page.&lt;/p&gt;

&lt;pre&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;Next, we import the namespaces that we will be using in validating the XML document.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Xml&amp;quot; %&amp;gt;
&amp;lt;%@ Import Namespace=&amp;quot;System.Xml.Schema&amp;quot; %&amp;gt;&lt;/pre&gt;

&lt;p&gt;We place our code in script tags.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;script runat=&amp;quot;server&amp;quot;&amp;gt;
	...
&amp;lt;/script&amp;gt;&lt;/pre&gt;

&lt;p&gt;Before we look at the code, we should see what server side controls we have laid in-between the HTML to display status messages to the user. &lt;code&gt;StatusLiteral&lt;/code&gt; will display the success or failure of the validation process in one sentence. &lt;code&gt;MessagesLiteral&lt;/code&gt; will display all the failure messages, if any, to the user in detail.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;asp:Label ID=&amp;quot;StatusLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;
&amp;lt;asp:Literal ID=&amp;quot;MessagesLiteral&amp;quot; runat=&amp;quot;server&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now, we will delve ourselves into the real code that does the validation. We are using two instance level variables to hold the data for this request. The first variable, &lt;code&gt;valid&lt;/code&gt;, will be set to &lt;code&gt;false&lt;/code&gt; by a segment of code later if the XML document turns out to be invalid. The second variable, &lt;code&gt;msgs&lt;/code&gt;, will be appended error messages one after the other (again, if any), and displayed to the user in the end.&lt;/p&gt;

&lt;pre&gt;
private bool valid = true;
private StringBuilder msgs = new StringBuilder();&lt;/pre&gt;

&lt;p&gt;We have placed our code in the &lt;code&gt;Load&lt;/code&gt; event of the &lt;code&gt;Page&lt;/code&gt; object. This way, every time the page loads, our code will be run.&lt;/p&gt;

&lt;pre&gt;
protected void Page_Load(object source, EventArgs e)
{
	..
}&lt;/pre&gt;

&lt;p&gt;The first thing we do is to get the full physical path to the &amp;apos;article.xml&amp;apos; file, using &lt;code&gt;Server.MapPath()&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;
string fullPathToXmlFile = Server.MapPath(&amp;quot;~/App_Data/article.xml&amp;quot;);&lt;/pre&gt;

&lt;div align="center" style="background-color: #F7F7F7;"&gt;&lt;b&gt;Note:&lt;/b&gt; There is no direct reference to the &amp;apos;article.dtd&amp;apos; file in the code. It will be loaded by the objects we create later, automatically from the &lt;code&gt;DOCTYPE&lt;/code&gt; declaration given in the &amp;apos;article.xml&amp;apos; file.&lt;/div&gt;

&lt;p&gt;Next, we create an instance of &lt;code&gt;XmlReaderSettings&lt;/code&gt; object. This object contains the settings we want to use later when are about to the read the XML document. This object is required to create the &lt;code&gt;XmlReader&lt;/code&gt; object later. In the settings, we set its properties so that it knows we want to use DTD to validate an XML document. We also set a &lt;code&gt;ValidationEventHanlder&lt;/code&gt; method. We do this so that every time an error is thrown if the XML document contains invalid segments, we can set the &lt;code&gt;valid&lt;/code&gt; property to &lt;code&gt;false&lt;/code&gt; and append the error message to the &lt;code&gt;msgs&lt;/code&gt; variable.&lt;/p&gt;

&lt;pre&gt;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.ValidationType = ValidationType.DTD;
settings.ValidationEventHandler +=
	new ValidationEventHandler(ValidationHandler);&lt;/pre&gt;

&lt;p&gt;The working of this event handler has already been explained.&lt;/p&gt;

&lt;pre&gt;
protected void ValidationHandler(object sender, ValidationEventArgs args)
{
	valid = false;

	msgs.Append(args.Message);
	msgs.Append(&amp;quot;&amp;lt;br /&amp;gt;&amp;quot;);
}&lt;/pre&gt;

&lt;p&gt;It is this &lt;code&gt;XmlReader&lt;/code&gt; object which we create that does the actual job of validating the XML document against that DTD. We create it by calling a static method of &lt;code&gt;XmlReader&lt;/code&gt; object and passing as its arguments, the reference to full physical path of the XML document and a reference to the &lt;code&gt;XmlReaderSettings&lt;/code&gt; object which we created earlier.&lt;/p&gt;

&lt;pre&gt;
XmlReader reader = XmlReader.Create(fullPathToXmlFile, settings);&lt;/pre&gt;

&lt;p&gt;Once we have created the &lt;code&gt;XmlReader&lt;/code&gt; object, we enter a &lt;code&gt;while&lt;/code&gt; loop to repeatidly call its &lt;code&gt;Read()&lt;/code&gt; method. In each iteration, the &lt;code&gt;XmlReader&lt;/code&gt; object examines each node of the XML document. Any error messages that generated during the call to this method are handled by our event handler method we set earlier and are saved to be displayed to the user, later.&lt;/p&gt;

&lt;pre&gt;
while (reader.Read())
	;&lt;/pre&gt;

&lt;p&gt;Once all the nodes have been examined, we close the &lt;code&gt;XmlReader&lt;/code&gt; object.&lt;/p&gt;

&lt;pre&gt;
reader.Close();
reader = null;&lt;/pre&gt;

&lt;p&gt;We set the text to be displayed to the user depending if the &lt;code&gt;valid&lt;/code&gt; variable is &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. This variable will be &lt;code&gt;false&lt;/code&gt; if even a single error was encountered during validating the XML document.&lt;/p&gt;

&lt;pre&gt;
if (valid == true)
	StatusLiteral.Text = &amp;quot;Is Valid&amp;quot;;
else
	StatusLiteral.Text = &amp;quot;Is NOT Valid&amp;quot;;&lt;/pre&gt;

&lt;p&gt;Error messages, if any, are set to the appropriate control, to be displayed to the user.&lt;/p&gt;

&lt;pre&gt;
MessagesLiteral.Text = msgs.ToString();&lt;/pre&gt;&lt;p&gt;This is pretty much it. The code is extremely simple and easy to understand and use. When this ASP.NET page was run with the XML document and DTD file as given in this tutorial above, it produced following result:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009060501_xml-valid-dtd.gif" width="52" height="19" border="0" alt="ASP.NET Page Validating an XML Document" /&gt;
&lt;/div&gt;

&lt;p&gt;This XML document was a valid XML document to begin with, and we validated it against that DTD, programmatically. Now let us see what happens if we change the XML document a bit, by adding one extra element, so that the XML document becomes non-conforming. After adding one extra element, the XML document looks like this:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;

&amp;lt;!DOCTYPE article SYSTEM &amp;quot;article.dtd&amp;quot;&amp;gt;

&amp;lt;article&amp;gt;
	&amp;lt;title&amp;gt;Sample XML Document.&amp;lt;/title&amp;gt;
	&amp;lt;author email=&amp;quot;hidden@xyz.com&amp;quot;&amp;gt;Faisal Khan&amp;lt;/author&amp;gt;
	&amp;lt;body&amp;gt;This is a sample XML Document.&amp;lt;/body&amp;gt;
	&amp;lt;test&amp;gt;Hello&amp;lt;/test&amp;gt;
&amp;lt;/article&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now, when I accessed &amp;apos;ValidateXml.aspx&amp;apos; from my browser, it produced following result:&lt;/p&gt;

&lt;div align="center"&gt;
&lt;img src="http://www.stardeveloper.com/images/articles/2009060501_xml-invalid-dtd.gif" width="387" height="51" border="0" alt="ASP.NET Page Validating an XML Document" /&gt;
&lt;/div&gt;

&lt;p&gt;You can see that the ASP.NET page was able to successfully identify the document as invalid. The detailed error message shows that an extra &amp;apos;test&amp;apos; element was found in the XML document which was not declared in the DTD.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;
In this tutorial, we learned the code to programmatically validate an XML document with DTD.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=AOnPbjy19qY:410NUPHsYUc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.stardeveloper.com/~ff/StardevelopercomArticleHeadlines?a=AOnPbjy19qY:410NUPHsYUc:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StardevelopercomArticleHeadlines?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StardevelopercomArticleHeadlines/~4/AOnPbjy19qY" height="1" width="1"/&gt;</description>
<guid isPermaLink="false"><![CDATA[http://www.stardeveloper.com/articles/display.html?article=2009060501&page=1]]></guid>
<author>Faisal Khan</author>
<pubDate>Fri, 05 Jun 2009 03:36:00 GMT</pubDate>
<atom:link href="http://feeds.stardeveloper.com/StardevelopercomArticleHeadlines" rel="self" type="application/rss+xml" /><feedburner:origLink>http://www.stardeveloper.com/articles/display.html?article=2009060501&amp;page=1</feedburner:origLink></item>
</channel>
</rss>
