1999-10-13 03:29:15 -04:00
|
|
|
=begin
|
|
|
|
|
2001-12-13 14:15:21 -05:00
|
|
|
= net/pop.rb
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2003-03-09 11:53:30 -05:00
|
|
|
Copyright (c) 1999-2003 Yukihiro Matsumoto
|
|
|
|
Copyright (c) 1999-2003 Minero Aoki
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
written & maintained by Minero Aoki <aamine@loveruby.net>
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
This program is free software. You can re-distribute and/or
|
|
|
|
modify this program under the same terms as Ruby itself,
|
|
|
|
Ruby Distribute License or GNU General Public License.
|
2001-02-23 23:53:50 -05:00
|
|
|
|
2001-12-07 05:04:25 -05:00
|
|
|
NOTE: You can find Japanese version of this document in
|
|
|
|
the doc/net directory of the standard ruby interpreter package.
|
2000-09-21 02:58:01 -04:00
|
|
|
|
2001-12-13 14:15:21 -05:00
|
|
|
$Id$
|
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
== What is This Module?
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
This module provides your program the functions to retrieve
|
|
|
|
mails via POP3, Post Office Protocol version 3. For details
|
|
|
|
of POP3, refer [RFC1939] ((<URL:http://www.ietf.org/rfc/rfc1939.txt>)).
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
== Examples
|
|
|
|
|
|
|
|
=== Retrieving Mails
|
|
|
|
|
|
|
|
This example retrieves mails from server and delete it (on server).
|
|
|
|
Mails are written in file named 'inbox/1', 'inbox/2', ....
|
|
|
|
Replace 'pop3.server.address' your POP3 server address.
|
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
require 'net/pop'
|
|
|
|
|
2003-03-09 11:53:30 -05:00
|
|
|
pop = Net::POP3.new('pop3.server.address', 110)
|
|
|
|
pop.start('YourAccount', 'YourPassword') ###
|
2001-12-09 03:58:30 -05:00
|
|
|
if pop.mails.empty? then
|
|
|
|
puts 'no mail.'
|
|
|
|
else
|
|
|
|
i = 0
|
|
|
|
pop.each_mail do |m| # or "pop.mails.each ..."
|
2003-03-09 11:53:30 -05:00
|
|
|
File.open('inbox/' + i.to_s, 'w') {|f|
|
2001-06-26 20:59:08 -04:00
|
|
|
f.write m.pop
|
2001-12-09 03:58:30 -05:00
|
|
|
}
|
|
|
|
m.delete
|
|
|
|
i += 1
|
2001-06-26 19:49:21 -04:00
|
|
|
end
|
2001-06-26 20:59:08 -04:00
|
|
|
puts "#{pop.mails.size} mails popped."
|
2001-12-09 03:58:30 -05:00
|
|
|
end
|
2003-03-09 11:53:30 -05:00
|
|
|
pop.finish ###
|
2001-12-09 03:58:30 -05:00
|
|
|
|
|
|
|
(1) call Net::POP3#start and start POP session
|
|
|
|
(2) access mails by using POP3#each_mail and/or POP3#mails
|
|
|
|
(3) close POP session by calling POP3#finish or use block form #start.
|
|
|
|
|
|
|
|
This example is using block form #start to close the session.
|
2003-05-02 10:35:01 -04:00
|
|
|
|
2001-12-09 03:58:30 -05:00
|
|
|
=== Enshort Code
|
|
|
|
|
|
|
|
The example above is very verbose. You can enshort code by using
|
|
|
|
some utility methods. At first, block form of Net::POP3.start can
|
|
|
|
alternates POP3.new, POP3#start and POP3#finish.
|
|
|
|
|
|
|
|
require 'net/pop'
|
|
|
|
|
2003-03-09 11:53:30 -05:00
|
|
|
Net::POP3.start('pop3.server.address', 110)
|
|
|
|
'YourAccount', 'YourPassword')
|
|
|
|
if pop.mails.empty?
|
|
|
|
puts 'no mail.'
|
|
|
|
else
|
|
|
|
i = 0
|
|
|
|
pop.each_mail do |m| # or "pop.mails.each ..."
|
|
|
|
File.open('inbox/' + i.to_s, 'w') {|f|
|
2001-12-09 03:58:30 -05:00
|
|
|
f.write m.pop
|
2003-03-09 11:53:30 -05:00
|
|
|
}
|
|
|
|
m.delete
|
|
|
|
i += 1
|
|
|
|
end
|
2001-12-09 03:58:30 -05:00
|
|
|
puts "#{pop.mails.size} mails popped."
|
2003-03-09 11:53:30 -05:00
|
|
|
end
|
2001-06-26 20:59:08 -04:00
|
|
|
}
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2001-12-09 03:58:30 -05:00
|
|
|
POP3#delete_all alternates #each_mail and m.delete.
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
require 'net/pop'
|
2001-12-09 03:58:30 -05:00
|
|
|
|
2003-03-09 11:53:30 -05:00
|
|
|
Net::POP3.start('pop3.server.address', 110,
|
|
|
|
'YourAccount', 'YourPassword') {|pop|
|
|
|
|
if pop.mails.empty?
|
|
|
|
puts 'no mail.'
|
|
|
|
else
|
|
|
|
i = 0
|
|
|
|
pop.delete_all do |m|
|
|
|
|
File.open('inbox/' + i.to_s, 'w') {|f|
|
|
|
|
f.write m.pop
|
|
|
|
}
|
|
|
|
i += 1
|
|
|
|
end
|
|
|
|
end
|
2001-06-26 20:59:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
And here is more shorter example.
|
|
|
|
|
|
|
|
require 'net/pop'
|
2001-12-09 03:58:30 -05:00
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
i = 0
|
2003-03-09 11:53:30 -05:00
|
|
|
Net::POP3.delete_all('pop3.server.address', 110,
|
|
|
|
'YourAccount', 'YourPassword') do |m|
|
|
|
|
File.open('inbox/' + i.to_s, 'w') {|f|
|
2001-12-09 03:58:30 -05:00
|
|
|
f.write m.pop
|
2001-06-26 19:49:21 -04:00
|
|
|
}
|
|
|
|
i += 1
|
|
|
|
end
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
=== Writing to File directly
|
|
|
|
|
|
|
|
All examples above get mail as one big string.
|
|
|
|
This example does not create such one.
|
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
require 'net/pop'
|
2003-03-09 11:53:30 -05:00
|
|
|
Net::POP3.delete_all('pop3.server.address', 110,
|
|
|
|
'YourAccount', 'YourPassword') do |m|
|
|
|
|
File.open('inbox', 'w') {|f|
|
2001-12-09 03:58:30 -05:00
|
|
|
m.pop f ####
|
2001-06-26 20:59:08 -04:00
|
|
|
}
|
|
|
|
end
|
2001-06-26 19:49:21 -04:00
|
|
|
|
|
|
|
=== Using APOP
|
|
|
|
|
2001-12-13 14:15:21 -05:00
|
|
|
The net/pop library supports APOP authentication.
|
|
|
|
To use APOP, use Net::APOP class instead of Net::POP3 class.
|
|
|
|
You can use utility method, Net::POP3.APOP(). Example:
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
require 'net/pop'
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Use APOP authentication if $isapop == true
|
2003-03-09 11:53:30 -05:00
|
|
|
pop = Net::POP3.APOP($isapop).new('apop.server.address', 110)
|
|
|
|
pop.start(YourAccount', 'YourPassword') {|pop|
|
2001-12-09 03:58:30 -05:00
|
|
|
# Rest code is same.
|
2001-06-26 20:59:08 -04:00
|
|
|
}
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
=== Fetch Only Selected Mail Using POP UIDL Function
|
|
|
|
|
|
|
|
If your POP server provides UIDL function,
|
|
|
|
you can pop only selected mails from POP server.
|
|
|
|
e.g.
|
|
|
|
|
|
|
|
def need_pop?( id )
|
|
|
|
# determine if we need pop this mail...
|
|
|
|
end
|
|
|
|
|
|
|
|
Net::POP3.start('pop.server', 110,
|
|
|
|
'Your account', 'Your password') {|pop|
|
|
|
|
pop.mails.select {|m| need_pop?(m.unique_id) }.each do |m|
|
|
|
|
do_something(m.pop)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
POPMail#unique_id method returns the unique-id of the message (String).
|
|
|
|
Normally unique-id is a hash of the message.
|
|
|
|
|
2001-12-13 14:15:21 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
== class Net::POP3
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
=== Class Methods
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: new( address, port = 110, isapop = false )
|
2001-06-26 20:59:08 -04:00
|
|
|
creates a new Net::POP3 object.
|
2003-05-02 10:35:01 -04:00
|
|
|
This method does NOT open TCP connection yet.
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: start( address, port = 110, account, password, isapop = false )
|
|
|
|
: start( address, port = 110, account, password, isapop = false ) {|pop| .... }
|
|
|
|
equals to Net::POP3.new(address, port, isapop).start(account, password).
|
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Typical usage
|
|
|
|
Net::POP3.start(addr, port, account, password) {|pop|
|
2003-03-09 11:53:30 -05:00
|
|
|
pop.each_mail do |m|
|
|
|
|
file.write m.pop
|
|
|
|
m.delete
|
|
|
|
end
|
2001-12-09 03:58:30 -05:00
|
|
|
}
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2001-12-13 14:15:21 -05:00
|
|
|
: APOP( is_apop )
|
|
|
|
returns Net::APOP class object if IS_APOP is true.
|
|
|
|
returns Net::POP3 class object if false.
|
|
|
|
Use this method like:
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Example 1
|
2001-12-13 14:15:21 -05:00
|
|
|
pop = Net::POP3::APOP($isapop).new( addr, port )
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Example 2
|
2001-12-13 14:15:21 -05:00
|
|
|
Net::POP3::APOP($isapop).start( addr, port ) {|pop|
|
|
|
|
....
|
|
|
|
}
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: foreach( address, port = 110, account, password, isapop = false ) {|mail| .... }
|
2001-06-26 20:59:08 -04:00
|
|
|
starts POP3 protocol and iterates for each POPMail object.
|
2003-05-02 10:35:01 -04:00
|
|
|
This method equals to:
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2001-06-26 20:59:08 -04:00
|
|
|
Net::POP3.start( address, port, account, password ) {|pop|
|
2001-12-09 03:58:30 -05:00
|
|
|
pop.each_mail do |m|
|
2003-03-09 11:53:30 -05:00
|
|
|
yield m
|
|
|
|
end
|
2001-06-26 20:59:08 -04:00
|
|
|
}
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
|
|
|
|
|
|
|
# Typical usage
|
2001-06-26 20:59:08 -04:00
|
|
|
Net::POP3.foreach( 'your.pop.server', 110,
|
|
|
|
'YourAccount', 'YourPassword' ) do |m|
|
|
|
|
file.write m.pop
|
|
|
|
m.delete if $DELETE
|
|
|
|
end
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: delete_all( address, port = 110, account, password, isapop = false )
|
|
|
|
: delete_all( address, port = 110, account, password, isapop = false ) {|mail| .... }
|
2001-06-26 19:49:21 -04:00
|
|
|
starts POP3 session and delete all mails.
|
|
|
|
If block is given, iterates for each POPMail object before delete.
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Example
|
2001-06-26 19:49:21 -04:00
|
|
|
Net::POP3.delete_all( addr, nil, 'YourAccount', 'YourPassword' ) do |m|
|
|
|
|
m.pop file
|
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: auth_only( address, port = 110, account, password, isapop = false )
|
2001-06-26 19:49:21 -04:00
|
|
|
(just for POP-before-SMTP)
|
|
|
|
opens POP3 session and does autholize and quit.
|
|
|
|
This method must not be called while POP3 session is opened.
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Example
|
2001-12-09 03:58:30 -05:00
|
|
|
Net::POP3.auth_only( 'your.pop3.server',
|
|
|
|
nil, # using default (110)
|
|
|
|
'YourAccount',
|
|
|
|
'YourPassword' )
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2001-02-06 06:14:51 -05:00
|
|
|
=== Instance Methods
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: start( account, password )
|
2000-05-18 04:57:37 -04:00
|
|
|
: start( account, password ) {|pop| .... }
|
2001-06-26 19:49:21 -04:00
|
|
|
starts POP3 session.
|
|
|
|
|
|
|
|
When called with block, gives a POP3 object to block and
|
|
|
|
closes the session after block call finish.
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
|
|
|
|
|
|
|
: started?
|
2001-06-26 19:49:21 -04:00
|
|
|
true if POP3 session is started.
|
|
|
|
|
|
|
|
: address
|
|
|
|
the address to connect
|
|
|
|
|
|
|
|
: port
|
|
|
|
the port number to connect
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
: open_timeout
|
|
|
|
: open_timeout=(n)
|
|
|
|
seconds to wait until connection is opened.
|
|
|
|
If POP3 object cannot open a conection in this seconds,
|
|
|
|
it raises TimeoutError exception.
|
|
|
|
|
|
|
|
: read_timeout
|
|
|
|
: read_timeout=(n)
|
|
|
|
seconds to wait until reading one block (by one read(1) call).
|
|
|
|
If POP3 object cannot open a conection in this seconds,
|
|
|
|
it raises TimeoutError exception.
|
|
|
|
|
|
|
|
: finish
|
|
|
|
finishes POP3 session.
|
2001-07-03 15:03:16 -04:00
|
|
|
If POP3 session had not be started, raises an IOError.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: mails
|
2001-06-26 19:49:21 -04:00
|
|
|
an array of Net::POPMail objects.
|
2003-05-02 10:35:01 -04:00
|
|
|
This array is renewed when session restarts.
|
|
|
|
|
|
|
|
This method raises POPError if any problem happend.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2000-12-22 13:40:55 -05:00
|
|
|
: each_mail {|popmail| .... }
|
|
|
|
: each {|popmail| .... }
|
2001-06-26 19:49:21 -04:00
|
|
|
is equals to "pop3.mails.each"
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
2000-12-22 13:40:55 -05:00
|
|
|
: delete_all
|
|
|
|
: delete_all {|popmail| .... }
|
2001-06-26 19:49:21 -04:00
|
|
|
deletes all mails on server.
|
|
|
|
If called with block, gives mails to the block before deleting.
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# Example
|
2001-06-26 19:49:21 -04:00
|
|
|
n = 1
|
|
|
|
pop.delete_all do |m|
|
|
|
|
File.open("inbox/#{n}") {|f| f.write m.pop }
|
|
|
|
n += 1
|
|
|
|
end
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
: auth_only( account, password )
|
|
|
|
(just for POP-before-SMTP)
|
2003-05-02 10:35:01 -04:00
|
|
|
|
|
|
|
opens POP3 session, does authorization, then quit.
|
|
|
|
You must not call this method after POP3 session is opened.
|
|
|
|
|
|
|
|
This method raises POPAuthenticationError if authentication is failed.
|
|
|
|
|
|
|
|
# Typical usage
|
|
|
|
pop = Net::POP3.new('your.pop3.server')
|
|
|
|
pop.auth_only('Your account', 'Your password')
|
|
|
|
Net::SMTP.start(....) {|smtp|
|
|
|
|
....
|
|
|
|
}
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2000-10-12 05:54:32 -04:00
|
|
|
: reset
|
2001-06-26 20:59:08 -04:00
|
|
|
reset the session. All "deleted mark" are removed.
|
2000-10-12 05:54:32 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
|
|
|
|
|
|
|
== class Net::APOP
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
This class defines no new methods.
|
|
|
|
Only difference from POP3 is using APOP authentification.
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
=== Super Class
|
2003-05-02 10:35:01 -04:00
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
Net::POP3
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
|
|
|
|
== class Net::POPMail
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
A class of mail which exists on POP server.
|
|
|
|
|
2001-06-26 19:49:21 -04:00
|
|
|
=== Instance Methods
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2000-12-24 15:01:44 -05:00
|
|
|
: pop( dest = '' )
|
2001-06-26 19:49:21 -04:00
|
|
|
This method fetches a mail and write to 'dest' using '<<' method.
|
2000-02-21 10:25:37 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
|
|
|
# Typical usage
|
2001-06-26 19:49:21 -04:00
|
|
|
allmails = nil
|
|
|
|
POP3.start( 'your.pop3.server', 110,
|
2001-12-09 03:58:30 -05:00
|
|
|
'YourAccount, 'YourPassword' ) {|pop|
|
|
|
|
allmails = pop.mails.collect {|popmail| popmail.pop }
|
|
|
|
}
|
2000-02-21 10:25:37 -05:00
|
|
|
|
2000-12-24 15:01:44 -05:00
|
|
|
: pop {|str| .... }
|
2001-06-26 19:49:21 -04:00
|
|
|
gives the block part strings of a mail.
|
2000-02-21 10:25:37 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
|
|
|
# Typical usage
|
2001-06-26 19:49:21 -04:00
|
|
|
POP3.start( 'localhost', 110 ) {|pop3|
|
2003-03-09 11:53:30 -05:00
|
|
|
pop3.each_mail do |m|
|
|
|
|
m.pop do |str|
|
|
|
|
# do anything
|
|
|
|
end
|
|
|
|
end
|
2001-06-26 19:49:21 -04:00
|
|
|
}
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: header
|
2003-05-02 10:35:01 -04:00
|
|
|
fetches only mail header.
|
|
|
|
|
|
|
|
This method raises POPError if any problem happend.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: top( lines )
|
2003-05-02 10:35:01 -04:00
|
|
|
fetches mail header and LINES lines of body.
|
|
|
|
|
|
|
|
This method raises POPError if any problem happend.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: delete
|
2001-06-26 19:49:21 -04:00
|
|
|
deletes mail on server.
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
: size
|
2001-06-26 19:49:21 -04:00
|
|
|
mail size (bytes)
|
1999-10-13 03:29:15 -04:00
|
|
|
|
|
|
|
: deleted?
|
2001-06-26 19:49:21 -04:00
|
|
|
true if mail was deleted
|
1999-10-13 03:29:15 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
: unique_id
|
|
|
|
returns an unique-id of the message.
|
|
|
|
Normally unique-id is a hash of the message.
|
|
|
|
|
|
|
|
This method raises POPError if any problem happend.
|
|
|
|
|
1999-10-13 03:29:15 -04:00
|
|
|
=end
|
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
require 'net/protocol'
|
2001-12-01 09:07:01 -05:00
|
|
|
require 'digest/md5'
|
2000-06-12 12:42:46 -04:00
|
|
|
|
|
|
|
|
|
|
|
module Net
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
class POPError < ProtocolError; end
|
|
|
|
class POPAuthenticationError < ProtoAuthError; end
|
|
|
|
class POPBadResponse < StandardError; end
|
|
|
|
|
|
|
|
|
|
|
|
class POP3
|
|
|
|
|
|
|
|
Revision = %q$Revision$.split[1]
|
2003-03-09 11:53:30 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
#
|
|
|
|
# Class Parameters
|
|
|
|
#
|
2003-03-09 11:53:30 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def POP3.default_port
|
|
|
|
110
|
|
|
|
end
|
2000-06-12 12:42:46 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def POP3.socket_type
|
|
|
|
Net::InternetMessageIO
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Utilities
|
|
|
|
#
|
2000-06-12 12:42:46 -04:00
|
|
|
|
2002-11-21 06:50:09 -05:00
|
|
|
def POP3.APOP( isapop )
|
|
|
|
isapop ? APOP : POP3
|
2002-02-19 07:33:52 -05:00
|
|
|
end
|
2001-12-13 14:15:21 -05:00
|
|
|
|
2002-02-19 07:33:52 -05:00
|
|
|
def POP3.foreach( address, port = nil,
|
2003-05-02 10:35:01 -04:00
|
|
|
account = nil, password = nil,
|
|
|
|
isapop = false, &block )
|
|
|
|
start(address, port, account, password, isapop) {|pop|
|
2002-11-21 06:50:09 -05:00
|
|
|
pop.each_mail(&block)
|
2002-02-19 07:33:52 -05:00
|
|
|
}
|
|
|
|
end
|
2000-12-22 13:40:55 -05:00
|
|
|
|
2002-02-19 07:33:52 -05:00
|
|
|
def POP3.delete_all( address, port = nil,
|
2003-05-02 10:35:01 -04:00
|
|
|
account = nil, password = nil,
|
|
|
|
isapop = false, &block )
|
|
|
|
start(address, port, account, password, isapop) {|pop|
|
2002-11-21 06:50:09 -05:00
|
|
|
pop.delete_all(&block)
|
2002-02-19 07:33:52 -05:00
|
|
|
}
|
|
|
|
end
|
2001-06-26 19:49:21 -04:00
|
|
|
|
2002-02-19 07:33:52 -05:00
|
|
|
def POP3.auth_only( address, port = nil,
|
2003-05-02 10:35:01 -04:00
|
|
|
account = nil, password = nil,
|
|
|
|
isapop = false )
|
|
|
|
new(address, port, isapop).auth_only account, password
|
2000-12-22 13:40:55 -05:00
|
|
|
end
|
|
|
|
|
2001-12-30 14:18:45 -05:00
|
|
|
def auth_only( account, password )
|
2002-02-19 07:33:52 -05:00
|
|
|
raise IOError, 'opening already opened POP session' if active?
|
2002-11-21 06:50:09 -05:00
|
|
|
start(account, password) {
|
2003-03-09 11:53:30 -05:00
|
|
|
;
|
2001-12-30 14:18:45 -05:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2003-05-02 10:35:01 -04:00
|
|
|
# Session management
|
2001-12-30 14:18:45 -05:00
|
|
|
#
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def POP3.start( address, port = nil,
|
|
|
|
account = nil, password = nil,
|
|
|
|
isapop = false, &block )
|
|
|
|
new(address, port, isapop).start(account, password, &block)
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize( addr, port = nil, isapop = false )
|
|
|
|
@address = addr
|
|
|
|
@port = port || self.class.default_port
|
|
|
|
@apop = isapop
|
|
|
|
|
|
|
|
@command = nil
|
|
|
|
@socket = nil
|
|
|
|
@started = false
|
|
|
|
@open_timeout = 30
|
|
|
|
@read_timeout = 60
|
|
|
|
@debug_output = nil
|
|
|
|
|
2000-10-12 05:54:32 -04:00
|
|
|
@mails = nil
|
2003-05-02 10:35:01 -04:00
|
|
|
@nmails = nil
|
|
|
|
@bytes = nil
|
2000-06-12 12:42:46 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def apop?
|
|
|
|
@apop
|
|
|
|
end
|
|
|
|
|
|
|
|
def inspect
|
|
|
|
"#<#{self.class} #{@address}:#{@port} open=#{@started}>"
|
|
|
|
end
|
|
|
|
|
|
|
|
def set_debug_output( arg ) # :nodoc:
|
|
|
|
@debug_output = arg
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :address
|
|
|
|
attr_reader :port
|
|
|
|
|
|
|
|
attr_accessor :open_timeout
|
|
|
|
attr_reader :read_timeout
|
|
|
|
|
|
|
|
def read_timeout=( sec )
|
|
|
|
@command.socket.read_timeout = sec if @command
|
|
|
|
@read_timeout = sec
|
|
|
|
end
|
|
|
|
|
|
|
|
def started?
|
|
|
|
@started
|
|
|
|
end
|
|
|
|
|
|
|
|
alias active? started? # backward compatibility
|
|
|
|
|
|
|
|
def start( account, password )
|
|
|
|
raise IOError, 'already closed POP session' if @started
|
|
|
|
|
|
|
|
if block_given?
|
|
|
|
begin
|
|
|
|
do_start account, password
|
|
|
|
return yield(self)
|
|
|
|
ensure
|
|
|
|
finish unless @started
|
|
|
|
end
|
|
|
|
else
|
|
|
|
do_start acount, password
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
end
|
2001-12-30 14:18:45 -05:00
|
|
|
|
|
|
|
def do_start( account, password )
|
2003-05-02 10:35:01 -04:00
|
|
|
@socket = self.class.socket_type.open(@address, @port,
|
|
|
|
@open_timeout, @read_timeout, @debug_output)
|
|
|
|
on_connect
|
|
|
|
@command = POP3Command.new(@socket)
|
|
|
|
if apop?
|
|
|
|
@command.apop account, password
|
|
|
|
else
|
|
|
|
@command.auth account, password
|
|
|
|
end
|
|
|
|
@started = true
|
2001-12-30 14:18:45 -05:00
|
|
|
end
|
2003-05-02 10:35:01 -04:00
|
|
|
private :do_start
|
2001-12-30 14:18:45 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def on_connect
|
2002-11-21 06:50:09 -05:00
|
|
|
end
|
2003-05-02 10:35:01 -04:00
|
|
|
private :on_connect
|
2002-11-21 06:50:09 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def finish
|
|
|
|
raise IOError, 'already closed POP session' unless @started
|
2001-12-30 14:18:45 -05:00
|
|
|
@mails = nil
|
2003-05-02 10:35:01 -04:00
|
|
|
@command.quit if @command
|
|
|
|
@command = nil
|
|
|
|
@socket.close if @socket and not @socket.closed?
|
|
|
|
@socket = nil
|
|
|
|
@started = false
|
2001-06-26 19:49:21 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def command
|
|
|
|
raise IOError, 'POP session not opened yet' \
|
|
|
|
if not @socket or @socket.closed?
|
|
|
|
@command
|
|
|
|
end
|
|
|
|
private :command
|
|
|
|
|
2001-12-30 14:18:45 -05:00
|
|
|
#
|
2003-05-02 10:35:01 -04:00
|
|
|
# POP protocol wrapper
|
2001-12-30 14:18:45 -05:00
|
|
|
#
|
|
|
|
|
2003-03-09 11:53:30 -05:00
|
|
|
def mail_size
|
|
|
|
return @nmails if @nmails
|
|
|
|
@nmails, @bytes = command().stat
|
|
|
|
@nmails
|
|
|
|
end
|
|
|
|
|
|
|
|
def bytes
|
|
|
|
return @bytes if @bytes
|
|
|
|
@nmails, @bytes = command().stat
|
|
|
|
@bytes
|
|
|
|
end
|
|
|
|
|
2001-12-30 14:18:45 -05:00
|
|
|
def mails
|
2003-05-02 10:35:01 -04:00
|
|
|
return @mails.dup if @mails
|
2003-03-09 11:53:30 -05:00
|
|
|
if mail_size() == 0
|
|
|
|
# some popd raises error for LIST on the empty mailbox.
|
|
|
|
@mails = []
|
2003-05-02 10:35:01 -04:00
|
|
|
return []
|
2003-03-09 11:53:30 -05:00
|
|
|
end
|
2001-12-30 14:18:45 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
@mails = command().list.map {|num, size|
|
|
|
|
POPMail.new(num, size, self, command())
|
|
|
|
}
|
|
|
|
@mails.dup
|
2001-12-30 14:18:45 -05:00
|
|
|
end
|
2000-06-12 12:42:46 -04:00
|
|
|
|
2000-12-22 13:40:55 -05:00
|
|
|
def each_mail( &block )
|
2002-11-21 06:50:09 -05:00
|
|
|
mails().each(&block)
|
2000-12-22 13:40:55 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
alias each each_mail
|
|
|
|
|
|
|
|
def delete_all
|
2001-12-30 14:18:45 -05:00
|
|
|
mails().each do |m|
|
2000-12-22 13:40:55 -05:00
|
|
|
yield m if block_given?
|
|
|
|
m.delete unless m.deleted?
|
|
|
|
end
|
2000-10-12 05:54:32 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def reset
|
2001-12-30 14:18:45 -05:00
|
|
|
command().rset
|
|
|
|
mails().each do |m|
|
2003-03-09 11:53:30 -05:00
|
|
|
m.instance_eval {
|
|
|
|
@deleted = false
|
|
|
|
}
|
2000-10-12 05:54:32 -04:00
|
|
|
end
|
2000-06-12 12:42:46 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# internal use only (called from POPMail#uidl).
|
|
|
|
def set_all_uids
|
|
|
|
command().uidl.each do |num, uid|
|
|
|
|
@mails.find {|m| m.number == num }.uid = uid
|
|
|
|
end
|
2000-10-12 05:54:32 -04:00
|
|
|
end
|
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
# aliases
|
2003-03-09 11:53:30 -05:00
|
|
|
POP = POP3
|
2002-02-19 07:33:52 -05:00
|
|
|
POPSession = POP3
|
|
|
|
POP3Session = POP3
|
2000-06-12 12:42:46 -04:00
|
|
|
|
aamine
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.26.
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb:
add module Net::NetPrivate and its inner classes
{Read,Write}Adapter, Command, Socket,
SMTPCommand, POP3Command, APOPCommand, HTTPCommand
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2000-07-12 02:04:40 -04:00
|
|
|
class APOP < POP3
|
2003-05-02 10:35:01 -04:00
|
|
|
def apop?
|
|
|
|
true
|
2002-02-19 07:33:52 -05:00
|
|
|
end
|
aamine
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.26.
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb:
add module Net::NetPrivate and its inner classes
{Read,Write}Adapter, Command, Socket,
SMTPCommand, POP3Command, APOPCommand, HTTPCommand
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2000-07-12 02:04:40 -04:00
|
|
|
end
|
|
|
|
|
2002-02-19 07:33:52 -05:00
|
|
|
APOPSession = APOP
|
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
|
1999-12-17 10:00:13 -05:00
|
|
|
class POPMail
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def initialize( num, size, pop, cmd )
|
|
|
|
@number = num
|
|
|
|
@size = size
|
|
|
|
@pop = pop
|
1999-12-29 06:14:04 -05:00
|
|
|
@command = cmd
|
1999-12-17 10:00:13 -05:00
|
|
|
@deleted = false
|
2003-05-02 10:35:01 -04:00
|
|
|
@uid = nil
|
1999-12-17 10:00:13 -05:00
|
|
|
end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
attr_reader :number
|
2003-03-09 11:53:30 -05:00
|
|
|
attr_reader :size
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2000-06-12 12:42:46 -04:00
|
|
|
def inspect
|
2003-05-02 10:35:01 -04:00
|
|
|
"#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>"
|
2000-06-12 12:42:46 -04:00
|
|
|
end
|
|
|
|
|
2001-12-07 05:04:25 -05:00
|
|
|
def pop( dest = '', &block )
|
2003-05-02 10:35:01 -04:00
|
|
|
@command.retr(@number, (block ? ReadAdapter.new(block) : dest))
|
1999-12-17 10:00:13 -05:00
|
|
|
end
|
2001-12-07 05:04:25 -05:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
alias all pop # backward compatibility
|
|
|
|
alias mail pop # backward compatibility
|
1999-09-22 03:32:33 -04:00
|
|
|
|
1999-12-17 10:00:13 -05:00
|
|
|
def top( lines, dest = '' )
|
2003-05-02 10:35:01 -04:00
|
|
|
@command.top(@number, lines, dest)
|
1999-12-17 10:00:13 -05:00
|
|
|
end
|
1999-10-18 05:03:16 -04:00
|
|
|
|
1999-12-17 10:00:13 -05:00
|
|
|
def header( dest = '' )
|
2003-05-02 10:35:01 -04:00
|
|
|
top(0, dest)
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
1999-12-17 10:00:13 -05:00
|
|
|
def delete
|
2003-05-02 10:35:01 -04:00
|
|
|
@command.dele @number
|
1999-12-17 10:00:13 -05:00
|
|
|
@deleted = true
|
|
|
|
end
|
2000-10-12 05:54:32 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
alias delete! delete # backward compatibility
|
1999-10-13 03:29:15 -04:00
|
|
|
|
1999-12-17 10:00:13 -05:00
|
|
|
def deleted?
|
|
|
|
@deleted
|
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def unique_id
|
|
|
|
return @uid if @uid
|
|
|
|
@pop.set_all_uids
|
|
|
|
@uid
|
|
|
|
end
|
|
|
|
|
|
|
|
alias uidl unique_id
|
|
|
|
|
|
|
|
# internal use only (used from POP3#set_all_uids).
|
|
|
|
def uid=( uid )
|
|
|
|
@uid = uid
|
1999-12-17 10:00:13 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
1999-10-13 03:29:15 -04:00
|
|
|
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
class POP3Command
|
1999-12-17 10:00:13 -05:00
|
|
|
|
|
|
|
def initialize( sock )
|
2003-05-02 10:35:01 -04:00
|
|
|
@socket = sock
|
|
|
|
@in_critical_block = false
|
|
|
|
res = check_response(critical { recv_response() })
|
|
|
|
@apop_stamp = res.slice(/<.+>/)
|
1999-12-17 10:00:13 -05:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def inspect
|
|
|
|
"#<#{self.class} socket=#{@socket}>"
|
|
|
|
end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def auth( account, password )
|
|
|
|
check_response_auth(critical { get_response('USER ' + account) })
|
|
|
|
check_response_auth(critical { get_response('PASS ' + password) })
|
|
|
|
end
|
|
|
|
|
|
|
|
def apop( account, password )
|
|
|
|
raise POPAuthenticationError.new('not APOP server; cannot login', nil)\
|
|
|
|
unless @apop_stamp
|
|
|
|
check_response_auth(critical {
|
|
|
|
get_reply('APOP %s %s',
|
|
|
|
account,
|
|
|
|
Digest::MD5.hexdigest(@apop_stamp + password))
|
|
|
|
})
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def list
|
2003-05-02 10:35:01 -04:00
|
|
|
critical {
|
2001-12-30 14:18:45 -05:00
|
|
|
getok 'LIST'
|
2003-03-09 11:53:30 -05:00
|
|
|
list = []
|
2002-02-19 07:33:52 -05:00
|
|
|
@socket.each_list_item do |line|
|
2001-12-30 14:18:45 -05:00
|
|
|
m = /\A(\d+)[ \t]+(\d+)/.match(line) or
|
2003-05-02 10:35:01 -04:00
|
|
|
raise POPBadResponse, "bad response: #{line}"
|
|
|
|
list.push [m[1].to_i, m[2].to_i]
|
2001-12-30 14:18:45 -05:00
|
|
|
end
|
2003-05-02 10:35:01 -04:00
|
|
|
list
|
2003-03-09 11:53:30 -05:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def stat
|
2003-05-02 10:35:01 -04:00
|
|
|
res = check_response(critical { get_response('STAT') })
|
|
|
|
m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or
|
|
|
|
raise POPBadResponse, "wrong response format: #{res}"
|
|
|
|
[m[1].to_i, m[2].to_i]
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def rset
|
2003-05-02 10:35:01 -04:00
|
|
|
check_reply(critical { get_response 'RSET' })
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def top( num, lines = 0, dest = '' )
|
2003-05-02 10:35:01 -04:00
|
|
|
critical {
|
|
|
|
getok('TOP %d %d', num, lines)
|
|
|
|
@socket.read_message_to(dest)
|
2000-03-27 10:52:27 -05:00
|
|
|
}
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
2002-02-19 07:33:52 -05:00
|
|
|
def retr( num, dest = '' )
|
2003-05-02 10:35:01 -04:00
|
|
|
critical {
|
|
|
|
getok('RETR %d', num)
|
2002-02-19 07:33:52 -05:00
|
|
|
@socket.read_message_to dest
|
2000-03-27 10:52:27 -05:00
|
|
|
}
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def dele( num )
|
2003-05-02 10:35:01 -04:00
|
|
|
check_response(critical { get_response('DELE %d', num) })
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def uidl( num = nil )
|
|
|
|
if num
|
|
|
|
res = check_response(critical { get_response('UIDL %d', num) })
|
|
|
|
res.split(/ /)[1]
|
|
|
|
else
|
|
|
|
critical {
|
|
|
|
getok('UIDL')
|
|
|
|
table = {}
|
|
|
|
@socket.each_list_item do |line|
|
|
|
|
num, uid = line.split
|
|
|
|
table[num.to_i] = uid
|
|
|
|
end
|
|
|
|
table
|
|
|
|
}
|
|
|
|
end
|
1999-10-18 05:03:16 -04:00
|
|
|
end
|
|
|
|
|
2000-03-27 10:52:27 -05:00
|
|
|
def quit
|
2003-05-02 10:35:01 -04:00
|
|
|
check_response(critical { get_response('QUIT') })
|
2000-03-27 10:52:27 -05:00
|
|
|
end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2000-03-27 10:52:27 -05:00
|
|
|
private
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def getok( *reqs )
|
|
|
|
@socket.writeline sprintf(*reqs)
|
|
|
|
check_response(recv_response())
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def get_response( *reqs )
|
|
|
|
@socket.writeline sprintf(*reqs)
|
|
|
|
recv_response()
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def recv_response
|
|
|
|
@socket.readline
|
|
|
|
end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def check_response( res )
|
|
|
|
raise POPError, res unless /\A\+OK/i === res
|
|
|
|
res
|
|
|
|
end
|
1999-09-22 03:32:33 -04:00
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def check_response_auth( res )
|
|
|
|
raise POPAuthenticationError, res unless /\A\+OK/i === res
|
|
|
|
res
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
2003-05-02 10:35:01 -04:00
|
|
|
def critical
|
|
|
|
return if @in_critical_block
|
|
|
|
# Do not use ensure-block.
|
|
|
|
@in_critical_block = true
|
|
|
|
result = yield
|
|
|
|
@in_critical_block = false
|
|
|
|
result
|
1999-09-22 03:32:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
aamine
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.26.
* lib/net/protocol.rb, smtp.rb, pop.rb, http.rb:
add module Net::NetPrivate and its inner classes
{Read,Write}Adapter, Command, Socket,
SMTPCommand, POP3Command, APOPCommand, HTTPCommand
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2000-07-12 02:04:40 -04:00
|
|
|
end # module Net
|