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