mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
version 1.1.16
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:
parent
ee38413bf0
commit
acbb1c9434
2 changed files with 56 additions and 7 deletions
|
@ -15,7 +15,7 @@ require 'socket'
|
||||||
|
|
||||||
module Net
|
module Net
|
||||||
|
|
||||||
Version = '1.1.15'
|
Version = '1.1.16'
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
|
@ -346,6 +346,7 @@ Object
|
||||||
SyntaxErrorCode = ErrorCode.mkchild( ProtoSyntaxError )
|
SyntaxErrorCode = ErrorCode.mkchild( ProtoSyntaxError )
|
||||||
FatalErrorCode = ErrorCode.mkchild( ProtoFatalError )
|
FatalErrorCode = ErrorCode.mkchild( ProtoFatalError )
|
||||||
ServerErrorCode = ErrorCode.mkchild( ProtoServerError )
|
ServerErrorCode = ErrorCode.mkchild( ProtoServerError )
|
||||||
|
AuthErrorCode = ErrorCode.mkchild( ProtoAuthError )
|
||||||
RetriableCode = ReplyCode.mkchild( ProtoRetriableError )
|
RetriableCode = ReplyCode.mkchild( ProtoRetriableError )
|
||||||
UnknownCode = ReplyCode.mkchild( ProtoUnknownError )
|
UnknownCode = ReplyCode.mkchild( ProtoUnknownError )
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ You can freely distribute/modify this library.
|
||||||
|
|
||||||
|
|
||||||
require 'net/protocol'
|
require 'net/protocol'
|
||||||
|
require 'md5'
|
||||||
|
|
||||||
|
|
||||||
module Net
|
module Net
|
||||||
|
@ -32,10 +33,13 @@ Net::Protocol
|
||||||
|
|
||||||
=== Methods
|
=== 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.
|
This method opens TCP connection and start SMTP.
|
||||||
If protocol had been started, do nothing and return false.
|
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 )
|
: sendmail( mailsrc, from_addr, to_addrs )
|
||||||
This method sends 'mailsrc' as mail. SMTPSession read strings
|
This method sends 'mailsrc' as mail. SMTPSession read strings
|
||||||
from 'mailsrc' by calling 'each' iterator, and convert them
|
from 'mailsrc' by calling 'each' iterator, and convert them
|
||||||
|
@ -102,12 +106,15 @@ Net::Protocol
|
||||||
@command.data
|
@command.data
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_start( helodom = ENV['HOSTNAME'] )
|
def do_start( helodom = nil,
|
||||||
|
user = nil, secret = nil, authtype = nil )
|
||||||
unless helodom then
|
unless helodom then
|
||||||
raise ArgumentError, "cannot get hostname"
|
helodom = ENV['HOSTNAME'] || ENV['HOST']
|
||||||
|
unless helodom then
|
||||||
|
raise ArgumentError, "cannot get hostname"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@esmtp = false
|
|
||||||
begin
|
begin
|
||||||
if @esmtp then
|
if @esmtp then
|
||||||
@command.ehlo helodom
|
@command.ehlo helodom
|
||||||
|
@ -122,6 +129,15 @@ Net::Protocol
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -154,6 +170,35 @@ Net::Protocol
|
||||||
end
|
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 )
|
def mailfrom( fromaddr )
|
||||||
critical {
|
critical {
|
||||||
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
getok sprintf( 'MAIL FROM:<%s>', fromaddr )
|
||||||
|
@ -198,7 +243,6 @@ Net::Protocol
|
||||||
arr = read_reply
|
arr = read_reply
|
||||||
stat = arr[0][0,3]
|
stat = arr[0][0,3]
|
||||||
|
|
||||||
klass = UnknownCode
|
|
||||||
klass = case stat[0]
|
klass = case stat[0]
|
||||||
when ?2 then SuccessCode
|
when ?2 then SuccessCode
|
||||||
when ?3 then ContinueCode
|
when ?3 then ContinueCode
|
||||||
|
@ -206,9 +250,11 @@ Net::Protocol
|
||||||
when ?5 then
|
when ?5 then
|
||||||
case stat[1]
|
case stat[1]
|
||||||
when ?0 then SyntaxErrorCode
|
when ?0 then SyntaxErrorCode
|
||||||
|
when ?3 then AuthErrorCode
|
||||||
when ?5 then FatalErrorCode
|
when ?5 then FatalErrorCode
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
klass ||= UnknownCode
|
||||||
|
|
||||||
Response.new( klass, stat, arr.join('') )
|
Response.new( klass, stat, arr.join('') )
|
||||||
end
|
end
|
||||||
|
@ -217,7 +263,9 @@ Net::Protocol
|
||||||
def read_reply
|
def read_reply
|
||||||
arr = []
|
arr = []
|
||||||
|
|
||||||
while (str = @socket.readline)[3] == ?- do # ex: "210-..."
|
while true do
|
||||||
|
str = @socket.readline
|
||||||
|
break unless str[3] == ?- # ex: "210-..."
|
||||||
arr.push str
|
arr.push str
|
||||||
end
|
end
|
||||||
arr.push str
|
arr.push str
|
||||||
|
|
Loading…
Reference in a new issue