Friday, November 14, 2008

POP-Before-SMTP

Dot .Net Dilemmas

I recently had to move one of my web applications off one hosting provider (that changed their trust levels without informing anyone) and on to a new hosting provider where I could set the trust level in my web.config file. I wanted to keep the web and mail service on the old provider as transferring the domain to the new provider could have meant even more downtime for my client and she really couldn't afford that (who could at the moment?).

Anyhow, all was ok until I was testing the application on the new server, went to purchases some sessions and BANG! Another issue raised its ugly head; 

"The server rejected one or more recipient addresses. The server response was: 450 : Recipient address rejected: Greylisted for 5 minutes"

I contacted my old hosting provider and the response I got back was;
"If a valid POP login is not received before sending mail through the server, then the mail is greylisted and held for 5 minutes before a retry"

To the point but, it didn’t actually explain how I might do this. They actually suggested that;

“The easiest way would be to click on "Send/Receive" in the email software before sending the email."

Even though they knew that the email was being created from within code.

I posted a message on Stackoverflow, and found out that I would basically have to write the code myself, as ‘POP3 is not built into the .NET framework’.

Below is the code that I put in place. Basically, I do a POP-Before-SMTP. This logs me into the POP3 server, my credentials are authenticated and I can send the email that I need to send, immediately after the call. (I tried to put snapshots in here but the quality was awful.)

Ultimately, I will move everything over the new hosting provider (and hopefully talk my client into moving to a dedicated server) but for now, this works perfectly well.

using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace Pop3
{
public class Pop3Client
{
private Pop3Credential m_credential;
private const int m_pop3port = 110;
private const int MAX_BUFFER_READ_SIZE = 256;
private long m_inboxPosition = 0;
private long m_directPosition = -1;
private Socket m_socket = null;
   private Pop3Message m_pop3Message = null;

public Pop3Credential UserDetails
{
set { m_credential = value; }
get { return m_credential; }
}

public string From
{get { return m_pop3Message.From; }}

public string To
{get { return m_pop3Message.To; }}

public string Subject
{get { return m_pop3Message.Subject; }}

public string Body
{get { return m_pop3Message.Body; }}

public IEnumerator MultipartEnumerator
{get { return m_pop3Message.MultipartEnumerator; }}

public bool IsMultipart
{get { return m_pop3Message.IsMultipart; }}


public Pop3Client(string user, string pass, string server)
{m_credential = new Pop3Credential(user,pass,server);}

private Socket GetClientSocket()
{
Socket s = null;

try
{
IPHostEntry hostEntry = null;

// Get host related information.

hostEntry = Dns.GetHostEntry(m_credential.Server);

// Loop through the AddressList to obtain the supported
// AddressFamily. This is to avoid an exception that
// occurs when the host IP Address is not compatible
// with the address family
// (typical in the IPv6 case).

foreach(IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, m_pop3port);

Socket tempSocket =
new Socket(ipe.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);

tempSocket.Connect(ipe);

if(tempSocket.Connected)
{
// we have a connection.
// return this socket ...
s = tempSocket;
break;
}
else
{
continue;
}
}
}
catch(Exception e)
{
throw new Pop3ConnectException(e.ToString());
}
// throw exception if can't connect ...
if(s == null)
{
throw new Pop3ConnectException("Error : connecting to "
+m_credential.Server);
}
   return s;
}

private string GetPop3String()
{
if(m_socket == null)
{
throw new
Pop3MessageException("Connection to POP3 server is closed");
}

byte[] buffer = new byte[MAX_BUFFER_READ_SIZE];
string line = null;

try
{
int byteCount =
m_socket.Receive(buffer,buffer.Length,0);
line =
Encoding.ASCII.GetString(buffer, 0, byteCount);
}
catch(Exception e)
{
throw new Pop3ReceiveException(e.ToString());
}

return line;
}

private void LoginToInbox()
{
string returned;

// send username ...
Send("user "+m_credential.User);

// get response ...
returned = GetPop3String();

if( !returned.Substring(0,3).Equals("+OK") )
{
throw new Pop3LoginException("login not excepted");
}

// send password ...
Send("pass "+m_credential.Pass);

// get response ...
returned = GetPop3String();

if( !returned.Substring(0,3).Equals("+OK") )
{
throw new
Pop3LoginException("login/password not accepted");
}
}


public void CloseConnection()
{
Send("quit");

m_socket = null;
m_pop3Message = null;
}

public void OpenInbox()
{
// get a socket ...
m_socket = GetClientSocket();

// get initial header from POP3 server ...
string header = GetPop3String();

if( !header.Substring(0,3).Equals("+OK") )
{
throw new Exception("Invalid initial POP3 response");
}

// send login details ...
LoginToInbox();
}
}
}

Login to the POP server just before you try to send the email.. 

p = new Pop3Client("user","password","server");
if(p != null)
{
p.OpenInbox();
// ...Send Email.
}

Monday, November 10, 2008

DeployLX - Software Protection System

Dot .Net Dilemmas

The company that I work for are looking into completely overhauling our Licensing and Software protection system for all our software products. We currently have 4-5 products that are sold over the web and installed on the clients' machine and each needs to be protected.

Our current 'in-house' system ties the license to a machine profile and this makes it difficult to manage the licenses. In the future, we need our license system to be a lot more flexible allowing for; extensions on trial versions of our software, subscriptions for both our single and floating licenses and ease of license transfer.

I was given the task of investigating the various licensing system out there and come back with a recommendation. The basic brief was;

Single License:
  • Tied to a machine profile.
  • Must be easily deactivated from one machine and transferred to another.
Floating License:
  • A company should be able to install our software on each PC/Laptops required, without having to go through a complicated registering/activation process. The Activation of the software licences should only happen on the server which controls the licences and use of software. 
  • The monitoring software should ensure that it can only be installed on one server even if that server is part of a server farm.
Trial License
  • The software can be evaluated for a predetermined amount of time. 
  • An extension may be give on the trial of the software by the use of an extension code
Subscription License
  • On both the Single and Floating licenses.

In the end, after looking at 8-10 products, I put my money (well, my company's money) on DeployLX and Codeveil from Xheo. It seemed to offer everything that we needed and compared to a lot of companies, it was pretty well priced.

Even though the support from Xheo was excellent (Gary would respond to my emails in a matter of hours and this while I was still only trialling the software). I found that the level of documentation, particularly with regards to 'How-To' style documentation to be lacking. 

There is little-or-no help of any kind on the web so I've decided to document, over the next few weeks, how to achieve the results that I need to achieve and hopefully they will be of help to others. 

Hopefully, it will also be a way of me getting out of doing too much internal documentation as I will just be able to point future employees who have to work with DeployLX to my blog.

Monday, November 3, 2008

Don't you just love when something is simple?

Dot .Net Dilemmas.

Recently I had to change my hosting provider (more about that later) and one of the issues that it caused was with a web application that was created for an Irish business.

The dates that were displayed and used in various searches needed to be in the format "dd/MM/yyyy" but because my new provider was based in the US, the hosting server reports in Pacific time. All of my code fell over and the searches produced the "String was not recognized as a valid DateTime." error.

I honestly felt that I was going to have to change a lot of code and set the CultureInfo but then I posted the question on Stackoverflow and the answer was oh so simple.

In your web.config file add the element under the node (if you don't already have one) and add the correct culture. In our case "en-gb".

<system.web>
<globalization culture="en-gb">
<!-- ... -->
</system.web>

Monday, September 22, 2008

Port 443 - Configure your firewall

Dot .Net Dilemmas
We were having some issues recently where a client could not register our software.
We got an email from them asking if we "used any any ports other than Port 80 or 8080 during the registration process?"
It turned out that they were behind a firewall where all ports were 'locked down' unless the firewall was specifically configured to allow them access. This meant that their firewall was blocking access to one of our web services but they weren't sure why. They had configured it to enable access to Port 80 and Port 8080 and assumed that this was all that they needed to do.

As part of our registration we use Port 443 for HTTPS calls (note the 'S' at the end.) Using a HTTPS URL indicated that HTTP is to be used but with a different default TCP Port - Port 443. Port 443 an additional encryption/authentication layer between the HTTP and TCP and is widely used for security-sensitive communication such as payment transactions and corporate information systems. Port 80 is typically used for unsecured HTTP calls. They configured their firewall to enable communication through Port 443 and so far so good, all registrations have gone through.

You can check the Ports used by opening IIS and clicking on 'Web Sites'. The Ports will be displayed against your various web sites in the right hand pane.

Wednesday, September 17, 2008

How do you show "<" and ">" on your blog page?

Dot .Net Dilemmas
In yesterday's blog I was trying to show an entry in a web.config file and I couldn't get the "<" to be displayed correctly so, my output was displayed as:
compilation defaultlanguage="c#" debug="false"

when of course I wanted to display it as:
<compilation defaultlanguage="c#" debug="false">

Turns out to be very simple (once you know how)
&lt; = <
&gt; = >

So
&lt;compilation defaultlanguage="c#" debug="false"&gt;
Would display as
<compilation defaultlanguage="c#" debug="false">
That's it.

Another you might need to use is:
&quot; = "

And while I'm at it, if you want to actually display &lt; and not < etc. on your blog:
Use &amp; before the &lt;

Tuesday, September 16, 2008

Making HTTP 'appear' more reliable.

Dot .Net Dilemmas
I was listening to the .NET Rocks episode 'Udi Dahan Scales Web Applications!' (date 12/08/2008) and about 1/3 of the way through it they discuss something that is, what I consider, very important and seldom discussed issue regarding making HTTP 'appear' more reliable and give our users a better and more confidence building experience while using our web sites or services.
(Some of what is written below is from notes that I have taken while listening to the .NET episode so I am not claiming this to be an original idea.)

Something that I have always struggled with is, what to do when I am on a web site purchasing something and I go to make a payment by clicking the ‘Submit’ button and hey-presto; nothing happens?
I think that it has been drilled into us over the years NOT to hit that submit button again as it could mean multiple payments on our credit card. If you are like me, you simply click the little ‘X’ button at the top of the page or browser and keep an eye on your card transactions over the next month. So, how do we stop this happening when we are designing our own sites where we want to instill some customer confidence and not lose customer business?

I came across what at the early stages sounds like a pretty good and clean solution to this problem but as yet, I have not tried to implement it.

Basically HTTP is inherently unreliable and there is not much in the broader sense of the internet that we can do about this. However, there are a number of steps we can take to lessen the impact of this shortcoming.
Basically we design a retry protocol in such a way that if we send a request from the browser to the server we don’t get a satisfactory response back from the server in a reasonable time (for any action on data where we need to ensure it remains consistent), we resend the request again.
We would also need to ensure that server side code is designed in such away that, even is the request is sent any number of times, it is only processed once. One way we could do this is to tag a GUID (Globally Unique IDentifier ) onto the request. The same GUID would be also tagged onto the response and in this way, it wouldn’t matter if the first request got lost or the first response got lost we can be pretty sure that the data that was sent was received and processed. From the user’s perspective they don't see any of this as it is all under the hood. Until that point where we say ‘yeah, we got your data’, we can ensure that our service is fairly reliable on top of an fairly unreliable protocol (HTTP).

As I’m sure you can see, this sounds a very promising solution to what is, from what I can see, a pretty universal problem for any web site that has to ensure data persistence. I am going to try and implement this on some of the web applications that I use to take customer payments over and I will update my blog on how I got on and problems that I had to overcome but for now, as I am off to Uluru for the weekend, I’ll simply post this as a reminder.

Unable to start debugging... - Part 2.

Dot .Net Dilemmas
Ok, I just got over the hump of trying to run a project developed in VS2003 with .NET 1.1 in VS2008 with .NET 2.0 or 3.0 when I get the 'Unable to start debugging on the web server' message AGAIN but with a different twist.

"Unable to start debugging on the web server. The web server is not configured correctly. See help for common configuration errors. Running the web page outside of the debugger may provide further information."

One thing that you can check first is that you have debug enabled in your web.config file. I know that this sounds obvious but it has caught me and others out on more than one occasion.

Step 1: Open the web.config
Step 2: If debug is set to "false" change it to "true".

Example:
In the web.config there will be a line similar:
<compilation defaultlanguage="c#" debug="false">

Change this to:
<compilation defaultlanguage="c#" debug="true">

(Don't forget to set this back to 'false' before you promote the code to production)

If this doesn't work, as the message says, It usually means that the web server is not configured correctly but, have you ever looked at the list that Microsoft recommend that you check to try and get it working?
I have spent hours and hours trying to implement all these 'checks' and it still didn't work. All I want to be able to do is debug the application so that I can finish me work. So, one of the great things about VS since 2005 is the ability to use the Visual Studio Development Server to run and debug your web based .NET work without the need for IIS.

The steps:
1. Right click on your project in VS2005/2008.
2. Click on Properties
3. Click on Web tab
4. Under Servers, click on the radio button Use Visual Studio Development Server
5. Check Auto Assign Port radio button
6. Uncheck NTLM Authentication and Enable Edit and Continue

Friday, September 12, 2008

Unable to Start Debugging on the Web Server.

Dot .Net Dilemmas.
"Unable to start debugging on the web server. Debugging failed because integrated Windows authentication is not enabled."

Two possible solutions that have worked for me in the past:

Solution 1:
Start --> Control Panel --> Programs And Features --> Turn Windows features on or off



Select
Internet Information Server --> World Wide Web Services --> Security
Check
Windows Authentication


Be warned, this can take a LONG time to complete and you may think your PC has hung but stay with it.

Solution 2:

1. Open IIS 7. Click "Default web sites"
2. Under 'IIS' Click "Authentication"

3. Ensure that “Anonymous Authentication” and “Windows Authentication” are 'Enabled'.

Friday, September 5, 2008

ASP.NET "Could not load file or assembly App_Web..." Error

Dot .Net Dilemmas.
God, I spent a lot of time over the last few months looking for a proper solution for this one and at the end of the day, the best solution I found was to delete all temporary ASP.NET files, by removing the folders under

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files

I closed down all instances of VS before doing this just to ensure that all the files were released so that they could be deleted.

Friday, August 29, 2008

Test a Web Service operation using the HTTP POST protocol

Dot .Net Dilemmas
It's on a million other forums and blogs but it's one that I found very useful and has I have said, the main reason for this blog is to keep all the tips and pieces of code that I use over and over in once place (and at the same time, maybe help one or two others that have the same issues).

If you need to test a Web Service that is not staged locally, you need to enable remote testing. To do this, add <add name="HttpPost"/> under <system.web> in the web.config of the web service.

<configuration>
  <system.web>
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
  </system.web>
</configuration>

Now you can call the web service from a different machine and get the test form.

Monday, August 25, 2008

.NET Rocks.

Dot .Net Dilemmas
It's an awful name for a web site and there is nothing that I hate more than people trying to make coding and IT sound "cool" and trendy (it's simply not) but I have to recommend the excellent Podcasts at .NetRocks.Com

I heard about this website a few years ago when I first started to subscribe to Code magazine but at the time I wasn't really one for downloading and listening to Podcasts. However, now that I am that much older, listening to Podcasts has kinda become what I do on my bus or ferry journey into and out of the CBD in Sydney. I just put them on and to be honest, without even really tuning in to what is being said, I have taken information in by osmosis.
Since I started in my new job, one of the issues that we have had and I have had to deal with is response times and scalability. I just assumed that the site and web services would have taken advantage of page and object caching to ensure that a new call was not needed to an external database on every call to the web server. Having listened to the Podcast 'Udi Dahan Scales Web Applications!' (dated 12/08/2008) where Udi gave some excellent ideas on web scalability, I decided to look into our code a bit more to see what was going on.

To cut a long story short there were a million and one places both at page and at class level where the code was crying out for caching. (this is something that you need to be VERY careful about. Even though you may think that caching every page and every object is a good idea, a lot of thought needs to go into your design to ensure that you get the benefits of caching. Look at every page and object and ask yourself, how up to date does this information need to be and what benefit will my applications get from holding this information in memory on the server) For instance, every time there was some need to populate a currency drop down a new call was made to the database.
So, to start with, I simply found everywhere there was a "...GetAll()") for methods like currency, postcodes, countries etc and implemented caching. Already we can see a positive outcome in response rates. It's simply a no brainer.

I think that there is a new .NET Rock show ever week and I doubt that it's something that you'll want to discuss with your girlfriend or mates but it will make you sound more knowledgeable in meeting or interviews.

Friday, August 22, 2008

Day 1: My Reason for a Blog.

Dot .Net Dilemmas
Not too sure if this is the best place for keeping all this type of stuff but, recently I moved from Dublin to Sydney for a very good reason and stated a job in a new company on George Street in the CBD. It's winter in Sydney at the moment and a lot colder than I ever thought it would be in Australia but, I have to say that the Sydney winter is pretty much like the Dublin summer so I feel right at home and am loving it.

I have taken over the development, upgrade and maintenance of the company website which sells an excellent product and training online.
So far so good. Good company to work for but in the course of getting everything set up on my new laptop for development and testing, I have had to solve some problems that I have had to solve many times before but of course, when I go to fix them this time, I forgot what I did the last time and have to start searching for the answers all over again. So, this blog is more for me in a attempt to keep all my bits of information, website and solutions for fixing those .NET, C#, IIS and ASP.NET issues that come up again and again. Hopefully others will find it a help too? Not sure if it will be a daily blog, but I will try to add to it whenever I find or fix something interesting.

Anyhow, to start it off, here are a list of the .NET/Computer Architecture books that I am currently trying to get through.
I'm always on the look out for books that people recommend and I am especially looking for a good book on Silverlight 2.0 for a complete beginner, so if you know of any I would be more than grateful for any suggestions.