discourse/app/models/incoming_email.rb
Martin Brennan 2920988b3a
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
2020-08-03 13:10:17 +10:00

68 lines
2.1 KiB
Ruby

# frozen_string_literal: true
class IncomingEmail < ActiveRecord::Base
belongs_to :user
belongs_to :topic
belongs_to :post
belongs_to :group, foreign_key: :imap_group_id, class_name: 'Group'
scope :errored, -> { where("NOT is_bounce AND error IS NOT NULL") }
scope :addressed_to, -> (email) do
where(<<~SQL, email: "%#{email}%")
incoming_emails.from_address = :email OR
incoming_emails.to_addresses ILIKE :email OR
incoming_emails.cc_addresses ILIKE :email
SQL
end
scope :addressed_to_user, ->(user) do
where(<<~SQL, user_id: user.id)
EXISTS(
SELECT 1
FROM user_emails
WHERE user_emails.user_id = :user_id AND
(incoming_emails.from_address = user_emails.email OR
incoming_emails.to_addresses ILIKE '%' || user_emails.email || '%' OR
incoming_emails.cc_addresses ILIKE '%' || user_emails.email || '%')
)
SQL
end
end
# == Schema Information
#
# Table name: incoming_emails
#
# id :integer not null, primary key
# user_id :integer
# topic_id :integer
# post_id :integer
# raw :text
# error :text
# message_id :text
# from_address :text
# to_addresses :text
# cc_addresses :text
# subject :text
# created_at :datetime not null
# updated_at :datetime not null
# rejection_message :text
# is_auto_generated :boolean default(FALSE)
# is_bounce :boolean default(FALSE), not null
# imap_uid_validity :integer
# imap_uid :integer
# imap_sync :boolean
# imap_group_id :bigint
#
# Indexes
#
# index_incoming_emails_on_created_at (created_at)
# index_incoming_emails_on_error (error)
# index_incoming_emails_on_imap_group_id (imap_group_id)
# index_incoming_emails_on_imap_sync (imap_sync)
# index_incoming_emails_on_message_id (message_id)
# index_incoming_emails_on_post_id (post_id)
# index_incoming_emails_on_user_id (user_id) WHERE (user_id IS NOT NULL)
#