<commit_before>require 'net/smtp' 


class Mailing::SendGridSender < Mailing::Base

  SENDING_WINDOW_SIZE = 250

  def self.mailing_sender_handler_info
    { :name => 'Send Grid Mailer',
      :options_partial => '/mailing/senders/sendgrid_options',
      :secure_options => %w(username password)
    }
  end

  def self.options(hsh)
    Options.new(hsh)
  end

  def options_description; ''; end

  class Options < HashModel
    attributes :username => nil, :password => <PASSWORD>

    validates_presence_of :username, :password

    def validate
      data = self.service.get_profile
      if ! data || data['error']
        self.errors.add(:username, 'is invalid')
        self.errors.add(:password, 'is <PASSWORD>')
      end
    end

    def service
      @service ||= SendGrid::WebService.new self.username, self.password
    end
  end

  def prepare_mail_template(mail_template, online)
    mail_template.replace_image_sources
    tracking_variables = []

    if @campaign.tracking_image?
      tracking_image_filename,tracking_image_variable = mail_template.replace_tracking_image
      @campaign.tracking_image_filename = tracking_image_filename
      tracking_variables << [ tracking_image_variable, "http://#{Configuration.full_domain}/mailing/image/#{@campaign.identifier_hash}/" ]
    end

    # Prepare template by sending market links
    # For replacement
    if @campaign.track_links?
      links = mail_template.track_link_hrefs
      tracking_variables += @campaign.generate_market_links(links)
    else
      mail_template.replace_link_hrefs
    end

    if(@campaign.view_online? && !online && mail_template.is_html) 
      view_online_variable = mail_template.view_online_href
      tracking_variables << [ view_online_variable, "http://#{Configuration.full_domain}/mailing/view/#{@campaign.identifier_hash}/" ]
    end

    unsubscribe_variable = mail_template.add_unsubscribe_links
    
    tracking_variables << [ unsubscribe_variable,  "#{@campaign.get_mail_module_path}/unsubscribe/#{@campaign.identifier_hash}/" ]

    mail_template.prepare_template

    return mail_template, tracking_variables  
  end  

  def send!(mail_template, message, tracking_variables)
    send_grid_vars = {}

    (message.fields||{}).each do |fld_orig,val|
      fld = fld_orig.downcase
      send_grid_vars[fld_orig] = "-#{fld}-"
    end

    tracking_variables.each do |fld_orig,val|
      next unless fld_orig
      fld = fld_orig.downcase
      send_grid_vars[fld_orig] = "-#{fld}-"
    end

    email_vars = send_grid_vars.clone
    @campaign.add_delivery_variables(email_vars)

    self.smtp.html = mail_template.is_html ? mail_template.render_html(email_vars) : nil
    self.smtp.text = mail_template.is_text ? mail_template.render_text(email_vars) : nil
    self.smtp.subject = mail_template.render_subject(email_vars)
    self.smtp.category_name = self.category_name
    self.smtp.from = email_vars['system:from']
    self.smtp.reply_to = email_vars['system:reply_to']

    mdl = @campaign.data_model_class

    @campaign.market_campaign_queues.find_in_batches(:conditions => 'handled=0', :batch_size => SENDING_WINDOW_SIZE) do |queues|
      @campaign.reload
      # If the campaign has been paused or otherwise interrupted
      return unless @campaign.status == 'active'

      skip_count = 0
      sent_count = 0

      entries = mdl.find(:all, :conditions => {:id => queues.collect(&:model_id)}).index_by(&:id)
      skip_targets = UserUnsubscription.find(:all, :select => 'id, email', :conditions => {:email => queues.collect(&:email)}).index_by(&:email)

      self.smtp.receivers = []
      self.smtp.data = {}
      send_grid_vars.each { |fld_orig, fld| self.smtp.data[fld] = [] }

      skipped_ids = []
      self.mark_as_sent queues.collect(&:id)
      queues.each do |queue|
        skip_target = skip_targets[queue.email] ? true : false
        skip_target ||= RFC822::EmailAddress.match(queue.email).nil?

        if skip_target
          skip_count += 1
          skipped_ids << queue.id
        else
          entry = entries[queue.model_id]
          if @campaign.data_model == 'subscription'
            entry = entry.end_user if entry.end_user_id
          end

          vars = message.field_values(entry.attributes,queue.queue_hash)
          vars.merge!(@campaign.add_tracking_links(tracking_variables,queue.queue_hash))
          @campaign.add_delivery_variables(vars)

          self.smtp.receivers << queue.email
          send_grid_vars.each { |fld_orig, fld| self.smtp.data[fld] << vars[fld_orig] }
          sent_count += 1
        end
      end

      begin
        self.smtp.send
      rescue Net::SMTPSyntaxError => e
        @campaign.reload(:lock => true)
        @campaign.status = 'error'
        @campaign.error_message = e.to_s
        @campaign.save
        self.mark_as_unhandled queues.collect(&:id)
        return<commit_msg>Check for socket errors<commit_after>require 'net/smtp' 


class Mailing::SendGridSender < Mailing::Base

  SENDING_WINDOW_SIZE = 250

  def self.mailing_sender_handler_info
    { :name => 'Send Grid Mailer',
      :options_partial => '/mailing/senders/sendgrid_options',
      :secure_options => %w(username password)
    }
  end

  def self.options(hsh)
    Options.new(hsh)
  end

  def options_description; ''; end

  class Options < HashModel
    attributes :username => nil, :password => nil

    validates_presence_of :username, :password

    def validate
      data = self.service.get_profile
      if ! data || data['error']
        self.errors.add(:username, 'is invalid')
        self.errors.add(:password, 'is invalid')
      end
    end

    def service
      @service ||= SendGrid::WebService.new self.username, self.password
    end
  end

  def prepare_mail_template(mail_template, online)
    mail_template.replace_image_sources
    tracking_variables = []

    if @campaign.tracking_image?
      tracking_image_filename,tracking_image_variable = mail_template.replace_tracking_image
      @campaign.tracking_image_filename = tracking_image_filename
      tracking_variables << [ tracking_image_variable, "http://#{Configuration.full_domain}/mailing/image/#{@campaign.identifier_hash}/" ]
    end

    # Prepare template by sending market links
    # For replacement
    if @campaign.track_links?
      links = mail_template.track_link_hrefs
      tracking_variables += @campaign.generate_market_links(links)
    else
      mail_template.replace_link_hrefs
    end

    if(@campaign.view_online? && !online && mail_template.is_html) 
      view_online_variable = mail_template.view_online_href
      tracking_variables << [ view_online_variable, "http://#{Configuration.full_domain}/mailing/view/#{@campaign.identifier_hash}/" ]
    end

    unsubscribe_variable = mail_template.add_unsubscribe_links
    
    tracking_variables << [ unsubscribe_variable,  "#{@campaign.get_mail_module_path}/unsubscribe/#{@campaign.identifier_hash}/" ]

    mail_template.prepare_template

    return mail_template, tracking_variables  
  end  

  def send!(mail_template, message, tracking_variables)
    send_grid_vars = {}

    (message.fields||{}).each do |fld_orig,val|
      fld = fld_orig.downcase
      send_grid_vars[fld_orig] = "-#{fld}-"
    end

    tracking_variables.each do |fld_orig,val|
      next unless fld_orig
      fld = fld_orig.downcase
      send_grid_vars[fld_orig] = "-#{fld}-"
    end

    email_vars = send_grid_vars.clone
    @campaign.add_delivery_variables(email_vars)

    self.smtp.html = mail_template.is_html ? mail_template.render_html(email_vars) : nil
    self.smtp.text = mail_template.is_text ? mail_template.render_text(email_vars) : nil
    self.smtp.subject = mail_template.render_subject(email_vars)
    self.smtp.category_name = self.category_name
    self.smtp.from = email_vars['system:from']
    self.smtp.reply_to = email_vars['system:reply_to']

    mdl = @campaign.data_model_class

    @campaign.market_campaign_queues.find_in_batches(:conditions => 'handled=0', :batch_size => SENDING_WINDOW_SIZE) do |queues|
      @campaign.reload
      # If the campaign has been paused or otherwise interrupted
      return unless @campaign.status == 'active'

      skip_count = 0
      sent_count = 0

      entries = mdl.find(:all, :conditions => {:id => queues.collect(&:model_id)}).index_by(&:id)
      skip_targets = UserUnsubscription.find(:all, :select => 'id, email', :conditions => {:email => queues.collect(&:email)}).index_by(&:email)

      self.smtp.receivers = []
      self.smtp.data = {}
      send_grid_vars.each { |fld_orig, fld| self.smtp.data[fld] = [] }

      skipped_ids = []
      self.mark_as_sent queues.collect(&:id)
      queues.each do |queue|
        skip_target = skip_targets[queue.email] ? true : false
        skip_target ||= RFC822::EmailAddress.match(queue.email).nil?

        if skip_target
          skip_count += 1
          skipped_ids << queue.id
        else
          entry = entries[queue.model_id]
          if @campaign.data_model == 'subscription'
            entry = entry.end_user if entry.end_user_id
          end

          vars = message.field_values(entry.attributes,queue.queue_hash)
          vars.merge!(@campaign.add_tracking_links(tracking_variables,queue.queue_hash))
          @campaign.add_delivery_variables(vars)

          self.smtp.receivers << queue.email
          send_grid_vars.each { |fld_orig, fld| self.smtp.data[fld] << vars[fld_orig] }
          sent_count += 1
        end
      end

      begin
        self.smtp.send
      rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE, SocketError, Net::SMTPSyntaxError => e
        @campaign.reload(:lock => true)
        @campaign.status = 'error'
        @campaign.error_message = e.to_s
        @campaign.save
        self.mark_as_unhandled queues.collect(&:id)
        return
{'fraction_non_alphanumeric': 0.10940518556176919, 'fraction_numerical': 0.0022369089984748346, 'mean_word_length': 3.2616984402079723, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '806964', 'n_tokens_mistral': 3233, 'n_tokens_neox': 3078, 'n_words': 522}