File: mail.rb

package info (click to toggle)
zonecheck 3.0.2-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 1,312 kB
  • ctags: 836
  • sloc: ruby: 6,664; xml: 693; sh: 518; python: 301; makefile: 75
file content (222 lines) | stat: -rw-r--r-- 6,513 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# $Id: mail.rb,v 1.29 2010/06/07 08:51:25 chabannf Exp $

# 
# CONTACT     : zonecheck@nic.fr
# AUTHOR      : Stephane D'Alu <sdalu@nic.fr>
#
# CREATED     : 2002/09/25 08:58:17
# REVISION    : $Revision: 1.29 $ 
# DATE        : $Date: 2010/06/07 08:51:25 $
#
# CONTRIBUTORS: (see also CREDITS file)
#
#
# LICENSE     : GPL v3
# COPYRIGHT   : AFNIC (c) 2003
#
# This file is part of ZoneCheck.
#
# ZoneCheck is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# 
# ZoneCheck is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ZoneCheck; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
module ZoneCheck
require 'socket'
require 'timeout'


##
##
##
class  Mail
    ##
    ##
    ##
    class  MailError < StandardError
    end

    def initialize(mhost, mip, dbgio=nil)
	@myhostname = Socket::gethostname
	@mhost      = mhost
	@mip        = mip
	@mrelay     = nil
	@dbgio      = dbgio
    end

    def open(tout=nil)
	Timeout::timeout(tout) {
	    @mrelay = TCPSocket::new(@mip, 25)
	}
    end

    def fake_info(user, mdest, mfrom)
	@user	= user
	@mdest	= mdest
	@mfrom	= mfrom

	@openrelay_testlist = [ 
	    [ "Test 0",
		"spamtest@#{@mhost}",	"\"nobody@#{@mdest}\""		],
	    [ "Test 1",
		"spamtest@#{@mdest}",	"nobody@#{@mdest}"		],
	    [ "Test 2",
		"spamtest@#{@mfrom}",	"nobody@#{@mdest}"		],
	    [ "Test 3",
		"spamtest@localhost",	"nobody@#{@mdest}"		],
	    [ "Test 4",
		"spamtest",		"nobody@#{@mdest}"		],
	    [ "Test 5",
		"",			"nobody@#{@mdest}"		],
	    [ "Test 6",
		"spamtest@#{@mhost}",	"nobody@#{@mdest}"		],
	    [ "Test 7",
		"spamtest@[#{@mip}]",	"nobody@#{@mdest}"		],
	    [ "Test 8",
		"spamtest@#{@mhost}",	"nobody%#{@mdest}@#{@mhost}"	],
	    [ "Test 9",
		"spamtest@#{@mhost}",	"nobody%#{@mdest}@[#{@mip}]"	],
	    [ "Test 10",
		"spamtest@#{@mhost}",	"\"nobody@#{@mdest}\""		],
	    [ "Test 11",
		"spamtest@#{@mhost}",	"\"nobody%#{@mdest}\""		],
	    [ "Test 12",
		"spamtest@[#{@mip}]",	"\"nobody@#{@mdest}@#{@mhost}\""],
	    [ "Test 13",
		"spamtest@#{@mhost}",	"\"nobody@#{@mdest}\"@[#{@mip}]"],
	    [ "Test 14",
		"spamtest@#{@mhost}",	"nobody@#{@mdest}@[#{@mip}]"	],
	    [ "Test 15",
		"spamtest@[#{@mip}]",	"@#{@mhost}:nobody@#{@mdest}"	],
	    [ "Test 16",
		"spamtest@#{@mhost}",	"@[#{@mip}]:nobody@#{@mdest}"	],
	    [ "Test 17",
		"spamtest@[#{@mip}]",	"#{@mdest}!nobody"		],
	    [ "Test 18",
		"spamtest@#{@mhost}",	"#{@mdest}!nobody@[#{@mip}]"	],
	    [ "test 19",
		"postmaster@#{@mhost}",	"nobody@#{@mdest}"		] ]
    end

    def close
	@mrelay.close
    end

    def cmd(str)
	if str
	    @dbgio << ">> #{str}\n" if @dbgio
	    @mrelay.write("#{str}\r\n") ; @mrelay.flush
	end

	begin
	    desc = ""	
	    while true
		# Bug Fix by Romuald 
    # Timeout added to SMTP requests if server is not responding
    line = nil 
    Timeout.timeout(10, Timeout::Error) { 
    line = @mrelay.readline 
    }
		
		@dbgio << "<< #{line}" if @dbgio
		case line
		when NilClass         then raise  ZoneCheck::Mail::MailError, "parsing error"
		when /^(\d{3}) (.*)$/ then return [ $1.to_i, desc << $2 ]
		when /^(\d{3})-(.*)$/ then desc << $2
		else raise  ZoneCheck::Mail::MailError, "parsing error"
		end
	    end
	rescue EOFError
	    raise  ZoneCheck::Mail::MailError, "Unexpected closing of connection"
  rescue Timeout::Error 
      raise  ZoneCheck::Mail::MailError, "Timeout from SMTP server"
	end
	# NOT REACHED
    end

    def banner          ; cmd(nil)					; end
    def helo(host)      ; cmd("HELO #{host.gsub(/\.$/, "")}")		; end
    def vrfy(user)	; cmd("VRFY #{user.gsub(/\.$/, "")}")		; end
    def mail_from(from) ; cmd("MAIL FROM:<#{from.gsub(/\.$/, "")}>")	; end
    def rcpt_to(to)     ; cmd("RCPT TO:<#{to.gsub(/\.$/, "")}>")	; end
    def rset            ; cmd("RSET")					; end
    def quit            ; cmd("QUIT")					; end


    def test_userexists(user, use_vrfy=false)
	if use_vrfy
	    case vrfy(user)[0]
	    when 250, 251, 252 then rset ; return true
	    end
	end
	mail_from("#{@user}@#{@mdest}")
	res = rcpt_to(user)[0] == 250
	rset
	res
    end


    def test_openrelay(count=1)
	tests = [ @openrelay_testlist[1] ]

	tests.each { |name, from, to|
	    if (r = mail_from(from)[0]) == 250
		case rcpt_to(to)[0]
		when 250..259 then return true
		end
	    else
		raise  ZoneCheck::Mail::MailError, "Unexpected return code #{r}"
	    end
	    rset
	}
	false
    end
end



#         500 Syntax error, command unrecognized
#            [This may include errors such as command line too long]
#         501 Syntax error in parameters or arguments
#         502 Command not implemented
#         503 Bad sequence of commands
#         504 Command parameter not implemented
#          
#         211 System status, or system help reply
#         214 Help message
#            [Information on how to use the receiver or the meaning of a
#            particular non-standard command; this reply is useful only
#            to the human user]
#          
#         220 <domain> Service ready
#         221 <domain> Service closing transmission channel
#         421 <domain> Service not available,
#             closing transmission channel
#            [This may be a reply to any command if the service knows it
#            must shut down]
#          
#         250 Requested mail action okay, completed
#         251 User not local; will forward to <forward-path>
#         450 Requested mail action not taken: mailbox unavailable
#            [E.g., mailbox busy]
#         550 Requested action not taken: mailbox unavailable
#            [E.g., mailbox not found, no access]
#         451 Requested action aborted: error in processing
#         551 User not local; please try <forward-path>
#         452 Requested action not taken: insufficient system storage
#         552 Requested mail action aborted: exceeded storage allocation
#         553 Requested action not taken: mailbox name not allowed
#            [E.g., mailbox syntax incorrect]
#         354 Start mail input; end with <CRLF>.<CRLF>
#         554 Transaction failed
 
end