Implemented issue #539 - Add email address without importing historical emails.
This commit is contained in:
parent
efad1f9fb1
commit
d8ad2b1b2f
8 changed files with 340 additions and 52 deletions
|
@ -127,6 +127,17 @@ test:integration:email_deliver:
|
||||||
- ruby -I test/ test/integration/email_deliver_test.rb
|
- ruby -I test/ test/integration/email_deliver_test.rb
|
||||||
- rake db:drop
|
- rake db:drop
|
||||||
|
|
||||||
|
test:integration:email_keep_on_server:
|
||||||
|
stage: test
|
||||||
|
tags:
|
||||||
|
- core
|
||||||
|
script:
|
||||||
|
- export RAILS_ENV=test
|
||||||
|
- rake db:create
|
||||||
|
- rake db:migrate
|
||||||
|
- ruby -I test/ test/integration/email_keep_on_server_test.rb
|
||||||
|
- rake db:drop
|
||||||
|
|
||||||
test:integration:twitter:
|
test:integration:twitter:
|
||||||
stage: test
|
stage: test
|
||||||
tags:
|
tags:
|
||||||
|
|
|
@ -562,19 +562,22 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
|
||||||
configureAttributesInbound = [
|
configureAttributesInbound = [
|
||||||
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
|
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
{ 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, autocomplete: 'off', },
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off' },
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
|
||||||
{ name: 'options::ssl', display: 'SSL', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
|
{ name: 'options::ssl', display: 'SSL', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
|
||||||
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
|
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
|
||||||
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false },
|
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
|
||||||
|
{ name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
|
||||||
]
|
]
|
||||||
|
|
||||||
showHideFolder = (params, attribute, attributes, classname, form, ui) ->
|
showHideFolder = (params, attribute, attributes, classname, form, ui) ->
|
||||||
return if !params
|
return if !params
|
||||||
if params.adapter is 'imap'
|
if params.adapter is 'imap'
|
||||||
ui.show('options::folder')
|
ui.show('options::folder')
|
||||||
|
ui.show('options::keep_on_server')
|
||||||
return
|
return
|
||||||
ui.hide('options::folder')
|
ui.hide('options::folder')
|
||||||
|
ui.hide('options::keep_on_server')
|
||||||
|
|
||||||
handlePort = (params, attribute, attributes, classname, form, ui) ->
|
handlePort = (params, attribute, attributes, classname, form, ui) ->
|
||||||
return if !params
|
return if !params
|
||||||
|
@ -609,6 +612,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
|
||||||
channel_used['options']['user'] = @account['meta']['email']
|
channel_used['options']['user'] = @account['meta']['email']
|
||||||
channel_used['options']['password'] = @account['meta']['password']
|
channel_used['options']['password'] = @account['meta']['password']
|
||||||
channel_used['options']['folder'] = @account['meta']['folder']
|
channel_used['options']['folder'] = @account['meta']['folder']
|
||||||
|
channel_used['options']['keep_on_server'] = @account['meta']['keep_on_server']
|
||||||
|
|
||||||
# show used backend
|
# show used backend
|
||||||
@$('.base-outbound-settings').html('')
|
@$('.base-outbound-settings').html('')
|
||||||
|
@ -670,7 +674,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
|
||||||
for key, value of data.setting
|
for key, value of data.setting
|
||||||
@account[key] = value
|
@account[key] = value
|
||||||
|
|
||||||
if data.content_messages && data.content_messages > 0
|
if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
|
||||||
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
||||||
@$('.js-inbound-acknowledge .js-message').html(message)
|
@$('.js-inbound-acknowledge .js-message').html(message)
|
||||||
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
|
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
|
||||||
|
@ -724,7 +728,7 @@ class App.ChannelEmailAccountWizard extends App.WizardModal
|
||||||
# remember account settings
|
# remember account settings
|
||||||
@account.inbound = params
|
@account.inbound = params
|
||||||
|
|
||||||
if data.content_messages && data.content_messages > 0
|
if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
|
||||||
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
||||||
@$('.js-inbound-acknowledge .js-message').html(message)
|
@$('.js-inbound-acknowledge .js-message').html(message)
|
||||||
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
|
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
|
||||||
|
|
|
@ -450,8 +450,8 @@ class EmailNotification extends App.WizardFullScreen
|
||||||
if adapter is 'smtp'
|
if adapter is 'smtp'
|
||||||
configureAttributesOutbound = [
|
configureAttributesOutbound = [
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
|
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
|
||||||
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password' },
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off' },
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
|
||||||
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
|
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
|
||||||
]
|
]
|
||||||
@form = new App.ControllerForm(
|
@form = new App.ControllerForm(
|
||||||
|
@ -673,18 +673,22 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
configureAttributesInbound = [
|
configureAttributesInbound = [
|
||||||
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
|
{ name: 'adapter', display: 'Type', tag: 'select', multiple: false, null: false, options: @channelDriver.email.inbound },
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false },
|
{ 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, autocomplete: 'new-password', },
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', },
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'new-password', single: true },
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: false, autocapitalize: false, autocomplete: 'off', single: true },
|
||||||
{ name: 'options::ssl', display: 'SSL', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
|
{ name: 'options::ssl', display: 'SSL', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, default: true, translate: true, item_class: 'formGroup--halfSize' },
|
||||||
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
|
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false, default: '993', item_class: 'formGroup--halfSize' },
|
||||||
|
{ name: 'options::folder', display: 'Folder', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, item_class: 'formGroup--halfSize' },
|
||||||
|
{ name: 'options::keep_on_server', display: 'Keep messages on server', tag: 'boolean', null: true, options: { true: 'yes', false: 'no' }, translate: true, default: false, item_class: 'formGroup--halfSize' },
|
||||||
]
|
]
|
||||||
|
|
||||||
showHideFolder = (params, attribute, attributes, classname, form, ui) ->
|
showHideFolder = (params, attribute, attributes, classname, form, ui) ->
|
||||||
return if !params
|
return if !params
|
||||||
if params.adapter is 'imap'
|
if params.adapter is 'imap'
|
||||||
ui.show('options::folder')
|
ui.show('options::folder')
|
||||||
|
ui.show('options::keep_on_server')
|
||||||
return
|
return
|
||||||
ui.hide('options::folder')
|
ui.hide('options::folder')
|
||||||
|
ui.hide('options::keep_on_server')
|
||||||
|
|
||||||
handlePort = (params, attribute, attributes, classname, form, ui) ->
|
handlePort = (params, attribute, attributes, classname, form, ui) ->
|
||||||
return if !params
|
return if !params
|
||||||
|
@ -700,7 +704,7 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
return
|
return
|
||||||
|
|
||||||
new App.ControllerForm(
|
new App.ControllerForm(
|
||||||
el: @$('.base-inbound-settings'),
|
el: @$('.base-inbound-settings')
|
||||||
model:
|
model:
|
||||||
configure_attributes: configureAttributesInbound
|
configure_attributes: configureAttributesInbound
|
||||||
className: ''
|
className: ''
|
||||||
|
@ -718,6 +722,8 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
if @account['meta']
|
if @account['meta']
|
||||||
channel_used['options']['user'] = @account['meta']['email']
|
channel_used['options']['user'] = @account['meta']['email']
|
||||||
channel_used['options']['password'] = @account['meta']['password']
|
channel_used['options']['password'] = @account['meta']['password']
|
||||||
|
channel_used['options']['folder'] = @account['meta']['folder']
|
||||||
|
channel_used['options']['keep_on_server'] = @account['meta']['keep_on_server']
|
||||||
|
|
||||||
# show used backend
|
# show used backend
|
||||||
@$('.base-outbound-settings').html('')
|
@$('.base-outbound-settings').html('')
|
||||||
|
@ -725,8 +731,8 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
if adapter is 'smtp'
|
if adapter is 'smtp'
|
||||||
configureAttributesOutbound = [
|
configureAttributesOutbound = [
|
||||||
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
|
{ name: 'options::host', display: 'Host', tag: 'input', type: 'text', limit: 120, null: false, autocapitalize: false, autofocus: true },
|
||||||
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', },
|
{ name: 'options::user', display: 'User', tag: 'input', type: 'text', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', },
|
||||||
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'new-password', single: true },
|
{ name: 'options::password', display: 'Password', tag: 'input', type: 'password', limit: 120, null: true, autocapitalize: false, autocomplete: 'off', single: true },
|
||||||
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
|
{ name: 'options::port', display: 'Port', tag: 'input', type: 'text', limit: 6, null: true, autocapitalize: false },
|
||||||
]
|
]
|
||||||
@form = new App.ControllerForm(
|
@form = new App.ControllerForm(
|
||||||
|
@ -760,7 +766,7 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
for key, value of data.setting
|
for key, value of data.setting
|
||||||
@account[key] = value
|
@account[key] = value
|
||||||
|
|
||||||
if data.content_messages && data.content_messages > 0
|
if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
|
||||||
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
message = App.i18n.translateContent('We have already found %s email(s) in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
||||||
@$('.js-inbound-acknowledge .js-message').html(message)
|
@$('.js-inbound-acknowledge .js-message').html(message)
|
||||||
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
|
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-intro')
|
||||||
|
@ -809,7 +815,7 @@ class ChannelEmail extends App.WizardFullScreen
|
||||||
# remember account settings
|
# remember account settings
|
||||||
@account.inbound = params
|
@account.inbound = params
|
||||||
|
|
||||||
if data.content_messages && data.content_messages > 0
|
if data.content_messages && data.content_messages > 0 && (!@account['inbound']['options'] || @account['inbound']['options']['keep_on_server'] isnt true)
|
||||||
message = App.i18n.translateContent('We have already found %s emails in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
message = App.i18n.translateContent('We have already found %s emails in your mailbox. Zammad will move it all from your mailbox into Zammad.', data.content_messages)
|
||||||
@$('.js-inbound-acknowledge .js-message').html(message)
|
@$('.js-inbound-acknowledge .js-message').html(message)
|
||||||
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
|
@$('.js-inbound-acknowledge .js-back').attr('data-slide', 'js-inbound')
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form class="setup wizard hide js-inbound">
|
<form class="setup wizard hide js-inbound">
|
||||||
<div class="wizard-slide">
|
<div class="wizard-slide wizard-slide--large">
|
||||||
<h2><%- @T('Email Inbound') %></h2>
|
<h2><%- @T('Email Inbound') %></h2>
|
||||||
<div class="wizard-body vertical justified">
|
<div class="wizard-body vertical justified">
|
||||||
<div class="alert alert--danger hide" role="alert"></div>
|
<div class="alert alert--danger hide" role="alert"></div>
|
||||||
|
|
|
@ -6457,6 +6457,10 @@ footer {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
padding-bottom: 18px;
|
padding-bottom: 18px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
&.wizard-slide--large {
|
||||||
|
width: 460px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard h2 {
|
.wizard h2 {
|
||||||
|
|
|
@ -52,6 +52,7 @@ example
|
||||||
host: 'outlook.office365.com',
|
host: 'outlook.office365.com',
|
||||||
user: 'xxx@znuny.onmicrosoft.com',
|
user: 'xxx@znuny.onmicrosoft.com',
|
||||||
password: 'xxx',
|
password: 'xxx',
|
||||||
|
keep_on_server: true,
|
||||||
}
|
}
|
||||||
channel = Channel.last
|
channel = Channel.last
|
||||||
instance = Channel::Driver::Imap.new
|
instance = Channel::Driver::Imap.new
|
||||||
|
@ -62,11 +63,16 @@ example
|
||||||
def fetch (options, channel, check_type = '', verify_string = '')
|
def fetch (options, channel, check_type = '', verify_string = '')
|
||||||
ssl = true
|
ssl = true
|
||||||
port = 993
|
port = 993
|
||||||
|
keep_on_server = false
|
||||||
|
folder = 'INBOX'
|
||||||
|
if options[:keep_on_server] == true || options[:keep_on_server] == 'true'
|
||||||
|
keep_on_server = true
|
||||||
|
end
|
||||||
if options.key?(:ssl) && options[:ssl] == false
|
if options.key?(:ssl) && options[:ssl] == false
|
||||||
ssl = false
|
ssl = false
|
||||||
port = 143
|
port = 143
|
||||||
end
|
end
|
||||||
if options.key?(:port) && !options[:port].empty?
|
if options.key?(:port) && options[:port].present?
|
||||||
port = options[:port]
|
port = options[:port]
|
||||||
|
|
||||||
# disable ssl for non ssl ports
|
# disable ssl for non ssl ports
|
||||||
|
@ -74,8 +80,11 @@ example
|
||||||
ssl = false
|
ssl = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if options[:folder].present?
|
||||||
|
folder = options[:folder]
|
||||||
|
end
|
||||||
|
|
||||||
Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},folder=#{options[:folder]})"
|
Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},folder=#{folder},keep_on_server=#{keep_on_server})"
|
||||||
|
|
||||||
# on check, reduce open_timeout to have faster probing
|
# on check, reduce open_timeout to have faster probing
|
||||||
timeout = 45
|
timeout = 45
|
||||||
|
@ -90,17 +99,17 @@ example
|
||||||
@imap.login(options[:user], options[:password])
|
@imap.login(options[:user], options[:password])
|
||||||
|
|
||||||
# select folder
|
# select folder
|
||||||
if !options[:folder] || options[:folder].empty?
|
@imap.select(folder)
|
||||||
@imap.select('INBOX')
|
|
||||||
else
|
|
||||||
@imap.select(options[:folder])
|
|
||||||
end
|
|
||||||
|
|
||||||
# sort messages by date on server (if not supported), if not fetch messages via search (first in, first out)
|
# sort messages by date on server (if not supported), if not fetch messages via search (first in, first out)
|
||||||
|
filter = ['ALL']
|
||||||
|
if keep_on_server && check_type != 'check' && check_type != 'verify'
|
||||||
|
filter = %w(NOT SEEN)
|
||||||
|
end
|
||||||
begin
|
begin
|
||||||
message_ids = @imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
message_ids = @imap.sort(['DATE'], filter, 'US-ASCII')
|
||||||
rescue
|
rescue
|
||||||
message_ids = @imap.search(['ALL'])
|
message_ids = @imap.search(filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
# check mode only
|
# check mode only
|
||||||
|
@ -168,9 +177,8 @@ example
|
||||||
message_ids.each do |message_id|
|
message_ids.each do |message_id|
|
||||||
count += 1
|
count += 1
|
||||||
Rails.logger.info " - message #{count}/#{count_all}"
|
Rails.logger.info " - message #{count}/#{count_all}"
|
||||||
#Rails.logger.info msg.to_s
|
|
||||||
|
|
||||||
message_meta = @imap.fetch(message_id, ['RFC822.SIZE', 'FLAGS', 'INTERNALDATE'])[0]
|
message_meta = @imap.fetch(message_id, ['RFC822.SIZE', 'ENVELOPE', 'FLAGS', 'INTERNALDATE'])[0]
|
||||||
|
|
||||||
# ignore to big messages
|
# ignore to big messages
|
||||||
info = too_big?(message_meta, count, count_all)
|
info = too_big?(message_meta, count, count_all)
|
||||||
|
@ -182,14 +190,23 @@ example
|
||||||
# ignore deleted messages
|
# ignore deleted messages
|
||||||
next if deleted?(message_meta, count, count_all)
|
next if deleted?(message_meta, count, count_all)
|
||||||
|
|
||||||
|
# ignore already imported
|
||||||
|
next if already_imported?(message_id, message_meta, count, count_all, keep_on_server)
|
||||||
|
|
||||||
# delete email from server after article was created
|
# delete email from server after article was created
|
||||||
msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822']
|
msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822']
|
||||||
next if !msg
|
next if !msg
|
||||||
process(channel, msg, false)
|
process(channel, msg, false)
|
||||||
|
if !keep_on_server
|
||||||
@imap.store(message_id, '+FLAGS', [:Deleted])
|
@imap.store(message_id, '+FLAGS', [:Deleted])
|
||||||
|
else
|
||||||
|
@imap.store(message_id, '+FLAGS', [:Seen])
|
||||||
|
end
|
||||||
count_fetched += 1
|
count_fetched += 1
|
||||||
end
|
end
|
||||||
|
if !keep_on_server
|
||||||
@imap.expunge()
|
@imap.expunge()
|
||||||
|
end
|
||||||
disconnect
|
disconnect
|
||||||
if count.zero?
|
if count.zero?
|
||||||
Rails.logger.info ' - no message'
|
Rails.logger.info ' - no message'
|
||||||
|
@ -209,6 +226,20 @@ example
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def already_imported?(message_id, message_meta, count, count_all, keep_on_server)
|
||||||
|
return false if !keep_on_server
|
||||||
|
return false if !message_meta.attr
|
||||||
|
return false if !message_meta.attr['ENVELOPE']
|
||||||
|
local_message_id = message_meta.attr['ENVELOPE'].message_id
|
||||||
|
return false if local_message_id.blank?
|
||||||
|
local_message_id_md5 = Digest::MD5.hexdigest(local_message_id)
|
||||||
|
article = Ticket::Article.where(message_id_md5: local_message_id_md5).order('created_at DESC, id DESC').limit(1).first
|
||||||
|
return false if !article
|
||||||
|
@imap.store(message_id, '+FLAGS', [:Seen])
|
||||||
|
Rails.logger.info " - ignore message #{count}/#{count_all} - because message message id already imported"
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def deleted?(message_meta, count, count_all)
|
def deleted?(message_meta, count, count_all)
|
||||||
return false if !message_meta.attr['FLAGS'].include?(:Deleted)
|
return false if !message_meta.attr['FLAGS'].include?(:Deleted)
|
||||||
Rails.logger.info " - ignore message #{count}/#{count_all} - because message has already delete flag"
|
Rails.logger.info " - ignore message #{count}/#{count_all} - because message has already delete flag"
|
||||||
|
|
|
@ -4,16 +4,16 @@ require 'test_helper'
|
||||||
class EmailDeliverTest < ActiveSupport::TestCase
|
class EmailDeliverTest < ActiveSupport::TestCase
|
||||||
test 'basic check' do
|
test 'basic check' do
|
||||||
|
|
||||||
if !ENV['MAIL_SERVER']
|
if ENV['MAIL_SERVER'].blank?
|
||||||
raise "Need MAIL_SERVER as ENV variable like export MAIL_SERVER='mx.example.com'"
|
raise "Need MAIL_SERVER as ENV variable like export MAIL_SERVER='mx.example.com'"
|
||||||
end
|
end
|
||||||
if !ENV['MAIL_SERVER_ACCOUNT']
|
if ENV['MAIL_SERVER_ACCOUNT'].blank?
|
||||||
raise "Need MAIL_SERVER_ACCOUNT as ENV variable like export MAIL_SERVER_ACCOUNT='user:somepass'"
|
raise "Need MAIL_SERVER_ACCOUNT as ENV variable like export MAIL_SERVER_ACCOUNT='user:somepass'"
|
||||||
end
|
end
|
||||||
server_login = ENV['MAIL_SERVER_ACCOUNT'].split(':')[0]
|
server_login = ENV['MAIL_SERVER_ACCOUNT'].split(':')[0]
|
||||||
server_password = ENV['MAIL_SERVER_ACCOUNT'].split(':')[1]
|
server_password = ENV['MAIL_SERVER_ACCOUNT'].split(':')[1]
|
||||||
|
|
||||||
email_address = EmailAddress.create(
|
email_address = EmailAddress.create!(
|
||||||
realname: 'me Helpdesk',
|
realname: 'me Helpdesk',
|
||||||
email: "me#{rand(999_999_999)}@example.com",
|
email: "me#{rand(999_999_999)}@example.com",
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
|
@ -27,7 +27,7 @@ class EmailDeliverTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
channel = Channel.create(
|
channel = Channel.create!(
|
||||||
area: 'Email::Account',
|
area: 'Email::Account',
|
||||||
group_id: group.id,
|
group_id: group.id,
|
||||||
options: {
|
options: {
|
||||||
|
@ -50,9 +50,9 @@ class EmailDeliverTest < ActiveSupport::TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
email_address.channel_id = channel.id
|
email_address.channel_id = channel.id
|
||||||
email_address.save
|
email_address.save!
|
||||||
|
|
||||||
ticket1 = Ticket.create(
|
ticket1 = Ticket.create!(
|
||||||
title: 'some delivery test',
|
title: 'some delivery test',
|
||||||
group: group,
|
group: group,
|
||||||
customer_id: 2,
|
customer_id: 2,
|
||||||
|
@ -63,7 +63,7 @@ class EmailDeliverTest < ActiveSupport::TestCase
|
||||||
)
|
)
|
||||||
assert(ticket1, 'ticket created')
|
assert(ticket1, 'ticket created')
|
||||||
|
|
||||||
article1 = Ticket::Article.create(
|
article1 = Ticket::Article.create!(
|
||||||
ticket_id: ticket1.id,
|
ticket_id: ticket1.id,
|
||||||
to: 'some_recipient@example_not_existing_what_ever.com',
|
to: 'some_recipient@example_not_existing_what_ever.com',
|
||||||
subject: 'some subject',
|
subject: 'some subject',
|
||||||
|
@ -189,7 +189,7 @@ class EmailDeliverTest < ActiveSupport::TestCase
|
||||||
# remove background jobs
|
# remove background jobs
|
||||||
Delayed::Job.destroy_all
|
Delayed::Job.destroy_all
|
||||||
|
|
||||||
article2 = Ticket::Article.create(
|
article2 = Ticket::Article.create!(
|
||||||
ticket_id: ticket1.id,
|
ticket_id: ticket1.id,
|
||||||
to: 'some_recipient@example_not_existing_what_ever.com',
|
to: 'some_recipient@example_not_existing_what_ever.com',
|
||||||
subject: 'some subject2',
|
subject: 'some subject2',
|
||||||
|
|
232
test/integration/email_keep_on_server_test.rb
Normal file
232
test/integration/email_keep_on_server_test.rb
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
require 'test_helper'
|
||||||
|
require 'net/imap'
|
||||||
|
|
||||||
|
class EmailKeepOnServerTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
|
||||||
|
if ENV['KEEP_ON_MAIL_SERVER'].blank?
|
||||||
|
raise "Need KEEP_ON_MAIL_SERVER as ENV variable like export KEEP_ON_MAIL_SERVER='mx.example.com'"
|
||||||
|
end
|
||||||
|
if ENV['KEEP_ON_MAIL_SERVER_ACCOUNT'].blank?
|
||||||
|
raise "Need KEEP_ON_MAIL_SERVER_ACCOUNT as ENV variable like export KEEP_ON_MAIL_SERVER_ACCOUNT='user:somepass'"
|
||||||
|
end
|
||||||
|
@server_login = ENV['KEEP_ON_MAIL_SERVER_ACCOUNT'].split(':')[0]
|
||||||
|
@server_password = ENV['KEEP_ON_MAIL_SERVER_ACCOUNT'].split(':')[1]
|
||||||
|
|
||||||
|
@folder = "keep_on_mail_server_#{rand(999_999_999)}"
|
||||||
|
|
||||||
|
email_address = EmailAddress.create!(
|
||||||
|
realname: 'me Helpdesk',
|
||||||
|
email: "me#{rand(999_999_999)}@example.com",
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
group = Group.create_or_update(
|
||||||
|
name: 'KeepOnServerTest',
|
||||||
|
email_address_id: email_address.id,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
@channel = Channel.create!(
|
||||||
|
area: 'Email::Account',
|
||||||
|
group_id: group.id,
|
||||||
|
options: {
|
||||||
|
inbound: {
|
||||||
|
adapter: 'imap',
|
||||||
|
options: {
|
||||||
|
host: ENV['KEEP_ON_MAIL_SERVER'],
|
||||||
|
user: @server_login,
|
||||||
|
password: @server_password,
|
||||||
|
ssl: true,
|
||||||
|
folder: @folder,
|
||||||
|
#keep_on_server: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
outbound: {
|
||||||
|
adapter: 'sendmail'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
email_address.channel_id = @channel.id
|
||||||
|
email_address.save!
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'keep on server' do
|
||||||
|
@channel.options[:inbound][:options][:keep_on_server] = true
|
||||||
|
@channel.save!
|
||||||
|
|
||||||
|
# clean mailbox
|
||||||
|
imap = Net::IMAP.new(ENV['KEEP_ON_MAIL_SERVER'], 993, true, nil, false)
|
||||||
|
imap.login(@server_login, @server_password)
|
||||||
|
imap.create(@folder)
|
||||||
|
imap.select(@folder)
|
||||||
|
|
||||||
|
# put unseen message in it
|
||||||
|
imap.append(@folder, "Subject: hello1
|
||||||
|
From: shugo@example.com
|
||||||
|
To: shugo@example.com
|
||||||
|
Message-ID: <some1@example_keep_on_server>
|
||||||
|
|
||||||
|
hello world
|
||||||
|
".gsub(/\n/, "\r\n"), [], Time.zone.now)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['FLAGS'])[0].attr
|
||||||
|
assert_not(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count + 1, Ticket::Article.count)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['RFC822.HEADER', 'FLAGS'])[0].attr
|
||||||
|
assert(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count, Ticket::Article.count)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
# put unseen message in it
|
||||||
|
imap.append(@folder, "Subject: hello2
|
||||||
|
From: shugo@example.com
|
||||||
|
To: shugo@example.com
|
||||||
|
Message-ID: <some2@example_keep_on_server>
|
||||||
|
|
||||||
|
hello world
|
||||||
|
".gsub(/\n/, "\r\n"), [], Time.zone.now)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['FLAGS'])[0].attr
|
||||||
|
assert(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
message_meta = imap.fetch(2, ['FLAGS'])[0].attr
|
||||||
|
assert_not(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count + 1, Ticket::Article.count)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(2, message_ids.count)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['FLAGS'])[0].attr
|
||||||
|
assert(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
message_meta = imap.fetch(2, ['FLAGS'])[0].attr
|
||||||
|
assert(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# set messages to not seen
|
||||||
|
imap.store(1, '-FLAGS', [:Seen])
|
||||||
|
imap.store(2, '-FLAGS', [:Seen])
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count, Ticket::Article.count)
|
||||||
|
|
||||||
|
imap.delete(@folder)
|
||||||
|
@channel.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'keep not on server' do
|
||||||
|
@channel.options[:inbound][:options][:keep_on_server] = false
|
||||||
|
@channel.save!
|
||||||
|
|
||||||
|
# clean mailbox
|
||||||
|
imap = Net::IMAP.new(ENV['KEEP_ON_MAIL_SERVER'], 993, true, nil, false)
|
||||||
|
imap.login(@server_login, @server_password)
|
||||||
|
imap.create(@folder)
|
||||||
|
imap.select(@folder)
|
||||||
|
|
||||||
|
# put unseen message in it
|
||||||
|
imap.append(@folder, "Subject: hello1
|
||||||
|
From: shugo@example.com
|
||||||
|
To: shugo@example.com
|
||||||
|
Message-ID: <some1@example_remove_from_server>
|
||||||
|
|
||||||
|
hello world
|
||||||
|
".gsub(/\n/, "\r\n"), [], Time.zone.now)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['FLAGS'])[0].attr
|
||||||
|
assert_not(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count + 1, Ticket::Article.count)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
# put unseen message in it
|
||||||
|
imap.append(@folder, "Subject: hello2
|
||||||
|
From: shugo@example.com
|
||||||
|
To: shugo@example.com
|
||||||
|
Message-ID: <some2@example_remove_from_server>
|
||||||
|
|
||||||
|
hello world
|
||||||
|
".gsub(/\n/, "\r\n"), [], Time.zone.now)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
message_meta = imap.fetch(1, ['FLAGS'])[0].attr
|
||||||
|
assert_not(message_meta['FLAGS'].include?(:Seen))
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count + 1, Ticket::Article.count)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
# put unseen message in it
|
||||||
|
imap.append(@folder, "Subject: hello2
|
||||||
|
From: shugo@example.com
|
||||||
|
To: shugo@example.com
|
||||||
|
Message-ID: <some2@example_remove_from_server>
|
||||||
|
|
||||||
|
hello world
|
||||||
|
".gsub(/\n/, "\r\n"), [], Time.zone.now)
|
||||||
|
|
||||||
|
# verify if message is still on server
|
||||||
|
message_ids = imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
||||||
|
assert_equal(1, message_ids.count)
|
||||||
|
|
||||||
|
# fetch messages
|
||||||
|
article_count = Ticket::Article.count
|
||||||
|
@channel.fetch(true)
|
||||||
|
assert_equal(article_count + 1, Ticket::Article.count)
|
||||||
|
|
||||||
|
imap.delete(@folder)
|
||||||
|
@channel.destroy!
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue