123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874 |
- # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
- require 'resolv'
- class GettingStartedController < ApplicationController
- =begin
- Resource:
- GET /api/v1/getting_started
- Response:
- {
- "master_user": 1,
- "groups": [
- {
- "name": "group1",
- "active":true
- },
- {
- "name": "group2",
- "active":true
- }
- ]
- }
- Test:
- curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
- =end
- def index
- # check if first user already exists
- return if setup_done_response
- # if master user already exists, we need to be authenticated
- if setup_done
- return if !authentication_check
- end
- # get all groups
- groups = Group.where( :active => true )
- # return result
- render :json => {
- :setup_done => setup_done,
- :import_mode => Setting.get('import_mode'),
- :import_backend => Setting.get('import_backend'),
- :groups => groups,
- }
- end
- def base
- # check admin permissions
- return if deny_if_not_role('Admin')
- # validate url
- messages = {}
- if !params[:url] ||params[:url] !~ /^(http|https):\/\/.+?$/
- messages[:url] = 'A URL looks like http://zammad.example.com'
- end
- # validate organization
- if !params[:organization] || params[:organization].empty?
- messages[:organization] = 'Invalid!'
- end
- # validate image
- if params[:logo] && params[:logo] =~ /^data:image/i
- file = StaticAssets.data_url_attributes( params[:logo] )
- if !file[:content] || !file[:content_type]
- messages[:logo] = 'Unable to process image upload.'
- end
- end
- if !messages.empty?
- render :json => {
- :result => 'invalid',
- :messages => messages,
- }
- return
- end
- # split url in http_type and fqdn
- settings = {}
- if params[:url] =~ /^(http|https):\/\/(.+?)$/
- Setting.set('http_type', $1)
- settings[:http_type] = $1
- Setting.set('fqdn', $2)
- settings[:fqdn] = $2
- end
- # save organization
- Setting.set('organization', params[:organization])
- settings[:organization] = params[:organization]
- # save image
- if params[:logo] && params[:logo] =~ /^data:image/i
- # data:image/png;base64
- file = StaticAssets.data_url_attributes( params[:logo] )
- # store image 1:1
- StaticAssets.store_raw( file[:content], file[:content_type] )
- end
- if params[:logo_resize] && params[:logo_resize] =~ /^data:image/i
- # data:image/png;base64
- file = StaticAssets.data_url_attributes( params[:logo_resize] )
- # store image 1:1
- settings[:product_logo] = StaticAssets.store( file[:content], file[:content_type] )
- end
- # set changed settings
- settings.each {|key, value|
- Setting.set(key, value)
- }
- render :json => {
- :result => 'ok',
- :settings => settings,
- }
- end
- def email_probe
- # check admin permissions
- return if deny_if_not_role('Admin')
- # validation
- user = nil
- domain = nil
- if params[:email] =~ /^(.+?)@(.+?)$/
- user = $1
- domain = $2
- end
- if !user || !domain
- render :json => {
- :result => 'invalid',
- :messages => {
- :email => 'Invalid email.'
- },
- }
- return
- end
- # check domain based attributes
- providerMap = {
- :google => {
- :domain => 'gmail.com|googlemail.com|gmail.de',
- :inbound => {
- :adapter => 'imap',
- :options => {
- :host => 'imap.gmail.com',
- :port => '993',
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- :outbound => {
- :adapter => 'smtp',
- :options => {
- :host => 'smtp.gmail.com',
- :port => '25',
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- }
- },
- },
- }
- # probe based on email domain and mx
- domains = [domain]
- mail_exchangers = mxers(domain)
- if mail_exchangers && mail_exchangers[0]
- logger.info "MX for #{domain}: #{mail_exchangers} - #{mail_exchangers[0][0]}"
- end
- if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
- domains.push mail_exchangers[0][0]
- end
- providerMap.each {|provider, settings|
- domains.each {|domain_to_check|
- if domain_to_check =~ /#{settings[:domain]}/i
- # probe inbound
- result = email_probe_inbound( settings[:inbound] )
- if result[:result] != 'ok'
- render :json => result
- return
- end
- # probe outbound
- result = email_probe_outbound( settings[:outbound], params[:email] )
- if result[:result] != 'ok'
- render :json => result
- return
- end
- render :json => {
- :result => 'ok',
- :setting => settings,
- }
- return
- end
- }
- }
- # probe inbound
- inboundMap = []
- if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
- inboundMx = [
- {
- :adapter => 'imap',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 993,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'imap',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 993,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- ]
- inboundMap = inboundMap + inboundMx
- end
- inboundAuto = [
- {
- :adapter => 'imap',
- :options => {
- :host => "mail.#{domain}",
- :port => 993,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'imap',
- :options => {
- :host => "mail.#{domain}",
- :port => 993,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'imap',
- :options => {
- :host => "imap.#{domain}",
- :port => 993,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'imap',
- :options => {
- :host => "imap.#{domain}",
- :port => 993,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "mail.#{domain}",
- :port => 995,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "mail.#{domain}",
- :port => 995,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "pop.#{domain}",
- :port => 995,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "pop.#{domain}",
- :port => 995,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "pop3.#{domain}",
- :port => 995,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'pop3',
- :options => {
- :host => "pop3.#{domain}",
- :port => 995,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- ]
- inboundMap = inboundMap + inboundAuto
- settings = {}
- success = false
- inboundMap.each {|config|
- logger.info "INBOUND PROBE: #{config.inspect}"
- result = email_probe_inbound( config )
- logger.info "INBOUND RESULT: #{result.inspect}"
- if result[:result] == 'ok'
- success = true
- settings[:inbound] = config
- break
- end
- }
- if !success
- render :json => {
- :result => 'failed',
- }
- return
- end
- # probe outbound
- outboundMap = []
- if mail_exchangers && mail_exchangers[0] && mail_exchangers[0][0]
- outboundMx = [
- {
- :adapter => 'smtp',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 25,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 25,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 465,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => mail_exchangers[0][0],
- :port => 465,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- ]
- outboundMap = outboundMap + outboundMx
- end
- outboundAuto = [
- {
- :adapter => 'smtp',
- :options => {
- :host => "mail.#{domain}",
- :port => 25,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "mail.#{domain}",
- :port => 25,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "mail.#{domain}",
- :port => 465,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "mail.#{domain}",
- :port => 465,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "smtp.#{domain}",
- :port => 25,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "smtp.#{domain}",
- :port => 25,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "smtp.#{domain}",
- :port => 465,
- :ssl => true,
- :user => user,
- :password => params[:password],
- },
- },
- {
- :adapter => 'smtp',
- :options => {
- :host => "smtp.#{domain}",
- :port => 465,
- :ssl => true,
- :user => params[:email],
- :password => params[:password],
- },
- },
- ]
- success = false
- outboundMap.each {|config|
- logger.info "OUTBOUND PROBE: #{config.inspect}"
- result = email_probe_outbound( config, params[:email] )
- logger.info "OUTBOUND RESULT: #{result.inspect}"
- if result[:result] == 'ok'
- success = true
- settings[:outbound] = config
- break
- end
- }
- if !success
- render :json => {
- :result => 'failed',
- }
- return
- end
- render :json => {
- :result => 'ok',
- :setting => settings,
- }
- end
- def email_outbound
- # check admin permissions
- return if deny_if_not_role('Admin')
- # validate params
- if !params[:adapter]
- render :json => {
- :result => 'invalid',
- }
- return
- end
- # connection test
- result = email_probe_outbound( params, params[:email] )
- render :json => result
- end
- def email_inbound
- # check admin permissions
- return if deny_if_not_role('Admin')
- # validate params
- if !params[:adapter]
- render :json => {
- :result => 'invalid',
- }
- return
- end
- # connection test
- result = email_probe_inbound( params )
- render :json => result
- return
- end
- def email_verify
- # check admin permissions
- return if deny_if_not_role('Admin')
- # send verify email to inbox
- if !params[:subject]
- subject = '#' + rand(99999999999).to_s
- else
- subject = params[:subject]
- end
- result = email_probe_outbound( params[:outbound], params[:meta][:email], subject )
- (1..5).each {|loop|
- sleep 10
- # fetch mailbox
- found = nil
- begin
- if params[:inbound][:adapter] =~ /^imap$/i
- found = Channel::IMAP.new.fetch( { :options => params[:inbound][:options] }, 'verify', subject )
- else
- found = Channel::POP3.new.fetch( { :options => params[:inbound][:options] }, 'verify', subject )
- end
- rescue Exception => e
- render :json => {
- :result => 'invalid',
- :message => e.to_s,
- :subject => subject,
- }
- return
- end
- if found && found == 'verify ok'
- # remember address
- address = EmailAddress.all.first
- if address
- address.update_attributes(
- :realname => params[:meta][:realname],
- :email => params[:meta][:email],
- :active => 1,
- :updated_by_id => 1,
- :created_by_id => 1,
- )
- else
- EmailAddress.create(
- :realname => params[:meta][:realname],
- :email => params[:meta][:email],
- :active => 1,
- :updated_by_id => 1,
- :created_by_id => 1,
- )
- end
- # store mailbox
- Channel.create(
- :area => 'Email::Inbound',
- :adapter => params[:inbound][:adapter],
- :options => params[:inbound][:options],
- :group_id => 1,
- :active => 1,
- :updated_by_id => 1,
- :created_by_id => 1,
- )
- # save settings
- if params[:outbound][:adapter] =~ /^smtp$/i
- smtp = Channel.where( :adapter => 'SMTP', :area => 'Email::Outbound' ).first
- smtp.options = params[:outbound][:options]
- smtp.active = true
- smtp.save!
- sendmail = Channel.where( :adapter => 'Sendmail' ).first
- sendmail.active = false
- sendmail.save!
- else
- sendmail = Channel.where( :adapter => 'Sendmail', :area => 'Email::Outbound' ).first
- sendmail.options = {}
- sendmail.active = true
- sendmail.save!
- smtp = Channel.where( :adapter => 'SMTP' ).first
- smtp.active = false
- smtp.save
- end
- render :json => {
- :result => 'ok',
- }
- return
- end
- }
- # check delivery for 30 sek.
- render :json => {
- :result => 'invalid',
- :message => 'Verification Email not found in mailbox.',
- :subject => subject,
- }
- end
- private
- def email_probe_outbound(params, email, subject = nil)
- # validate params
- if !params[:adapter]
- result = {
- :result => 'invalid',
- :message => 'Invalid, need adapter!',
- }
- return result
- end
- if subject
- mail = {
- :from => email,
- :to => email,
- :subject => "Zammad Getting started Test Email #{subject}",
- :body => '.',
- 'x-zammad-ignore' => 'true',
- }
- else
- mail = {
- :from => email,
- :to => 'emailtrytest@znuny.com',
- :subject => 'test',
- :body => 'test',
- }
- end
- # test connection
- translationMap = {
- 'authentication failed' => 'Authentication failed!',
- 'Incorrect username' => 'Authentication failed!',
- 'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
- 'No route to host' => 'No route to host!',
- 'Connection refused' => 'Connection refused!',
- }
- if params[:adapter] =~ /^smtp$/i
- # in case, fill missing params
- if !params[:options].has_key?(:port)
- params[:options][:port] = 25
- end
- if !params[:options].has_key?(:ssl)
- params[:options][:ssl] = true
- end
- begin
- Channel::SMTP.new.send(
- mail,
- {
- :options => params[:options]
- }
- )
- rescue Exception => e
- # check if sending email was ok, but mailserver rejected
- if !subject
- whiteMap = {
- 'Recipient address rejected' => true,
- }
- whiteMap.each {|key, message|
- if e.message =~ /#{Regexp.escape(key)}/i
- result = {
- :result => 'ok',
- :settings => params,
- :notice => e.message,
- }
- return result
- end
- }
- end
- message_human = ''
- translationMap.each {|key, message|
- if e.message =~ /#{Regexp.escape(key)}/i
- message_human = message
- end
- }
- result = {
- :result => 'invalid',
- :settings => params,
- :message => e.message,
- :message_human => message_human,
- }
- return result
- end
- result = {
- :result => 'ok',
- }
- return result
- end
- begin
- Channel::Sendmail.new.send(
- mail,
- nil
- )
- rescue Exception => e
- message_human = ''
- translationMap.each {|key, message|
- if e.message =~ /#{Regexp.escape(key)}/i
- message_human = message
- end
- }
- result = {
- :result => 'invalid',
- :settings => params,
- :message => e.message,
- :message_human => message_human,
- }
- return result
- end
- result = {
- :result => 'ok',
- }
- return result
- end
- def email_probe_inbound(params)
- # validate params
- if !params[:adapter]
- raise 'need :adapter param'
- end
- # connection test
- translationMap = {
- 'authentication failed' => 'Authentication failed!',
- 'Incorrect username' => 'Authentication failed!',
- 'getaddrinfo: nodename nor servname provided, or not known' => 'Hostname not found!',
- 'No route to host' => 'No route to host!',
- 'Connection refused' => 'Connection refused!',
- }
- if params[:adapter] =~ /^imap$/i
- begin
- Channel::IMAP.new.fetch( { :options => params[:options] }, 'check' )
- rescue Exception => e
- message_human = ''
- translationMap.each {|key, message|
- if e.message =~ /#{Regexp.escape(key)}/i
- message_human = message
- end
- }
- result = {
- :result => 'invalid',
- :settings => params,
- :message => e.message,
- :message_human => message_human,
- }
- return result
- end
- result = {
- :result => 'ok',
- }
- return result
- end
- begin
- Channel::POP3.new.fetch( { :options => params[:options] }, 'check' )
- rescue Exception => e
- message_human = ''
- translationMap.each {|key, message|
- if e.message =~ /#{Regexp.escape(key)}/i
- message_human = message
- end
- }
- result = {
- :result => 'invalid',
- :settings => params,
- :message => e.message,
- :message_human => message_human,
- }
- return result
- end
- result = {
- :result => 'ok',
- }
- return result
- end
- def mxers(domain)
- 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
- mxs
- end
- def setup_done
- #return false
- count = User.all.count()
- done = true
- if count <= 2
- done = false
- end
- done
- end
- def setup_done_response
- if !setup_done
- return false
- end
- render :json => {
- :setup_done => true,
- :import_mode => Setting.get('import_mode'),
- :import_backend => Setting.get('import_backend'),
- }
- true
- end
- end
|