# frozen_string_literal: true
# Copyright (c) 1999-2007 Yukihiro Matsumoto.
# Copyright (c) 1999-2007 Minero Aoki.
# Written & maintained by Minero Aoki <aamine@loveruby.net>.
# Documented by William Webber and Minero Aoki.
# This program is free software. You can re-distribute and/or
# modify this program under the same terms as Ruby itself,
# Ruby Distribute License.
# NOTE: You can find Japanese version of this document at:
# http://docs.ruby-lang.org/ja/latest/library/net=2fpop.html
# See Net::POP3 for documentation.
# Non-authentication POP3 protocol error
# (reply code "-ERR", except authentication).
class POPError < ProtocolError; end
# POP3 authentication error.
class POPAuthenticationError < ProtoAuthError; end
# Unexpected response from the server.
class POPBadResponse < POPError; end
# == What is This Library?
# This library provides functionality for retrieving
# email via POP3, the Post Office Protocol version 3. For details
# of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt).
# === Retrieving Messages
# This example retrieves messages from the server and deletes them
# Messages are written to files named 'inbox/1', 'inbox/2', ....
# Replace 'pop.example.com' with your POP3 server address, and
# 'YourAccount' and 'YourPassword' with the appropriate account
# pop = Net::POP3.new('pop.example.com')
# pop.start('YourAccount', 'YourPassword') # (1)
# pop.each_mail do |m| # or "pop.mails.each ..." # (2)
# File.open("inbox/#{i}", 'w') do |f|
# puts "#{pop.mails.size} mails popped."
# 1. Call Net::POP3#start and start POP session.
# 2. Access messages by using POP3#each_mail and/or POP3#mails.
# 3. Close POP session by calling POP3#finish or use the block form of #start.
# The example above is very verbose. You can shorten the code by using
# some utility methods. First, the block form of Net::POP3.start can
# be used instead of POP3.new, POP3#start and POP3#finish.
# Net::POP3.start('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |pop|
# pop.each_mail do |m| # or "pop.mails.each ..."
# File.open("inbox/#{i}", 'w') do |f|
# puts "#{pop.mails.size} mails popped."
# POP3#delete_all is an alternative for #each_mail and #delete.
# Net::POP3.start('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |pop|
# File.open("inbox/#{i}", 'w') do |f|
# And here is an even shorter example.
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# File.open("inbox/#{i}", 'w') do |f|
# === Memory Space Issues
# All the examples above get each message as one big string.
# This example avoids this.
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
# File.open("inbox/#{i}", 'w') do |f|
# m.pop do |chunk| # get a message little by little.
# The net/pop library supports APOP authentication.
# To use APOP, use the Net::APOP class instead of the Net::POP3 class.
# You can use the utility method, Net::POP3.APOP(). For example:
# # Use APOP authentication if $isapop == true
# pop = Net::POP3.APOP($isapop).new('apop.example.com', 110)
# pop.start('YourAccount', 'YourPassword') do |pop|
# # Rest of the code is the same.
# === Fetch Only Selected Mail Using 'UIDL' POP Command
# If your POP server provides UIDL functionality,
# you can grab only selected mails from the POP server.
# # determine if we need pop this mail...
# Net::POP3.start('pop.example.com', 110,
# 'Your account', 'Your password') do |pop|
# pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
# The POPMail#unique_id() method returns the unique-id of the message as a
# String. Normally the unique-id is a hash of the message.
# svn revision of this library
Revision = %q$Revision$.split[1]
# returns the port for POP3
# The default port for POP3 connections, port 110
def POP3.default_pop3_port
# The default port for POP3S connections, port 995
def POP3.default_pop3s_port
def POP3.socket_type #:nodoc: obsolete
# Returns the APOP class if +isapop+ is true; otherwise, returns
# the POP class. For example:
# pop = Net::POP3::APOP($is_apop).new(addr, port)
# Net::POP3::APOP($is_apop).start(addr, port) do |pop|
# Starts a POP3 session and iterates over each POPMail object,
# yielding it to the +block+.
# This method is equivalent to:
# Net::POP3.start(address, port, account, password) do |pop|
# This method raises a POPAuthenticationError if authentication fails.
# Net::POP3.foreach('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
def POP3.foreach(address, port = nil,
account = nil, password = nil,
isapop = false, &block) # :yields: message
start(address, port, account, password, isapop) {|pop|
# Starts a POP3 session and deletes all messages on the server.
# If a block is given, each POPMail object is yielded to it before
# This method raises a POPAuthenticationError if authentication fails.
# Net::POP3.delete_all('pop.example.com', 110,
# 'YourAccount', 'YourPassword') do |m|
def POP3.delete_all(address, port = nil,
account = nil, password = nil,
start(address, port, account, password, isapop) {|pop|
# Opens a POP3 session, attempts authentication, and quits.
# This method raises POPAuthenticationError if authentication fails.
# === Example: normal POP3
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword')
# Net::POP3.auth_only('pop.example.com', 110,
# 'YourAccount', 'YourPassword', true)
def POP3.auth_only(address, port = nil,
account = nil, password = nil,
new(address, port, isapop).auth_only account, password
# Starts a pop3 session, attempts authentication, and quits.
# This method must not be called while POP3 session is opened.
# This method raises POPAuthenticationError if authentication fails.
def auth_only(account, password)
raise IOError, 'opening previously opened POP session' if started?
start(account, password) {
# Net::POP.enable_ssl(params = {})
# Enable SSL for all new instances.
# +params+ is passed to OpenSSL::SSLContext#set_params.
def POP3.enable_ssl(*args)
@ssl_params = create_ssl_params(*args)
# Constructs proper parameters from arguments
def POP3.create_ssl_params(verify_or_params = {}, certs = nil)
params = verify_or_params.to_hash
params[:verify_mode] = verify_or_params
elsif File.directory?(certs)
# Disable SSL for all new instances.
# returns the SSL Parameters
# see also POP3.enable_ssl
# returns +true+ if POP3.ssl_params is set
# returns whether verify_mode is enable from POP3.ssl_params
return @ssl_params[:verify_mode]
# returns the :ca_file or :ca_path from POP3.ssl_params
return @ssl_params[:ca_file] || @ssl_params[:ca_path]
# Creates a new POP3 object and open the connection. Equivalent to
# Net::POP3.new(address, port, isapop).start(account, password)
# If +block+ is provided, yields the newly-opened POP3 object to it,
# and automatically closes it at the end of the session.
# Net::POP3.start(addr, port, account, password) do |pop|
def POP3.start(address, port = nil,
account = nil, password = nil,
isapop = false, &block) # :yield: pop
new(address, port, isapop).start(account, password, &block)
# Creates a new POP3 object.
# +address+ is the hostname or ip address of your POP3 server.
# The optional +port+ is the port to connect to.
# The optional +isapop+ specifies whether this connection is going
# to use APOP authentication; it defaults to +false+.
# This method does *not* open the TCP connection.
def initialize(addr, port = nil, isapop = false)
@ssl_params = POP3.ssl_params
# Does this instance use APOP authentication?
# does this instance use SSL?
# Net::POP#enable_ssl(params = {})
# Enables SSL for this instance. Must be called before the connection is
# established to have any effect.
# +params[:port]+ is port to establish the SSL connection on; Defaults to 995.
# +params+ (except :port) is passed to OpenSSL::SSLContext#set_params.
def enable_ssl(verify_or_params = {}, certs = nil, port = nil)
@ssl_params = verify_or_params.to_hash.dup
@port = @ssl_params.delete(:port) || @port
@ssl_params = POP3.create_ssl_params(verify_or_params, certs)
# Disable SSL for all new instances.
# Provide human-readable stringification of class state.
+"#<#{self.class} #{@address}:#{@port} open=#{@started}>"
# *WARNING*: This method causes a serious security hole.
# Use this method only for debugging.
# Set an output stream for debugging.
# pop = Net::POP.new(addr, port)
# pop.set_debug_output $stderr
# pop.start(account, passwd) do |pop|
def set_debug_output(arg)
# The address to connect to.
# The port number to connect to.
return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port)
# Seconds to wait until a connection is opened.
# If the POP3 object cannot open a connection within this time,
# it raises a Net::OpenTimeout exception. The default value is 30 seconds.