Backup and Convert iPhone SMS Conversations to an HTML File

I love my iPhone 3G and can’t wait until the end of my contract when I can upgrade to the latest and greatest version. However, one of my biggest gripes with the iPhone is that there is no standard way to backup and save your text messages in an easy-to-read fashion. After much searching, I’ve finally discovered a great application for backing up your messages. I’ve also combined that with a little web development trickery to convert the final product into a self contained and beautiful HTML file.

Exporting Your Messages

First off, you need a way to export your text messages from either your phone or your backup. All the messages are backed up on your computer with the normal iPhone sync process, but they aren’t in a format that is readable for humans. There are several different software applications that will do this for you. I’ve tried a few different ones with varying success. Most of them seemed downright kludgy. After trying out several apps, I finally discovered Decipher TextMessage from Decipher Media. It is very modestly priced at $6.99.

A Screenshot of the Decipher TextMessage software

Decipher TextMessage is an OS X only app (sorry Windows users) that simply pulls your text messages out of your iPhone data backup file. I like the idea of this because it’s only messing with the backup file, not your actual phone. The great part about Decipher Text Message is that it uses your address book to match up phone numbers with contact names. All texts are sorted into conversations with each contact. You can then easily select a conversation and save it as either a text file or a CSV file. For this method, I just exported the conversation I wanted as a text file.

Make Your Texts Into a Self Contained HTML File

The text file is great, but if it’s a long conversation, it’s going to be hard to read and not terribly useful. This is where a little regular expression kung fu and some HTML and CSS love come in handy.

Once you export your text conversation, you’ll get a text document that looks something like this:

Conversation with: Johnny Appleseed (5555558555)


Wednesday Mar 31 14:56

Me: Do you still have that spare ticket?

Johnny Appleseed: I dont BUT if you want to go I can probably grab another.

Me: What time is it at?

Johnny Appleseed: Doors @ 8 but we'll most likely grab food down there first and get there shortly after 8

Me: Hmm. I think I'll pass. I got into work late today so should prolly stay until at least 8. Have a good time though!

Johnny Appleseed: Mmmkay. :P Perhaps next time.


Sunday Apr 04 15:49

Me: I just got home.

Johnny Appleseed: Hey, im @ the field. You should come here

Me: Oh yeah? Who you out with?

Johnny Appleseed: Work peeps. Theyre cool. Come out ;-)

As you can tell, although there is a lot of text, it’s all in a very predictable pattern. One part at the top, dates, texts from your contact, and texts from you.

Make the document into an HTML file

The first thing we need to do to our text file is convert it to HTML. Setting our text into an HTML template is easy. Just surround the whole conversation with a very basic HTML head tag and a body tag. For the purpose of this document, I’m not even worried about getting all the right tags in there, just enough to make it work. Here’s what it looks like now:

<!DOCTYPE html>
<html>
<head>
    <title>Me and Johnny Appleseed Converstaion</title>
</head>

<body>
    Wednesday Mar 31 14:56

    Me: Do you still have that spare ticket?

    Johnny Appleseed: I dont BUT if you want to go I can probably grab another.

    Me: What time is it at?

    Johnny Appleseed: Doors @ 8 but we'll most likely grab food down there first and get there shortly after 8

    Me: Hmm. I think I'll pass. I got into work late today so should prolly stay until at least 8. Have a good time though!

    Johnny Appleseed: Mmmkay. :P Perhaps next time.


    Sunday Apr 04 15:49

    Me: I just got home.

    Johnny Appleseed: Hey, im @ the field. You should come here

    Me: Oh yeah? Who you out with?

    Johnny Appleseed: Work peeps. Theyre cool. Come out ;-)
</body>
</html>

As you can see, I deleted the first line from the text file that said “Conversation with: Johnny Appleseed (5555558555)”. I don’t need that for this case. If I had wanted, I could have used that as the title of the document. I’ve also changed the extension of my document from .txt to .html.

TextWrangler is a beast

Next up is putting all of our text into HTML tags. Now, for any conversation that is more than a few texts, doing this by hand is just out of the question. That’s where some regular expression kung fu and my favorite find and replace tool come in handy.

For this job, I use TextWrangler from Bare Bones Software. It’s a great free text editor that includes the best search and find and replace tools I’ve found. In my opinion, it’s much better than the search tool for TextMate, which is the editor I use for pretty much everything else.

Get rid of the pesky extra line breaks

The first thing we’ll do is reduce the length of the file by getting rid of the extra line breaks. The line break pattern will match our line breaks. We just use \r for this. We want to end up with just one line break after each line with text and no empty lines. We do this by searching for two line breaks in a row and replacing them with one. A Screenshot of the TextWrangler find and replace box searching for multiple line breaks in a row

Doing “Replace All” once on this search will give us a much more manageable file length.

Mark up the dates

Next we want to put all of the date lines in a paragraph tag with a class of “date”. We can use the TextWrangler find and replace and, making sure that the Grep option is checked, search for a regular expression that matches all of the date lines. The following regex does just the trick:

^[a-zA-Z]* [a-zA-Z]{3} \d{2} \d{2}:\d{2}$

The above regex will match the entire line and then we use the ampersand (which just represents the entire match) in our replace string. We just surround the ampersand with our HTML:

<p class="date">&</p>

Here’s what it looks like in TextWrangler:A Screenshot of the TextWrangler find and replace box searching for the date line

Mark up each of the conversation bits

Next I’ll search for all of my parts of the conversation. These each start with the label “Me:”. I want to code the classes so that the CSS will be easily to reuse later for different conversations. So in this case, I’ll just use generic ‘me’ and ‘you’ classes. For my parts of the conversation, I want to do the following things:

  • Mark up each of my texts in a paragraph
  • Give each of the paragraphs two clases: ‘message’ and ‘me’.
  • Change the starting label from “Me:” to be my full name instead.
  • Enclose my name in a strong tag.

In order to accomplish each of these things in one fell swoop, we can basically just match the text “Me:” at the start of a line and save the match that is everything after it in that line. There parenthesis save the pattern that is matched inside them. Since we’re getting rid of the “Me:” part, we don’t save it. Here’s what the regular expression looks like:

^Me:( .*)$

In the replace string we just surround the entire match that we saved (indicated by \1) with our appropriate HTML and label. Here’s the replace string (Obviously you wouldn’t want to use my name):

<p class="message me"><strong>Alissa Miller:</strong>\1</p>

The step is to match the other person’s texts. Here we’re trying to accomplish a very similar thing:

  • Mark up each of the other person’s texts in a paragraph
  • Give each of the paragraphs two clases: ‘message’ and ‘you’.
  • Enclose the other person’s name in a strong tag.

We’ll use almost exactly the same search pattern as the last time, except this time I’m using Johnny’s name instead of mine. Just substitute the Johnny part for whoever the conversation is with.

Here are screenshots of each of the last two searches in TextWrangler.

A Screenshot of the TextWrangler find and replace box searching for my part of conversation line A Screenshot of the TextWrangler find and replace box searching for the other part of the conversation line

And there we have it. Just a small bit of regex kung fu has given us a fully marked up HTML document. This is a great start, but in order to make it actually usable, we have to add some CSS styling to it. Here’s what are document looks like so far.

<!DOCTYPE html>
<html>
<head>
    <title>Me and Johnny Appleseed Converstaion</title>
</head>

<body>

    <p class="date">Wednesday Mar 31 14:56</p>
    <p class="message me"><strong>Alissa Miller:</strong> Do you still have that spare ticket?</p>
    <p class="message you"><strong>Johnny Appleseed:</strong> . I dont BUT if you want to go I can probably grab another.</p>
    <p class="message me"><strong>Alissa Miller:</strong> What time is it at?</p>
    <p class="message you"><strong>Johnny Appleseed:</strong> Doors @ 8 but we'll most likely grab food down there first and get there shortly after 8</p>
    <p class="message me"><strong>Alissa Miller:</strong> Hmm. I think I'll pass. I got into work late today so should prolly stay until at least 8. Have a good time though!</p>
    <p class="message you"><strong>Johnny Appleseed:</strong> Mmmkay. :P Perhaps next time.</p>

    <p class="date">Sunday Apr 04 15:49</p>
    <p class="message me"><strong>Alissa Miller:</strong> I just got home.</p>
    <p class="message you"><strong>Johnny Appleseed:</strong> Hey, im @ the field. You should come here</p>
    <p class="message me"><strong>Alissa Miller:</strong> Oh yeah? Who you out with?</p>
    <p class="message you"><strong>Johnny Appleseed:</strong> Work peeps. Theyre cool. Come out ;-)</p>

</body>
</html>

Styling Our Conversation

For the purpose of this conversation, my goal was to make the HTML page mimic the look of the iPhone text messages. I also want to make the HTML page self-contained, so I’m going to use internal CSS styles for everything.

Basic body styles

The first thing is to add some very basic styles to the body element. Here we are setting the background color and fonts. We also use the margin: 40px auto; to center the page and the width property to give us a nice narrow page width for our conversation.

body {
    background-color: #dbe1ed;
    color: #000;
    font: 14px/1.4 helvetica, arial, verdana, sans-serif;
    margin: 40px auto;
    width: 450px;
}

Styling the strong tags

Next we should style the strong tags. In this case, I want the strong elements to have a normal font-weight, but to be a different color. I styled all the strong elements as a medium gray color and then used the me class to override the the gray color with a bright green for my texts.

strong {
    color: #555;
    font-weight: normal;
}
.me strong {color: rgb(78,145,3);}

Basic paragraph and date styles

Now we style the paragraphs and the date class. We’re going to be floating elements in a bit, so we want to make sure to add a clear to all of the paragraphs on both sides. Also, the date class should have bold text that is centered and slightly larger than usual. Here are the styles:

p {clear: both;}
p.date {
    color: #777;
    font: bold 14px/1.4 helvetica, arial, verdana, sans-serif;
    text-align: center;
}

Creating rounded speech bubbles

Now that we’ve done some basic styling, we can start mimicking the speech bubbles. First we’ll style the message class to give some padding and rounded corners. We’ll also set the max-width of the each message to 70% so that it will stretch only slightly less than three quarters across the page.

p.message {
    position:relative;
    padding:5px 10px;
    border:2px solid rgb(74,77,82);
    border:2px solid rgba(74,77,82,.5);
    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;
    max-width: 70%;
}

Add the fancy CSS gradients

After that, we’ll set the background colors and use CSS3 gradients to create the green and gray speech bubbles. The gradients are a bit complex, so I used the online Ultimate CSS Gradient Generator tool. This was a fabulous way to visually match the iPhone styles as closely as possible while getting the cross-browser compatible code automatically generated. After generating the two sets of gradients, this is the CSS I ended up with:

/* Gradients and styles for each bubble */
p.you {
    background: #EBEBEB; /* old browsers */
    background: -moz-linear-gradient(top, #EBEBEB 5%, #D6D6D6 15%, #D2D2D2 71%, #E7E7E7 99%); /* firefox */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(5%,#EBEBEB), color-stop(15%,#D6D6D6), color-stop(71%,#D2D2D2), color-stop(99%,#E7E7E7)); /* webkit */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EBEBEB', endColorstr='#E7E7E7',GradientType=0 ); /* ie */
}
p.me {
    background: #D0ECCC; /* old browsers */
    background: -moz-linear-gradient(top, #D0ECCC 5%, #87CD65 15%, #92D664 70%, #ADE763 99%); /* firefox */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(5%,#D0ECCC), color-stop(15%,#87CD65), color-stop(70%,#92D664), color-stop(99%,#ADE763)); /* webkit */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#D0ECCC', endColorstr='#ADE763',GradientType=0 ); /* ie */

    float: right;
}

Notice that I also tucked in a float:right to the ‘me’ class. This will set my speech bubbles off to the right of the page.

Using just these few styles, we’ve created a nice looking self contained HTML page displaying our exported SMS conversation. Take a look at the HTML page so far.

Make more better speech bubbles

We could stop here and the page would be fine. However, we’ll use some really fancy CSS border trickery to make the text bubbles looks just a little bit better. Using images would make the text bubbles perfect, but remember, we want the file to be self contained.

In order to make the speech bubbles, I used a technique of arranging multiple CSS borders and using positioning to create a small triangle off to the side. The code is modified from Nicolas Gallagher’s excellent post on Pure CSS Speech Bubbles. In this case, I chose to use a modified version of the “Triangle Border” shown in Gallagher’s demo page (the one’ with the thick green border). The CSS had to be changed a bit because I didn’t actually want borders. Here is the final CSS I used:

/* The basic speech triangle */
p.message:before {
    content:"";
    display:block; /* reduce the damage in FF3.0 */
    position:absolute;
    border-style:solid;
    border-color:transparent rgb(74,77,82);
    border-color:transparent rgba(74,77,82,.5);
}
p.message:after {/* creates the smaller  triangle */
    content:"";
    display:block; /* reduce the damage in FF3.0 */
    position:absolute;
    border-style:solid;
}
/* Me points to the right */
p.message.me:before {
    right:-14px;
    bottom:7px;
    border-width:8px 0 8px 14px;
}
p.message.me:after {/* creates the smaller  triangle */
    right:-10px;
    bottom:8px;
    border-width:7px 0 7px 14px;
    border-color:transparent #94d749; /* green */
}
/* Other person points to the left */
p.message.you:before {  /* creates the larger triangle */
    left:-16px;
    bottom:7px;
    border-width:8px 16px 8px 0;
}
p.message.you:after {   /* creates the smaller  triangle */
    left:-10px;
    bottom:8px;
    border-width:7px 14px 7px 0;
    border-color:transparent #d3d3d3; /* grey */
}

You can see the finished effect on this page.

So with just a little bit of work we’ve marked up our conversation into HTML and created some advanced CSS styles to put our entire text conversation into a nice self contained HTML page that should be easily viewed in browsers for years to come.

Even better, we’ve made the CSS generic enough that we can just copy and paste it into another conversation we’ve marked up using HTML.

Obviously, there are a few caveats here. The Decipher Text Message program only on works on Macs. I haven’t tested any Windows-based software for the same purpose, but I stumbled across quite a few of them when I was looking for the software, so there are definitely options out there. Also, we’ve used some pretty complex CSS and several CSS3 properties that aren’t fully supported by all browsers. I have tested this in Firefox, Chrome and Safari. Hopefully things shouldn’t look too terrible in other browsers. I confess though, I did not even check it in IE.



appointive
appointive
appointive
appointive