github.com/gophish/gophish@v0.12.2-0.20230915144530-8e7929441393/static/js/src/app/sending_profiles.js (about)

     1  var profiles = []
     2  
     3  // Attempts to send a test email by POSTing to /campaigns/
     4  function sendTestEmail() {
     5      var headers = [];
     6      $.each($("#headersTable").DataTable().rows().data(), function (i, header) {
     7          headers.push({
     8              key: unescapeHtml(header[0]),
     9              value: unescapeHtml(header[1]),
    10          })
    11      })
    12      var test_email_request = {
    13          template: {},
    14          first_name: $("input[name=to_first_name]").val(),
    15          last_name: $("input[name=to_last_name]").val(),
    16          email: $("input[name=to_email]").val(),
    17          position: $("input[name=to_position]").val(),
    18          url: '',
    19          smtp: {
    20              from_address: $("#from").val(),
    21              host: $("#host").val(),
    22              username: $("#username").val(),
    23              password: $("#password").val(),
    24              ignore_cert_errors: $("#ignore_cert_errors").prop("checked"),
    25              headers: headers,
    26          }
    27      }
    28      btnHtml = $("#sendTestModalSubmit").html()
    29      $("#sendTestModalSubmit").html('<i class="fa fa-spinner fa-spin"></i> Sending')
    30      // Send the test email
    31      api.send_test_email(test_email_request)
    32          .success(function (data) {
    33              $("#sendTestEmailModal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-success\">\
    34  	    <i class=\"fa fa-check-circle\"></i> Email Sent!</div>")
    35              $("#sendTestModalSubmit").html(btnHtml)
    36          })
    37          .error(function (data) {
    38              $("#sendTestEmailModal\\.flashes").empty().append("<div style=\"text-align:center\" class=\"alert alert-danger\">\
    39  	    <i class=\"fa fa-exclamation-circle\"></i> " + escapeHtml(data.responseJSON.message) + "</div>")
    40              $("#sendTestModalSubmit").html(btnHtml)
    41          })
    42  }
    43  
    44  // Save attempts to POST to /smtp/
    45  function save(idx) {
    46      var profile = {
    47          headers: []
    48      }
    49      $.each($("#headersTable").DataTable().rows().data(), function (i, header) {
    50          profile.headers.push({
    51              key: unescapeHtml(header[0]),
    52              value: unescapeHtml(header[1]),
    53          })
    54      })
    55      profile.name = $("#name").val()
    56      profile.interface_type = $("#interface_type").val()
    57      profile.from_address = $("#from").val()
    58      profile.host = $("#host").val()
    59      profile.username = $("#username").val()
    60      profile.password = $("#password").val()
    61      profile.ignore_cert_errors = $("#ignore_cert_errors").prop("checked")
    62      if (idx != -1) {
    63          profile.id = profiles[idx].id
    64          api.SMTPId.put(profile)
    65              .success(function (data) {
    66                  successFlash("Profile edited successfully!")
    67                  load()
    68                  dismiss()
    69              })
    70              .error(function (data) {
    71                  modalError(data.responseJSON.message)
    72              })
    73      } else {
    74          // Submit the profile
    75          api.SMTP.post(profile)
    76              .success(function (data) {
    77                  successFlash("Profile added successfully!")
    78                  load()
    79                  dismiss()
    80              })
    81              .error(function (data) {
    82                  modalError(data.responseJSON.message)
    83              })
    84      }
    85  }
    86  
    87  function dismiss() {
    88      $("#modal\\.flashes").empty()
    89      $("#name").val("")
    90      $("#interface_type").val("SMTP")
    91      $("#from").val("")
    92      $("#host").val("")
    93      $("#username").val("")
    94      $("#password").val("")
    95      $("#ignore_cert_errors").prop("checked", true)
    96      $("#headersTable").dataTable().DataTable().clear().draw()
    97      $("#modal").modal('hide')
    98  }
    99  
   100  var dismissSendTestEmailModal = function () {
   101      $("#sendTestEmailModal\\.flashes").empty()
   102      $("#sendTestModalSubmit").html("<i class='fa fa-envelope'></i> Send")
   103  }
   104  
   105  
   106  var deleteProfile = function (idx) {
   107      Swal.fire({
   108          title: "Are you sure?",
   109          text: "This will delete the sending profile. This can't be undone!",
   110          type: "warning",
   111          animation: false,
   112          showCancelButton: true,
   113          confirmButtonText: "Delete " + escapeHtml(profiles[idx].name),
   114          confirmButtonColor: "#428bca",
   115          reverseButtons: true,
   116          allowOutsideClick: false,
   117          preConfirm: function () {
   118              return new Promise(function (resolve, reject) {
   119                  api.SMTPId.delete(profiles[idx].id)
   120                      .success(function (msg) {
   121                          resolve()
   122                      })
   123                      .error(function (data) {
   124                          reject(data.responseJSON.message)
   125                      })
   126              })
   127          }
   128      }).then(function (result) {
   129          if (result.value){
   130              Swal.fire(
   131                  'Sending Profile Deleted!',
   132                  'This sending profile has been deleted!',
   133                  'success'
   134              );
   135          }
   136          $('button:contains("OK")').on('click', function () {
   137              location.reload()
   138          })
   139      })
   140  }
   141  
   142  function edit(idx) {
   143      headers = $("#headersTable").dataTable({
   144          destroy: true, // Destroy any other instantiated table - http://datatables.net/manual/tech-notes/3#destroy
   145          columnDefs: [{
   146              orderable: false,
   147              targets: "no-sort"
   148          }]
   149      })
   150  
   151      $("#modalSubmit").unbind('click').click(function () {
   152          save(idx)
   153      })
   154      var profile = {}
   155      if (idx != -1) {
   156          $("#profileModalLabel").text("Edit Sending Profile")
   157          profile = profiles[idx]
   158          $("#name").val(profile.name)
   159          $("#interface_type").val(profile.interface_type)
   160          $("#from").val(profile.from_address)
   161          $("#host").val(profile.host)
   162          $("#username").val(profile.username)
   163          $("#password").val(profile.password)
   164          $("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
   165          $.each(profile.headers, function (i, record) {
   166              addCustomHeader(record.key, record.value)
   167          });
   168      } else {
   169          $("#profileModalLabel").text("New Sending Profile")
   170      }
   171  }
   172  
   173  function copy(idx) {
   174      $("#modalSubmit").unbind('click').click(function () {
   175          save(-1)
   176      })
   177      var profile = {}
   178      profile = profiles[idx]
   179      $("#name").val("Copy of " + profile.name)
   180      $("#interface_type").val(profile.interface_type)
   181      $("#from").val(profile.from_address)
   182      $("#host").val(profile.host)
   183      $("#username").val(profile.username)
   184      $("#password").val(profile.password)
   185      $("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
   186  }
   187  
   188  function load() {
   189      $("#profileTable").hide()
   190      $("#emptyMessage").hide()
   191      $("#loading").show()
   192      api.SMTP.get()
   193          .success(function (ss) {
   194              profiles = ss
   195              $("#loading").hide()
   196              if (profiles.length > 0) {
   197                  $("#profileTable").show()
   198                  profileTable = $("#profileTable").DataTable({
   199                      destroy: true,
   200                      columnDefs: [{
   201                          orderable: false,
   202                          targets: "no-sort"
   203                      }]
   204                  });
   205                  profileTable.clear()
   206                  profileRows = []
   207                  $.each(profiles, function (i, profile) {
   208                      profileRows.push([
   209                          escapeHtml(profile.name),
   210                          profile.interface_type,
   211                          moment(profile.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
   212                          "<div class='pull-right'><span data-toggle='modal' data-backdrop='static' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Profile' onclick='edit(" + i + ")'>\
   213                      <i class='fa fa-pencil'></i>\
   214                      </button></span>\
   215  		    <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Profile' onclick='copy(" + i + ")'>\
   216                      <i class='fa fa-copy'></i>\
   217                      </button></span>\
   218                      <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Profile' onclick='deleteProfile(" + i + ")'>\
   219                      <i class='fa fa-trash-o'></i>\
   220                      </button></div>"
   221                      ])
   222                  })
   223                  profileTable.rows.add(profileRows).draw()
   224                  $('[data-toggle="tooltip"]').tooltip()
   225              } else {
   226                  $("#emptyMessage").show()
   227              }
   228          })
   229          .error(function () {
   230              $("#loading").hide()
   231              errorFlash("Error fetching profiles")
   232          })
   233  }
   234  
   235  function addCustomHeader(header, value) {
   236      // Create new data row.
   237      var newRow = [
   238          escapeHtml(header),
   239          escapeHtml(value),
   240          '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'
   241      ];
   242  
   243      // Check table to see if header already exists.
   244      var headersTable = headers.DataTable();
   245      var existingRowIndex = headersTable
   246          .column(0) // Email column has index of 2
   247          .data()
   248          .indexOf(escapeHtml(header));
   249  
   250      // Update or add new row as necessary.
   251      if (existingRowIndex >= 0) {
   252          headersTable
   253              .row(existingRowIndex, {
   254                  order: "index"
   255              })
   256              .data(newRow);
   257      } else {
   258          headersTable.row.add(newRow);
   259      }
   260      headersTable.draw();
   261  }
   262  
   263  $(document).ready(function () {
   264      // Setup multiple modals
   265      // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html
   266      $('.modal').on('hidden.bs.modal', function (event) {
   267          $(this).removeClass('fv-modal-stack');
   268          $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1);
   269      });
   270      $('.modal').on('shown.bs.modal', function (event) {
   271          // Keep track of the number of open modals
   272          if (typeof ($('body').data('fv_open_modals')) == 'undefined') {
   273              $('body').data('fv_open_modals', 0);
   274          }
   275          // if the z-index of this modal has been set, ignore.
   276          if ($(this).hasClass('fv-modal-stack')) {
   277              return;
   278          }
   279          $(this).addClass('fv-modal-stack');
   280          // Increment the number of open modals
   281          $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1);
   282          // Setup the appropriate z-index
   283          $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals')));
   284          $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
   285          $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack');
   286      });
   287      $.fn.modal.Constructor.prototype.enforceFocus = function () {
   288          $(document)
   289              .off('focusin.bs.modal') // guard against infinite focus loop
   290              .on('focusin.bs.modal', $.proxy(function (e) {
   291                  if (
   292                      this.$element[0] !== e.target && !this.$element.has(e.target).length
   293                      // CKEditor compatibility fix start.
   294                      &&
   295                      !$(e.target).closest('.cke_dialog, .cke').length
   296                      // CKEditor compatibility fix end.
   297                  ) {
   298                      this.$element.trigger('focus');
   299                  }
   300              }, this));
   301      };
   302      // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay
   303      $(document).on('hidden.bs.modal', '.modal', function () {
   304          $('.modal:visible').length && $(document.body).addClass('modal-open');
   305      });
   306      $('#modal').on('hidden.bs.modal', function (event) {
   307          dismiss()
   308      });
   309      $("#sendTestEmailModal").on("hidden.bs.modal", function (event) {
   310          dismissSendTestEmailModal()
   311      })
   312      // Code to deal with custom email headers
   313      $("#addCustomHeader").on('click', function () {
   314          headerKey = $("#headerKey").val();
   315          headerValue = $("#headerValue").val();
   316  
   317          if (headerKey == "" || headerValue == "") {
   318              return false;
   319          }
   320          addCustomHeader(headerKey, headerValue);
   321          // Reset user input.
   322          $("#headerKey").val('');
   323          $("#headerValue").val('');
   324          $("#headerKey").focus();
   325          return false;
   326      });
   327      // Handle Deletion
   328      $("#headersTable").on("click", "span>i.fa-trash-o", function () {
   329          headers.DataTable()
   330              .row($(this).parents('tr'))
   331              .remove()
   332              .draw();
   333      });
   334      load()
   335  })