* lib/net/smtp.rb: support LOGIN authentication. The patch is contributed by Kazuhiko Izawa. [ruby-talk:78981]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3863 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 2003-05-24 18:24:26 +00:00
parent 0ece2407d2
commit d5d2ca754b
2 changed files with 45 additions and 10 deletions

View File

@ -1,3 +1,8 @@
Sun May 25 03:27:25 2003 Minero Aoki <aamine@loveruby.net>
* lib/net/smtp.rb: support LOGIN authentication, based on
the patch by Kazuhiko Izawa. [ruby-talk:78981]
Sat May 24 18:19:51 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp> Sat May 24 18:19:51 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp>
* wince/Makefile.sub: add eMbedded Visual C++ 4.0 support. * wince/Makefile.sub: add eMbedded Visual C++ 4.0 support.

View File

@ -108,8 +108,24 @@ of SMTP.start/SMTP#start. It is the domain name which you are on
SMTP server will judge if he/she should send or reject SMTP server will judge if he/she should send or reject
the SMTP session by inspecting HELO domain. the SMTP session by inspecting HELO domain.
Net::SMTP.start( 'your.smtp.server', 25, Net::SMTP.start('your.smtp.server', 25,
'mail.from.domain' ) {|smtp| 'mail.from.domain') {|smtp|
=== SMTP Authentication
net/smtp supports three authentication scheme.
PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554])
# PLAIN
Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain',
'Your Account', 'Your Password', :plain)
# LOGIN
Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain',
'Your Account', 'Your Password', :login)
# CRAM MD5
Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain',
'Your Account', 'Your Password', :cram_md5)
== class Net::SMTP == class Net::SMTP
@ -141,8 +157,8 @@ the SMTP session by inspecting HELO domain.
close session after block call finished. close session after block call finished.
If both of account and password are given, is trying to get If both of account and password are given, is trying to get
authentication by using AUTH command. :plain or :cram_md5 is authentication by using AUTH command. AUTHTYPE is an either of
allowed for AUTHTYPE. :login, :plain, and :cram_md5.
: started? : started?
true if SMTP session is started. true if SMTP session is started.
@ -410,15 +426,23 @@ module Net
getok('EHLO %s', domain) getok('EHLO %s', domain)
end end
# "PLAIN" authentication [RFC2554]
def auth_plain( user, secret ) def auth_plain( user, secret )
res = critical { get_response('AUTH PLAIN %s', res = critical { get_response('AUTH PLAIN %s',
["\0#{user}\0#{secret}"].pack('m').chomp) } base64_encode("\0#{user}\0#{secret}")) }
raise SMTPAuthenticationError, res unless /\A2../ === res
end
def auth_login( user, secret )
res = critical {
check_response(get_response('AUTH LOGIN'), true)
check_response(get_response(base64_encode(user)), true)
get_response(base64_encode(secret))
}
raise SMTPAuthenticationError, res unless /\A2../ === res raise SMTPAuthenticationError, res unless /\A2../ === res
end end
# "CRAM-MD5" authentication [RFC2195]
def auth_cram_md5( user, secret ) def auth_cram_md5( user, secret )
# CRAM-MD5: [RFC2195]
res = nil res = nil
critical { critical {
res = check_response(get_response('AUTH CRAM-MD5'), true) res = check_response(get_response('AUTH CRAM-MD5'), true)
@ -434,11 +458,17 @@ module Net
tmp = Digest::MD5.digest(isecret + challenge) tmp = Digest::MD5.digest(isecret + challenge)
tmp = Digest::MD5.hexdigest(osecret + tmp) tmp = Digest::MD5.hexdigest(osecret + tmp)
res = get_response([user + ' ' + tmp].pack('m').gsub(/\s+/, '')) res = get_response(base64_encode(user + ' ' + tmp))
} }
raise SMTPAuthenticationError, res unless /\A2../ === res raise SMTPAuthenticationError, res unless /\A2../ === res
end end
def base64_encode( str )
# expects "str" may not become too long
[str].pack('m').gsub(/\s+/, '')
end
private :base64_encode
def mailfrom( fromaddr ) def mailfrom( fromaddr )
getok('MAIL FROM:<%s>', fromaddr) getok('MAIL FROM:<%s>', fromaddr)
end end
@ -493,10 +523,10 @@ module Net
res res
end end
def check_response( res, cont = false ) def check_response( res, allow_continue = false )
etype = case res[0] etype = case res[0]
when ?2 then nil when ?2 then nil
when ?3 then cont ? nil : ProtoUnknownError when ?3 then allow_continue ? nil : ProtoUnknownError
when ?4 then ProtoServerError when ?4 then ProtoServerError
when ?5 then when ?5 then
case res[1] case res[1]