DEV: IMAP log to database (#10435)
Convert all IMAP logging to write to a database table for easier inspection. These logs are cleaned up daily if they are > 5 days old. Logs can easily be watched in dev by setting DISCOURSE_DEV_LOG_LEVEL=\"debug\" and running tail -f development.log | grep IMAP
This commit is contained in:
parent
eae8b0465c
commit
4670b62969
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jobs
|
||||||
|
class CleanupImapSyncLog < ::Jobs::Scheduled
|
||||||
|
every 1.day
|
||||||
|
|
||||||
|
def execute(args)
|
||||||
|
ImapSyncLog.where("created_at < ?", ImapSyncLog::RETAIN_LOGS_DAYS.days.ago).delete_all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -111,6 +111,8 @@ class Group < ActiveRecord::Base
|
||||||
validates :mentionable_level, inclusion: { in: ALIAS_LEVELS.values }
|
validates :mentionable_level, inclusion: { in: ALIAS_LEVELS.values }
|
||||||
validates :messageable_level, inclusion: { in: ALIAS_LEVELS.values }
|
validates :messageable_level, inclusion: { in: ALIAS_LEVELS.values }
|
||||||
|
|
||||||
|
scope :with_imap_configured, -> { where.not(imap_mailbox_name: '') }
|
||||||
|
|
||||||
scope :visible_groups, Proc.new { |user, order, opts|
|
scope :visible_groups, Proc.new { |user, order, opts|
|
||||||
groups = self.order(order || "name ASC")
|
groups = self.order(order || "name ASC")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ImapSyncLog < ActiveRecord::Base
|
||||||
|
RETAIN_LOGS_DAYS = 5
|
||||||
|
|
||||||
|
belongs_to :group
|
||||||
|
|
||||||
|
def self.levels
|
||||||
|
@levels ||= Enum.new(
|
||||||
|
debug: 1,
|
||||||
|
info: 2,
|
||||||
|
warn: 3,
|
||||||
|
error: 4
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.log(message, level, group_id = nil)
|
||||||
|
now = Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")
|
||||||
|
new_log = create(message: message, level: ImapSyncLog.levels[level], group_id: group_id)
|
||||||
|
Rails.logger.send(level, "#{level[0].upcase}, [#{now}] [IMAP] (group_id #{group_id}) #{message}")
|
||||||
|
new_log
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.debug(message, group_or_id)
|
||||||
|
group_id = group_or_id.is_a?(Integer) ? group_or_id : group_or_id.id
|
||||||
|
log(message, :debug, group_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.info(message, group_or_id)
|
||||||
|
group_id = group_or_id.is_a?(Integer) ? group_or_id : group_or_id.id
|
||||||
|
log(message, :info, group_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.warn(message, group_or_id)
|
||||||
|
group_id = group_or_id.is_a?(Integer) ? group_or_id : group_or_id.id
|
||||||
|
log(message, :warn, group_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.error(message, group_or_id)
|
||||||
|
group_id = group_or_id.is_a?(Integer) ? group_or_id : group_or_id.id
|
||||||
|
log(message, :error, group_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: imap_sync_logs
|
||||||
|
#
|
||||||
|
# id :bigint not null, primary key
|
||||||
|
# level :integer
|
||||||
|
# message :string
|
||||||
|
# group_id :bigint
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_imap_sync_logs_on_group_id (group_id)
|
||||||
|
# index_imap_sync_logs_on_level (level)
|
||||||
|
#
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CreateImapSyncLog < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
create_table :imap_sync_logs do |t|
|
||||||
|
t.integer :level
|
||||||
|
t.string :message
|
||||||
|
t.bigint :group_id, null: true
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :imap_sync_logs, :group_id
|
||||||
|
add_index :imap_sync_logs, :level
|
||||||
|
end
|
||||||
|
end
|
|
@ -23,28 +23,28 @@ class Demon::EmailSync < ::Demon::Base
|
||||||
def start_thread(db, group)
|
def start_thread(db, group)
|
||||||
Thread.new do
|
Thread.new do
|
||||||
RailsMultisite::ConnectionManagement.with_connection(db) do
|
RailsMultisite::ConnectionManagement.with_connection(db) do
|
||||||
puts "[EmailSync] Thread started for group #{group.name} (id = #{group.id}) in db #{db}"
|
ImapSyncLog.debug("Thread started for group #{group.name} in db #{db}", group)
|
||||||
begin
|
begin
|
||||||
obj = Imap::Sync.new(group)
|
syncer = Imap::Sync.new(group)
|
||||||
rescue Net::IMAP::NoResponseError => e
|
rescue Net::IMAP::NoResponseError => e
|
||||||
group.update(imap_last_error: e.message)
|
group.update(imap_last_error: e.message)
|
||||||
Thread.exit
|
Thread.exit
|
||||||
end
|
end
|
||||||
|
|
||||||
@sync_lock.synchronize { @sync_data[db][group.id][:obj] = obj }
|
@sync_lock.synchronize { @sync_data[db][group.id][:syncer] = syncer }
|
||||||
|
|
||||||
status = nil
|
status = nil
|
||||||
idle = false
|
idle = false
|
||||||
|
|
||||||
while @running && group.reload.imap_mailbox_name.present? do
|
while @running && group.reload.imap_mailbox_name.present? do
|
||||||
puts "[EmailSync] Processing IMAP mailbox for group #{group.name} (id = #{group.id}) in db #{db}"
|
ImapSyncLog.debug("Processing mailbox for group #{group.name} in db #{db}", group)
|
||||||
status = obj.process(
|
status = syncer.process(
|
||||||
idle: obj.can_idle? && status && status[:remaining] == 0,
|
idle: syncer.can_idle? && status && status[:remaining] == 0,
|
||||||
old_emails_limit: status && status[:remaining] > 0 ? 0 : nil,
|
old_emails_limit: status && status[:remaining] > 0 ? 0 : nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
if !obj.can_idle? && status[:remaining] == 0
|
if !syncer.can_idle? && status[:remaining] == 0
|
||||||
puts "[EmailSync] Going to sleep for group #{group.name} (id = #{group.id}) in db #{db} to wait for new emails."
|
ImapSyncLog.debug("Going to sleep for group #{group.name} in db #{db} to wait for new emails", group)
|
||||||
|
|
||||||
# Thread goes into sleep for a bit so it is better to return any
|
# Thread goes into sleep for a bit so it is better to return any
|
||||||
# connection back to the pool.
|
# connection back to the pool.
|
||||||
|
@ -54,7 +54,7 @@ class Demon::EmailSync < ::Demon::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
obj.disconnect!
|
syncer.disconnect!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -70,7 +70,7 @@ class Demon::EmailSync < ::Demon::Base
|
||||||
sync_data.each do |_, data|
|
sync_data.each do |_, data|
|
||||||
data[:thread].kill
|
data[:thread].kill
|
||||||
data[:thread].join
|
data[:thread].join
|
||||||
data[:obj]&.disconnect! rescue nil
|
data[:syncer]&.disconnect! rescue nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -106,44 +106,46 @@ class Demon::EmailSync < ::Demon::Base
|
||||||
sync_data.each do |_, data|
|
sync_data.each do |_, data|
|
||||||
data[:thread].kill
|
data[:thread].kill
|
||||||
data[:thread].join
|
data[:thread].join
|
||||||
data[:obj]&.disconnect!
|
data[:syncer]&.disconnect!
|
||||||
end
|
end
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
RailsMultisite::ConnectionManagement.each_connection do |db|
|
RailsMultisite::ConnectionManagement.each_connection do |db|
|
||||||
if SiteSetting.enable_imap
|
next if !SiteSetting.enable_imap
|
||||||
groups = Group.where.not(imap_mailbox_name: '').map { |group| [group.id, group] }.to_h
|
|
||||||
|
|
||||||
@sync_lock.synchronize do
|
groups = Group.with_imap_configured.map { |group| [group.id, group] }.to_h
|
||||||
@sync_data[db] ||= {}
|
|
||||||
|
|
||||||
# Kill threads for group's mailbox that are no longer synchronized.
|
@sync_lock.synchronize do
|
||||||
@sync_data[db].filter! do |group_id, data|
|
@sync_data[db] ||= {}
|
||||||
next true if groups[group_id] && data[:thread]&.alive? && !data[:obj]&.disconnected?
|
|
||||||
|
|
||||||
if !groups[group_id]
|
# Kill threads for group's mailbox that are no longer synchronized.
|
||||||
puts("[EmailSync] Killing thread for group (id = #{group_id}) because mailbox is no longer synced")
|
@sync_data[db].filter! do |group_id, data|
|
||||||
else
|
next true if groups[group_id] && data[:thread]&.alive? && !data[:syncer]&.disconnected?
|
||||||
puts("[EmailSync] Thread for group #{groups[group_id].name} (id = #{group_id}) is dead")
|
|
||||||
end
|
|
||||||
|
|
||||||
data[:thread].kill
|
if !groups[group_id]
|
||||||
data[:thread].join
|
ImapSyncLog.warn("Killing thread for group because mailbox is no longer synced", group_id)
|
||||||
data[:obj]&.disconnect!
|
else
|
||||||
|
ImapSyncLog.warn("Thread for group is dead", group_id)
|
||||||
false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Spawn new threads for groups that are now synchronized.
|
data[:thread].kill
|
||||||
groups.each do |group_id, group|
|
data[:thread].join
|
||||||
if !@sync_data[db][group_id]
|
data[:syncer]&.disconnect!
|
||||||
puts("[EmailSync] Starting thread for group #{group.name} (id = #{group.id}) and mailbox #{group.imap_mailbox_name}")
|
|
||||||
@sync_data[db][group_id] = {
|
false
|
||||||
thread: start_thread(db, group), obj: nil
|
end
|
||||||
}
|
|
||||||
end
|
# Spawn new threads for groups that are now synchronized.
|
||||||
|
groups.each do |group_id, group|
|
||||||
|
if !@sync_data[db][group_id]
|
||||||
|
ImapSyncLog.debug("Starting thread for group #{group.name} mailbox #{group.imap_mailbox_name}", group)
|
||||||
|
|
||||||
|
@sync_data[db][group_id] = {
|
||||||
|
thread: start_thread(db, group),
|
||||||
|
syncer: nil
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,7 +77,7 @@ module Imap
|
||||||
new_labels = labels.reject { |l| l == "\\Inbox" }
|
new_labels = labels.reject { |l| l == "\\Inbox" }
|
||||||
store(email["UID"], "LABELS", labels, new_labels)
|
store(email["UID"], "LABELS", labels, new_labels)
|
||||||
end
|
end
|
||||||
Imap::Sync::Logger.log("[IMAP] Thread ID #{thread_id} (UID #{uid}) archived in Gmail mailbox for #{@username}")
|
ImapSyncLog.log("Thread ID #{thread_id} (UID #{uid}) archived in Gmail mailbox for #{@username}", :debug)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Though Gmail considers the email thread unarchived if the first email
|
# Though Gmail considers the email thread unarchived if the first email
|
||||||
|
@ -94,7 +94,7 @@ module Imap
|
||||||
end
|
end
|
||||||
store(email["UID"], "LABELS", labels, new_labels)
|
store(email["UID"], "LABELS", labels, new_labels)
|
||||||
end
|
end
|
||||||
Imap::Sync::Logger.log("[IMAP] Thread ID #{thread_id} (UID #{uid}) unarchived in Gmail mailbox for #{@username}")
|
ImapSyncLog.log("Thread ID #{thread_id} (UID #{uid}) unarchived in Gmail mailbox for #{@username}", :debug)
|
||||||
end
|
end
|
||||||
|
|
||||||
def thread_id_from_uid(uid)
|
def thread_id_from_uid(uid)
|
||||||
|
@ -116,7 +116,7 @@ module Imap
|
||||||
email_uids_to_trash = emails_in_thread(thread_id).map { |e| e['UID'] }
|
email_uids_to_trash = emails_in_thread(thread_id).map { |e| e['UID'] }
|
||||||
|
|
||||||
imap.uid_move(email_uids_to_trash, trash_mailbox)
|
imap.uid_move(email_uids_to_trash, trash_mailbox)
|
||||||
Imap::Sync::Logger.log("[IMAP] Thread ID #{thread_id} (UID #{uid}) trashed in Gmail mailbox for #{@username}")
|
ImapSyncLog.log("Thread ID #{thread_id} (UID #{uid}) trashed in Gmail mailbox for #{@username}", :debug)
|
||||||
{ trash_uid_validity: open_trash_mailbox, email_uids_to_trash: email_uids_to_trash }
|
{ trash_uid_validity: open_trash_mailbox, email_uids_to_trash: email_uids_to_trash }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,6 @@ require 'net/imap'
|
||||||
|
|
||||||
module Imap
|
module Imap
|
||||||
class Sync
|
class Sync
|
||||||
class Logger
|
|
||||||
def self.log(msg, level = :debug)
|
|
||||||
if ENV['DISCOURSE_EMAIL_SYNC_LOG_OVERRIDE'] == 'warn'
|
|
||||||
Rails.logger.warn(msg)
|
|
||||||
else
|
|
||||||
Rails.logger.send(level, msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(group, opts = {})
|
def initialize(group, opts = {})
|
||||||
@group = group
|
@group = group
|
||||||
@provider = Imap::Providers::Detector.init_with_detected_provider(@group.imap_config)
|
@provider = Imap::Providers::Detector.init_with_detected_provider(@group.imap_config)
|
||||||
|
@ -53,12 +43,12 @@ module Imap
|
||||||
# If UID validity changes, the whole mailbox must be synchronized (all
|
# If UID validity changes, the whole mailbox must be synchronized (all
|
||||||
# emails are considered new and will be associated to existent topics
|
# emails are considered new and will be associated to existent topics
|
||||||
# in Email::Reciever by matching Message-Ids).
|
# in Email::Reciever by matching Message-Ids).
|
||||||
Logger.log("[IMAP] (#{@group.name}) UIDVALIDITY = #{@status[:uid_validity]} does not match expected #{@group.imap_uid_validity}, invalidating IMAP cache and resyncing emails for group #{@group.name} and mailbox #{@group.imap_mailbox_name}", :warn)
|
ImapSyncLog.warn("UIDVALIDITY = #{@status[:uid_validity]} does not match expected #{@group.imap_uid_validity}, invalidating IMAP cache and resyncing emails for mailbox #{@group.imap_mailbox_name}", @group)
|
||||||
@group.imap_last_uid = 0
|
@group.imap_last_uid = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if idle && !can_idle?
|
if idle && !can_idle?
|
||||||
Logger.log("[IMAP] (#{@group.name}) IMAP server for group cannot IDLE", :warn)
|
ImapSyncLog.warn("IMAP server for group cannot IDLE or imap idle site setting is disabled", @group)
|
||||||
idle = false
|
idle = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -70,7 +60,7 @@ module Imap
|
||||||
ActiveRecord::Base.connection_handler.clear_active_connections!
|
ActiveRecord::Base.connection_handler.clear_active_connections!
|
||||||
|
|
||||||
idle_polling_mins = SiteSetting.imap_polling_period_mins.minutes.to_i
|
idle_polling_mins = SiteSetting.imap_polling_period_mins.minutes.to_i
|
||||||
Logger.log("[IMAP] (#{@group.name}) Going IDLE for #{idle_polling_mins} seconds to wait for more work")
|
ImapSyncLog.debug("Going IDLE for #{idle_polling_mins} seconds to wait for more work", @group)
|
||||||
|
|
||||||
@provider.imap.idle(idle_polling_mins) do |resp|
|
@provider.imap.idle(idle_polling_mins) do |resp|
|
||||||
if resp.kind_of?(Net::IMAP::UntaggedResponse) && resp.name == 'EXISTS'
|
if resp.kind_of?(Net::IMAP::UntaggedResponse) && resp.name == 'EXISTS'
|
||||||
|
@ -92,7 +82,7 @@ module Imap
|
||||||
# Sometimes, new_uids contains elements from old_uids.
|
# Sometimes, new_uids contains elements from old_uids.
|
||||||
new_uids = new_uids - old_uids
|
new_uids = new_uids - old_uids
|
||||||
|
|
||||||
Logger.log("[IMAP] (#{@group.name}) Remote email server has #{old_uids.size} old emails and #{new_uids.size} new emails")
|
ImapSyncLog.debug("Remote email server has #{old_uids.size} old emails and #{new_uids.size} new emails", @group)
|
||||||
|
|
||||||
all_old_uids_size = old_uids.size
|
all_old_uids_size = old_uids.size
|
||||||
all_new_uids_size = new_uids.size
|
all_new_uids_size = new_uids.size
|
||||||
|
@ -134,7 +124,7 @@ module Imap
|
||||||
private
|
private
|
||||||
|
|
||||||
def process_old_uids(old_uids)
|
def process_old_uids(old_uids)
|
||||||
Logger.log("[IMAP] (#{@group.name}) Syncing #{old_uids.size} randomly-selected old emails")
|
ImapSyncLog.debug("Syncing #{old_uids.size} randomly-selected old emails", @group)
|
||||||
emails = old_uids.empty? ? [] : @provider.emails(old_uids, ['UID', 'FLAGS', 'LABELS', 'ENVELOPE'])
|
emails = old_uids.empty? ? [] : @provider.emails(old_uids, ['UID', 'FLAGS', 'LABELS', 'ENVELOPE'])
|
||||||
emails.each do |email|
|
emails.each do |email|
|
||||||
incoming_email = IncomingEmail.find_by(
|
incoming_email = IncomingEmail.find_by(
|
||||||
|
@ -161,7 +151,7 @@ module Imap
|
||||||
)
|
)
|
||||||
update_topic(email, incoming_email, mailbox_name: @group.imap_mailbox_name)
|
update_topic(email, incoming_email, mailbox_name: @group.imap_mailbox_name)
|
||||||
else
|
else
|
||||||
Logger.log("[IMAP] (#{@group.name}) Could not find old email (UIDVALIDITY = #{@status[:uid_validity]}, UID = #{email['UID']})", :warn)
|
ImapSyncLog.warn("Could not find old email (UIDVALIDITY = #{@status[:uid_validity]}, UID = #{email['UID']})", @group)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -204,18 +194,18 @@ module Imap
|
||||||
# not exist, and this sync is just updating the old UIDs to the new ones
|
# not exist, and this sync is just updating the old UIDs to the new ones
|
||||||
# in the trash, and we don't need to re-destroy the post
|
# in the trash, and we don't need to re-destroy the post
|
||||||
if incoming.post
|
if incoming.post
|
||||||
Logger.log("[IMAP] (#{@group.name}) Deleting post ID #{incoming.post_id}; it has been deleted on the IMAP server.")
|
ImapSyncLog.debug("Deleting post ID #{incoming.post_id}, topic id #{incoming.topic_id}; email has been deleted on the IMAP server.", @group)
|
||||||
PostDestroyer.new(Discourse.system_user, incoming.post).destroy
|
PostDestroyer.new(Discourse.system_user, incoming.post).destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
# the email has moved mailboxes, we don't want to try trashing again next time
|
# the email has moved mailboxes, we don't want to try trashing again next time
|
||||||
Logger.log("[IMAP] (#{@group.name}) Updating incoming ID #{incoming.id} uid data FROM [UID #{incoming.imap_uid} | UIDVALIDITY #{incoming.imap_uid_validity}] TO [UID #{matching_trashed.uid} | UIDVALIDITY #{response.trash_uid_validity}] (TRASHED)")
|
ImapSyncLog.debug("Updating incoming ID #{incoming.id} uid data FROM [UID #{incoming.imap_uid} | UIDVALIDITY #{incoming.imap_uid_validity}] TO [UID #{matching_trashed.uid} | UIDVALIDITY #{response.trash_uid_validity}] (TRASHED)", @group)
|
||||||
incoming.update(imap_uid_validity: response.trash_uid_validity, imap_uid: matching_trashed.uid)
|
incoming.update(imap_uid_validity: response.trash_uid_validity, imap_uid: matching_trashed.uid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_new_uids(new_uids, import_mode, all_old_uids_size, all_new_uids_size)
|
def process_new_uids(new_uids, import_mode, all_old_uids_size, all_new_uids_size)
|
||||||
Logger.log("[IMAP] (#{@group.name}) Syncing #{new_uids.size} new emails (oldest first)")
|
ImapSyncLog.debug("Syncing #{new_uids.size} new emails (oldest first)", @group)
|
||||||
|
|
||||||
emails = @provider.emails(new_uids, ['UID', 'FLAGS', 'LABELS', 'RFC822'])
|
emails = @provider.emails(new_uids, ['UID', 'FLAGS', 'LABELS', 'RFC822'])
|
||||||
processed = 0
|
processed = 0
|
||||||
|
@ -242,7 +232,7 @@ module Imap
|
||||||
|
|
||||||
update_topic(email, receiver.incoming_email, mailbox_name: @group.imap_mailbox_name)
|
update_topic(email, receiver.incoming_email, mailbox_name: @group.imap_mailbox_name)
|
||||||
rescue Email::Receiver::ProcessingError => e
|
rescue Email::Receiver::ProcessingError => e
|
||||||
Logger.log("[IMAP] (#{@group.name}) Could not process (UIDVALIDITY = #{@status[:uid_validity]}, UID = #{email['UID']}): #{e.message}", :warn)
|
ImapSyncLog.warn("Could not process (UIDVALIDITY = #{@status[:uid_validity]}, UID = #{email['UID']}): #{e.message}", @group)
|
||||||
end
|
end
|
||||||
|
|
||||||
processed += 1
|
processed += 1
|
||||||
|
@ -262,7 +252,7 @@ module Imap
|
||||||
if to_sync.size > 0
|
if to_sync.size > 0
|
||||||
@provider.open_mailbox(@group.imap_mailbox_name, write: true)
|
@provider.open_mailbox(@group.imap_mailbox_name, write: true)
|
||||||
to_sync.each do |incoming_email|
|
to_sync.each do |incoming_email|
|
||||||
Logger.log("[IMAP] (#{@group.name}) Updating email and incoming email ID = #{incoming_email.id}")
|
ImapSyncLog.debug("Updating email on IMAP server for incoming email ID = #{incoming_email.id}, UID = #{incoming_email.imap_uid}", @group)
|
||||||
update_email(incoming_email)
|
update_email(incoming_email)
|
||||||
incoming_email.update(imap_sync: false)
|
incoming_email.update(imap_sync: false)
|
||||||
end
|
end
|
||||||
|
@ -276,8 +266,10 @@ module Imap
|
||||||
email_is_archived = !email['LABELS'].include?('\\Inbox') && !email['LABELS'].include?('INBOX')
|
email_is_archived = !email['LABELS'].include?('\\Inbox') && !email['LABELS'].include?('INBOX')
|
||||||
|
|
||||||
if topic_is_archived && !email_is_archived
|
if topic_is_archived && !email_is_archived
|
||||||
|
ImapSyncLog.debug("Unarchiving topic ID #{topic.id}, email was unarchived", @group)
|
||||||
GroupArchivedMessage.move_to_inbox!(@group.id, topic, skip_imap_sync: true)
|
GroupArchivedMessage.move_to_inbox!(@group.id, topic, skip_imap_sync: true)
|
||||||
elsif !topic_is_archived && email_is_archived
|
elsif !topic_is_archived && email_is_archived
|
||||||
|
ImapSyncLog.debug("Archiving topic ID #{topic.id}, email was archived", @group)
|
||||||
GroupArchivedMessage.archive!(@group.id, topic, skip_imap_sync: true)
|
GroupArchivedMessage.archive!(@group.id, topic, skip_imap_sync: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -346,6 +338,7 @@ module Imap
|
||||||
if !topic
|
if !topic
|
||||||
# no need to do anything further here, we will recognize the UIDs in the
|
# no need to do anything further here, we will recognize the UIDs in the
|
||||||
# mail server email thread have been trashed on next sync
|
# mail server email thread have been trashed on next sync
|
||||||
|
ImapSyncLog.debug("Trashing UID #{incoming_email.imap_uid} (incoming ID #{incoming_email.id})", @group)
|
||||||
return @provider.trash(incoming_email.imap_uid)
|
return @provider.trash(incoming_email.imap_uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -358,12 +351,12 @@ module Imap
|
||||||
# at the same time.
|
# at the same time.
|
||||||
new_labels << "\\Inbox"
|
new_labels << "\\Inbox"
|
||||||
|
|
||||||
Logger.log("[IMAP] (#{@group.name}) Unarchiving UID #{incoming_email.imap_uid}")
|
ImapSyncLog.debug("Unarchiving UID #{incoming_email.imap_uid} (incoming ID #{incoming_email.id})", @group)
|
||||||
|
|
||||||
# some providers need special handling for unarchiving too
|
# some providers need special handling for unarchiving too
|
||||||
@provider.unarchive(incoming_email.imap_uid)
|
@provider.unarchive(incoming_email.imap_uid)
|
||||||
else
|
else
|
||||||
Logger.log("[IMAP] (#{@group.name}) Archiving UID #{incoming_email.imap_uid}")
|
ImapSyncLog.debug("Archiving UID #{incoming_email.imap_uid} (incoming ID #{incoming_email.id})", @group)
|
||||||
|
|
||||||
# some providers need special handling for archiving. this way we preserve
|
# some providers need special handling for archiving. this way we preserve
|
||||||
# any new tag-labels, and archive, even though it may cause extra requests
|
# any new tag-labels, and archive, even though it may cause extra requests
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe Jobs::CleanupImapSyncLog do
|
||||||
|
let(:job_class) { Jobs::CleanupImapSyncLog.new }
|
||||||
|
|
||||||
|
it "deletes logs older than RETAIN_LOGS_DAYS" do
|
||||||
|
log1 = ImapSyncLog.log("Test log 1", :debug)
|
||||||
|
log2 = ImapSyncLog.log("Test log 2", :debug)
|
||||||
|
log3 = ImapSyncLog.log("Test log 3", :debug)
|
||||||
|
|
||||||
|
log2.update(created_at: Time.now - 6.days)
|
||||||
|
log3.update(created_at: Time.now - 7.days)
|
||||||
|
|
||||||
|
job_class.execute({})
|
||||||
|
|
||||||
|
expect(ImapSyncLog.count).to eq(1)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue