# class GxG::Networking::SmtpClient

SMTP Classes:

### Public Class Methods

new(host=nil,port=nil,options={}) click to toggle source

    # File lib/gxg/net_clients.rb, line 1375
    def initialize(host=nil,port=nil,options={})
      if port.is_a?(::Hash)
        options = port
        port = nil
      end
      @user = nil
      @password = nil
      @client = nil
      @host = host
      unless @host
        raise ArgumentError, "You MUST provide a HOST, like this: <host>,(<port>),(<options>)"
      end
      if options[:use_ssl] == true
        @port = (port || 465)
        if options[:ssl_method]
          # Valid: [:TLSv1, :TLSv1_server, :TLSv1_client, :TLSv1_1, :TLSv1_1_server, :TLSv1_1_client, :TLSv1_2, :TLSv1_2_server, :TLSv1_2_client, :SSLv23, :SSLv23_server, :SSLv23_client]
          unless OpenSSL::SSL::SSLContext::METHODS.include?(options[:ssl_method])
            raise ArgumentError, "Encryption method #{options[:ssl_method].inspect} is not valid. Choose one of these: #{OpenSSL::SSL::SSLContext::METHODS.inspect}"
          end
          openssl_context = OpenSSL::SSL::SSLContext.new(options[:ssl_method])
        else
          openssl_context = ::Net::SMTP.default_ssl_context
        end
        if options[:ignore_ssl_errors] == true
          openssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
        else
          openssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
        end
      else
        @port = (port || 25)
        openssl_context = nil
      end
      @client = ::Net::SMTP.new(@host, @port)
      if openssl_context
        @client.enable_ssl(openssl_context)
      end
      #
      self
    end

### Public Instance Methods

attachment_template(the_path="", content_parameters={"name" => ""}) click to toggle source

    # File lib/gxg/net_clients.rb, line 1472
    def attachment_template(the_path="", content_parameters={"name" => ""})
      result = nil
      begin
        unless the_path.to_s.valid_path?
          raise ArgumentError, "You MUST provide a valid file system path to the file."
        end
        unless content_parameters.is_a?(::Hash)
          raise ArgumentError, "You MUST provide content_parameters as a Hash."
        end
        unless content_parameters["name"].to_s.size > 0
          content_parameters["name"] = ::File.basename(the_path)
        end
        discovered_mime = ::MimeMagic.by_magic(::File.open(the_path,"rb"))
        if discovered_mime
          discovered_mime = discovered_mime.type
        else
          discovered_mime = "application/octet-stream"
        end
        result = {:content_type => {:type => discovered_mime, :parameters => content_parameters}, :filename => (::File.basename(the_path)), :path => the_path, :content => ::GxG::ByteArray.new}
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:path => the_path, :content_parameters => content_parameters}})
      end
      result
    end

host() click to toggle source

    # File lib/gxg/net_clients.rb, line 1415
    def host()
      @host.clone
    end

login(user_id=nil,password=nil,authentication_method=:plain) click to toggle source

    # File lib/gxg/net_clients.rb, line 1423
    def login(user_id=nil,password=nil,authentication_method=:plain)
      result = false
      if @client
        begin
          @user = user_id
          unless @user
            raise ArgumentError, "You MUST provide a USER id, like this: <user_id>,<password/oauth-token>,(<options>)"
          end
          @password = password
          unless @password
            raise ArgumentError, "You MUST provide a PASSWORD/OAUTH-TOKEN, like this: <user_id>,<password/oauth-token>,(<options>)"
          end
          unless @client.started?
            unless [:plain, :login, :cram_md5, :oauth2].include?(authentication_method.to_s.to_sym)
              raise ArgumentError, "Authentication method #{authentication_method.inspect} is invalid. Choose one of these: [:plain, :login, :cram_md5, :oauth2]"
            end
            # Internal cosmetics for interface consistency.
            if authentication_method == :oauth2
              authentication_method = :xoauth2
            end
            @client.start(@host, @user, @password, authentication_method)
          end
          result = true
        rescue Exception => the_error
          # Internal cosmetics for interface consistency.
          if authentication_method == :xoauth2
            authentication_method = :oauth2
          end
          log_error({:error => the_error, :parameters => {:user => user_id, :authentication => authentication_method}})
        end
      end
      result
    end

logout() click to toggle source

    # File lib/gxg/net_clients.rb, line 1457
    def logout()
      if @client
        begin
          @client.finish
          @client = nil
          true
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {}})
          false
        end
      else
        false
      end
    end

message_template(mime_type="text/plain", content_parameters={"charset"=>"UTF-8"}) click to toggle source

    # File lib/gxg/net_clients.rb, line 1497
    def message_template(mime_type="text/plain", content_parameters={"charset"=>"UTF-8"})
      result = nil
      begin
        unless ['text/plain', 'text/html', 'text/xhtml', 'text/xml'].include?(mime_type.to_s)
          raise ArgumentError, "Content Type specified was invalid. Choose one of these: ['text/plain', 'text/html', 'text/xhtml', 'text/xml']"
        end
        unless content_parameters.is_a?(::Hash)
          raise ArgumentError, "You MUST provide content_parameters as a Hash."
        end
        gxg_message = new_message
        gxg_message[:sender] = ""
        gxg_message[:id] = "<#{gxg_message[:id].to_s}@#{::Socket.gethostname}.mail>"
        gxg_message[:to] = ""
        gxg_message[:cc] = nil
        gxg_message[:bcc] = nil
        gxg_message[:subject] = ""
        gxg_message[:date] = ::DateTime.now
        gxg_message[:header] = {}
        gxg_message[:body] = [{:prologue => ""},{:content_type => {:type => mime_type.to_s, :parameters => content_parameters}, :content => ""},{:epilogue => ""}]
        gxg_message[:attachments] = []
        result = gxg_message
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:content_type => mime_type, :content_parameters => content_parameters}})
      end
      result
    end

port() click to toggle source

    # File lib/gxg/net_clients.rb, line 1419
    def port()
      @port.clone
    end

send_message(gxg_message=nil) click to toggle source

    # File lib/gxg/net_clients.rb, line 1524
    def send_message(gxg_message=nil)
      result = false
      if @client
        begin
          unless @client.started?
            raise Exception, "SMTP session not started yet."
          end
          unless gxg_message.is_a?(::GxG::Events::Message)
            raise ArgumentError, "You MUST provide a valid message object of class ::GxG::Events::Message. Suggested: <SmtpClient>.message_template(<Mime-Type-String>)"
          end
          # Build suitable mail message
          message = Mail.new
          the_fields = []
          gxg_message[:header].each_pair do |the_key, the_value|
            if the_value.is_a?(::Array)
              the_value.each do |the_field_value|
                the_fields << "#{the_key.to_s}: #{the_field_value.to_s}"
              end
            else
              the_fields << "#{the_key.to_s}: #{the_value.to_s}"
            end
          end
          message.header = the_fields.join("\r\n")
          message.from = gxg_message[:sender]
          message.reply_to = gxg_message[:sender]
          if gxg_message[:id].to_s.include?("@")
            message.message_id = gxg_message[:id].to_s
          else
            message.message_id = "<#{gxg_message[:id].to_s}@#{::Socket.gethostname}.mail>"
          end
          message.to = gxg_message[:to]
          if gxg_message[:cc]
            message.cc = gxg_message[:cc]
          end
          if gxg_message[:bcc]
            message.bcc = gxg_message[:bcc]
          end
          message.subject = gxg_message[:subject]
          message.date = (gxg_message[:date].to_s || ::DateTime.now.to_s)
          if gxg_message[:attachments].size > 0
            multipart = true
          else
            part_count = 0
            gxg_message[:body].each do |part|
              unless part[:prologue] || part[:epilogue]
                part_count += 1
              end
            end
            if part_count > 1
              multipart = true
            else
              multipart = false
            end
          end
          if multipart
            gxg_message[:body].each do |part|
              unless part[:prologue] || part[:epilogue]
                type_info = "Content-Type: #{part[:content_type][:type]}"
                if part[:content_type][:parameters].keys.size > 0
                  part[:content_type][:parameters].each_pair do |the_key, the_value|
                    type_info << "; '#{the_key.to_s}': '#{the_value.to_s}'"
                  end
                end
                new_part = Mail::Part.new(type_info)
                new_part.body = part[:content]
                message.add_part(new_part)
              end
            end
            # Add file attachments:
            gxg_message[:attachments].each do |attachment|
              if attachment[:content].size == 0
                file_size = ::File.size(attachment[:path])
                file_handle = ::File.open(attachment[:path],"rb")
                ::GxG::apportioned_ranges(file_size,65536).each do |the_range|
                  file_handle.seek(the_range.first)
                  attachment[:content] << file_handle.read(the_range.size)
                end
                file_handle.close
              end
              message.add_file({:filename => attachment[:filename], :content => attachment[:content].to_s})
            end
          else
            gxg_message[:body].each do |part|
              unless part[:prologue] || part[:epilogue]
                message.body = part[:content]
                break
              end
            end
          end
          # Send it
          @client.send_message(message.to_s, gxg_message[:sender], message.destinations)
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:message => gxg_message}})
        end
      end
      result
    end