New version of setup wizard.

This commit is contained in:
Martin Edenhofer 2014-11-16 23:45:57 +01:00
parent 7242581723
commit be8280c1b1
12 changed files with 1312 additions and 473 deletions

View file

@ -13,7 +13,7 @@ class Index extends App.ControllerContent
# if not import backend exists, go ahead # if not import backend exists, go ahead
if !App.Config.get('ImportPlugins') if !App.Config.get('ImportPlugins')
@navigate 'getting_started/base' @navigate 'getting_started/admin'
return return
@fetch() @fetch()
@ -51,230 +51,10 @@ class Index extends App.ControllerContent
App.Config.set( 'getting_started', Index, 'Routes' ) App.Config.set( 'getting_started', Index, 'Routes' )
class Base extends App.ControllerContent
className: 'getstarted fit'
events:
'change [name=adapter]': 'toggleAdapter'
'submit .base': 'storeUrl'
'submit .base-outbound': 'storeOutbound'
'submit .base-inbound': 'storeInbound'
'click .js-next': 'submit'
constructor: ->
super
if @authenticate(true)
@navigate '#'
return
# set title
@title 'Configure Base'
@fetch()
release: =>
@el.removeClass('fit getstarted')
fetch: ->
# get data
@ajax(
id: 'getting_started',
type: 'GET',
url: @apiPath + '/getting_started',
processData: true,
success: (data, status, xhr) =>
# redirect to login if master user already exists
if @Config.get('system_init_done')
@navigate '#login'
return
# check if import is active
if data.import_mode == true
@navigate '#import/' + data.import_backend
return
# render page
@render()
)
render: ->
@html App.view('getting_started/base')()
# url
url = window.location.origin
configureAttributesBase = [
{ name: 'url', display: 'System URL (where the system can be reached)', tag: 'input', null: false, placeholder: 'http://yourhost', default: url },
]
new App.ControllerForm(
el: @$('.base-url'),
model: { configure_attributes: configureAttributesBase, className: '' },
)
# outbound
adapters =
sendmail: 'Local MTA (Sendmail/Postfix/Exim/...)'
smtp: 'SMTP'
adapter_used = 'sendmail'
configureAttributesOutbound = [
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , default: adapter_used },
]
new App.ControllerForm(
el: @$('.base-outbound-type'),
model: { configure_attributes: configureAttributesOutbound, className: '' },
)
@toggleAdapter()
# inbound
configureAttributesInbound = [
{ name: 'email', display: 'Email', tag: 'input', type: 'text', limit: 200, null: false, autocapitalize: false, default: '' },
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { IMAP: 'IMAP', POP3: 'POP3' } },
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true},
]
new App.ControllerForm(
el: @$('.base-inbound-settings'),
model: { configure_attributes: configureAttributesInbound, className: '' },
)
toggleAdapter: (channel_used = {}) =>
adapter = @$('[name=adapter]').val()
if adapter is 'smtp'
configureAttributesOutbound = [
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['host']) },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['user']) },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['password']) },
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , translate: true, default: (channel_used['options']&&channel_used['options']['ssl']||true) },
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 5, null: false, class: 'span1', autocapitalize: false, default: ((channel_used['options']&&channel_used['options']['port']) || 25) },
]
@form = new App.ControllerForm(
el: @$('.base-outbound-settings')
model: { configure_attributes: configureAttributesOutbound, className: '' }
autofocus: true
)
else
@el.find('.base-outbound-settings').html('')
submit: (e) =>
e.preventDefault()
form = $(e.target).attr('data-form')
console.log('submit', form)
@$(".#{form}").trigger('submit')
showOutbound: =>
@$('.base').addClass('hide')
@$('.base-outbound').removeClass('hide')
@$('.base-inbound').addClass('hide')
@$('.wizard-controls .btn').text('Check').attr('data-form', 'base-outbound').addClass('btn--primary').removeClass('btn--danger btn--success')
@enable( @$('.btn') )
showInbound: =>
@$('.base').addClass('hide')
@$('.base-outbound').addClass('hide')
@$('.base-inbound').removeClass('hide')
@$('.wizard-controls .btn').text('Check').attr('data-form', 'base-inbound').addClass('btn--primary').removeClass('btn--danger btn--success')
@enable( @$('.btn') )
storeUrl: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
console.log('submit', params, e)
@disable(e)
@ajax(
id: 'base_url'
type: 'POST'
url: @apiPath + '/getting_started/base_url'
data: JSON.stringify( {url:params.url} )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
@delay( @showOutbound, 1500 )
else
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
@enable(e)
fail: =>
@enable(e)
)
storeOutbound: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
@disable(e)
@ajax(
id: 'base_outbound'
type: 'POST'
url: @apiPath + '/getting_started/base_outbound'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
@delay( @showInbound, 1500 )
else
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
@enable(e)
fail: =>
@enable(e)
)
storeInbound: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
@disable(e)
console.log('PA', params)
@ajax(
id: 'base_inbound'
type: 'POST'
url: @apiPath + '/getting_started/base_inbound'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
@$('.wizard-controls .btn').text('Done').removeClass('btn--primary btn--danger').addClass('btn--success')
@delay( @goToAdmin, 1500 )
else
@$('.wizard-controls .btn').text( data.message_human || data.message ).addClass('btn--danger').removeClass('btn--primary btn--success')
@enable(e)
fail: =>
@enable(e)
)
disable: (e) =>
@formDisable(e)
@$('.wizard-controls .btn').attr('disabled', true)
enable: (e) =>
@formEnable(e)
@$('.wizard-controls .btn').attr('disabled', false)
goToAdmin: =>
@navigate 'getting_started/admin'
App.Config.set( 'getting_started/base', Base, 'Routes' )
class Admin extends App.ControllerContent class Admin extends App.ControllerContent
className: 'getstarted fit' className: 'getstarted fit'
events: events:
'submit .js-admin': 'submit' 'submit form': 'submit'
constructor: -> constructor: ->
super super
@ -295,13 +75,10 @@ class Admin extends App.ControllerContent
# get data # get data
@ajax( @ajax(
id: 'getting_started', id: 'getting_started'
type: 'GET', type: 'GET'
url: @apiPath + '/getting_started', url: @apiPath + '/getting_started'
data: { processData: true
# view: @view,
}
processData: true,
success: (data, status, xhr) => success: (data, status, xhr) =>
# redirect to login if master user already exists # redirect to login if master user already exists
@ -384,29 +161,35 @@ class Admin extends App.ControllerContent
relogin: (data, status, xhr) => relogin: (data, status, xhr) =>
@log 'notice', 'relogin:success', data @log 'notice', 'relogin:success', data
# add notify
App.Event.trigger 'notify:removeall' App.Event.trigger 'notify:removeall'
@navigate 'getting_started/agents' @navigate 'getting_started/base'
App.Config.set( 'getting_started/admin', Admin, 'Routes' ) App.Config.set( 'getting_started/admin', Admin, 'Routes' )
class Agent extends App.ControllerContent
className: 'getstarted' class Base extends App.ControllerContent
className: 'getstarted fit'
elements:
'.logo-preview': 'logoPreview'
events: events:
'submit .js-agent': 'submit' 'submit form': 'submit'
'change .js-upload': 'onLogoPick'
constructor: -> constructor: ->
super super
return if !@authenticate() # redirect if we are not admin
if !@authenticate(true)
@navigate '#'
return
# set title # set title
@title 'Invite Agents' @title 'Configure Base'
@fetch() @fetch()
release: => release: =>
@el.removeClass('fit getstarted') @el.removeClass('fit getstarted')
@ -420,11 +203,409 @@ class Agent extends App.ControllerContent
processData: true, processData: true,
success: (data, status, xhr) => success: (data, status, xhr) =>
# redirect to login if master user already exists # check if import is active
if !data.setup_done if data.import_mode == true
@navigate '#getting_started/admin' @navigate '#import/' + data.import_backend
return return
# render page
@render()
)
render: ->
fqdn = App.Config.get('fqdn')
http_type = App.Config.get('http_type')
if !fqdn || fqdn is 'zammad.example.com'
url = window.location.origin
else
url = "#{http_type}://#{fqdn}"
organization = App.Config.get('organization')
@html App.view('getting_started/base')(
url: url
organization: organization
)
onLogoPick: (event) =>
reader = new FileReader()
reader.onload = (e) =>
@logoPreview.attr('src', e.target.result)
file = event.target.files[0]
@hideAlerts()
# if no file is given, about in file upload was used
if !file
return
maxSiteInMb = 3
if file.size && file.size > 1024 * 1024 * maxSiteInMb
@showAlert( 'logo', App.i18n.translateInline( 'File too big, max. %s MB allowed.', maxSiteInMb ) )
@logoPreview.attr( 'src', '' )
return
reader.readAsDataURL(file)
submit: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
params['logo'] = @logoPreview.attr('src')
@hideAlerts()
@disable(e)
@ajax(
id: 'getting_started_base'
type: 'POST'
url: @apiPath + '/getting_started/base'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
for key, value of data.settings
App.Config.set( key, value )
@navigate 'getting_started/channel'
else
for key, value of data.messages
@showAlert( key, value )
@enable(e)
fail: =>
@enable(e)
)
hideAlerts: =>
@$('.form-group').removeClass('has-error')
@$('.alert').addClass('hide')
showAlert: (field, message) =>
@$("[name=#{field}]").closest('.form-group').addClass('has-error')
@$("[name=#{field}]").closest('.form-group').find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
disable: (e) =>
@formDisable(e)
@$('.wizard-controls .btn').attr('disabled', true)
enable: (e) =>
@formEnable(e)
@$('.wizard-controls .btn').attr('disabled', false)
App.Config.set( 'getting_started/base', Base, 'Routes' )
class Channel extends App.ControllerContent
className: 'getstarted fit'
constructor: ->
super
# redirect if we are not admin
if !@authenticate(true)
@navigate '#'
return
# set title
@title 'Connect Channels'
@adapters = [
{
name: 'Email'
class: 'email'
link: '#getting_started/channel/email'
},
]
@fetch()
release: =>
@el.removeClass('fit getstarted')
fetch: ->
# get data
@ajax(
id: 'getting_started',
type: 'GET',
url: @apiPath + '/getting_started',
processData: true,
success: (data, status, xhr) =>
# check if import is active
if data.import_mode == true
@navigate '#import/' + data.import_backend
return
# render page
@render()
)
render: ->
@html App.view('getting_started/channel')(
adapters: @adapters
)
App.Config.set( 'getting_started/channel', Channel, 'Routes' )
class ChannelEmail extends App.ControllerContent
className: 'getstarted fit'
events:
'submit .js-intro': 'emailProbe'
'submit .js-inbound': 'storeInbound'
'change .js-outbound [name=adapter]': 'toggleAdapter'
'submit .js-outbound': 'storeOutbound'
constructor: ->
super
# redirect if we are not admin
if !@authenticate(true)
@navigate '#'
return
# set title
@title 'Email Account'
# store account settings
@account =
inbound: {}
outbound: {}
meta: {}
@fetch()
release: =>
@el.removeClass('fit getstarted')
fetch: ->
# get data
@ajax(
id: 'getting_started',
type: 'GET',
url: @apiPath + '/getting_started',
processData: true,
success: (data, status, xhr) =>
# check if import is active
if data.import_mode == true
@navigate '#import/' + data.import_backend
return
# render page
@render()
)
render: ->
@html App.view('getting_started/email')()
# outbound
adapters =
sendmail: 'Local MTA (Sendmail/Postfix/Exim/...) - use server setup'
smtp: 'SMTP - configure your own outgoing SMTP settings'
adapter_used = 'sendmail'
configureAttributesOutbound = [
{ name: 'adapter', display: 'Send Mails via', tag: 'select', multiple: false, null: false, options: adapters , default: adapter_used },
]
new App.ControllerForm(
el: @$('.base-outbound-type'),
model: { configure_attributes: configureAttributesOutbound, className: '' },
)
@toggleAdapter()
# inbound
configureAttributesInbound = [
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: { imap: 'IMAP', pop3: 'POP3' } },
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' }, translate: true, default: true},
]
new App.ControllerForm(
el: @$('.base-inbound-settings'),
model: { configure_attributes: configureAttributesInbound, className: '' },
)
toggleAdapter: (channel_used = {}) =>
adapter = @$('.js-outbound [name=adapter]').val()
if adapter is 'smtp'
configureAttributesOutbound = [
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['host']) },
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['user']) },
{ name: 'options::password', display: 'Password', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, default: (channel_used['options']&&channel_used['options']['password']) },
{ name: 'options::ssl', display: 'SSL', tag: 'select', multiple: false, null: false, options: { true: 'yes', false: 'no' } , translate: true, default: (channel_used['options']&&channel_used['options']['ssl']||true) },
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 5, null: false, class: 'span1', autocapitalize: false, default: ((channel_used['options']&&channel_used['options']['port']) || 25) },
]
@form = new App.ControllerForm(
el: @$('.base-outbound-settings')
model: { configure_attributes: configureAttributesOutbound, className: '' }
)
else
@el.find('.base-outbound-settings').html('')
emailProbe: (e) =>
e.preventDefault()
params = @formParam(e.target)
# remember account settings
@account.meta = params
@disable(e)
@$('.js-probe .js-email').text( params.email )
@showSlide('js-probe')
@ajax(
id: 'email_probe'
type: 'POST'
url: @apiPath + '/getting_started/email_probe'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
if data.setting
for key, value of data.setting
@account[key] = value
@verify(@account)
else
@showSlide('js-inbound')
@enable(e)
fail: =>
@enable(e)
@showSlide('js-intro')
)
showSlide: (name) =>
@$('.setup.wizard').addClass('hide')
@$(".setup.wizard.#{name}").removeClass('hide')
storeOutbound: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
params['email'] = @account['meta']['email']
@disable(e)
@hideAlert('js-outbound')
@ajax(
id: 'email_outbound'
type: 'POST'
url: @apiPath + '/getting_started/email_outbound'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
# remember account settings
@account.outbound = params
@verify(@account)
else
@showAlert('js-outbound', data.message_human || data.message )
@enable(e)
fail: =>
@enable(e)
)
storeInbound: (e) =>
e.preventDefault()
# get params
params = @formParam(e.target)
@disable(e)
@hideAlert('js-inbound')
@ajax(
id: 'email_inbound'
type: 'POST'
url: @apiPath + '/getting_started/email_inbound'
data: JSON.stringify( params )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
@showSlide('js-outbound')
# remember account settings
@account.inbound = params
else
@showAlert('js-inbound', data.message_human || data.message )
@enable(e)
fail: =>
@enable(e)
)
verify: (account) =>
@showSlide('js-verify')
@hideAlert('js-verify')
@ajax(
id: 'email_verify'
type: 'POST'
url: @apiPath + '/getting_started/email_verify'
data: JSON.stringify( account )
processData: true
success: (data, status, xhr) =>
if data.result is 'ok'
@navigate 'getting_started/agents'
else
@showAlert('js-verify', data.message_human || data.message )
@enable(e)
fail: =>
@enable(e)
)
showAlert: (screen, message) =>
@$(".#{screen}").find('.alert').removeClass('hide').text( App.i18n.translateInline( message ) )
hideAlert: (screen) =>
@$(".#{screen}").find('.alert').addClass('hide')
disable: (e) =>
@formDisable(e)
@$('.wizard-controls .btn').attr('disabled', true)
enable: (e) =>
@formEnable(e)
@$('.wizard-controls .btn').attr('disabled', false)
App.Config.set( 'getting_started/channel/email', ChannelEmail, 'Routes' )
class Agent extends App.ControllerContent
className: 'getstarted fit'
events:
'submit form': 'submit'
constructor: ->
super
return if !@authenticate()
# set title
@title 'Invite Agents'
@fetch()
release: =>
@el.removeClass('fit getstarted')
fetch: ->
# get data
@ajax(
id: 'getting_started',
type: 'GET',
url: @apiPath + '/getting_started',
processData: true,
success: (data, status, xhr) =>
# check if import is active # check if import is active
if data.import_mode == true if data.import_mode == true
@navigate '#import/' + data.import_backend @navigate '#import/' + data.import_backend
@ -495,4 +676,33 @@ class Agent extends App.ControllerContent
} }
) )
App.Config.set( 'getting_started/agents', Agent, 'Routes' ) App.Config.set( 'getting_started/agents', Agent, 'Routes' )
class Channel extends App.ControllerContent
className: 'getstarted fit'
constructor: ->
super
return if !@authenticate()
# set title
@title 'Setup Finished'
@render()
release: =>
@el.removeClass('fit getstarted')
render: ->
@html App.view('getting_started/finish')()
@delay(
=> @$('.wizard-slide').addClass('hide')
2300
)
@delay(
=> @navigate '#'
4300
)
App.Config.set( 'getting_started/finish', Channel, 'Routes' )

View file

@ -1,14 +1,13 @@
<div class="fullHeight flex vertical center justified getstarted fit"> <div class="main flex vertical centered darkBackground">
<div class="hero-unit"> <img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<ol class="horizontal tabs progress-tabs tabs-condensed"> <form class="setup wizard">
<li class="configure_channels tab u-textTruncate"><%- @T( 'Configure Base' ) %></li> <div class="wizard-slide">
<li class="create_admin tab u-textTruncate active"><%- @T( 'Create Admin' ) %></li> <h2><%- @T('Administrator Account') %></h2>
<li class="invite_agents tab u-textTruncate"><%- @T( 'Invite Agents' ) %></li> <div class="wizard-body vertical justified js-admin"></div>
</ol> <div class="wizard-controls center">
<div class="master-user hero-left"> <a class="subtle-link" href="#getting_started"><%- @T('Go Back') %></a>
<form class="form-stacked js-admin"> <button class="btn btn--success align-right"><%- @T( 'Create' ) %></button>
<button type="submit" class="btn btn--primary submit pull-right"><%- @T( 'Create Admin' ) %></button> </div>
</form>
</div> </div>
</div> </form>
</div> </div>

View file

@ -1,16 +1,13 @@
<div class="fullHeight flex vertical center justified getstarted"> <div class="main flex vertical centered darkBackground">
<div class="hero-unit"> <img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<ol class="horizontal tabs progress-tabs tabs-condensed"> <form class="setup wizard">
<li class="configure_channels tab u-textTruncate"><%- @T( 'Configure Base' ) %></li> <div class="wizard-slide">
<li class="create_admin tab u-textTruncate"><%- @T( 'Create Admin' ) %></li> <h2><%- @T('Invite Colleagues') %></h2>
<li class="invite_agents tab u-textTruncate active"><%- @T( 'Invite Agents' ) %></li> <div class="wizard-body vertical justified js-agent"></div>
</ol> <div class="wizard-controls center">
<div class="master-user hero-left"> <a class="btn btn--primary align-left" href="#getting_started/finish"><%- @T( 'Continue' ) %></a>
<form class="form-stacked js-agent"> <button class="btn btn--success align-right"><%- @T( 'Invite' ) %></button>
<div class="form-controls"> </div>
<button type="submit" class="btn btn--primary submit pull-right"><%- @T( 'Send Invitation' ) %></button>
</div>
</form>
</div> </div>
</div> </form>
</div> </div>

View file

@ -1,31 +1,32 @@
<div class="fullHeight flex vertical center justified"> <div class="main flex vertical centered darkBackground">
<div class="hero-unit"> <img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<ol class="horizontal tabs progress-tabs tabs-condensed"> <form class="setup wizard">
<li class="configure_channels tab u-textTruncate active"><%- @T( 'Configure Base' ) %></li> <div class="wizard-slide">
<li class="create_admin tab u-textTruncate"><%- @T( 'Create Admin' ) %></li> <h2><%- @T('Organization') %></h2>
<li class="invite_agents tab u-textTruncate"><%- @T( 'Invite Agents' ) %></li> <div class="wizard-body vertical justified">
</ol> <fieldset>
<div class="form-group">
<form class="base"> <label><%- @T('Organization Name') %></label>
<div class="base-url"></div> <div class="alert alert--danger hide" role="alert"></div>
</form> <input class="form-control" name="organization" placeholder="<%- @Ti('Company Inc.') %>" value="<%= @organization %>" required>
</div>
<div class="form-group">
<form class="base-outbound hide"> <label><%- @T('Logo') %></label>
<h2><%- @T('E-Mail Outbound') %></h2> <div class="alert alert--danger hide" role="alert"></div>
<div class="base-outbound-type"></div> <img class="logo-preview" src="" data-placeholder="<%- @T('Your Logo') %>">
<div class="base-outbound-settings"></div> <div class="btn btn--success fileUpload"><%- @T('Upload') %><input type="file" class="js-upload" name="logo" accept="image/*"></div>
</form> </div>
<div class="form-group">
<form class="base-inbound hide"> <label><%- @T('System URL') %></label>
<h2><%- @T('E-Mail Inbound') %></h2> <div class="alert alert--danger hide" role="alert"></div>
<div class="base-inbound-settings"></div> <input type="text" class="form-control" name="url" value="<%= @url %>" placeholder="http://zammad.example.com" required>
</form> <p class="help-block">The URL to this installation of Zammad.</p>
</div>
<div class="wizard-controls horizontal center"> </fieldset>
<a class="subtle-link" href="#getting_started"><%- @T('Go Back') %></a> </div>
<div class="btn btn--primary js-next align-right" data-form="base"><%- @T('Next') %></div> <div class="wizard-controls center">
<button class="btn btn--primary align-right"><%- @T( 'Next' ) %></button>
</div>
</div> </div>
</form>
</div>
</div> </div>

View file

@ -0,0 +1,25 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<form class="setup wizard">
<div class="wizard-slide">
<h2><%- @T('Connect Channels') %></h2>
<div class="wizard-body vertical center">
<p class="help-block help-block--center"><%- @T('Setup the communication channels you want to use with your Zammad.') %></p>
<div class="wizard-buttonList vertical">
<% for adapter in @adapters: %>
<div class="btn auth_provider auth_provider--wide <%= adapter.class %>">
<div class="<%= adapter.class %> provider_icon"></div>
<a class="provider_name" href="<%= adapter.link %>"><%- @T( adapter.name ) %></a>
</div>
<% end %>
</div>
</div>
<div class="wizard-controls center">
<a class="subtle-link" href="#getting_started/base"><%- @T('Go Back') %></a>
<a class="btn align-right" href="#getting_started/finish"><%- @T( 'Skip' ) %></a>
</div>
</div>
</form>
</div>

View file

@ -0,0 +1,82 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<form class="setup wizard js-intro">
<div class="wizard-slide">
<h2><%- @T('Email Account') %></h2>
<div class="wizard-body vertical justified">
<fieldset>
<div class="form-group">
<label><%- @T('Full Name') %></label>
<input type="text" class="form-control" value="" name="realname" placeholder="<%- @T('Organization Support') %>">
</div>
<div class="form-group">
<label><%- @T('Email') %></label>
<input type="email" class="form-control" value="" name="email" placeholder="<%- @T('support@example.com') %>">
</div>
<div class="form-group">
<label><%- @T('Password') %></label>
<input type="password" class="form-control" name="password" value="">
</div>
</fieldset>
</div>
<div class="wizard-controls center">
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
<button class="btn btn--primary align-right"><%- @T( 'Connect' ) %></button>
</div>
</div>
</form>
<form class="setup wizard hide js-probe">
<div class="wizard-slide">
<h2><%- @T('Email Account') %></h2>
<div class="wizard-body vertical justified">
<p class="wizard-loadingText">
<span class="loading icon"></span> <%- @T('Testing') %> <span class="js-email"></span>
</p>
</div>
</div>
</form>
<form class="setup wizard hide js-verify">
<div class="wizard-slide">
<h2><%- @T('Email Account') %></h2>
<div class="wizard-body vertical justified">
<div class="alert alert--danger hide" role="alert"></div>
<p class="wizard-loadingText">
<span class="loading icon"></span> <%- @T('Verify sending and receiving') %>
</p>
</div>
</div>
</form>
<form class="setup wizard hide js-inbound">
<div class="wizard-slide">
<h2><%- @T('E-Mail Inbound') %></h2>
<div class="wizard-body vertical justified">
<div class="alert alert--danger hide" role="alert"></div>
<div class="base-inbound-settings"></div>
<div class="wizard-controls center">
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
<button class="btn btn--primary align-right"><%- @T( 'Continue' ) %></button>
</div>
</div>
</div>
</form>
<form class="setup wizard hide js-outbound">
<div class="wizard-slide">
<h2><%- @T('E-Mail Outbound') %></h2>
<div class="wizard-body vertical justified">
<div class="alert alert--danger hide" role="alert"></div>
<div class="base-outbound-type"></div>
<div class="base-outbound-settings"></div>
<div class="wizard-controls center">
<a class="subtle-link" href="#getting_started/channel"><%- @T('Go Back') %></a>
<button class="btn btn--primary align-right"><%- @T( 'Continue' ) %></button>
</div>
</div>
</div>
</form>
</div>

View file

@ -0,0 +1,13 @@
<div class="main flex vertical centered darkBackground">
<img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<form class="setup wizard">
<div class="wizard-slide">
<h2><%- @T('Setup Finished') %></h2>
<div class="wizard-body vertical justified">
<p class="wizard-loadingText">
<span class="loading icon"></span> Starting Zammad
</p>
</div>
</div>
</form>
</div>

View file

@ -1,12 +1,12 @@
<div class="main flex centered darkBackground"> <div class="main flex vertical centered darkBackground">
<div class="import wizard hero-unit"> <img class="zammad full logo" src="<%= @C('image_path') + '/' + 'full logo on dark.svg' %>" alt="Zammad">
<div class="wizard-slide vertical" data-slide="home"> <div class="setup wizard">
<h2><%- @T('Welcome to %s', @C('product_name') ) %></h2> <div class="wizard-slide">
<div class="wizard-body flex vertical centered"> <div class="wizard-body vertical centered">
<div class="vertical"> <a class="btn btn--primary" href="#getting_started/admin"><%- @T('Setup new System') %></a>
<a class="btn btn--primary" href="#import"><%- @T('Import from other System') %></a> </div>
<a class="btn btn--success" href="#getting_started/base"><%- @T('Setup new System') %></a> <div class="wizard-aside">
</div> <%- @T('Or') %> <span class="u-clickable u-highlight"><a href="#import"><%- @T('migrate from another system') %></a></span>.
</div> </div>
</div> </div>
</div> </div>

View file

@ -4203,12 +4203,12 @@ label + .wizard-buttonList {
display: block; display: block;
background: hsl(0,0%,95%); background: hsl(0,0%,95%);
width: 100%; width: 100%;
height: 130px; height: 60px;
margin-bottom: 10px; margin-bottom: 10px;
content: ""; content: "";
color: hsl(0,0%,60%); color: hsl(0,0%,60%);
@extend .centered; @extend .centered;
&:after { &:after {
content: attr(data-placeholder); content: attr(data-placeholder);
} }
@ -4216,8 +4216,8 @@ label + .wizard-buttonList {
.setup.wizard .logo-preview:not([src=""]) { .setup.wizard .logo-preview:not([src=""]) {
content: initial; content: initial;
max-width: 100%; max-width: 240px;
max-height: 130px; max-height: 60px;
margin: 0 auto 15px; margin: 0 auto 15px;
background: none; background: none;
width: auto; width: auto;

View file

@ -1,11 +1,13 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
require 'resolv'
class GettingStartedController < ApplicationController class GettingStartedController < ApplicationController
=begin =begin
Resource: Resource:
GET /api/v1/getting_started.json GET /api/v1/getting_started
Response: Response:
{ {
@ -23,7 +25,7 @@ Response:
} }
Test: Test:
curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password} curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
=end =end
@ -49,45 +51,634 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
} }
end end
def base_url def base
return if setup_done_response
# validate # check admin permissions
return if deny_if_not_role('Admin')
# validate url
messages = {}
if !params[:url] ||params[:url] !~ /^(http|https):\/\/.+?$/ 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].empty?
content_type = nil
content = nil
# data:image/png;base64
if params[:logo] =~ /^data:(.+?);base64,(.+?)$/
content_type = $1
content = $2
end
if !content_type || !content
messages[:logo] = 'Unable to process image upload.'
end
end
if !messages.empty?
render :json => { render :json => {
:result => 'invalid', :result => 'invalid',
:message => 'Invalid!', :messages => messages,
} }
return return
end end
# split url in http_type and fqdn # split url in http_type and fqdn
settings = {}
if params[:url] =~ /^(http|https):\/\/(.+?)$/ if params[:url] =~ /^(http|https):\/\/(.+?)$/
Setting.set('http_type', $1) Setting.set('http_type', $1)
settings[:http_type] = $1
Setting.set('fqdn', $2) 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].empty?
content_type = nil
content = nil
# data:image/png;base64
if params[:logo] =~ /^data:(.+?);base64,(.+?)$/
content_type = $1
content = Base64.decode64($2)
end
Store.remove( :object => 'System::Logo', :o_id => 1 )
Store.add(
:object => 'System::Logo',
:o_id => 1,
:data => content,
:filename => 'image',
:preferences => {
'Content-Type' => content_type
},
# :created_by_id => self.updated_by_id,
)
end
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 => { render :json => {
:result => 'ok', :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 => '465',
: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]
puts "MX #{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
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',
:account => 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|
puts "PROBE: #{config.inspect}"
result = email_probe_inbound( config )
puts "RESULT: #{result.inspect}"
if !result
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|
puts "PROBE: #{config.inspect}"
result = email_probe_outbound( config, params[:email] )
puts "RESULT: #{result.inspect}"
if result[:result] == 'ok'
success = true
settings[:outbound] = config
break
end
}
if !success
render :json => {
:result => 'failed',
} }
return return
end end
render :json => { render :json => {
:result => 'invalid', :result => 'ok',
:message => 'Unable to parse url!', :setting => settings,
} }
end end
def base_outbound def email_outbound
return if setup_done_response
# check admin permissions
return if deny_if_not_role('Admin')
# validate params # validate params
if !params[:adapter] if !params[:adapter]
render :json => { render :json => {
:result => 'invalid',
}
return
end
# connection test
result = email_probe_outbound( params, params[:email] )
if result[:result] != 'ok'
render :json => result
return
end
# return result
render :json => {
:result => 'ok',
}
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 )
if result
render :json => result
return
end
render :json => {
:result => 'ok',
}
end
def email_verify
# check admin permissions
return if deny_if_not_role('Admin')
# send verify email to inbox
subject = '#' + rand(99999999999).to_s
Channel::EmailSend.new.send(
{
:from => params[:meta][:email],
:to => params[:meta][:email],
:subject => "Zammad Getting started Test Email #{subject}",
:body => '.',
'x-zammad-ignore' => 'true',
}
)
(1..5).each {|loop|
sleep 10
# fetch mailbox
found = nil
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
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 dilivery for 30 sek.
render :json => {
:result => 'invalid',
:message => 'Verification Email not found in mailbox.',
}
end
private
def email_probe_outbound(params, email)
# validate params
if !params[:adapter]
result = {
:result => 'invalid', :result => 'invalid',
:message => 'Invalid!', :message => 'Invalid!',
} }
return return result
end end
# test connection # test connection
@ -101,7 +692,7 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
begin begin
Channel::SMTP.new.send( Channel::SMTP.new.send(
{ {
:from => 'me@example.com', :from => email,
:to => 'emailtrytest@znuny.com', :to => 'emailtrytest@znuny.com',
:subject => 'test', :subject => 'test',
:body => 'test', :body => 'test',
@ -118,10 +709,10 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
} }
whiteMap.each {|key, message| whiteMap.each {|key, message|
if e.message =~ /#{Regexp.escape(key)}/i if e.message =~ /#{Regexp.escape(key)}/i
render :json => { result = {
:result => 'ok', :result => 'ok',
} }
return return result
end end
} }
message_human = '' message_human = ''
@ -130,75 +721,48 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
message_human = message message_human = message
end end
} }
render :json => { result = {
:result => 'invalid', :result => 'invalid',
:message => e.message, :message => e.message,
:message_human => message_human, :message_human => message_human,
} }
return return result
end
else
begin
Channel::Sendmail.new.send(
{
:from => 'me@example.com',
:to => 'emailtrytest@znuny.com',
:subject => 'test',
:body => 'test',
},
nil
)
rescue Exception => e
message_human = ''
translationMap.each {|key, message|
if e.message =~ /#{Regexp.escape(key)}/i
message_human = message
end
}
render :json => {
:result => 'invalid',
:message => e.message,
:message_human => message_human,
}
return
end end
return
end end
# save settings begin
if params[:adapter] == 'smtp' Channel::Sendmail.new.send(
smtp = Channel.where( :adapter => 'SMTP', :area => 'Email::Outbound' ).first {
smtp.options = params[:options] :from => email,
smtp.active = true :to => 'emailtrytest@znuny.com',
smtp.save! :subject => 'test',
sendmail = Channel.where(:adapter => 'Sendmail').first :body => 'test',
sendmail.active = false },
sendmail.save! nil
else )
sendmail = Channel.where( :adapter => 'Sendmail', :area => 'Email::Outbound' ).first rescue Exception => e
sendmail.options = {} message_human = ''
sendmail.active = true translationMap.each {|key, message|
sendmail.save! if e.message =~ /#{Regexp.escape(key)}/i
smtp = Channel.where(:adapter => 'SMTP').first message_human = message
smtp.active = false end
smtp.save }
result = {
:result => 'invalid',
:message => e.message,
:message_human => message_human,
}
return result
end end
return
# return result
render :json => {
:result => 'ok',
}
end end
def base_inbound def email_probe_inbound(params)
return if setup_done_response
# validate params # validate params
if !params[:adapter] if !params[:adapter]
render :json => { raise 'need :adapter param'
:result => 'invalid',
}
return
end end
# connection test # connection test
@ -208,7 +772,7 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
'No route to host' => 'No route to host!', 'No route to host' => 'No route to host!',
'Connection refused' => 'Connection refused!', 'Connection refused' => 'Connection refused!',
} }
if params[:adapter] == 'IMAP' if params[:adapter] =~ /^imap$/i
begin begin
Channel::IMAP.new.fetch( { :options => params[:options] }, 'check' ) Channel::IMAP.new.fetch( { :options => params[:options] }, 'check' )
rescue Exception => e rescue Exception => e
@ -218,103 +782,42 @@ curl http://localhost/api/v1/getting_started.json -v -u #{login}:#{password}
message_human = message message_human = message
end end
} }
render :json => { result = {
:result => 'invalid', :result => 'invalid',
:message => e.message, :message => e.message,
:message_human => message_human, :message_human => message_human,
} }
return return result
end
else
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
}
render :json => {
:result => 'invalid',
:message => e.message,
:message_human => message_human,
}
return
end end
return
end end
# send verify email to inbox begin
subject = '#' + rand(99999999999).to_s Channel::POP3.new.fetch( { :options => params[:options] }, 'check' )
Channel::EmailSend.new.send( rescue Exception => e
{ message_human = ''
:from => params[:email], translationMap.each {|key, message|
:to => params[:email], if e.message =~ /#{Regexp.escape(key)}/i
:subject => "Zammad Getting started Test Email #{subject}", message_human = message
:body => '.',
'x-zammad-ignore' => 'true',
}
)
(1..5).each {|loop|
sleep 10
# fetch mailbox
found = nil
if params[:adapter] == 'IMAP'
found = Channel::IMAP.new.fetch( { :options => params[:options] }, 'verify', subject )
else
found = Channel::POP3.new.fetch( { :options => params[:options] }, 'verify', subject )
end
if found && found == 'verify ok'
# remember address
address = EmailAddress.all.first
if address
address.update_attributes(
:realname => 'Zammad',
:email => params[:email],
:active => 1,
:updated_by_id => 1,
:created_by_id => 1,
)
else
EmailAddress.create(
:realname => 'Zammad',
:email => params[:email],
:active => 1,
:updated_by_id => 1,
:created_by_id => 1,
)
end end
}
# store mailbox result = {
Channel.create( :result => 'invalid',
:area => 'Email::Inbound', :message => e.message,
:adapter => params[:adapter], :message_human => message_human,
:options => params[:options], }
:group_id => 1, return result
:active => 1, end
:updated_by_id => 1,
:created_by_id => 1,
)
render :json => {
:result => 'ok',
}
return
end
}
# check dilivery for 30 sek.
render :json => {
:result => 'invalid',
:message => 'Verification Email not found in mailbox.',
}
return return
end end
private 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 def setup_done
#return false #return false

View file

@ -15,8 +15,15 @@ class Channel::POP3 < Channel::EmailParser
puts "fetching pop3 (#{channel[:options][:host]}/#{channel[:options][:user]} port=#{port},ssl=#{ssl})" puts "fetching pop3 (#{channel[:options][:host]}/#{channel[:options][:user]} port=#{port},ssl=#{ssl})"
@pop = Net::POP3.new( channel[:options][:host], port ) @pop = Net::POP3.new( channel[:options][:host], port )
# on check, reduce open_timeout to have faster probing
if check_type == 'check'
@pop.open_timeout = 5
@pop.read_timeout = 6
end
if ssl if ssl
@pop.enable_ssl @pop.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
end end
@pop.start( channel[:options][:user], channel[:options][:password] ) @pop.start( channel[:options][:user], channel[:options][:password] )
if check_type == 'check' if check_type == 'check'

View file

@ -2,9 +2,11 @@ Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path api_path = Rails.configuration.api_path
# getting_started # getting_started
match api_path + '/getting_started', :to => 'getting_started#index', :via => :get match api_path + '/getting_started', :to => 'getting_started#index', :via => :get
match api_path + '/getting_started/base_url', :to => 'getting_started#base_url', :via => :post match api_path + '/getting_started/base', :to => 'getting_started#base', :via => :post
match api_path + '/getting_started/base_outbound', :to => 'getting_started#base_outbound', :via => :post match api_path + '/getting_started/email_probe', :to => 'getting_started#email_probe', :via => :post
match api_path + '/getting_started/base_inbound', :to => 'getting_started#base_inbound', :via => :post match api_path + '/getting_started/email_outbound', :to => 'getting_started#email_outbound', :via => :post
match api_path + '/getting_started/email_inbound', :to => 'getting_started#email_inbound', :via => :post
match api_path + '/getting_started/email_verify', :to => 'getting_started#email_verify', :via => :post
end end