github.com/Ne0nd0g/gophish@v0.7.1-0.20190220040016-11493024a07d/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> " + 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({
   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 () {
   129          swal(
   130              'Sending Profile Deleted!',
   131              'This sending profile has been deleted!',
   132              'success'
   133          );
   134          $('button:contains("OK")').on('click', function () {
   135              location.reload()
   136          })
   137      })
   138  }
   139  
   140  function edit(idx) {
   141      headers = $("#headersTable").dataTable({
   142          destroy: true, // Destroy any other instantiated table - http://datatables.net/manual/tech-notes/3#destroy
   143          columnDefs: [{
   144              orderable: false,
   145              targets: "no-sort"
   146          }]
   147      })
   148  
   149      $("#modalSubmit").unbind('click').click(function () {
   150          save(idx)
   151      })
   152      var profile = {}
   153      if (idx != -1) {
   154          profile = profiles[idx]
   155          $("#name").val(profile.name)
   156          $("#interface_type").val(profile.interface_type)
   157          $("#from").val(profile.from_address)
   158          $("#host").val(profile.host)
   159          $("#username").val(profile.username)
   160          $("#password").val(profile.password)
   161          $("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
   162          $.each(profile.headers, function (i, record) {
   163              addCustomHeader(record.key, record.value)
   164          });
   165      }
   166  }
   167  
   168  function copy(idx) {
   169      $("#modalSubmit").unbind('click').click(function () {
   170          save(-1)
   171      })
   172      var profile = {}
   173      profile = profiles[idx]
   174      $("#name").val("Copy of " + profile.name)
   175      $("#interface_type").val(profile.interface_type)
   176      $("#from").val(profile.from_address)
   177      $("#host").val(profile.host)
   178      $("#username").val(profile.username)
   179      $("#password").val(profile.password)
   180      $("#ignore_cert_errors").prop("checked", profile.ignore_cert_errors)
   181  }
   182  
   183  function load() {
   184      $("#profileTable").hide()
   185      $("#emptyMessage").hide()
   186      $("#loading").show()
   187      api.SMTP.get()
   188          .success(function (ss) {
   189              profiles = ss
   190              $("#loading").hide()
   191              if (profiles.length > 0) {
   192                  $("#profileTable").show()
   193                  profileTable = $("#profileTable").DataTable({
   194                      destroy: true,
   195                      columnDefs: [{
   196                          orderable: false,
   197                          targets: "no-sort"
   198                      }]
   199                  });
   200                  profileTable.clear()
   201                  $.each(profiles, function (i, profile) {
   202                      profileTable.row.add([
   203                          escapeHtml(profile.name),
   204                          profile.interface_type,
   205                          moment(profile.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
   206                          "<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 + ")'>\
   207                      <i class='fa fa-pencil'></i>\
   208                      </button></span>\
   209  		    <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Profile' onclick='copy(" + i + ")'>\
   210                      <i class='fa fa-copy'></i>\
   211                      </button></span>\
   212                      <button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Profile' onclick='deleteProfile(" + i + ")'>\
   213                      <i class='fa fa-trash-o'></i>\
   214                      </button></div>"
   215                      ]).draw()
   216                  })
   217                  $('[data-toggle="tooltip"]').tooltip()
   218              } else {
   219                  $("#emptyMessage").show()
   220              }
   221          })
   222          .error(function () {
   223              $("#loading").hide()
   224              errorFlash("Error fetching profiles")
   225          })
   226  }
   227  
   228  function addCustomHeader(header, value) {
   229      // Create new data row.
   230      var newRow = [
   231          escapeHtml(header),
   232          escapeHtml(value),
   233          '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'
   234      ];
   235  
   236      // Check table to see if header already exists.
   237      var headersTable = headers.DataTable();
   238      var existingRowIndex = headersTable
   239          .column(0) // Email column has index of 2
   240          .data()
   241          .indexOf(escapeHtml(header));
   242  
   243      // Update or add new row as necessary.
   244      if (existingRowIndex >= 0) {
   245          headersTable
   246              .row(existingRowIndex, {
   247                  order: "index"
   248              })
   249              .data(newRow);
   250      } else {
   251          headersTable.row.add(newRow);
   252      }
   253      headersTable.draw();
   254  }
   255  
   256  $(document).ready(function () {
   257      // Setup multiple modals
   258      // Code based on http://miles-by-motorcycle.com/static/bootstrap-modal/index.html
   259      $('.modal').on('hidden.bs.modal', function (event) {
   260          $(this).removeClass('fv-modal-stack');
   261          $('body').data('fv_open_modals', $('body').data('fv_open_modals') - 1);
   262      });
   263      $('.modal').on('shown.bs.modal', function (event) {
   264          // Keep track of the number of open modals
   265          if (typeof ($('body').data('fv_open_modals')) == 'undefined') {
   266              $('body').data('fv_open_modals', 0);
   267          }
   268          // if the z-index of this modal has been set, ignore.
   269          if ($(this).hasClass('fv-modal-stack')) {
   270              return;
   271          }
   272          $(this).addClass('fv-modal-stack');
   273          // Increment the number of open modals
   274          $('body').data('fv_open_modals', $('body').data('fv_open_modals') + 1);
   275          // Setup the appropriate z-index
   276          $(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals')));
   277          $('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
   278          $('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack');
   279      });
   280      $.fn.modal.Constructor.prototype.enforceFocus = function () {
   281          $(document)
   282              .off('focusin.bs.modal') // guard against infinite focus loop
   283              .on('focusin.bs.modal', $.proxy(function (e) {
   284                  if (
   285                      this.$element[0] !== e.target && !this.$element.has(e.target).length
   286                      // CKEditor compatibility fix start.
   287                      &&
   288                      !$(e.target).closest('.cke_dialog, .cke').length
   289                      // CKEditor compatibility fix end.
   290                  ) {
   291                      this.$element.trigger('focus');
   292                  }
   293              }, this));
   294      };
   295      // Scrollbar fix - https://stackoverflow.com/questions/19305821/multiple-modals-overlay
   296      $(document).on('hidden.bs.modal', '.modal', function () {
   297          $('.modal:visible').length && $(document.body).addClass('modal-open');
   298      });
   299      $('#modal').on('hidden.bs.modal', function (event) {
   300          dismiss()
   301      });
   302      $("#sendTestEmailModal").on("hidden.bs.modal", function (event) {
   303          dismissSendTestEmailModal()
   304      })
   305      // Code to deal with custom email headers
   306      $("#headersForm").on('submit', function () {
   307          headerKey = $("#headerKey").val();
   308          headerValue = $("#headerValue").val();
   309  
   310          if (headerKey == "" || headerValue == "") {
   311              return false;
   312          }
   313          addCustomHeader(headerKey, headerValue);
   314          // Reset user input.
   315          $("#headersForm>div>input").val('');
   316          $("#headerKey").focus();
   317          return false;
   318      });
   319      // Handle Deletion
   320      $("#headersTable").on("click", "span>i.fa-trash-o", function () {
   321          headers.DataTable()
   322              .row($(this).parents('tr'))
   323              .remove()
   324              .draw();
   325      });
   326      load()
   327  })