Fixed issue #2321 - IMAP fetch stops because of request timeout

This commit is contained in:
Thorsten Eckel 2018-11-06 09:43:14 +01:00
parent 13b3b841d5
commit ea318fb695

View file

@ -94,32 +94,40 @@ example
Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},starttls=#{starttls},folder=#{folder},keep_on_server=#{keep_on_server})" Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl},starttls=#{starttls},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
if check_type == 'check' if check_type == 'check'
timeout = 6 @timeout = 6
end end
Timeout.timeout(timeout) do timeout do
@imap = ::Net::IMAP.new(options[:host], port, ssl, nil, false) @imap = ::Net::IMAP.new(options[:host], port, ssl, nil, false)
if starttls if starttls
@imap.starttls() @imap.starttls()
end end
end end
@imap.login(options[:user], options[:password]) timeout do
@imap.login(options[:user], options[:password])
end
# select folder timeout do
@imap.select(folder) # select folder
@imap.select(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'] filter = ['ALL']
if keep_on_server && check_type != 'check' && check_type != 'verify' if keep_on_server && check_type != 'check' && check_type != 'verify'
filter = %w[NOT SEEN] filter = %w[NOT SEEN]
end end
begin
message_ids = @imap.sort(['DATE'], filter, 'US-ASCII') message_ids = nil
rescue timeout do
message_ids = @imap.search(filter) begin
message_ids = @imap.sort(['DATE'], filter, 'US-ASCII')
rescue
message_ids = @imap.search(filter)
end
end end
# check mode only # check mode only
@ -131,7 +139,10 @@ example
# check messages # check messages
message_ids.each do |message_id| message_ids.each do |message_id|
message_meta = @imap.fetch(message_id, ['RFC822.HEADER'])[0].attr message_meta = nil
timeout do
message_meta = @imap.fetch(message_id, ['RFC822.HEADER'])[0].attr
end
# check how many content messages we have, for notice used # check how many content messages we have, for notice used
header = message_meta['RFC822.HEADER'] header = message_meta['RFC822.HEADER']
@ -158,7 +169,10 @@ example
# check for verify message # check for verify message
message_ids.each do |message_id| message_ids.each do |message_id|
message_meta = @imap.fetch(message_id, ['ENVELOPE'])[0].attr message_meta = nil
timeout do
message_meta = @imap.fetch(message_id, ['ENVELOPE'])[0].attr
end
# check if verify message exists # check if verify message exists
subject = message_meta['ENVELOPE'].subject subject = message_meta['ENVELOPE'].subject
@ -166,8 +180,10 @@ example
next if subject !~ /#{verify_string}/ next if subject !~ /#{verify_string}/
Rails.logger.info " - verify email #{verify_string} found" Rails.logger.info " - verify email #{verify_string} found"
@imap.store(message_id, '+FLAGS', [:Deleted]) timeout do
@imap.expunge() @imap.store(message_id, '+FLAGS', [:Deleted])
@imap.expunge()
end
disconnect disconnect
return { return {
result: 'ok', result: 'ok',
@ -189,7 +205,10 @@ example
count += 1 count += 1
Rails.logger.info " - message #{count}/#{count_all}" Rails.logger.info " - message #{count}/#{count_all}"
message_meta = @imap.fetch(message_id, ['RFC822.SIZE', 'ENVELOPE', 'FLAGS', 'INTERNALDATE'])[0] message_meta = nil
timeout do
message_meta = @imap.fetch(message_id, ['RFC822.SIZE', 'ENVELOPE', 'FLAGS', 'INTERNALDATE'])[0]
end
# ignore to big messages # ignore to big messages
info = too_big?(message_meta, count, count_all) info = too_big?(message_meta, count, count_all)
@ -205,19 +224,28 @@ example
next if already_imported?(message_id, message_meta, count, count_all, keep_on_server, channel) next if already_imported?(message_id, message_meta, count, count_all, keep_on_server, channel)
# 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 = nil
timeout do
msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822']
end
next if !msg next if !msg
process(channel, msg, false) process(channel, msg, false)
if !keep_on_server
@imap.store(message_id, '+FLAGS', [:Deleted]) timeout do
else if !keep_on_server
@imap.store(message_id, '+FLAGS', [:Seen]) @imap.store(message_id, '+FLAGS', [:Deleted])
else
@imap.store(message_id, '+FLAGS', [:Seen])
end
end end
count_fetched += 1 count_fetched += 1
end end
if !keep_on_server if !keep_on_server
@imap.expunge() timeout do
@imap.expunge()
end
end end
disconnect disconnect
if count.zero? if count.zero?
@ -234,7 +262,9 @@ example
def disconnect def disconnect
return if !@imap return if !@imap
@imap.disconnect() timeout do
@imap.disconnect()
end
end end
=begin =begin
@ -273,7 +303,9 @@ returns
return false if ticket.preferences[:channel_id] != channel[:id] return false if ticket.preferences[:channel_id] != channel[:id]
end end
@imap.store(message_id, '+FLAGS', [:Seen]) timeout do
@imap.store(message_id, '+FLAGS', [:Seen])
end
Rails.logger.info " - ignore message #{count}/#{count_all} - because message message id already imported" Rails.logger.info " - ignore message #{count}/#{count_all} - because message message id already imported"
true true
end end
@ -296,4 +328,10 @@ returns
false false
end end
def timeout
Timeout.timeout(@timeout) do
yield
end
end
end end