module EmailHelper

=begin

get available driver

  result = EmailHelper.available_driver

returns

  {
    inbound: {
      imap: 'IMAP',
      pop3: 'POP3',
    },
    outbound: {
      smtp: 'SMTP - configure your own outgoing SMTP settings',
      sendmail: 'Local MTA (Sendmail/Postfix/Exim/...) - use server setup',
    },
  }

=end

  def self.available_driver
    if Setting.get('system_online_service')
      return {
        inbound: {
          imap: 'IMAP',
          pop3: 'POP3',
        },
        outbound: {
          smtp: 'SMTP - configure your own outgoing SMTP settings',
        },
      }
    end
    {
      inbound: {
        imap: 'IMAP',
        pop3: 'POP3',
      },
      outbound: {
        smtp: 'SMTP - configure your own outgoing SMTP settings',
        sendmail: 'Local MTA (Sendmail/Postfix/Exim/...) - use server setup',
      },
    }
  end

=begin

get mail parts

  user, domain = EmailHelper.parse_email('somebody@example.com')

returns

  [user, domain]

=end

  def self.parse_email(email)
    user   = nil
    domain = nil
    if email =~ /^(.+?)@(.+?)$/
      user   = $1
      domain = $2
    end
    [user, domain]
  end

=begin

get list of providers with inbound and outbound settings

  map = EmailHelper.provider(email, password)

returns

  {
    google: {
      domain: 'gmail.com|googlemail.com|gmail.de',
      inbound: {
        adapter: 'imap',
        options: {
          host: 'imap.gmail.com',
          port: 993,
          ssl: true,
          user: email,
          password: password,
        },
      },
      outbound: {
        adapter: 'smtp',
        options: {
          host: 'smtp.gmail.com',
          port: 25,
          start_tls: true,
          user: email,
          password: password,
        }
      },
    },
    ...
  }

=end

  def self.provider(email, password)
    # check domain based attributes
    provider_map = {
      google_imap: {
        domain: 'gmail|googlemail|google',
        inbound: {
          adapter: 'imap',
          options: {
            host: 'imap.gmail.com',
            port: 993,
            ssl: true,
            user: email,
            password: password,
          },
        },
        outbound: {
          adapter: 'smtp',
          options: {
            host: 'smtp.gmail.com',
            port: 25,
            start_tls: true,
            user: email,
            password: password,
          }
        },
      },
      microsoft: {
        domain: 'outlook.com|hotmail.com',
        inbound: {
          adapter: 'imap',
          options: {
            host: 'imap-mail.outlook.com',
            port: 993,
            ssl: true,
            user: email,
            password: password,
          },
        },
        outbound: {
          adapter: 'smtp',
          options: {
            host: 'smtp-mail.outlook.com',
            port: 25,
            start_tls: true,
            user: email,
            password: password,
          }
        },
      },
      google_pop3: {
        domain: 'gmail|googlemail|google',
        inbound: {
          adapter: 'pop3',
          options: {
            host: 'pop.gmail.com',
            port: 995,
            ssl: true,
            user: email,
            password: password,
          },
        },
        outbound: {
          adapter: 'smtp',
          options: {
            host: 'smtp.gmail.com',
            port: 25,
            start_tls: true,
            user: email,
            password: password,
          }
        },
      },
    }
    provider_map
  end

=begin

get possible inbound settings based on mx

  map = EmailHelper.provider_inbound_mx(user, email, password, mx_domains)

returns

  {
    adapter: 'imap',
    options: {
      host: mx_domains[0],
      port: 993,
      ssl: true,
      user: user,
      password: password,
    },
  },
  {
    adapter: 'imap',
    options: {
      host: mx_domains[0],
      port: 993,
      ssl: true,
      user: email,
      password: password,
    },
  },

=end

  def self.provider_inbound_mx(user, email, password, mx_domains)
    inbounds = []
    mx_domains.each { |domain|
      inbound = [
        {
          adapter: 'imap',
          options: {
            host: domain,
            port: 993,
            ssl: true,
            user: user,
            password: password,
          },
        },
        {
          adapter: 'imap',
          options: {
            host: domain,
            port: 993,
            ssl: true,
            user: email,
            password: password,
          },
        },
      ]
      inbounds = inbounds.concat(inbound)
    }
    inbounds
  end

=begin

get possible inbound settings based on guess

  map = EmailHelper.provider_inbound_guess(user, email, password, domain)

returns

  {
    adapter: 'imap',
    options: {
      host: "mail.#{domain}",
      port: 993,
      ssl: true,
      user: user,
      password: password,
    },
  },
  {
    adapter: 'imap',
    options: {
      host: "mail.#{domain}",
      port: 993,
      ssl: true,
      user: email,
      password: password,
    },
  },
  ...

=end

  def self.provider_inbound_guess(user, email, password, domain)
    inbound = [
      {
        adapter: 'imap',
        options: {
          host: "mail.#{domain}",
          port: 993,
          ssl: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'imap',
        options: {
          host: "mail.#{domain}",
          port: 993,
          ssl: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'imap',
        options: {
          host: "imap.#{domain}",
          port: 993,
          ssl: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'imap',
        options: {
          host: "imap.#{domain}",
          port: 993,
          ssl: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "mail.#{domain}",
          port: 995,
          ssl: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "mail.#{domain}",
          port: 995,
          ssl: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "pop.#{domain}",
          port: 995,
          ssl: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "pop.#{domain}",
          port: 995,
          ssl: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "pop3.#{domain}",
          port: 995,
          ssl: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'pop3',
        options: {
          host: "pop3.#{domain}",
          port: 995,
          ssl: true,
          user: email,
          password: password,
        },
      },
    ]
    inbound
  end

=begin

get possible outbound settings based on mx

  map = EmailHelper.provider_outbound_mx(user, email, password, mx_domains)

returns

  {
    adapter: 'smtp',
    options: {
      host: domain,
      port: 25,
      start_tls: true,
      user: user,
      password: password,
    },
  },
  {
    adapter: 'smtp',
    options: {
      host: domain,
      port: 25,
      start_tls: true,
      user: email,
      password: password,
    },
  },

=end

  def self.provider_outbound_mx(user, email, password, mx_domains)
    outbounds = []
    mx_domains.each { |domain|
      outbound = [
        {
          adapter: 'smtp',
          options: {
            host: domain,
            port: 25,
            start_tls: true,
            user: user,
            password: password,
          },
        },
        {
          adapter: 'smtp',
          options: {
            host: domain,
            port: 25,
            start_tls: true,
            user: email,
            password: password,
          },
        },
        {
          adapter: 'smtp',
          options: {
            host: domain,
            port: 465,
            start_tls: true,
            user: user,
            password: password,
          },
        },
        {
          adapter: 'smtp',
          options: {
            host: domain,
            port: 465,
            start_tls: true,
            user: email,
            password: password,
          },
        },
      ]
      outbounds = outbounds.concat(outbound)
    }
    outbounds
  end

=begin

get possible outbound settings based on guess

  map = EmailHelper.provider_outbound_guess(user, email, password, domain)

returns

  {
    adapter: 'imap',
    options: {
      host: "mail.#{domain}",
      port: 993,
      ssl: true,
      user: user,
      password: password,
    },
  },
  {
    adapter: 'imap',
    options: {
      host: "mail.#{domain}",
      port: 993,
      ssl: true,
      user: email,
      password: password,
    },
  },
  ...

=end

  def self.provider_outbound_guess(user, email, password, domain)
    outbound = [
      {
        adapter: 'smtp',
        options: {
          host: "mail.#{domain}",
          port: 25,
          start_tls: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "mail.#{domain}",
          port: 25,
          start_tls: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "mail.#{domain}",
          port: 465,
          start_tls: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "mail.#{domain}",
          port: 465,
          start_tls: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "smtp.#{domain}",
          port: 25,
          start_tls: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "smtp.#{domain}",
          port: 25,
          start_tls: true,
          user: email,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "smtp.#{domain}",
          port: 465,
          start_tls: true,
          user: user,
          password: password,
        },
      },
      {
        adapter: 'smtp',
        options: {
          host: "smtp.#{domain}",
          port: 465,
          start_tls: true,
          user: email,
          password: password,
        },
      },
    ]
    outbound
  end

=begin

get dns mx records of domain

  mx_records = EmailHelper.mx_records('example.com')

returns

  ['mx1.example.com', 'mx2.example.com']

=end

  def self.mx_records(domain)
    mail_exchangers = mxers(domain)
    if mail_exchangers && mail_exchangers[0]
      Rails.logger.info "MX for #{domain}: #{mail_exchangers} - #{mail_exchangers[0][0]}"
    end
    mx_records = []
    if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
      mx_records.push mail_exchangers[0][0]
    end
    mx_records
  end

  def self.mxers(domain)
    begin
      mxs = Resolv::DNS.open do |dns|
        ress = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
        ress.map { |r|
          [r.exchange.to_s, IPSocket.getaddress(r.exchange.to_s), r.preference]
        }
      end
    rescue => e
      Rails.logger.error e.message
      Rails.logger.error e.backtrace.inspect
    end
    mxs
  end

end