2020-07-10 17:05:55 +08:00
# frozen_string_literal: true
module Jobs
class GroupSmtpEmail < :: Jobs :: Base
2021-07-05 12:56:32 +08:00
include Skippable
2020-07-10 17:05:55 +08:00
sidekiq_options queue : 'critical'
2021-07-06 11:37:52 +08:00
sidekiq_retry_in do | count , exception |
# retry in an hour when SMTP server is busy
# or use default sidekiq retry formula. returning
# nil/0 will trigger the default sidekiq
# retry formula
#
# See https://github.com/mperham/sidekiq/blob/3330df0ee37cfd3e0cd3ef01e3e66b584b99d488/lib/sidekiq/job_retry.rb#L216-L234
case exception . wrapped
when Net :: SMTPServerBusy
return 1 . hour + ( rand ( 30 ) * ( count + 1 ) )
end
end
2020-07-10 17:05:55 +08:00
def execute ( args )
2021-07-05 12:56:32 +08:00
return if quit_email_early?
2020-07-10 17:05:55 +08:00
email = args [ :email ]
2021-07-05 12:56:32 +08:00
recipient_user = User . find_by_email ( email , primary : true )
2021-11-16 06:15:11 +08:00
post = Post . find_by ( id : args [ :post_id ] )
2021-07-05 12:56:32 +08:00
if post . blank?
return skip ( email , nil , recipient_user , :group_smtp_post_deleted )
end
2021-11-16 06:15:11 +08:00
group = Group . find_by ( id : args [ :group_id ] )
return if group . blank?
2021-07-05 12:56:32 +08:00
if ! group . smtp_enabled
return skip ( email , post , recipient_user , :group_smtp_disabled_for_group )
end
2020-07-10 17:05:55 +08:00
2021-11-16 06:15:11 +08:00
if ! Topic . exists? ( id : post . topic_id )
return skip ( email , post , recipient_user , :group_smtp_topic_deleted )
end
2022-02-18 09:12:51 +08:00
cc_addresses = args [ :cc_emails ] . filter do | address |
EmailAddressValidator . valid_value? ( address )
end
2021-11-16 06:15:11 +08:00
2021-01-05 13:32:04 +08:00
# There is a rare race condition causing the Imap::Sync class to create
# an incoming email and associated post/topic, which then kicks off
# the PostAlerter to notify others in the PM about a reply in the topic,
# but for the OP which is not necessary (because the person emailing the
# IMAP inbox already knows about the OP)
#
# Basically, we should never be sending this notification for the first
# post in a topic.
2021-07-14 12:23:14 +08:00
#
# If the group does not have IMAP enabled then this could be legitimate,
# for example in cases where we are creating a new topic to reply to another
# group PM and we need to send the participants the group OP email.
if post . is_first_post? && group . imap_enabled
2021-01-05 13:32:04 +08:00
ImapSyncLog . warn ( " Aborting SMTP email for post #{ post . id } in topic #{ post . topic_id } to #{ email } , the post is the OP and should not send an email. " , group )
return
end
ImapSyncLog . debug ( " Sending SMTP email for post #{ post . id } in topic #{ post . topic_id } to #{ email } . " , group )
2021-06-28 06:55:13 +08:00
# The EmailLog record created by the sender will have the raw email
# stored, the group smtp ID, and any cc addresses recorded for later
# cross referencing.
2021-07-05 12:56:32 +08:00
message = GroupSmtpMailer . send_mail ( group , email , post , cc_addresses )
2020-10-28 05:01:58 +08:00
Email :: Sender . new ( message , :group_smtp , recipient_user ) . send
2020-07-10 17:05:55 +08:00
# Create an incoming email record to avoid importing again from IMAP
2021-06-28 06:55:13 +08:00
# server. While this may not be technically required if IMAP is not
# currently enabled for the group, it will help a lot with the initial
# sync if it is turned on at a later date.
2020-07-10 17:05:55 +08:00
IncomingEmail . create! (
user_id : post . user_id ,
topic_id : post . topic_id ,
post_id : post . id ,
raw : message . to_s ,
2021-01-05 13:32:04 +08:00
subject : message . subject ,
message_id : message . message_id ,
to_addresses : message . to ,
cc_addresses : message . cc ,
2021-01-20 11:22:41 +08:00
from_address : message . from ,
created_via : IncomingEmail . created_via_types [ :group_smtp ]
2020-07-10 17:05:55 +08:00
)
end
2021-07-05 12:56:32 +08:00
def quit_email_early?
SiteSetting . disable_emails == 'yes' || ! SiteSetting . enable_smtp
end
def skip ( email , post , recipient_user , reason )
create_skipped_email_log (
email_type : :group_smtp ,
to_address : email ,
user_id : recipient_user & . id ,
post_id : post & . id ,
reason_type : SkippedEmailLog . reason_types [ reason ]
)
end
2020-07-10 17:05:55 +08:00
end
end