diff --git a/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql b/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql
new file mode 100644
index 00000000..f66183f5
--- /dev/null
+++ b/db/migrations/20160211211220_0.1.2_add_ignore_cert_errors.sql
@@ -0,0 +1,8 @@
+
+-- +goose Up
+-- SQL in section 'Up' is executed when this migration is applied
+ALTER TABLE smtp ADD COLUMN ignore_cert_errors BOOLEAN;
+
+-- +goose Down
+-- SQL section 'Down' is executed when this migration is rolled back
+
diff --git a/models/smtp.go b/models/smtp.go
index c93bd872..cf6d69d1 100644
--- a/models/smtp.go
+++ b/models/smtp.go
@@ -4,12 +4,13 @@ import "errors"
// SMTP contains the attributes needed to handle the sending of campaign emails
type SMTP struct {
- SMTPId int64 `json:"-" gorm:"column:smtp_id; primary_key:yes"`
- CampaignId int64 `json:"-" gorm:"column:campaign_id"`
- Host string `json:"host"`
- Username string `json:"username,omitempty"`
- Password string `json:"password,omitempty" sql:"-"`
- FromAddress string `json:"from_address"`
+ SMTPId int64 `json:"-" gorm:"column:smtp_id; primary_key:yes"`
+ CampaignId int64 `json:"-" gorm:"column:campaign_id"`
+ Host string `json:"host"`
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty" sql:"-"`
+ FromAddress string `json:"from_address"`
+ IgnoreCertErrors bool `json:"ignore_cert_errors"`
}
// ErrFromAddressNotSpecified is thrown when there is no "From" address
diff --git a/static/css/main.css b/static/css/main.css
index 64c02f39..dcf13bb9 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -374,6 +374,9 @@ table.dataTable thead .sorting_desc:after {
content: "\f0dd" !important;
opacity: .8 !important;
}
+td.details-control{
+ cursor:pointer;
+}
.timeline{
text-align:left;
background-color:#ffffff;
@@ -445,6 +448,10 @@ table.dataTable thead .sorting_desc:after {
margin-top: 10px;
margin-bottom: 10px;
}
-.timeline-event-table{
+.timeline-event-results{
+ font-size:16px;
display:none;
}
+.tooltip-inner {
+ width:300px !important;
+}
diff --git a/static/js/app/campaign_results.js b/static/js/app/campaign_results.js
index efddfd36..efba5e8b 100644
--- a/static/js/app/campaign_results.js
+++ b/static/js/app/campaign_results.js
@@ -139,21 +139,28 @@ function renderTimeline(data) {
' ' + moment(event.time).format('MMMM Do YYYY h:mm') + ''
if (event.details) {
results += '
View Details
'
- results += ''
- results += '
'
- results += ' Parameter | Value(s) |
'
details = JSON.parse(event.details)
- $.each(Object.keys(details.payload), function(i, param) {
- if (param == "rid") {
- return true;
- }
- results += ' '
- results += ' ' + param + ' | '
- results += ' ' + details.payload[param] + ' | '
- results += '
'
- })
- results += '
'
- results += '
'
+ if (details.payload) {
+ results += ''
+ results += '
'
+ results += ' Parameter | Value(s) |
'
+ $.each(Object.keys(details.payload), function(i, param) {
+ if (param == "rid") {
+ return true;
+ }
+ results += ' '
+ results += ' ' + param + ' | '
+ results += ' ' + details.payload[param] + ' | '
+ results += '
'
+ })
+ results += '
'
+ results += '
'
+ }
+ if (details.error) {
+ results += ''
+ results += 'Error ' + details.error
+ results += '
'
+ }
}
results += ''
}
@@ -174,15 +181,15 @@ $(document).ready(function() {
// Setup viewing the details of a result
$("#resultsTable").on("click", ".timeline-event-details", function() {
// Show the parameters
- payloadTable = $(this).parent().find(".timeline-event-table")
- if (payloadTable.is(":visible")) {
+ payloadResults = $(this).parent().find(".timeline-event-results")
+ if (payloadResults.is(":visible")) {
$(this).find("i").removeClass("fa-caret-down")
$(this).find("i").addClass("fa-caret-right")
- payloadTable.hide()
+ payloadResults.hide()
} else {
$(this).find("i").removeClass("fa-caret-right")
$(this).find("i").addClass("fa-caret-down")
- payloadTable.show()
+ payloadResults.show()
}
})
// Setup our graphs
diff --git a/static/js/app/campaigns.js b/static/js/app/campaigns.js
index e6c7052b..d12d4736 100644
--- a/static/js/app/campaigns.js
+++ b/static/js/app/campaigns.js
@@ -35,6 +35,7 @@ function launch() {
host: $("input[name=host]").val(),
username: $("input[name=username]").val(),
password: $("input[name=password]").val(),
+ ignore_cert_errors: $("#ignore_cert_errors").prop("checked")
},
groups: groups
}
@@ -73,6 +74,7 @@ function sendTestEmail() {
host: $("input[name=host]").val(),
username: $("input[name=username]").val(),
password: $("input[name=password]").val(),
+ ignore_cert_errors: $("#ignore_cert_errors").prop("checked")
}
}
btnHtml = $("#sendTestModalSubmit").html()
diff --git a/templates/campaigns.html b/templates/campaigns.html
index e1c807f2..4075ed79 100644
--- a/templates/campaigns.html
+++ b/templates/campaigns.html
@@ -96,7 +96,10 @@
-
+
+
+
+
diff --git a/util/util.go b/util/util.go
index 7ab57d8e..7343246c 100644
--- a/util/util.go
+++ b/util/util.go
@@ -8,8 +8,8 @@ import (
"net/http"
"net/mail"
- "github.com/jordan-wright/email"
"github.com/gophish/gophish/models"
+ "github.com/jordan-wright/email"
)
// ParseMail takes in an HTTP Request and returns an Email object
diff --git a/worker/worker.go b/worker/worker.go
index 0044753b..fdbdb64f 100644
--- a/worker/worker.go
+++ b/worker/worker.go
@@ -2,6 +2,8 @@ package worker
import (
"bytes"
+ "crypto/tls"
+ "encoding/json"
"errors"
"log"
"net/mail"
@@ -52,6 +54,10 @@ func processCampaign(c *models.Campaign) {
if c.SMTP.Username != "" && c.SMTP.Password != "" {
auth = smtp.PlainAuth("", c.SMTP.Username, c.SMTP.Password, strings.Split(c.SMTP.Host, ":")[0])
}
+ tc := &tls.Config{
+ ServerName: c.SMTP.Host,
+ InsecureSkipVerify: c.SMTP.IgnoreCertErrors,
+ }
f, err := mail.ParseAddress(c.SMTP.FromAddress)
if err != nil {
Logger.Println(err)
@@ -108,14 +114,23 @@ func processCampaign(c *models.Campaign) {
Logger.Println("Creating email using template")
e.To = []string{t.Email}
Logger.Printf("Sending Email to %s\n", t.Email)
- err = e.Send(c.SMTP.Host, auth)
+ err = e.SendWithTLS(c.SMTP.Host, auth, tc)
if err != nil {
Logger.Println(err)
+ es := struct {
+ Error string `json:"error"`
+ }{
+ Error: err.Error(),
+ }
+ ej, err := json.Marshal(es)
+ if err != nil {
+ Logger.Println(err)
+ }
err = t.UpdateStatus(models.ERROR)
if err != nil {
Logger.Println(err)
}
- err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR})
+ err = c.AddEvent(models.Event{Email: t.Email, Message: models.EVENT_SENDING_ERROR, Details: string(ej)})
if err != nil {
Logger.Println(err)
}
@@ -145,6 +160,10 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
if s.SMTP.Username != "" && s.SMTP.Password != "" {
auth = smtp.PlainAuth("", s.SMTP.Username, s.SMTP.Password, strings.Split(s.SMTP.Host, ":")[0])
}
+ t := &tls.Config{
+ ServerName: s.SMTP.Host,
+ InsecureSkipVerify: s.SMTP.IgnoreCertErrors,
+ }
f, err := mail.ParseAddress(s.SMTP.FromAddress)
if err != nil {
Logger.Println(err)
@@ -188,7 +207,7 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
e.Subject = string(subjBuff.Bytes())
e.To = []string{s.Email}
Logger.Printf("Sending Email to %s\n", s.Email)
- err = e.Send(s.SMTP.Host, auth)
+ err = e.SendWithTLS(s.SMTP.Host, auth, t)
if err != nil {
Logger.Println(err)
// For now, let's split the error and return