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