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 })