2016-10-19 03:11:36 +00:00
|
|
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
2013-06-12 15:59:58 +00:00
|
|
|
|
2012-04-10 14:06:46 +00:00
|
|
|
require 'net/imap'
|
|
|
|
|
2015-08-28 00:53:14 +00:00
|
|
|
class Channel::Driver::Imap < Channel::EmailParser
|
2012-04-10 14:06:46 +00:00
|
|
|
|
2016-01-10 13:24:54 +00:00
|
|
|
def fetchable?(_channel)
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2015-09-06 07:50:51 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
fetch emails from IMAP account
|
|
|
|
|
|
|
|
instance = Channel::Driver::Imap.new
|
|
|
|
result = instance.fetch(params[:inbound][:options], channel, 'verify', subject_looking_for)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
{
|
|
|
|
result: 'ok',
|
|
|
|
fetched: 123,
|
|
|
|
notice: 'e. g. message about to big emails in mailbox',
|
|
|
|
}
|
|
|
|
|
|
|
|
check if connect to IMAP account is possible, return count of mails in mailbox
|
|
|
|
|
|
|
|
instance = Channel::Driver::Imap.new
|
|
|
|
result = instance.fetch(params[:inbound][:options], channel, 'check')
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
{
|
|
|
|
result: 'ok',
|
|
|
|
content_messages: 123,
|
|
|
|
}
|
|
|
|
|
|
|
|
verify IMAP account, check if search email is in there
|
|
|
|
|
|
|
|
instance = Channel::Driver::Imap.new
|
|
|
|
result = instance.fetch(params[:inbound][:options], channel, 'verify', subject_looking_for)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
{
|
|
|
|
result: 'ok', # 'verify not ok'
|
|
|
|
}
|
|
|
|
|
2016-11-06 15:39:05 +00:00
|
|
|
example
|
|
|
|
|
|
|
|
params = {
|
|
|
|
host: 'outlook.office365.com',
|
|
|
|
user: 'xxx@znuny.onmicrosoft.com',
|
|
|
|
password: 'xxx',
|
|
|
|
}
|
|
|
|
channel = Channel.last
|
|
|
|
instance = Channel::Driver::Imap.new
|
|
|
|
result = instance.fetch(params, channel, 'verify')
|
|
|
|
|
2015-09-06 07:50:51 +00:00
|
|
|
=end
|
|
|
|
|
2015-08-28 00:53:14 +00:00
|
|
|
def fetch (options, channel, check_type = '', verify_string = '')
|
2014-11-18 21:09:01 +00:00
|
|
|
ssl = true
|
|
|
|
port = 993
|
2016-11-06 15:39:05 +00:00
|
|
|
if options.key?(:ssl) && options[:ssl] == false
|
2014-11-18 21:09:01 +00:00
|
|
|
ssl = false
|
|
|
|
port = 143
|
2013-01-03 19:01:26 +00:00
|
|
|
end
|
|
|
|
|
2015-08-28 00:53:14 +00:00
|
|
|
Rails.logger.info "fetching imap (#{options[:host]}/#{options[:user]} port=#{port},ssl=#{ssl})"
|
2012-04-10 14:06:46 +00:00
|
|
|
|
2014-11-18 11:51:35 +00:00
|
|
|
# on check, reduce open_timeout to have faster probing
|
|
|
|
timeout = 12
|
|
|
|
if check_type == 'check'
|
2014-12-11 10:44:23 +00:00
|
|
|
timeout = 6
|
2013-01-03 19:01:26 +00:00
|
|
|
end
|
2014-11-18 11:51:35 +00:00
|
|
|
|
|
|
|
Timeout.timeout(timeout) do
|
2016-03-10 13:41:42 +00:00
|
|
|
@imap = Net::IMAP.new(options[:host], port, ssl, nil, false)
|
2014-11-18 11:51:35 +00:00
|
|
|
end
|
|
|
|
|
2016-11-05 15:28:14 +00:00
|
|
|
@imap.login(options[:user], options[:password])
|
2014-11-18 11:51:35 +00:00
|
|
|
|
2015-09-06 07:50:51 +00:00
|
|
|
# select folder
|
2015-08-28 00:53:14 +00:00
|
|
|
if !options[:folder] || options[:folder].empty?
|
2014-06-22 07:00:09 +00:00
|
|
|
@imap.select('INBOX')
|
2013-01-04 23:14:08 +00:00
|
|
|
else
|
2015-09-06 07:50:51 +00:00
|
|
|
@imap.select(options[:folder])
|
2013-01-04 23:14:08 +00:00
|
|
|
end
|
2015-09-06 07:50:51 +00:00
|
|
|
|
2016-06-02 14:00:45 +00:00
|
|
|
begin
|
|
|
|
message_ids = @imap.sort(['DATE'], ['ALL'], 'US-ASCII')
|
|
|
|
rescue => e
|
|
|
|
Rails.logger.error "Unable to use imap sort: #{e.inspect}, use imap search now"
|
|
|
|
message_ids = @imap.search(['ALL'])
|
|
|
|
end
|
2015-09-06 07:50:51 +00:00
|
|
|
|
|
|
|
# check mode only
|
2014-10-22 21:00:11 +00:00
|
|
|
if check_type == 'check'
|
2015-05-04 19:34:04 +00:00
|
|
|
Rails.logger.info 'check only mode, fetch no emails'
|
2016-03-10 13:41:42 +00:00
|
|
|
content_max_check = 2
|
2015-09-06 07:50:51 +00:00
|
|
|
content_messages = 0
|
|
|
|
|
|
|
|
# check messages
|
|
|
|
message_ids.each do |message_id|
|
|
|
|
|
|
|
|
message_meta = @imap.fetch(message_id, ['RFC822.HEADER'])[0].attr
|
|
|
|
|
|
|
|
# check how many content messages we have, for notice used
|
|
|
|
header = message_meta['RFC822.HEADER']
|
|
|
|
if header && header !~ /x-zammad-ignore/i
|
|
|
|
content_messages += 1
|
|
|
|
break if content_max_check < content_messages
|
|
|
|
end
|
|
|
|
end
|
2015-09-06 11:39:16 +00:00
|
|
|
if content_messages >= content_max_check
|
2015-09-06 07:50:51 +00:00
|
|
|
content_messages = message_ids.count
|
|
|
|
end
|
2014-10-22 21:00:11 +00:00
|
|
|
disconnect
|
2015-09-06 07:50:51 +00:00
|
|
|
return {
|
|
|
|
result: 'ok',
|
|
|
|
content_messages: content_messages,
|
|
|
|
}
|
2014-10-22 21:00:11 +00:00
|
|
|
end
|
2014-11-09 20:10:23 +00:00
|
|
|
|
|
|
|
# reverse message order to increase performance
|
|
|
|
if check_type == 'verify'
|
2015-09-06 07:50:51 +00:00
|
|
|
Rails.logger.info "verify mode, fetch no emails #{verify_string}"
|
2014-11-09 20:10:23 +00:00
|
|
|
message_ids.reverse!
|
2012-04-10 14:06:46 +00:00
|
|
|
|
2014-10-22 21:00:11 +00:00
|
|
|
# check for verify message
|
2015-09-06 07:50:51 +00:00
|
|
|
message_ids.each do |message_id|
|
|
|
|
|
|
|
|
message_meta = @imap.fetch(message_id, ['ENVELOPE'])[0].attr
|
|
|
|
|
|
|
|
# check if verify message exists
|
|
|
|
subject = message_meta['ENVELOPE'].subject
|
2015-09-06 11:39:16 +00:00
|
|
|
next if !subject
|
|
|
|
next if subject !~ /#{verify_string}/
|
|
|
|
Rails.logger.info " - verify email #{verify_string} found"
|
|
|
|
@imap.store(message_id, '+FLAGS', [:Deleted])
|
|
|
|
@imap.expunge()
|
|
|
|
disconnect
|
|
|
|
return {
|
|
|
|
result: 'ok',
|
|
|
|
}
|
2015-09-06 07:50:51 +00:00
|
|
|
end
|
2014-10-22 21:00:11 +00:00
|
|
|
|
2015-09-06 07:50:51 +00:00
|
|
|
disconnect
|
|
|
|
return {
|
|
|
|
result: 'verify not ok',
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
# fetch regular messages
|
|
|
|
count_all = message_ids.count
|
|
|
|
count = 0
|
|
|
|
count_fetched = 0
|
|
|
|
notice = ''
|
|
|
|
message_ids.each do |message_id|
|
|
|
|
count += 1
|
|
|
|
Rails.logger.info " - message #{count}/#{count_all}"
|
|
|
|
#Rails.logger.info msg.to_s
|
|
|
|
|
|
|
|
message_meta = @imap.fetch(message_id, ['RFC822.SIZE', 'FLAGS', 'INTERNALDATE'])[0]
|
|
|
|
|
|
|
|
# ignore to big messages
|
2015-09-06 11:39:16 +00:00
|
|
|
max_message_size = Setting.get('postmaster_max_size').to_f
|
2015-09-06 07:50:51 +00:00
|
|
|
real_message_size = message_meta.attr['RFC822.SIZE'].to_f / 1024 / 1024
|
|
|
|
if real_message_size > max_message_size
|
2016-06-28 20:51:58 +00:00
|
|
|
info = " - ignore message #{count}/#{count_all} - because message is too big (is:#{real_message_size} MB/max:#{max_message_size} MB)"
|
2015-09-06 07:50:51 +00:00
|
|
|
Rails.logger.info info
|
|
|
|
notice += "#{info}\n"
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
# ignore deleted messages
|
|
|
|
if message_meta.attr['FLAGS'].include?(:Deleted)
|
|
|
|
Rails.logger.info " - ignore message #{count}/#{count_all} - because message has already delete flag"
|
|
|
|
next
|
|
|
|
end
|
|
|
|
|
|
|
|
# delete email from server after article was created
|
|
|
|
msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822']
|
2015-09-06 11:39:16 +00:00
|
|
|
next if !msg
|
2016-11-07 22:20:58 +00:00
|
|
|
process(channel, msg, false)
|
|
|
|
@imap.store(message_id, '+FLAGS', [:Deleted])
|
|
|
|
count_fetched += 1
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
2014-06-22 07:00:09 +00:00
|
|
|
@imap.expunge()
|
|
|
|
disconnect
|
2016-01-16 10:05:04 +00:00
|
|
|
if count.zero?
|
2015-05-04 19:34:04 +00:00
|
|
|
Rails.logger.info ' - no message'
|
2012-04-13 17:06:09 +00:00
|
|
|
end
|
2015-05-04 19:34:04 +00:00
|
|
|
Rails.logger.info 'done'
|
2015-09-06 07:50:51 +00:00
|
|
|
{
|
|
|
|
result: 'ok',
|
|
|
|
fetched: count_fetched,
|
|
|
|
notice: notice,
|
|
|
|
}
|
2012-04-10 14:06:46 +00:00
|
|
|
end
|
2014-06-22 07:00:09 +00:00
|
|
|
|
|
|
|
def disconnect
|
2015-04-30 15:25:04 +00:00
|
|
|
return if !@imap
|
|
|
|
@imap.disconnect()
|
2014-06-22 07:00:09 +00:00
|
|
|
end
|
2015-04-27 14:15:29 +00:00
|
|
|
end
|