Peter's Blog

Redefining the Impossible

How to do Photo Blogging


As promised, how to do photo blogging from mobile phone. Actually this should support submitting plain text blog posts from any email source as I want to use the same mechanism to post blog entries from work that are for public display, bypassing the firewall. This recipe works with UK O2 MMS messages.

The first line of text in the email message becomes the title of the post, the following lines become the body.

Requirements:

  • Exim (or any MTA that supports forward files)

  • Python Desktop Server (or any server that supports MetaWeblogAPI or Blogger API, although you have to hack the image upload yourself, depending on the server).

  • Python (or you can rewrite it all in some other language)

Exim has to be set up to allow .forward files to process email. The .forward file should look like this:

# Exim filter
logfile ~/.forward.log

if $header_subject is "Multimedia message"
then
    pipe "/home/me/MailBot.py"
    seen finish
endif

This will direct emails with this subject line (i.e. UK O2 MMS messages) to the python script that does the hard work. This script is as follows and has to be made executable by the exim process:

#!/usr/bin/python
#
# Take an email message from stdin and post it to PyDS Blog.
# This works with UK O2 media messaging.
#
import smtplib
import sys
import email
import xmlrpclib

strMobileNumber = "0123456"
strXMLRPCUser = "fred"
strXMLRPCPassword = "xxx"

#
# Read email message piped in by exim filter from stdin.
#
strMsg = ""

for strLine in sys.stdin.readlines():
    
strMsg += strLine

oEmail = email.message_from_string( strMsg)

#
# Mobile number is in from address on O2.
# Stop people posting pr0n on my web site
# Hack this to add extra senders or security.
#
if not( oEmail'from'">'from'.find( strMobileNumber) >= 0:
    
#
    
# Does not appear to be from me.
    
#
    
sys.exit()

#
# Run email through parser, collecting all text/plain parts.
#
body = ""
strImages = []

for oPart in oEmail.walk():
    
#
    
# Look for plain text
    
#
    
if oPart.get_content_type() == 'text/plain':
        
if oPart.is_multipart() == False:
            
strPart = oPart.get_payload( decode=True)

            
#
            
# Ignore blurb added to message by o2.
            
#
            
if strPart.find( "This is a Media Message from O2") >= 0:
                
continue

            
body += strPart

    
#
    
# Look for images
    
#
    
if oPart.get_content_type() == 'image/jpeg':
        
strImage = oPart.get_payload( decode=True)
        
strFileName = oPart'Content-Location'">'Content-Location'
        
#
        
# Hack to pyds dir
        
#
        
open( '/home/me/.PyDS/www/images/' + strFileName, 'wb').write( strImage)
        
strImages.append( "$macros.imageTag( 'images/%s')\n" % strFileName)

#
# The first line is the title. The rest is the body.
#
strBody = body.split( '\n')
strTitle = strBody0">0
strBody = "".join( strImages) + "\n".join( strBody1:">1:)

#
# Open xmlrpc link to pyds.
#
oPyDS = xmlrpclib.ServerProxy( 'http://localhost:4334/RPC2')

#
# Get recent posts and build a map of title->postid.
#
oPosts = oPyDS.metaWeblog.getRecentPosts( '', strXMLRPCUser, strXMLRPCPassword, 1000)

oExistingPosts = {}

for oPost in oPosts:
    
oExistingPostsoPost['title'">oPost['title'] = oPost'postid'">'postid'

#
# Build parameters for post using unicode to pass weird characters.
#
oPost'title'">'title' = unicode( strTitle, 'ISO-8859-1')
oPost'description'">'description' = unicode( strBody, 'ISO-8859-1')

#
# See if this is a new post from it's unique title.
# If it is unique then post it as a new article.
#
if not oExistingPosts.has_key( strTitle):
    
oPyDS.metaWeblog.newPost( '', strXMLRPCUser, strXMLRPCPassword, oPost, 1)
else:
    
#
    
# Edit existing post
    
#
    
oPyDS.metaWeblog.editPost( oExistingPostsstrTitle">strTitle, strXMLRPCUser, strXMLRPCPassword, oPost, 1)

I had to make a small hack in Python Desktop Server. Posted articles default to either raw html or strict structured text but the image link requires structured text + cheetah. I had to edit the file MetaWebWeblogAPI.py to change the two lines that said:

structured = 2

to

structured = 1

ToDo:

  • Try to get text to wrap round image

  • Save up to pay my mobile bill


Comments are Closed