Mobile Bonding Accepting and parsing MMS messages
problems that need to be solved How to… – Pull mails into application –Parse s –Associate to a user account –Decode attachments –Save to database
Pulling s into application Initial thought –run a cron job on mailbox every few minutes and parse new s, but very hackish and not instant. How we ended up doing it –setup MTA to forward to your applications method for handling s ActionMailer.recieve(raw_ )
Setting up MTA to forward s were using Exim – create a new alias in /etc/aliases mms_mail: "| /path/to/ruby /path/to/app/script/runner 'AccountMailer.receive(STDIN.read)" rebuid alias table sendmail –bi Virtual alias file: : mms_mail Now all send to gets forwarded to
Parsing s Go figure, rails provides a great built in method for this class MyMailer < ActionMailer::Base def receive(mail)... end Put in a raw , returns a workable object (TMAIL)
class AccountMailer < ActionMailer::Base def receive( ) puts .title if .has_attachments? puts .attachments.count end >> check out my car >> 3
Associating s with a user account Users need to know where to send s Site needs to know who sent an –Was it john doe, or a spam bot? s need to be verified
Verifying s / Users s contain FROM: which is in the format of Ask users for their mobile number on site Give users a verification code to send from their mobile device –send to verify your Site matches number / code combination => verifies users mobile device
def receive( _text) user = User.find_user_from_mms( _text) if !user raise Invalid Exception.new("Bunk ") elsif !user.is_bonded? #look for verification code only plainparts = [] _text.parts.each do |part| plainparts << part if part.content_type == "text/plain" code_correct = user.verification_code_correct?(plainparts.body) end if code_correct user.bonded = true begin user.save! AccountMailer.deliver_bond_confirmation(user, tmail.from[0]) rescue Exception => e puts "error saving new user bond" end else AccountMailer.deliver_bond_reminder(user) end elsif user.is_bonded? #user is found and bonded, return user, asset, post mms = MMS2R::Media.create( _text) mms.process begin if mms.media['image/jpeg'][0] asset = Asset.new(mms.media['image/jpeg]) asset.save end rescue MobileBondException => e puts e end Full process in Receive function 1)Parse for who it is from 2)Match mobile number to user 3)If user is not bonded, look for verification code 4)If user is bonded, parse
Decoding Attachments MMS messages are full of junk Plugin MMS2R handles removing junk by carrier (verizon puts in 6 images) mms = MMS2R::Media.create( _text) mms.process mms.media['text/plain'] mms.media[image/jpeg']
Testing Cant setup local server, so fake it class AccountMailerTest < Test::Unit::TestCase … def test_should_receive_video_from_ AccountMailer.receive(raw_ ("mms-video.mail")) assert_equal 1, user.media.size End Private def raw_ (action) IO.readlines("#{FIXTURES_PATH}/Mail/#{action}").join End end