#!/usr/bin/ruby -w # # Downloads emails with image attachment and uploads images to ftp/web site # Suitable for emailing cellphone pictures to websites # Copyright(C) 2004 - Patricio Carr # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # http://www.gnu.org/licenses/gpl.txt # $Id: picblog.rb,v 1.5 2004/08/10 04:12:19 pcarr Exp $ require 'net/pop' require 'net/ftp' require 'mailread' require 'stringio' class Picblogger < Object def initialize @config = { 'popserver' => '', 'popuser' => '', 'poppasswd' => '', 'phonemail' => '', 'ftpserver' => '', 'ftpuser' => '', 'ftppasswd' => '', 'imagefile' => '' } self.getconf @messages = Array.new @delete_from_server = true end def getmail begin @messages = [] puts "Trying #{@config['popserver']}..." pop = Net::POP3.new(@config['popserver']) pop.start(@config['popuser'], @config['poppasswd']) puts "Connected" if pop.mails.empty? puts 'No mail.' else puts "Downloading #{pop.mails.size} mails..." i = 0 pop.mails.each do |m| # transform string (m.header) into file handle message = Picmail.new( StringIO.new(m.header) ) puts message['FROM'] # TODO phonemail should be array of phone #s if( message['FROM'] == @config['phonemail'] ) then puts "Got one pic-email! #{message['DATE']}" # now get whole message File.open("inbox/#{i}", 'w') do |f| # message = Picmail.new( StringIO.new(m.pop) ) # no-file method f.write m.pop message = Picmail.new( "inbox/#{i}" ) end # add to array of picture messages @messages.push message.extract_pic m.delete if @delete_from_server end i += 1 end puts "#{pop.mails.size} mails popped." end pop.finish savecaption( @messages ) unless @messages.empty? sendpic( @messages ) unless @messages.empty? rescue puts "There was an error downloading email: " + $! end end def savecaption( msgs ) begin captions = File.open("inbox/captions.txt", File::WRONLY|File::APPEND|File::CREAT) msgs.each do |m| captions.puts "#{m.filename} #{m.caption}" end rescue puts "There was an error downloading email: " + $! ensure captions.close unless captions.nil? end end def sendpic( msgs ) begin puts "Trying to ftp to #{@config['ftpserver']}" ftp = Net::FTP.new(@config['ftpserver']) #ftp.debug_mode = true ftp.passive = true puts "Logging in..." ftp.login(@config['ftpuser'], @config['ftppasswd']) puts "Logged in" files = ftp.chdir(@config['ftpdir']) puts "Uploading inbox/captions.txt" ftp.putbinaryfile("inbox/captions.txt", "captions.txt", 1024) msgs.each { |m| puts "Uploading inbox/#{m.filename}" ftp.putbinaryfile("inbox/#{m.filename}", "#{m.filename}", 1024) } puts "Done." rescue puts "There was an error uploading files: " + $! ensure ftp.close unless ftp.nil? end end # Read config file def getconf Dir.mkdir("inbox") unless test(?d, "inbox") begin cf = File.open("config", "r") cf.each do |line| line.chomp! (pat, subst) = line.split(/\s*=\s*/) if pat && subst @config[pat] = subst #puts "Read #{pat} = #{subst}" end end cf.close rescue SystemCallError File.open("config", "w") do |f| @config.each{ |key, value| f.puts "#{key} = #{value}\n"} puts "'config' file doesn't exist." puts "You need to edit the empty file that was just created.\n" end raise "'config' file doesn't exist." end end end #-------- Message class; extends from built-in [poor] Mail library class Picmail < Mail attr_reader :caption, :encoded_pic, :pic, :filename def extract_pic # not-so-poor message parsing function state = '0' @filename = self['DATE'].gsub(/[ \(\)]/, '_') + '.jpg' @encoded_pic = '' parts = @body.join.split(/\n------=_Part_/) # split body in parts parts.each do |p| # scan thru the parts sections = p.split(/^\s*$/) # header/body of each part if( sections[0] =~ /\nContent-Type:\simage\/jpeg;\sname=.*picture.*\.jpg/ ) @encoded_pic = sections[1].gsub(/\n/, '') # remove \n @pic = @encoded_pic.unpack("m") # decode elsif( sections[0] =~ /\nContent-Type:\stext\/plain;\scharset=us-ascii/ ) @caption = sections[1].gsub(/\n/, '') # remove \n puts "Got pic!: #{@caption}" end end save_pic self end def save_pic begin File.open("inbox/#{@filename}", 'w') do |f| f.write @pic end rescue puts "There was an error saving the file inbox/#{@filename}: " + $! end end end #----- main loop plog = Picblogger.new mins = 10 while (true) do plog.getmail puts "#{Time.now}: Sleeping #{mins} minutes..." sleep( 60 * mins ) end