class Observer::Ticket::Article::CommunicateEmail::BackgroundJob def initialize(id) @article_id = id end def perform record = Ticket::Article.find(@article_id) # build subject ticket = Ticket.lookup(id: record.ticket_id) article_count = Ticket::Article.where(ticket_id: ticket.id).count subject = if article_count > 1 ticket.subject_build(record.subject, true) else ticket.subject_build(record.subject) end # set retry count if !record.preferences['delivery_retry'] record.preferences['delivery_retry'] = 0 end record.preferences['delivery_retry'] += 1 # send email email_address = nil if record.preferences['email_address_id'].present? email_address = EmailAddress.find_by(id: record.preferences['email_address_id']) end # fallback for articles without email_address_id if !email_address if !ticket.group.email_address_id log_error(record, "No email address defined for group id '#{ticket.group.id}'!") elsif !ticket.group.email_address.channel_id log_error(record, "No channel defined for email_address id '#{ticket.group.email_address_id}'!") end email_address = ticket.group.email_address end # log if ref objects are missing if !email_address log_error(record, "No email address defined for group id '#{ticket.group_id}'!") end if !email_address.channel_id log_error(record, "No channel defined for email_address id '#{email_address.id}'!") end channel = email_address.channel notification = false sender = Ticket::Article::Sender.lookup(id: record.sender_id) if sender['name'] == 'System' notification = true end # get linked channel and send begin message = channel.deliver( { message_id: record.message_id, in_reply_to: record.in_reply_to, references: ticket.get_references([record.message_id]), from: record.from, to: record.to, cc: record.cc, subject: subject, content_type: record.content_type, body: record.body, attachments: record.attachments }, notification ) rescue => e log_error(record, e.message, channel) return end if !message log_error(record, 'Unable to get sent email', channel) return end # set delivery status record.preferences['delivery_channel_id'] = channel.id record.preferences['delivery_status_message'] = nil record.preferences['delivery_status'] = 'success' record.preferences['delivery_status_date'] = Time.zone.now record.save! # store mail plain record.save_as_raw(message.to_s) # add history record recipient_list = '' [:to, :cc].each { |key| next if !record[key] next if record[key] == '' if recipient_list != '' recipient_list += ',' end recipient_list += record[key] } Rails.logger.info "Send email to: '#{recipient_list}' (from #{record.from})" return if recipient_list == '' History.add( o_id: record.id, history_type: 'email', history_object: 'Ticket::Article', related_o_id: ticket.id, related_history_object: 'Ticket', value_from: record.subject, value_to: recipient_list, created_by_id: record.created_by_id, ) end def log_error(local_record, message, channel = nil) if channel local_record.preferences['delivery_channel_id'] = channel.id end local_record.preferences['delivery_status'] = 'fail' local_record.preferences['delivery_status_message'] = message local_record.preferences['delivery_status_date'] = Time.zone.now local_record.save! Rails.logger.error message if local_record.preferences['delivery_retry'] > 3 recipient_list = '' [:to, :cc].each { |key| next if !local_record[key] next if local_record[key] == '' if recipient_list != '' recipient_list += ',' end recipient_list += local_record[key] } # reopen ticket and notify agent Observer::Transaction.reset UserInfo.current_user_id = 1 Ticket::Article.create!( ticket_id: local_record.ticket_id, content_type: 'text/plain', body: "Unable to send email to '#{recipient_list}': #{message}", internal: true, sender: Ticket::Article::Sender.find_by(name: 'System'), type: Ticket::Article::Type.find_by(name: 'note'), preferences: { delivery_article_id_related: local_record.id, delivery_message: true, notification: true, }, ) ticket = Ticket.find(local_record.ticket_id) ticket.state = Ticket::State.find_by(default_follow_up: true) ticket.save! Observer::Transaction.commit UserInfo.current_user_id = nil end raise message end def max_attempts 4 end def reschedule_at(current_time, attempts) if Rails.env.production? return current_time + attempts * 25.seconds end current_time + 5.seconds end end