mirror of
https://github.com/discourse/discourse.git
synced 2025-05-31 16:38:48 +08:00
FIX: IMAP sync email update uniqueness across groups and minor improvements (#10332)
Adds a imap_group_id column to IncomingEmail to deal with an issue where we were trying to update emails in the mailbox, calling IncomingEmail.where(imap_sync: true). However UID and UIDVALIDITY could be the same across accounts. So if group A used IMAP details for Gmail account A, and group B used IMAP details for Gmail account B, and both tried to sync changes to an email with UID of 3 (e.g. changing Labels), one account could affect the other. This even applied to Archiving! Also in this PR: * Fix error occurring if we do a uid_fetch and no emails are returned * Allow for creating labels within the target mailbox (previously we would not do this, only use existing labels) * Improve consistency for log messages * Add specs for generic IMAP provider (Gmail specs still to come) * Add custom archiving support for Gmail * Only use Message-ID for uniqueness of IncomingEmail if it was generated by us * Various refactors and improvements
This commit is contained in:
@ -4,6 +4,9 @@ require 'net/imap'
|
||||
|
||||
module Imap
|
||||
module Providers
|
||||
|
||||
class WriteDisabledError < StandardError; end
|
||||
|
||||
class Generic
|
||||
|
||||
def initialize(server, options = {})
|
||||
@ -65,19 +68,31 @@ module Imap
|
||||
|
||||
def open_mailbox(mailbox_name, write: false)
|
||||
if write
|
||||
raise 'two-way IMAP sync is disabled' if !SiteSetting.enable_imap_write
|
||||
if !SiteSetting.enable_imap_write
|
||||
raise WriteDisabledError.new("Two-way IMAP sync is disabled! Cannot write to inbox.")
|
||||
end
|
||||
imap.select(mailbox_name)
|
||||
else
|
||||
imap.examine(mailbox_name)
|
||||
end
|
||||
|
||||
@open_mailbox_name = mailbox_name
|
||||
@open_mailbox_write = write
|
||||
|
||||
{
|
||||
uid_validity: imap.responses['UIDVALIDITY'][-1]
|
||||
}
|
||||
end
|
||||
|
||||
def emails(uids, fields, opts = {})
|
||||
imap.uid_fetch(uids, fields).map do |email|
|
||||
fetched = imap.uid_fetch(uids, fields)
|
||||
|
||||
# This will happen if the email does not exist in the provided mailbox.
|
||||
# It may have been deleted or otherwise moved, e.g. if deleted in Gmail
|
||||
# it will end up in "[Gmail]/Bin"
|
||||
return [] if fetched.nil?
|
||||
|
||||
fetched.map do |email|
|
||||
attributes = {}
|
||||
|
||||
fields.each do |field|
|
||||
@ -105,12 +120,16 @@ module Imap
|
||||
end
|
||||
|
||||
def tag_to_label(tag)
|
||||
labels[tag]
|
||||
tag
|
||||
end
|
||||
|
||||
def list_mailboxes
|
||||
imap.list('', '*').map(&:name)
|
||||
end
|
||||
|
||||
def archive(uid)
|
||||
# do nothing by default, just removing the Inbox label should be enough
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user