Solving the problem of forgetting to take back library books, and having fun doing it…

Problem

With access to 4 library cards, each with 30 book capacity, that’s a whopping 120 books we can take out. The current “reminder” system from our local library involves emailing you 2 days before it’s due, and then 1 week AFTER it’s due (and you’ve picked up fines). We’re currently sitting at around $20 worth of fines and that’s not good at all.

Solution

Throw technology at the problem!

I built an end to end system using a Python, NodeJS and PushBullet. Allowing me to…

  • access a RESTful service to get info on current taken out books, per library card and…
  • send notifications as books approach due date.

Here’s how I did it:

  1. Scrape web site for data, using Python with HTMLParser to log in and extract the latest book data from the website, dumping it as a JSON string.
  2. Create a NodeJS service to wrap the Python data request and expose it as a RESTful service.

Tada… now we get notified via PushBullet (https://www.pushbullet.com/) whenever books are about to become due.

Code available on GitHub

Remember, it ain’t pretty, but it works 🙂

Emailing attachments directly to a Dropbox folder…

I’ve been toying with this idea for a while now, wanting to email attachments to my Dropbox account into a specific folder. There are lots of canned solutions to do this, but most of them require you to trust some third party with your documents. If you’re ok with that check out this post.

I decided my paranoia was high and I would not trust a third party. To achieve autonomous Dropbox emailing I figured I’d need to do the following:

  1. Install Dropbox on my headless Ubuntu server.
  2. Create an email account to receive the email attachments (let’s say dropbox@mydomain.com).
  3. Modify the postfix installation to redirect mail to dropbox@mydomain.com to a PHP script.
  4. Create a PHP script to process the inbound email stream and strip out all attachments saving them to a folder.

Install Dropbox

Lots of links for this one out there, not going to rehash it but the basics are:

  1. Download the latest Dropbox.
  2. Run it.
  3. Use the link supplied to link your account to your server.
  4. Create a service to run Dropbox at start.
  5. Do an initial sync.

You can follow the instructions here, or Google for it.

Create Email Account

I created a user called dropbox  and ran the install above as that user. One note if you follow the link, I did not do the auto startup as a cron job but as a standard service in /etc/init.d

Modify Postfix

I created a new transport in master.cf:


dropbox unix - n n - 50 pipe
flags=R user=dropbox argv=/usr/bin/php /usr/local/bin/dropboxattach/dropbox.php -o SENDER=${sender} -m USER=${user} EXTENSION=${extension}

then I added an entry to my main.cf to define different transport options:

transport_maps = hash:/etc/postfix/transport

Now edit /etc/postfix/transport and add an entry for your email address receiving the dropbox attachments:

dropbox@mydomain.com  dropbox:

then run

postmap transport 

to (re)build the transport database

Finally reload postfix

postfix reload 

The PHP Script

I found this nifty little Mime Mail Parser script at http://code.google.com/p/php-mime-mail-parser/, download the two files and add it to your code source. Here is the script I created to intercept the mail and parse for attachments. Check comments for explanation.


<?php

require_once('MimeMailParser.class.php');

// phrase to check for in SUBJECT to make sure only valid emails are processed
$check = "Add to dropbox";

// location to save attachments to
$save_dir = "/home/dropbox/Dropbox/attachments";

// temporary file name for incoming mail message
$file = "/tmp/mail.message." . microtime(true);

// delete the temp file if it exists, just in case
if (file_exists($file)) {
unlink($file);
}

// export the mail message to the temporary file
$data = file_get_contents("php://stdin");
file_put_contents($file, $data);

// parse the contents of the message and save attachments
$Parser = new MimeMailParser();
$Parser->setPath($file);

// get the subject and check for valid "phrase"
$subject = $Parser->getHeader('subject');

if (!($subject == $check)) {
// delete the temp mail message
if (file_exists($file)) {
unlink($file);
}
exit();
}

// get all attachments and save to directory
$attachments = $Parser->getAttachments();
foreach($attachments as $attachment) {
// get the attachment name
$filename = $attachment->filename;
// write the file to the directory you want to save it in
if ($fp = fopen($save_dir.$filename, 'w')) {
while($bytes = $attachment->read()) {
fwrite($fp, $bytes);
}
fclose($fp);
}
}

// delete the temp file (probably redundant but just in case)
if (file_exists($file)) {
unlink($file);
}

?>

For some “security” I added a “catch phrase” that must be the subject as a kind of “authentication”. Remember to save the script into the same directory as the Mail Parser code and everything should work.

That was it, I can now email dropbox@mydomain.com and it appears in my dropbox folder Attachments .. AWESOME!

What is code quality ?

So starting the new jobs has given me the opportunity to take a fresh look at software and how it should be approached.

One of the questions that I have been pondering on alot is “What is code quality ?”  Is it code that’s well documented ? Is it code that follows some sort of coding convention, code that is uniform throughout ? Well named variables ? Test cases ?

Obviously we all have our own perceptions, but in order to write good software I think its important to look at code from multiple perspectives, in order to do this I need your guys feedback!

Please tell me what you think makes good code ?

Software Craftsmanship…

Manifesto for Software Craftsmanship

I think this is long in the making and something that’s sorely needed in the industry. Too many people are getting away with too much these days. People call themselves “senior developers” but don’t have a clue when it comes to writing well understood and valuable code. Too many people entering the industry are being trained by institutions whose only interest is monetary gain and couldn’t care less about creating good software craftsmen. The revolution is upon us, fight the flood of ineptness and lack of any pride that seems to have taken over our industry and sign the manifesto; then live it!