class WcoEmail::MessageStub
#
# 2024-01-05 LFG
# 2023-12-28 vp Continue.
# Only object_key, no validations.
#
def self.mbox2stubs mbox_path, tagname:, skip:
def self.mbox2stubs mbox_path, tagname:, skip: skip ||= 0 self.new.mbox2stubs mbox_path, tagname: tagname, skip: skip end
def do_process
def do_process @client ||= Aws::S3::Client.new(::SES_S3_CREDENTIALS) 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 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 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. conv = WcoEmail::Conversation.find( conv.id ) if conv.tags.include? Wco::Tag.inbox out = WcoEmail::ApplicationMailer.forwarder_notify( @message.id.to_s ) Rails.env.production? ? out.deliver_later : out.deliver_now end end puts 'ok' end
def mbox2stubs mbox_path, tagname:, skip:
def mbox2stubs mbox_path, tagname:, skip: puts 'Starting...' skip ||= 0 @count = 1 @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], }) @tag = Wco::Tag.find_or_create_by({ slug: tagname }) message = nil File.readlines(mbox_path, encoding: "ISO8859-1" ).each do |line| if (line.match(/\AFrom /)) if message if skip < @count save_mbox_to_m3 message print "#{@count}." else print "s-#{@count}." end @count += 1 end message = '' else message << line.sub(/^\>From/, 'From') end end if message if skip < @count save_mbox_to_m3 message print "#{@count}." else print "s-#{@count}." end @count += 1 end message = '' end
def save_mbox_to_m3 message
def save_mbox_to_m3 message the_mail = Mail.new(message) key = the_mail.message_id || "no-key-#{Time.now.to_i}.#{rand(1000)}" @stub = WcoEmail::MessageStub.create({ bucket: ::S3_CREDENTIALS[:bucket_ses], object_key: key, status: WcoEmail::MessageStub::STATUS_PENDING, tags: [ @tag ], }) if @stub.persisted? @client.put_object({ body: message, bucket: ::S3_CREDENTIALS[:bucket_ses], key: key, }) else msg = @stub.errors.full_messages.join(", ") puts! msg Wco::Log.create({ message: "Stub duplicate object_key: #{key}", class_name: 'WcoEmail::MessageStub', raw_json: @stub.attributes.to_json, tags: [ @tag ], }) end end