o smtp.rb:  SMTP AUTH (contributed by Kazuhiro Izawa)


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@677 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 2000-04-25 09:23:21 +00:00
Родитель ee38413bf0
Коммит acbb1c9434
2 изменённых файлов: 56 добавлений и 7 удалений

Просмотреть файл

@ -15,7 +15,7 @@ require 'socket'
module Net
Version = '1.1.15'
Version = '1.1.16'
=begin
@ -346,6 +346,7 @@ Object
SyntaxErrorCode = ErrorCode.mkchild( ProtoSyntaxError )
FatalErrorCode = ErrorCode.mkchild( ProtoFatalError )
ServerErrorCode = ErrorCode.mkchild( ProtoServerError )
AuthErrorCode = ErrorCode.mkchild( ProtoAuthError )
RetriableCode = ReplyCode.mkchild( ProtoRetriableError )
UnknownCode = ReplyCode.mkchild( ProtoUnknownError )

Просмотреть файл

@ -11,6 +11,7 @@ You can freely distribute/modify this library.
require 'net/protocol'
require 'md5'
module Net
@ -32,10 +33,13 @@ Net::Protocol
=== Methods
: start( helo_domain = ENV['HOSTNAME'] )
: start( helo_domain = ENV['HOSTNAME'] || ENV['HOST'], account = nil, password = nil, authtype = nil )
This method opens TCP connection and start SMTP.
If protocol had been started, do nothing and return false.
If account and password are given, is trying to get authentication
by using AUTH command. "authtype" is :plain (symbol) or :cram_md5.
: sendmail( mailsrc, from_addr, to_addrs )
This method sends 'mailsrc' as mail. SMTPSession read strings
from 'mailsrc' by calling 'each' iterator, and convert them
@ -102,12 +106,15 @@ Net::Protocol
@command.data
end
def do_start( helodom = ENV['HOSTNAME'] )
def do_start( helodom = nil,
user = nil, secret = nil, authtype = nil )
unless helodom then
raise ArgumentError, "cannot get hostname"
helodom = ENV['HOSTNAME'] || ENV['HOST']
unless helodom then
raise ArgumentError, "cannot get hostname"
end
end
@esmtp = false
begin
if @esmtp then
@command.ehlo helodom
@ -122,6 +129,15 @@ Net::Protocol
raise
end
end
if user and secret then
begin
mid = 'auth_' + (authtype || 'cram_md5').to_s
@command.send mid, user, secret
rescue NameError
raise ArgumentError, "wrong auth type #{authtype.to_s}"
end
end
end
end
@ -154,6 +170,35 @@ Net::Protocol
end
# "PLAIN" authentication [RFC2554]
def auth_plain( user, secret )
critical {
getok sprintf( 'AUTH PLAIN %s',
["\0#{user}\0#{secret}"].pack('m').chomp )
}
end
# "CRAM-MD5" authentication [RFC2195]
def auth_cram_md5( user, secret )
critical {
rep = getok( 'AUTH CRAM-MD5', ContinueCode )
challenge = rep.msg.split(' ')[1].unpack('m')[0]
secret = MD5.new( secret ).digest if secret.size > 64
isecret = secret + "\0" * (64 - secret.size)
osecret = isecret.dup
0.upto( 63 ) do |i|
isecret[i] ^= 0x36
osecret[i] ^= 0x5c
end
tmp = MD5.new( isecret + challenge ).digest
tmp = MD5.new( osecret + tmp ).hexdigest
getok [user + ' ' + tmp].pack('m').chomp
}
end
def mailfrom( fromaddr )
critical {
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
@ -198,7 +243,6 @@ Net::Protocol
arr = read_reply
stat = arr[0][0,3]
klass = UnknownCode
klass = case stat[0]
when ?2 then SuccessCode
when ?3 then ContinueCode
@ -206,9 +250,11 @@ Net::Protocol
when ?5 then
case stat[1]
when ?0 then SyntaxErrorCode
when ?3 then AuthErrorCode
when ?5 then FatalErrorCode
end
end
klass ||= UnknownCode
Response.new( klass, stat, arr.join('') )
end
@ -217,7 +263,9 @@ Net::Protocol
def read_reply
arr = []
while (str = @socket.readline)[3] == ?- do # ex: "210-..."
while true do
str = @socket.readline
break unless str[3] == ?- # ex: "210-..."
arr.push str
end
arr.push str