HOWTO: Wordpress pretty URLs with Nginx 0.6 (the proper way)


October 9th, 2009

A lot of guides around the net for Nginx + Wordpress suggest something like this:

if (!-e $request_filename) { rewrite ^/blog /blog/index.php?q=$1 last; }

This is Bad. Try this:

if (!-e $request_filename) { rewrite ^/blog /blog/index.php last; }

What's the difference? Well, the latter form doesn't set a GET variable. Why is that better? wp-super-cache, should you choose to use it, refuses to create supercache files when the GET URL has variables in it. If you turn on the debug log, you see errors like these stream past:

Supercache caching disabled. Non empty GET request.
Supercache disabled: GET or feed detected or disabled by config.

You can find a full example of the required Super Cache config here.
 
 
Update:
For nginx >0.6.36 you can use the try_files directive instead:

location /blog { try_files $uri $uri/blog.index.php; }

There's a full example with this new method in this mailing list post.

Windows 7 (64-bit) on Dell Vostro 1310


August 26th, 2009

Everything works out of the box! Well, almost everything:

  • Install new Nvidia drivers from the Nvidia website. The included ones are too ancient to be much good, and don't support Aero or other fancy stuff.
  • Touchpad driver doesn't support scroll zones or middle click emulation. Install the touchpad driver for the Latitude E6400 (this one in particular). This driver has somewhat weird default settings. I dropped sensitivity a few notches and reduced the scroll detection threshold to minimum.

Broadcom BCM4328 wifi on Ubuntu 9.04 Jaunty


May 12th, 2009

Ubuntu now includes support for this wireless chip in its 'Restricted Driver Manager'. Sadly the activation silently fails on a fresh install of Ubuntu. The solution? Install b43-fwcutter. Then disable and re-enable the driver in Ubuntu's Restricted Driver Manager and it will work after a restart.

Processing email feedback loops for fun & profit, part 2


May 5th, 2009

Part 1 here.

So we know what a feedback loop is and how to use it to identify customers complaining about our mails. The next step is to automate removal of these people.

It turns out many (most?) feedback loop emails you get from ISPs follow the same format. The message is made up of three sections:

  • The first section is a generic message from the feedback loop provider, "this is an email abuse report, yadda yadda yadda".
  • The second section is basically useless. It contains some information from the abuse report, but is usually heavily censored.
  • The third section is a copy of the original email you sent. Some information is redacted, like the recipient, and the sender address.

To process this we need two pieces of information:

  • Which ISP our feedback loop email comes from.
  • Who we sent the original email to.

This is relatively easy with Python, which includes the email library module and will do most of the heavy lifting for you.

The 'standard' feedback loop format is ARF, and is used by (at least) AOL, Comcast and Yahoo. To process an email in this format:

import email
message = email.message_from_string(foo)
 
messagefrom = message['From'] # This is how you pull headers out.
                              # Note the keys are not case sensitive
 
messagebody = message.get_payload() # This returns three sections, as described above
 
originalmessage = messagebody[2].get_payload()[0] # This returns the original message.
                                       # We need to explicitly get the single payload.
 
originalmessagesender = originalmessage['Return-Path'] # Ta-da! The original sender.

You can then process originalmessagesender as required to retrieve your UID. Once you have that, send a request through to the appropriate interface and you're done.

Bonus Notes

  • Some providers also strip the return path from the original message. We solved this by hand setting the message-id header on all outgoing mail. If you also do that, make sure you set each message-id to a unique value. We use the same string as our sender address, but change the generic '@noreply.ourcompany.com' domain to the real machine involved in sending and also include the output of time.time(), which gives us useful troubleshooting info too.
  • The original plan was to process feedback loop messages as they come in by spawning a script for every returned mail. This turned out to be a bad idea because abuse messages seem to come in bursts, making it possible we'd accidentally DOS our own mailserver with tens of python scripts. Now every feedback email will be delivered to a Maildir. We iterate over every message in the Maildir with Python's mailbox module (which returns an email object as above for each message).
  • If your feedback loop is in another format, it's pretty easy to work out the structure by playing with a sample message in the Python interpreter (IDLE).

Misc