Mobile Photo Blog - Post from your Sprint phone to your blog using Coldfusion
I've had my Treo 650 for quite some time now. I've only recently started using the camera portion of my phone. I'd really like to get the photos on the web but the burden of transferring the images from my phone to my computer / from my computer to my blog kept me from doing so. I was able to put together a solution for this, read on.
Problem is, when you send a picture mail through Sprint you're not just getting a picture and a message, you're getting an html email with nested tables, inline scripts/styling along with a few sprint banners. If we could just send along a picture and a message we'd be better off. Here is the run down on what we need to do.
- Set up a dedicated email address for the sole purpose of posting pics from your Sprint phone.
- Send a "Sprint picture mail" to this email address.
- Pull the email from the mail server using POP3.
- Find the image URL and make an HTTP request to get the image and store it locally (on the server).
- Isolate the message from all of the poorly formatted html.
- From this point you can do whatever you want with it. In my case I'm creating a mophoblog entry and emailing the photo to flickr and twitter. More on that later.
Before going any further, I have to give credit to Ben Nadel a very well known and respected Coldfusion developer who posts code samples on his site. He even has a section on his site titled "Ask Ben Nadel" where he fields questions and gives solutions to common problems. Some of the snippets I used to achieve this modern miracle were taken from Ben's site, I'll cite those when I get to them.
Set-up Email
First thing's first, set up an email address. I set up a free account at Lavabit for a basic non-SSL POP3 account. It's a quick and painless process so take care of that first. I got the idea from Ben on his post where he covered cfpop, a Coldfusion tag.
Send a picture message to your email. Now, using cfpop we can retrieve this message. See all of the juicy details of cfpop from Ben's post above. You can also check out cfpop on cfquickdocs.
<!--- Get email from lavabit ---> <cfpop action="getall" name="getEmail" server="#Request.LavabitServer#" port="#Request.LavabitPort#" username="#Request.LavabitUserName#" password="#Request.LavabitPassword#" /> <cfdump var="#getEmail#">
Find the Image
We have our email, now we need to start picking it apart to extract the pieces we want. As I noted before, Sprint sends the picture embedded in a mess of tables. So we need a little regex and ReMatch() to narrow the email down to only URL's. ReMatch on CFQuickDocs.
<!--- Find all URL's in the HTMLBody --->
<cfset urlsInBody = REMatch("https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?", HTMLBody)>
Now we can loop through all of the URL's in the email. Some of them will point to Sprint's front page, some are for their silly advertisements. So how do we know which URL to look for? Easy, sprint stores the real pic in a directory titled "RECIPIENT" so we'll use that as our hook to start the processing.
<!--- Loop through the URL's --->
<cfloop index="i" from="1" to="#ArrayLen(urlsInBody)#">
<!--- Sprint stores these picture mail images in a directory named RECIPIENT
Look for this directory, if we find it, start processing --->
<cfif FindNoCase("RECIPIENT",urlsInBody[i])>
As you can see from the code sample above, once we find a URL with the word "RECIPIENT" then we'll start to process the photo. Herein lies the weak spot. If Sprint changes where they store the image we're going to have to change our code, no biggie. I don't anticipate this happening and if it does it'll be a minor adjustment. Since we're not hot linking and we're actually going to pull the image down from Sprint's server this should be a non-issue.
Get the image
We need to pull the image off of Sprint's server and store it locally on our own server. Then we can do whatever we want with it; Create a blog entry, email it to Flickr, TwitPic, Ping.fm, etc.. This is where I got a lot of help from Ben Nadel's post about spoofing a referrer using cfimage. I tried cfimage without the extra cfhttpparam and it didn't work. (cfimage on CFQuickDocs)
<!-- Get the image --->
<cfhttp
url="#urlsInBody[i]#"
method = "GET"
useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2"
getasbinary="yes"
result="objHttp">
<cfhttpparam
type="CGI"
name="http_referer"
value="http://pictures.sprintpcs.com/share.do"
encoded="false" />
</cfhttp>
<!--- If the image was found --->
<cfif (FindNoCase("200",objHttp.Statuscode) AND FindNoCase("image",objHttp.Responseheader["Content-Type"]))>
Get the message
Now we need to extract the message. I was using a different solution until I got some handy regex from Ben. I was stripping the HTML from the entire message and looping through each word. Once I got to the word "Message:" I started building the message one word at a time using ListAppend(). When I got to the next section titled "Options" I knew the message was over. Here is what I had.
<!--- strip out HTML ---> <cfset messageInBody = reReplace(HTMLBody, "<[^>]*>", "", "all")> <!--- Set defaults ---> <cfset ThisMessage = ""> <cfset StartMessage = 0> <cfset StopMessage = 0> <!--- Loop through each word in the email ---> <cfloop list="#Trim(messageInBody)#" index="i" delimiters=" "> <!--- Check for length on the list item ---> <cfif Len(Trim(i))> <!--- Start building the message when we reach the word "Message:" ---> <cfif Trim(i) IS "Message:"> <cfset StartMessage = 1> </cfif> <!--- If start message is true and we havent reached the final word of "Options" (StopMessage=1) ---> <cfif StartMessage EQ 1 AND StopMessage EQ 0> <!--- Build the message ---> <cfset ThisMessage = ListAppend(ThisMessage,Trim(i)," ")> </cfif> <!--- The word "Options" is the last word in the message, so stop building a the message ---> <cfif Trim(i) IS "Options"> <cfset StopMessage = 1> </cfif> </cfif> </cfloop>
It's a little lengthy but it worked. In fact 11 of the 12 photos I have now were posted using the method above. But! Using regex proved to be a better solution by far, thanks again to Ben. He even wrote his on UDF to make this easier, check that out here.
<!--- Sprint stores the message you send along with the pic in <pre> tags.
Use ReMatchNoCase to extract everything but the pre tags and what is inside --->
<cfset ThisMessage = REMatchNoCase("<pre[^<]*</pre>",HTMLBody)>
<!--- Strip out the pre tags --->
<cfset ThisMessage = REReplaceNoCase(ThisMessage[1],"<[^>]*>","","all")>
Do something
We have our image, we have our message, now it's time to do something. In addition to creating my own blog entry, I wanted to send the photo to flickr and twitter (via ping.fm).
The idea I came up with was to add something to the message I send with the pic that I could use as a hook. In this case I use @fk to send the image to flickr, @tt to send it to twitter or @all to send it to both. If I don't use any @'s nothing happens but the mophoblog entry.
You'll also see in the code below how I get the file from the Sprint server, save it and resize a copy as a thumbnail. I make a practice of storing photos in a directory named after the ID of the entry (which is why you'll see below I add the entry and then save the image).
<!--- Set flags to send emails --->
<cfif ThisMessage CONTAINS "@all">
<cfset SendToFlickr = 1>
<cfset SendToTwitter = 1>
<cfelse>
<!--- Flickr --->
<cfif ThisMessage CONTAINS "@fk">
<cfset SendToFlickr = 1>
<cfelse>
<cfset SendToFlickr = 0>
</cfif>
<!--- Twitter (ping.fm) --->
<cfif ThisMessage CONTAINS "@tt">
<cfset SendToTwitter = 1>
<cfelse>
<cfset SendToTwitter = 0>
</cfif>
</cfif>
<!--- Clean up the message a bit (remove the @ stuff)--->
<cfset ThisMessage = reReplaceNoCase(ThisMessage, "@tt|@fk|@ALL", "", "all")>
<!--- Insert content --- I'm doing this first so I can get ID to name the directory --->
[This is where I add the content to my site]
<!--- Set the path to upload & create a the directory if it doesn't exist --->
<cfset destination = #Request.PhotoPath# & "#InsertContent.ContentID#">
<cfif NOT DirectoryExists(destination)>
<cfdirectory action="create" directory="#destination#">
</cfif>
<!--- Save the image to the server --->
<cfimage
source = "#objHttp.FileContent#"
action = "write"
isBase64 = "yes"
destination = "#destination#\#UID#.jpg"
overwrite = "true">
<!---Resize a thumbnail --->
<cfimage
action = "resize"
height = "150"
width = ""
source = "#destination#\#UID#.jpg"
destination = "#destination#\#UID#-thumb.jpg"
name = "thumbnail"
overwrite = "yes">
<!--- email pics --->
<cfif SendToTwitter EQ 1>
<cfmail from="#Request.SiteOwnerEmail#" to="#Request.PingfmEmail#" subject="New MoPhoBlog Pic">
@tt #ThisMessage# www.jyoseph.com/mophoblog/detail.cfm/pic/#InsertContent.ContentID#
</cfmail>
</cfif>
<cfif SendToFlickr EQ 1>
<!--- Send to Flickr --->
<cfmail from="#Request.SiteOwnerEmail#" to="#Request.FlickrEmail#" subject="#ThisMessage#">
#ThisMessage# <a href="http:jyoseph.com/mophoblog/detail.cfm/pic/#InsertContent.ContentID#">http:jyoseph.com/mophoblog/detail.cfm/pic/#InsertContent.ContentID#</a>
tags: mophoblog,mobile phone,treo 650,jyoseph.com,moblog,camera phone
<cfmailparam file="#destination#\#UID#.jpg">
</cfmail>
</cfif>
Only thing left to do now is delete the email we just processed so we don't process it again.
<!--- delete the pop ---> <cfpop action="delete" uid="#UID#" server="#Request.LavabitServer#" port="#Request.LavabitPort#" username="#Request.LavabitUserName#" password="#Request.LavabitPassword#" />
Voila!
That should be it! Let me know if I missed anything. It may be easier for you to see the entire thing from top to bottom. Check that out here.

Comments
Leave One