summaryrefslogtreecommitdiff
path: root/lib/custodian/protocoltest/smtprelay.rb
blob: 45abf16a729b183e363a06032c8430380f1ad7bc (plain)
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
require 'net/smtp'



#
#  The open SMTP-relay test.
#
#  This object is instantiated if the parser sees a line such as:
#
###
### mail.bytemark.co.uk must not run smtprelay otherwise 'smtp fail'.
###
#
#  The specification of the port is optional and defaults to 25
#

module Custodian

  module ProtocolTest

    class SMTPRelayTest < TestFactory


      #
      # Save away state from the configuration line.
      #
      def initialize( line )
        @line = line
        @host = line.split( /\s+/)[0]

        #
        # Save the port
        #
        if ( line =~ /on\s+([0-9]+)/ )
          @port = $1.dup
        else
          @port = 25
        end

        #
        # Is this test inverted?
        #
        if ( line =~ /must\s+not\s+run\s+/ )
          @inverted = true
        else
          @inverted = false
        end
      end



      #
      # Allow this test to be serialized.
      #
      def to_s
          @line
      end


      #
      # Read the hostname for usage in the SMTP-transaction.
      #
      def get_hostname
        hostname = "localhost.localdomain"

        if ( File.exist?( "/etc/hostname" ) )
          File.readlines("/etc/hostname" ).each do |line|
            hostname = line if ( !line.nil? )
            hostname.chomp!
          end
        end

        hostname
      end



      #
      # run the test for open relays of SMTP protocol - return true on success.
      # false on fail.
      #
      def run_test
        # for if we've run the test before
        @error  = nil
        message = "Subject: SMTP Relay check\nThis is a test for OPEN SMTP relays."

        begin

          Net::SMTP.start(@host,@port, get_hostname ) do |smtp|
            sent    = smtp.send_message message, "noreply@bytemark.co.uk", "noreply@bytemark.co.uk"
            @status = sent.status.to_s

            if @status === "250"
              @error = "NOT OK: message sent on #{@host} with status #{@status}"
            else
              @error = "OK: message not sent on #{@host} with status #{@status}"
            end

            #
            # give the parser an appropriate response depending on the smtp code
            # and whether or not we're inverting the test. (eg, 'must not')
            #

            return @inverted  if @status == "250" and @inverted
            return !@inverted if @status == "250" and !@inverted
            return @inverted  if @status != "250" and !@inverted
            return !@inverted if @status != "250" and @inverted

          end # Net SMTP

        rescue StandardError => ex
          #
          # for if we fail to send a message; this is a good thing
          #
          @error = "OK: Timed out or connection refused on #{@host} with status #{@status}"
          return !@inverted if @inverted
          return @inverted if !@inverted
        end

      end


      #
      # If the test failed here we will return a suitable error message.
      #
      def error
        @error
      end

      # register ourselves with the class-factory
      register_test_type "smtprelay"
    end
  end
end