[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

accessing gmail account via POP3

ptkwt

4/5/2005 3:39:00 PM

Has anyone written any Ruby code for accessing their gmail account that
they would be willing to share?

Here are the requirements according to google:

pop.gmail.com
Use SSL: Yes
Port: 995

Phil

4 Answers

Douglas Livingstone

4/5/2005 5:51:00 PM

0

Would this help?

http://www.ruby-doc.org/stdlib/libdoc/net/pop/rdoc/classes/Net...

Douglas

On Apr 5, 2005 4:59 PM, Phil Tomson <ptkwt@aracnet.com> wrote:
> Has anyone written any Ruby code for accessing their gmail account that
> they would be willing to share?
>
> Here are the requirements according to google:
>
> pop.gmail.com
> Use SSL: Yes
> Port: 995
>
> Phil
>
>


Pete Elmore

4/5/2005 7:24:00 PM

0

Douglas Livingstone wrote:
> Would this help?
>
> http://www.ruby-doc.org/stdlib/libdoc/net/pop/rdoc/classes/Net...
It doesn't support SSL, does it? I couldn't find anything about it in
the docs. I tried this about a week or two ago, and was unable to get
it to authenticate me without SSL.


Doug Beaver

4/5/2005 9:15:00 PM

0

On Wed, Apr 06, 2005 at 12:59:45AM +0900, Phil Tomson wrote:
> Has anyone written any Ruby code for accessing their gmail account
> that they would be willing to share?
>
> Here are the requirements according to google:

ruby-core#2703 and ruby-core#2745 include patches to add ssl support to
Net::POP3. from the thread, it looks like it was checked in, but maybe
into 1.9 only?

i imagine you could use the patches as a guide and write a small wrapper
class that sets up the SSLSocket to gmail...

doug

> pop.gmail.com
> Use SSL: Yes
> Port: 995
>
> Phil
>
>

--
"Contrary to what most people say, the most dangerous animal in the
world is not the lion or the tiger or even the elephant. It's a shark
riding on an elephant's back, just trampling and eating everything they
see." -- Jack Handey


Eric Anderson

4/11/2005 2:56:00 PM

0

Phil Tomson wrote:
> Has anyone written any Ruby code for accessing their gmail account that
> they would be willing to share?
>
> Here are the requirements according to google:
>
> pop.gmail.com
> Use SSL: Yes
> Port: 995

I have a bit of code that might help. I briefly tried Kapsules since it
had Ruby support but I found it to be unstable, slow and resource
intensive. But while I was using it I needed to get the Mail Kapsule
using SSL and since it was written in Ruby I added the necessary
support. Of course ruby-1.8 doesn't support SSL but the CVS version does
so I sort of backported it (my version is a bit simpler, therefore the
interface is different). The great thing is with Ruby this backport only
took about 1 hour! Anyway I have attached my modified mail kapsule file.
You don't need all the kapsule stuff. Just the stuff at the end where I
add added the SSL POP3 support. I included the entire script so you can
see how the code should be used (plus I'm too lazy to cut out just the
parts you need).

Eric
require 'socket'
require 'net/pop'
require 'net/imap'
require 'net/protocol'
require 'openssl/ssl'

def log( text )
File.open( Info.WidgetPath + "kapmail.log", "a" ) do |f|
f.puts( Time.now.strftime( "[%m/%d %H:%M:%S] " ) + text.to_s )
end
end

def Widget_Activate()
path = Info.WidgetPath() + "Resources/email.png"
$icon = Graphics.LoadImage( path )
$msg_ids = Hash.new
$seen = Hash.new

readConfiguration

Widget_Paint()
end

def Widget_Deactivate()
Widget.DeleteTimer "POPCheck"
$icon.Dispose
end

def Widget_ConfigChange()
readConfiguration
Widget_Paint()
end

def readConfiguration()
# Read the conf file.

$classes = Hash.new
$delete_regexps = Array.new
$servers = Array.new
lines = IO.readlines( Info.WidgetPath + Settings.GetSettingNode( "widgetroot/conf" ) )
lines.each do |l|
line = l.chomp
command, args = line.split( /\s+/, 2 )
case command
when "class"
cl, regexp_str = args.split( /\s+/, 2 )
if regexp_str != nil
$classes[ cl ] = Regexp.new( regexp_str )
end
when "server"
args =~ /^(.+?)\s+(.+?):(\d+)\s+(.+?);(.+)/
$servers.push( {
"protocol" => $1,
"host" => $2,
"port" => $3.to_i,
"username" => $4,
"password" => $5
} )
when "delete"
$delete_regexps.push( Regexp.new( args ) )
end
end

# Remaining configuration.

Graphics.Font.ColorHTML( Settings.GetSettingAttribute( "widgetroot/font", "color" ) )
Graphics.Font.Name = Settings.GetSettingAttribute( "widgetroot/font", "name" )
Graphics.Font.Size = Settings.GetSettingAttribute( "widgetroot/font", "size" )

# Setup the check interval.
Widget.DeleteTimer "POPCheck"
Widget.AddTimer( "POPCheck", Settings.GetSettingNode( "widgetroot/interval" ).to_i * 60 * 1000 )

# Sound file.

@soundfile = Settings.GetSettingNode( "widgetroot/sound" )
# Absolute or relative filepath?
if @soundfile != nil and @soundfile != ""
if @soundfile !~ /(?:[A-Za-z]:)?\\/
# Relative
@soundfile = Info.WidgetPath + @soundfile
end
end
end

def checkAgainstClasses( line )
$classes.each do |cl, regexp|
if line =~ regexp
$counts[ cl ] = ( $counts[ cl ] or 0 ) + 1
end
end
end

def Widget_Paint()
Graphics.Clear()
drawBackground
Graphics.DrawString( "(checking mail...)", 5, 5 )
Widget.UpdateWidget()

# ---------

$counts = Hash.new

num_lines = 1
num_msgs = 0
msg = ""

server_threads = Array.new

$servers.each do |server|
t = Thread.new do ||
protocol = server[ "protocol" ].downcase
host = server[ "host" ]
port = server[ "port" ]
username = server[ "username" ]
password = server[ "password" ]

log "Connecting to #{protocol} server #{host}:#{port} with username '#{username}'..."

begin
case protocol
when /pop/
kls = protocol =~ /spop/ ? Net::POP3S : Net::POP3
kls.start( host, port, username, password ) do |pop|
pop.mails.each do |m|
header = m.header.split( /\n/ )

# Get message ID.

id = nil
header.each do |l|
line = l.chomp
if line =~ /^Message-Id: <(.*)>/
id = $1
$msg_ids[ id ] = true
break
end
end

# Check for regexp matches.

result = checkDeletion( header )
if result != nil
subject, from = result
log "Deleting '#{subject}' from #{from}"
m.delete
else
if not $seen[ id ]
header.each do |l|
line = l.chomp
checkAgainstClasses( line )
end
num_msgs += 1
end
end
end
end
when /imap/
log "Connecting to #{host}:#{port}..."
imap = Net::IMAP.new( host, port )
log imap.capability().join( "|" )
#imap.authenticate( 'LOGIN', username, password )
imap.login( username, password )
#imap.examine( 'INBOX' )
imap.select( "INBOX" )

# Check for matches.

to_delete = Array.new

imap.search( [ "RECENT" ] ).each do |message_id|
uid = imap.fetch( message_id, "UID" )[ 0 ].attr[ "UID" ]
log "UID: #{uid}"
$msg_ids[ uid ] = true

header = imap.fetch( message_id, "RFC822.HEADER" )[ 0 ].attr[ "RFC822.HEADER" ].split( "\n" )
result = checkDeletion( header )
if result != nil
subject, from = result
log "Deleting '#{subject}' from #{from}"
to_delete.push uid
else
if not $seen[ uid ]
header.each do |l|
line = l.chomp
checkAgainstClasses( line )
end
num_msgs += 1
end
end
end

if to_delete.length > 0
imap.uid_store( to_delete, "+FLAGS", [:Deleted] )
end
end
rescue Errno::ECONNREFUSED => error
msg = "Connection to #{host}:#{port} refused.\n"
rescue Exception => e
msg = "CRITICAL EXCEPTION!\nShift-right-click in here to check your configuration."
log e.message
log "protocol: '#{protocol}' host: '#{host}' port: #{port} username: '#{username}'"
e.backtrace.each do |stack_element|
log stack_element
end
num_lines += 1
end
end
if Settings.GetSettingNode( "widgetroot/multithreaded" ) == "Yes"
t.priority = 2
server_threads.push t
else
t.join
end
end

main_thread = Thread.new do ||
server_threads.each do |t|
t.join
end
widest = 0
if $counts.length > 0
$counts.each do |cl, count|
sub_msg = cl + ": " + count.to_s
width = Graphics.GetStringWidth( sub_msg )
widest = width if width > widest
msg += sub_msg + "\n"
end
end
sub_msg = "Total: #{num_msgs}"
width = Graphics.GetStringWidth( sub_msg )
widest = width if width > widest
msg += sub_msg

# Bug in Kapsules? Workaround:
widest += 1

Graphics.Clear()

Widget.Width = widest + 20
Widget.Height = Graphics.GetStringHeight( msg, widest ) + 20

if num_msgs > 0
corner_x, corner_y = mailIconCorner
Widget.Width = [ Widget.Width, corner_x + 10 ].max
Widget.Height = [ Widget.Height, corner_y + 10 ].max
end

drawBackground( Widget.Height, Widget.Width )
if num_msgs > 0
drawNewMailIcon
if @soundfile != nil and @soundfile != ""
Widget.PlayWav @soundfile
end
end
Graphics.DrawString( msg, 10, 10, Widget.Width - 20, Widget.Height - 20 )
Widget.UpdateWidget()
end
if Settings.GetSettingNode( "widgetroot/multithreaded" ) == "Yes"
main_thread.priority = 2
else
main_thread.join
end
end

# Return the subject and the sender in an array if the message
# should be deleted. Otherwise, return nil.
def checkDeletion( header )
do_delete = false
subject = nil
from = nil

header.each do |l|
line = l.chomp
if not do_delete
$delete_regexps.each do |regexp|
if line =~ regexp
do_delete = true
end
end
end

if line =~ /^Subject: (.+)/
subject = $1
end
if line =~ /^From: (.+)/
from = $1
end
end

return ( do_delete ? [ subject, from ] : nil )
end

def drawBackground( height = Widget.Height, width = Widget.Width )
Graphics.DrawImageFromFile( Info.WidgetPath() + "Resources/default.bg.png", 0, 0, width, height )
end

def drawNewMailIcon
Graphics.DrawImage(
$icon,
Settings.GetSettingAttribute( "widgetroot/icon", "x" ).to_i,
Settings.GetSettingAttribute( "widgetroot/icon", "y" ).to_i,
Settings.GetSettingAttribute( "widgetroot/icon", "width" ).to_i,
Settings.GetSettingAttribute( "widgetroot/icon", "height" ).to_i
)
end

def mailIconCorner
x = Settings.GetSettingAttribute( "widgetroot/icon", "x" ).to_i +
Settings.GetSettingAttribute( "widgetroot/icon", "width" ).to_i
y = Settings.GetSettingAttribute( "widgetroot/icon", "y" ).to_i +
Settings.GetSettingAttribute( "widgetroot/icon", "height" ).to_i

return [x, y]
end

def Widget_OnDoubleClick()
$seen = $msg_ids.dup
Widget_Paint()
end

def POPCheck_tick()
Widget_Paint()
end

def Widget_OnKeyPress( key )
$seen = Hash.new
Widget_Paint()
end

# These functions are for handling the "move away on right click" functionality.

def Widget_OnMouseUp( x, y, button )
if button == MouseButton.Right
move( x, y )
end
end
def MoveTimer_Tick()
moveBack
end

# Moves the widget away, based on the click coordinates.
MOVE_POSITIONS = [ 0.5, 0.8, 0.9, 0.96, 1 ]
def move( click_x, click_y )
@old_top = Widget.Top
MOVE_POSITIONS.each do |pos|
Widget.Top = @old_top + ( Widget.Height * pos ).to_i
end
@moved = true
Widget.AddTimer( "MoveTimer", 5000 )
end
def moveBack
Widget.DeleteTimer "MoveTimer"
@moved = false
Widget.Top = @old_top
end

# POP3 SSL support
class Net::POP3S < Net::POP3
def self.default_port
995
end
def do_start( account, password )
s = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
sslctx = OpenSSL::SSL::SSLContext.new

s = OpenSSL::SSL::SSLSocket.new(s, sslctx)
s.sync_close = true
s.connect
@socket = Net::SInternetMessageIO.new(s)
@socket.read_timeout = @read_timeout
@socket.debug_output = @debug_output
on_connect
@command = Net::POP3Command.new(@socket)
if apop?
@command.apop account, password
else
@command.auth account, password
end
@started = true
ensure
# Authentication failed, clean up connection.
unless @started
s.close if s and not s.closed?
@socket = nil
@command = nil
end
end
private :do_start
end

class Net::SInternetMessageIO < Net::InternetMessageIO
attr_accessor :debug_output
def initialize(s)
@socket = s
@rbuf = ''
end
end