class WcoEmail::MessageStub
def do_process
if Rails.env.production?
@client ||= Aws::S3::Client.new({
region: ::S3_CREDENTIALS[:region_ses],
access_key_id: ::S3_CREDENTIALS[:access_key_id_ses],
secret_access_key: ::S3_CREDENTIALS[:secret_access_key_ses],
})
else
@client ||= Aws::S3::Client.new(::SES_S3_CREDENTIALS)
end
stub = self
raw = @client.get_object( bucket: stub.bucket, key: stub.object_key ).body.read
raw = raw.encode('utf-8', invalid: :replace, undef: :replace, replace: '_' )
the_mail = Mail.new( raw )
# puts! the_mail, 'the_mail'
message_id = the_mail.header['message-id']&.decoded
message_id ||= "#{the_mail.date&.iso8601}::#{the_mail.from}"
# puts! message_id, 'message_id'
in_reply_to_id = the_mail.header['in-reply-to']&.to_s
# puts! in_reply_to_id, 'in_reply_to_id'
the_mail.to = [ 'NO-RECIPIENT' ] if !the_mail.to
subject = WcoEmail::Message.strip_emoji( the_mail.subject || '(wco-no-subject)' )
# puts! subject, 'subject'
## Conversation
if in_reply_to_id
in_reply_to_msg = WcoEmail::Message.where({ message_id: in_reply_to_id }).first
if !in_reply_to_msg
conv = WcoEmail::Conversation.find_or_create_by({
subject: subject,
})
in_reply_to_msg = WcoEmail::Message.find_or_create_by({
message_id: in_reply_to_id,
conversation: conv,
})
end
conv = in_reply_to_msg.conversation
else
conv = WcoEmail::Conversation.unscoped.find_or_create_by({
subject: subject,
})
conv.deleted_at = nil
end
## Leadset, Lead
from = the_mail.from ? the_mail.from[0] : "nobody@unknown-doma.in"
lead = Wco::Lead.find_or_create_by_email( from )
conv.leads.push lead
leadset = Wco::Leadset.from_email from
conv.leadsets.push leadset
# conv.save
message = WcoEmail::Message.unscoped.where( message_id: message_id ).first
if message
message.message_id = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.message_id}"
message.object_key = "#{Time.now.strftime('%Y%m%d')}-trash-#{message.object_key}"
message.save( validate: false )
message.delete
end
@message = WcoEmail::Message.create!({
stub: stub,
conversation: conv,
lead: lead,
message_id: message_id,
in_reply_to_id: in_reply_to_id,
object_key: stub.object_key,
subject: subject,
date: the_mail.date,
from: from,
froms: the_mail.from,
to: the_mail.to ? the_mail.to[0] : nil,
tos: the_mail.to,
cc: the_mail.cc ? the_mail.cc[0] : nil,
ccs: the_mail.cc,
})
# puts! @message, '@message'
## Parts
the_mail.parts.each do |part|
@message.churn_subpart( part )
end
@message.save
if the_mail.parts.length == 0
body = the_mail.body.decoded.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
if the_mail.content_type&.include?('text/html')
@message.part_html = body
elsif the_mail.content_type&.include?('text/plain')
@message.part_html = "<pre>#{body}</pre>"
elsif the_mail.content_type.blank?
@message.part_html = "<pre>#{body}</pre>"
else
@message.logs.push "mail body of unknown type: #{the_mail.content_type}"
@message.part_html = "<pre>#{body}</pre>"
end
@message.save
end
## Attachments, which are parts (omit!)
# the_mail.attachments.each do |att|
# @message.save_attachment( att )
# end
if !@message.save
puts! @message.errors.full_messages.join(", "), "Could not save @message"
end
the_mail.cc&.each do |cc|
Wco::Lead.find_or_create_by_email( cc )
end
conv.update_attributes({
status: WcoEmail::Conversation::STATUS_UNREAD,
latest_at: the_mail.date || Time.now.to_datetime,
from_emails: ( conv.from_emails + the_mail.from ).uniq,
preview: @message.preview_str,
})
##
## Tags
##
conv.tags.push Wco::Tag.inbox
conv.tags.push stub.tags
conv.save
## Actions & Filters
email_filters = WcoEmail::EmailFilter.all
email_filters.each do |filter|
reason = nil
if filter.from_regex.present? && @message.from.downcase.match( filter.from_regex )
reason = 'from_regex'
end
if filter.from_exact.present? && @message.from.downcase.include?( filter.from_exact.downcase )
reason = 'from_exact'
end
if filter.body_exact.present? && @message.part_html&.include?( filter.body_exact )
reason = 'body_exact'
end
if filter.subject_regex.present? && @message.subject.match( filter.subject_regex )
reason = 'subject_regex'
end
if filter.subject_exact.present? && @message.subject.downcase.include?( filter.subject_exact.downcase )
reason = 'subject_exact'
end
filter.conditions.each do |scond|
reason ||= scond.apply(leadset: leadset, message: @message )
end
if reason
puts! "Applying filter #{filter} to conv #{@message.conversation} for matching #{reason}" if DEBUG
## skip
skip_reason = nil
if filter.skip_to_exact.present? && @message.to&.downcase.include?( filter.skip_to_exact.downcase )
skip_reason = 'skip_to_exact'
end
if filter.skip_from_regex.present? && @message.from.downcase.match( filter.skip_from_regex )
skip_reason = 'skip_from_regex'
end
filter.skip_conditions.each do |scond|
skip_reason ||= scond.apply(leadset: leadset, message: @message )
end
if skip_reason
puts! "NOT Applying filter #{filter} to conv #{@message.conversation} for matching #{skip_reason}" if DEBUG
else
@message.apply_filter( filter )
end
end
end
stub.update_attributes({ status: WcoEmail::MessageStub::STATUS_PROCESSED })
## Notification
config = JSON.parse(stub.config)
if config['skip_notification']
;
else
## 2024-07-30 I'm no longer sending these to google.
## 2024-11-03 restarted sending.
## 2025-01-23 no longer sending to google.
conv = WcoEmail::Conversation.find( conv.id )
if conv.tags.include? Wco::Tag.inbox
if defined?(::NOTIFY_TO_GOOGLE) && ::NOTIFY_TO_GOOGLE
out = WcoEmail::ApplicationMailer.forwarder_notify( @message.id.to_s )
Rails.env.production? ? out.deliver_later : out.deliver_now
end
end
end
puts 'ok'
end