mirror of https://github.com/gophish/gophish
Compare commits
4 Commits
fc7fb2b7c6
...
9efae77f6f
Author | SHA1 | Date |
---|---|---|
David Maciejak | 9efae77f6f | |
Jordan Wright | 9561846979 | |
Caetan | 908886f2cd | |
David Maciejak | 22f881e7ea |
|
@ -1,5 +1,7 @@
|
||||||
name: CI
|
name: CI
|
||||||
on: [push]
|
on:
|
||||||
|
- pull_request
|
||||||
|
- push
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
@ -7,17 +9,17 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
goVer: [1.16, 1.17, 1.18]
|
goVer: [1.21, 1.22, 1.23]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go ${{ matrix.goVer }}
|
- name: Set up Go ${{ matrix.goVer }}
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.goVer }}
|
go-version: ${{ matrix.goVer }}
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: |
|
run: |
|
||||||
|
@ -31,4 +33,4 @@ jobs:
|
||||||
run: diff -u <(echo -n) <(gofmt -d .)
|
run: diff -u <(echo -n) <(gofmt -d .)
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -v ./...
|
run: go test ./...
|
||||||
|
|
|
@ -38,7 +38,7 @@ jobs:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.14
|
go-version: 1.22
|
||||||
- if: matrix.os == 'ubuntu-latest'
|
- if: matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt-get update && sudo apt-get install -y gcc-multilib
|
run: sudo apt-get update && sudo apt-get install -y gcc-multilib
|
||||||
- if: matrix.arch == '386'
|
- if: matrix.arch == '386'
|
||||||
|
@ -47,7 +47,7 @@ jobs:
|
||||||
run: echo "RELEASE=gophish-${{ github.event.release.tag_name }}-${{ matrix.releaseos }}-64bit" >> $GITHUB_ENV
|
run: echo "RELEASE=gophish-${{ github.event.release.tag_name }}-${{ matrix.releaseos }}-64bit" >> $GITHUB_ENV
|
||||||
- if: matrix.os == 'windows-latest'
|
- if: matrix.os == 'windows-latest'
|
||||||
run: echo "RELEASE=gophish-${{ github.event.release.tag_name }}-${{ matrix.releaseos }}-64bit" | Out-File -FilePath $env:GITHUB_ENV -Append # https://github.com/actions/runner/issues/1636
|
run: echo "RELEASE=gophish-${{ github.event.release.tag_name }}-${{ matrix.releaseos }}-64bit" | Out-File -FilePath $env:GITHUB_ENV -Append # https://github.com/actions/runner/issues/1636
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Build ${{ matrix.goos }}/${{ matrix.arch }}
|
- name: Build ${{ matrix.goos }}/${{ matrix.arch }}
|
||||||
run: go build -o ${{ matrix.bin }}
|
run: go build -o ${{ matrix.bin }}
|
||||||
env:
|
env:
|
||||||
|
@ -55,7 +55,7 @@ jobs:
|
||||||
GOARCH: ${{ matrix.arch }}
|
GOARCH: ${{ matrix.arch }}
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
- name: Upload to artifacts
|
- name: Upload to artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE }}
|
name: ${{ env.RELEASE }}
|
||||||
path: ${{ matrix.bin }}
|
path: ${{ matrix.bin }}
|
||||||
|
@ -65,8 +65,8 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: bin
|
path: bin
|
||||||
- name: Package Releases
|
- name: Package Releases
|
||||||
|
@ -96,7 +96,7 @@ jobs:
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
- name: Upload to artifacts
|
- name: Upload to artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: releases
|
name: releases
|
||||||
path: releases/*.zip
|
path: releases/*.zip
|
||||||
|
@ -106,7 +106,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: package
|
needs: package
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: releases
|
name: releases
|
||||||
path: releases/
|
path: releases/
|
||||||
|
|
|
@ -49,6 +49,44 @@ func (as *Server) ImportGroup(w http.ResponseWriter, r *http.Request) {
|
||||||
JSONResponse(w, ts, http.StatusOK)
|
JSONResponse(w, ts, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImportEmailFile allows for the importing of email.
|
||||||
|
// Returns a Message object
|
||||||
|
func (as *Server) ImportEmailFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if r.Method != "POST" {
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: "Method not allowed"}, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mr, nil := r.MultipartReader()
|
||||||
|
part, nil := mr.NextPart()
|
||||||
|
e, err := email.NewEmailFromReader(part)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
d, err := goquery.NewDocumentFromReader(bytes.NewReader(e.HTML))
|
||||||
|
if err != nil {
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.Find("a").Each(func(i int, a *goquery.Selection) {
|
||||||
|
a.SetAttr("href", "{{.URL}}")
|
||||||
|
})
|
||||||
|
h, err := d.Html()
|
||||||
|
if err != nil {
|
||||||
|
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.HTML = []byte(h)
|
||||||
|
|
||||||
|
er := emailResponse{
|
||||||
|
Subject: e.Subject,
|
||||||
|
Text: string(e.Text),
|
||||||
|
HTML: string(e.HTML),
|
||||||
|
}
|
||||||
|
JSONResponse(w, er, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// ImportEmail allows for the importing of email.
|
// ImportEmail allows for the importing of email.
|
||||||
// Returns a Message object
|
// Returns a Message object
|
||||||
func (as *Server) ImportEmail(w http.ResponseWriter, r *http.Request) {
|
func (as *Server) ImportEmail(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -82,6 +82,7 @@ func (as *Server) registerRoutes() {
|
||||||
router.HandleFunc("/util/send_test_email", as.SendTestEmail)
|
router.HandleFunc("/util/send_test_email", as.SendTestEmail)
|
||||||
router.HandleFunc("/import/group", as.ImportGroup)
|
router.HandleFunc("/import/group", as.ImportGroup)
|
||||||
router.HandleFunc("/import/email", as.ImportEmail)
|
router.HandleFunc("/import/email", as.ImportEmail)
|
||||||
|
router.HandleFunc("/import/emailfile", as.ImportEmailFile)
|
||||||
router.HandleFunc("/import/site", as.ImportSite)
|
router.HandleFunc("/import/site", as.ImportSite)
|
||||||
router.HandleFunc("/webhooks/", mid.Use(as.Webhooks, mid.RequirePermission(models.PermissionModifySystem)))
|
router.HandleFunc("/webhooks/", mid.Use(as.Webhooks, mid.RequirePermission(models.PermissionModifySystem)))
|
||||||
router.HandleFunc("/webhooks/{id:[0-9]+}/validate", mid.Use(as.ValidateWebhook, mid.RequirePermission(models.PermissionModifySystem)))
|
router.HandleFunc("/webhooks/{id:[0-9]+}/validate", mid.Use(as.ValidateWebhook, mid.RequirePermission(models.PermissionModifySystem)))
|
||||||
|
|
|
@ -109,6 +109,7 @@ func (as *Server) Users(w http.ResponseWriter, r *http.Request) {
|
||||||
Role: role,
|
Role: role,
|
||||||
RoleID: role.ID,
|
RoleID: role.ID,
|
||||||
PasswordChangeRequired: ur.PasswordChangeRequired,
|
PasswordChangeRequired: ur.PasswordChangeRequired,
|
||||||
|
AccountLocked: ur.AccountLocked,
|
||||||
}
|
}
|
||||||
err = models.PutUser(&user)
|
err = models.PutUser(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -115,8 +115,8 @@ func (im *Monitor) Shutdown() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkForNewEmails logs into an IMAP account and checks unread emails
|
// checkForNewEmails logs into an IMAP account and checks unread emails for the
|
||||||
// for the rid campaign identifier.
|
// rid campaign identifier.
|
||||||
func checkForNewEmails(im models.IMAP) {
|
func checkForNewEmails(im models.IMAP) {
|
||||||
im.Host = im.Host + ":" + strconv.Itoa(int(im.Port)) // Append port
|
im.Host = im.Host + ":" + strconv.Itoa(int(im.Port)) // Append port
|
||||||
mailServer := Mailbox{
|
mailServer := Mailbox{
|
||||||
|
|
|
@ -609,7 +609,7 @@ func PostCampaign(c *Campaign, uid int64) error {
|
||||||
return tx.Commit().Error
|
return tx.Commit().Error
|
||||||
}
|
}
|
||||||
|
|
||||||
//DeleteCampaign deletes the specified campaign
|
// DeleteCampaign deletes the specified campaign
|
||||||
func DeleteCampaign(id int64) error {
|
func DeleteCampaign(id int64) error {
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"campaign_id": id,
|
"campaign_id": id,
|
||||||
|
|
|
@ -222,6 +222,36 @@ function edit(idx) {
|
||||||
.remove()
|
.remove()
|
||||||
.draw();
|
.draw();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Handle file uploads
|
||||||
|
$("#emlupload").fileupload({
|
||||||
|
url: "/api/import/emailfile",
|
||||||
|
dataType: "json",
|
||||||
|
beforeSend: function (xhr) {
|
||||||
|
xhr.setRequestHeader('Authorization', 'Bearer ' + user.api_key);
|
||||||
|
},
|
||||||
|
add: function (e, data) {
|
||||||
|
$("#modal\\.flashes").empty()
|
||||||
|
var acceptFileTypes = /(eml)$/i;
|
||||||
|
var filename = data.originalFiles[0]['name']
|
||||||
|
if (filename && !acceptFileTypes.test(filename.split(".").pop())) {
|
||||||
|
modalError("Unsupported file extension (use .eml)")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data.submit();
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
$("#text_editor").val(data.text)
|
||||||
|
$("#html_editor").val(data.html)
|
||||||
|
$("#subject").val(data.subject)
|
||||||
|
// If the HTML is provided, let's open that view in the editor
|
||||||
|
if (data.html) {
|
||||||
|
CKEDITOR.instances["html_editor"].setMode('wysiwyg')
|
||||||
|
$('.nav-tabs a[href="#html"]').click()
|
||||||
|
}
|
||||||
|
$("#importEmailModal").modal("hide")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy(idx) {
|
function copy(idx) {
|
||||||
|
|
|
@ -52,8 +52,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button class="btn btn-danger" data-toggle="modal" data-backdrop="static" data-target="#importEmailModal"><i
|
<button class="btn btn-danger" data-toggle="modal" data-backdrop="static" data-target="#importEmailModal"><i
|
||||||
class="fa fa-envelope"></i>
|
class="fa fa-paste"></i>
|
||||||
Import Email</button>
|
Paste Raw Email</button>
|
||||||
|
<button class="btn btn-danger btn-file" data-toggle="tooltip" data-placement="right" title="Supports EML files" id="fileUpload"><i
|
||||||
|
class="fa fa-file"></i>
|
||||||
|
Import Email File<input type="file" id="emlupload"></button>
|
||||||
</div>
|
</div>
|
||||||
<label class="control-label" for="envelope-sender">Envelope Sender: <i class="fa fa-question-circle" data-toggle="tooltip" data-placement="right" title="This sender is shown to the user by most email clients. Defaults to the SMTP From as defined in the Sending Profile."></i></label>
|
<label class="control-label" for="envelope-sender">Envelope Sender: <i class="fa fa-question-circle" data-toggle="tooltip" data-placement="right" title="This sender is shown to the user by most email clients. Defaults to the SMTP From as defined in the Sending Profile."></i></label>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
Loading…
Reference in New Issue