Monday, August 10, 2009

Microsoft Junk Mail Reporting Program (JMRP) Sucks!

Anyone else frustrated with Microsoft's Junk Mail Reporting Program (JMRP)?

It's a feedback loop that lets legitimate email senders receive junk mail reports from hotmail.com/msn.com/live.com email users.

Well, that's how it's supposed to work.

We have been on this feedback loop for years now, and our company sends only legitimate email that our subscribers specifically request. As any mail sender knows, you can't avoid a few people each day that hit the "Report Spam" button for your email rather than "Delete." (Usually it's an accident since they put the buttons so close together, and don't tell them what a negative impact the Report Spam button has in the first place.)

So this JMRP program is supposed to solve this. You get on this program, and Microsoft will forward any spam reports to you for your email, and you can unsubscribe the user. Perfect!

Unfortunately, Microsoft routinely fails to send all the reports to us. If someone is reporting us as spam, and we aren't alerted to this, how can we unsubscribe the user? Now we're being punished for the spam report that we seem to be ignoring, because we're not getting the report in the first place!

We have confirmed this is happening by reviewing example reports Microsoft shows for us in their web interface (called SNDS -- "Smart" Network Data Services). We routinely see junk reports for emails that were never sent to us. We've even researched our mail server logs to make sure that no attempt from Microsoft was accidentally rejected or not processed. Nope. Everything is fine on our end.

Within a few days, our 'level' on JMRP (in the "SNDS" interface) shows as yellow or even red, even though our email routines have not changed one iota. This must be due to these missing reports.

It gets worse. When we've tried to explain what's happening, no one at JMRP gets it. Either they get confused and think we aren't on the feedback loop yet, and send us to the 30 part form that subscribes you to the program, or they simply do not get it, and I have to explain the problem again. And again. And again.

This time I thought it was different -- we actually got someone to repeat back the problem to us as if they understood it (after only 5 or 6 emails back and forth). AWESOME right? Nope. The next email we received was someone saying now they understand the problem and are doing research to help us fix it. What questions do they ask us to fill out (again)? Oh, the same 30 part questionnaire you fill out when you join the JMRP program.... nothing at all that would help them actually figure out what is wrong on their end.

I lost it at this point and berated the support drone for failing to grasp the problem. What do I get back? A response from a different drone saying, "I'm sorry you're [insert totally incorrect description of our problem here]." This is after there must be a paper trail a mile long of me repeatedly explaining the problem in very simple terms:

WE ARE ON JMRP ALREADY.
YOU ARE NOT SENDING US ALL THE JUNK REPORTS.

It never reaches anyone with a clue. And if it does, that person is never to be heard from again.

So we are stuck with thousands of our subscribers not receiving email from us that they want.

I understand fighting spam is a top priority for Microsoft, but the system they've devised is routinely blocking non-spam email from a company like ours, that has been sending only legitimate email for 15 years now, a company that is jumping through every single hoop they hold in front of us. What good is this system?

If you have any complaints about JMRP or the SNDS system, please post them as comments here. If Microsoft wants to contact me, please leave a comment and I will contact you in whatever way you wish.

Right now, JMRP is a big fat failure. It's worse than a failure, people actually think it's working, and it's seriously damaging the ability for legitimate senders to get through.

P.S. My favorite part of JMRP is the SNDS web interface. Check out the unreadable header, complete with nearly invisible white navigation links laid over a light blue background. You can just about make out "View Data," but I defy you to read the rest of the links:

Tuesday, August 4, 2009

Configuring a Wireless Bridge Using Two Apple Airport Expresses

Here's the scenario: You want to setup a wireless network, and you also need to connect a non-WiFi network device to your new wireless network. E.g. you're setting up a wireless network at work, and you've got a network printer that only has ethernet, no WiFi, that you want to connect to your network. For the purpose of this exercise, we'll use this scenario to explain the setup.

Step 1. Buy Two Airport Expresses. I recommend these because they are easy to setup, they work great, and the design is ingenious (it's about the size of your standard wall plug). If you don't have any ethernet cable, you'll need to buy at least one, maybe two ethernet cables. One will go from the cable/dsl modem to an airport express, the other will connect your printer to the second airport.

Optionally: You may want to buy the more expensive Airport Extremes instead of the Expresses, in the event that you want more ethernet ports available. But you can always add on a cheap switch later if you need more ports on an Airport Express.

Step 2. Unwrap both devices, and mark them to keep them straight. Put a sticker or mark one with a Sharpie so you can tell them apart. One of these will be the heart of your wifi network, the one every device connects to -- we'll call this Airport A. It will be connected to your cable/dsl modem.

The other will be connected to your non-Wifi device (e.g. your printer), allowing it to connect to Airport A and the Internet... we'll call this one Airport B.

Step 3. Plug Airport A into power. Plug it into the wall near your cable/dsl modem. You'll see an amber light blinking on the Airport, this is normal.

Step 4. Insert the Airport Express setup CD into your computer, and run the software. After a minute you should see an Airport available named "Base Station xxxxxx," where xxxxxx will be a series of letters and numbers. Select this, and press the Continue button to configure it.

Step 5. Configure Airport A.

You'll have a few options to fill in now:

  • AirPort Express Name: You can name it anything you want, such as Airport A.
  • AirPort Express Password: This is a password on the device you'll need whenever you want to re-configure the Airport Express. You will not be sharing this with others.
  • Select what you want to do with Airport Express: Choose "I want to create a new wireless network."
Continue to the next screen:
  • Wireless Network Name: This is different from above. Other people will use this to identify your WiFi network if you want them to connect to it. (And, hey, maybe even when you don't want them to connect to it?!)
  • WPA/WPA2 Personal: Choose this option and enter a password you will be comfortable giving to your guests to use your WiFi network. For strong security, this should be different from the password you chose on the previous screen. You wouldn't want your guests to be able to re-configure your Airport Express.
Continue to the next screen:
  • Select how you connect to the Internet. For this example, you'll choose the first option, "I use a DSL or cable modem with a static IP address or DHCP."
Continue past the next screen, "Using DHCP," is the normal option for most people. Your ISP will send information to the Airport Express to connect it to the internet using this setting.

Continue to the next screen and after reviewing your choices, press "Update."

The on-screen options should prompt you to finish and allow Airport A to restart if necessary. You should also restart your cable/dsl modem at this time.

You can now connect to the internet by connecting your computers to Airport A.

Step 6. Plug Airport B into power. Plug it into the wall near your printer. You'll see an amber light blinking the Airport, this is normal.

Step 7. Restart the Airport Utility software. If you don't see the new "Base Station xxxxxx" appear, go ahead and restart the Airport Utility software. Within a minute you should see it appear on the left side. Select it and continue on to configure it.

Step 8. Configure Airport B.

You'll have a few options to fill in now:
  • AirPort Express Name: You can name it anything you want, such as Airport B.
  • AirPort Express Password: This is a password on the device you'll need whenever you want to re-configure the Airport Express. You will not be sharing this with others. You should choose the same password as you chose above (not your WiFi password, but the first password you chose for the device configuration), just to keep them straight.
  • Select what you want to do with Airport Express: Choose "I want AirPort Express to join my current network."
Continue to the next screen:

  • Select what you want to do with AirPort Express: Choose "I want Airport Express to wirelessly join my current network."
Continue to the next screen:
  • Wireless Network Name: Enter the Wireless Network name you chose for Airport A here. This is the WiFi network that Airport B will connect to, wirelessly.
  • Wireless Security: Choose "WPA/WPA2 Personal."
  • Wireless Password: Enter the same Wireless Network password you chose above for Airport A's WiFi network. (The password you established to give out to your guests.)
Continue to the next screen and after reviewing your choices, press "Update."

The on-screen options should prompt you to finish and allow Airport A to restart if necessary.

Step 9. Connect Airport B to your printer with an ethernet cable. Follow your printer's instructions for setting up your network connectivity on the printer. When prompted, select "DHCP" and not static IP address.

Step 10. You're done.

Extremely Fast Luhn Function for C# (Credit Card Validation)

If you want to validate that a credit card number is valid, you need to use the Luhn algorithm. It uses the last digit in the card number and calculates a checksum to ensure the number is valid. (Obviously this doesn't ensure that the card actually works, only that the number seems real.)

Everyone and their mother has posted a .NET/C# version of Luhn, but they were all really drawn out and slow. I initially settled on this one by Paul Ingles hosted on CodeProject., since at least his code was commented and readable. I shortened it up and eliminated some blocks of code and variables, making it easier for me to follow, but without any change in performance. Then I swapped in some tricks to speed it up about 4x (cast char to int and subtract 48 to get the integer version of a number that starts as a char string).

I felt this was good enough, but then I stumbled upon this pseudo code for Luhn algorithm by Cliff L. Biffle. Not only is it much, much shorter, but it was about another 8x faster than my code! I went from validating 100,000 numbers in 550ms to 100,000 in 15ms, a 37x speed increase!

I wrote a C# function implementing the pseudocode, and here it is below.


/// Extremely fast Luhn algorithm implementation, based on
/// pseudo code from Cliff L. Biffle (http://microcoder.livejournal.com/17175.html)
///
/// Copyleft Thomas @ Orb of Knowledge:
/// http://orb-of-knowledge.blogspot.com/2009/08/extremely-fast-luhn-function-for-c.html

///

private static bool IsValidNumber(string number)
{
int[] DELTAS = new int[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 0 };
int checksum = 0;
char[] chars = number.ToCharArray();
for (int i = chars.Length - 1; i > -1; i--)
{
int j = ((int)chars[i]) - 48;
checksum += j;
if (((i - chars.Length) % 2) == 0)
checksum += DELTAS[j];
}

return ((checksum % 10) == 0);
}

That's it!