Skip to content

Commit

Permalink
- Add mail sending capabilities (net/smtp)
Browse files Browse the repository at this point in the history
- Various changes to the code
  • Loading branch information
0x111 committed Apr 29, 2019
1 parent 5bd4e2a commit b92b5d4
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
rs-backup.json
build/
32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.PHONY: all
all: build_linux_amd64 build_darwin_amd64 build_windows_amd64 checksums

.PHONY: build_linux_amd64
build_linux_amd64:
GOOS=linux GOARCH=amd64 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-linux-amd64

.PHONY: build_linux_i386
build_linux_i386:
GOOS=linux GOARCH=386 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-linux-i386

.PHONY: build_darwin_amd64
build_darwin_amd64:
GOOS=darwin GOARCH=amd64 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-darwin-amd64

.PHONY: build_darwin_i386
build_darwin_i386:
GOOS=darwin GOARCH=386 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-darwin-i386

.PHONY: build_windows_amd64
build_windows_amd64:
CC=/usr/local/bin/x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-windows-amd64.exe

.PHONY: build_windows_i386
build_windows_i386:
CC=/usr/local/bin/x86_64-w64-mingw32-gcc GOOS=windows GOARCH=386 go build -v -a -gcflags=-trimpath=$$PWD -asmflags=-trimpath=$$PWD -o build/rs-backup-windows-i386.exe

.PHONY: checksums
checksums:
shasum -a 256 build/* > build/checksum.txt

test:
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## rs-backup

A simple wrapper around rsync written in Go with mail sending possibilities.
A simple wrapper around rsync written in Go with mail sending possibilities.

The config is minimalistic, set the flags to true which you would like to be included in the command.

If you set `log` to true, the app will create a temporary file in the system tmp folder and will log the rsync output to that file and will attach this in the email sent at the end.

If the process is complete, there will be an email sent to the specified to adresses in the config. (accepts multiple adresses i.e. array of strings).

If there are any questions or bugs, please feel free to open an issue.
15 changes: 15 additions & 0 deletions helpers/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package helpers

import (
"fmt"
"io/ioutil"
)

func ReadFileContent(fileName string) []byte {
b, err := ioutil.ReadFile(fileName) // just pass the file name
if err != nil {
fmt.Print(err)
}

return b
}
127 changes: 122 additions & 5 deletions rs-backup.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
package main

import (
"encoding/base64"
"fmt"
"github.com/0x111/rs-backup/helpers"
"github.com/spf13/viper"
"io/ioutil"
"log"
"net/smtp"
"os"
"os/exec"
"strconv"
"strings"
_ "text/template"
"time"
)

func main() {
var err error
// log start time
start := time.Now()
log.Printf("Starting backup process %s", start)
// load config
viper.SetConfigName("rs-backup") // name of config file (without extension)
viper.AddConfigPath("/etc/rs-backup/") // path to look for the config file in
Expand All @@ -27,12 +39,117 @@ func main() {
log.Fatal("We could not find rsync in your path!")
}

fmt.Println(path)

// cmd
var args []string
// Dynamically append arguments to the args
if viper.GetBool("show_progress") == true {
args = append(args, "--progress")
}

if viper.GetBool("force_ipv4") == true {
args = append(args, "--ipv4")
}

if viper.GetBool("archive") == true {
args = append(args, "--archive")
}

if viper.GetBool("verbose") == true {
args = append(args, "--verbose")
}

if viper.GetBool("compress") == true {
args = append(args, "--compress")
}

remoteShellCommand := viper.GetString("remote_shell_command")

if remoteShellCommand != "" && len(remoteShellCommand) > 0 {
args = append(args, "--rsh")
sshCmd := fmt.Sprintf("%s", remoteShellCommand)
args = append(args, sshCmd)
}

// create a temporary file
file, err := ioutil.TempFile("", "rs-backup")
logFileName := file.Name() + ".log"
if err != nil {
log.Fatal(err)
}

defer os.Remove(logFileName)

if viper.GetBool("log") == true {
args = append(args, "--log-file="+logFileName)
}

localDirectoryPath := viper.GetString("local_directory_path")

if localDirectoryPath != "" && len(localDirectoryPath) > 0 {
args = append(args, localDirectoryPath)
}

remoteDirectoryPath := viper.GetString("remote_directory_path")

if remoteDirectoryPath != "" && len(remoteDirectoryPath) > 0 {
args = append(args, remoteDirectoryPath)
}

cmd := exec.Command("sleep", "5")
log.Println("Running command and waiting for it to finish...")
err = cmd.Run()
log.Printf("Command finished with error: %v", err)
_, err = exec.Command(path, args...).Output()

if err != nil {
//log.Fatal(fmt.Printf("Command finished with error: %v", err))
fmt.Println("asd")
}

sendTo := viper.GetStringSlice("mail.to")
// Content-Type: text/html; charset="UTF-8";
fileContent := helpers.ReadFileContent(logFileName)
mailBody := `From: %s
To: %s
Subject: Backup run at %s
Content-Type: multipart/mixed; boundary=_rssbckkgthbscrpt14467_
Content-Transfer-Encoding: 7bit
--_rssbckkgthbscrpt14467_
MIME-Version: 1.0
Content-Type: text/html; charset="UTF-8";
Content-Transfer-Encoding: 7bit
Backup started at: %s<br />
Backup ended at: %s <br />
Backup took: %s <br />
Find the contents of the rsync log in the attached log file.
<br />
Mailed by <a href="https://github.com/0x111/rs-backup">0x111/rs-backup</a>.<br />
--_rssbckkgthbscrpt14467_
Content-Type: application/octet-stream; name="rsync.log"
Content-Disposition: attachment; filename="rsync.log"
Content-Transfer-Encoding: base64
%s
--_rssbckkgthbscrpt14467_
`

// variables to make ExamplePlainAuth compile, without adding
// unnecessary noise there.
var (
from = viper.GetString("mail.from")
recipients = sendTo
)

end := time.Now().Format(time.RFC822)
mailBody = fmt.Sprintf(mailBody, from, strings.Join(sendTo, ","), start.Format(time.RFC822), start.Format(time.RFC822), end, time.Since(start), base64.StdEncoding.EncodeToString(fileContent))
msg := []byte(mailBody)

// hostname is used by PlainAuth to validate the TLS certificate.
hostname := viper.GetString("smtp.host")
port := strconv.Itoa(viper.GetInt("smtp.port"))
auth := smtp.PlainAuth("", viper.GetString("smtp.user"), viper.GetString("smtp.password"), hostname)

err = smtp.SendMail(hostname+":"+port, auth, from, recipients, msg)
if err != nil {
log.Fatal(err)
}
}
24 changes: 24 additions & 0 deletions rs-backup.sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"show_progress": true,
"force_ipv4": true,
"archive": true,
"verbose": true,
"compress": true,
"log": true,
"local_directory_path": "/path/to/the/directory",
"remote_directory_path": "remote_user@remote_host:/remote_path/to/directory",
"remote_shell_command": "ssh -p23",
"mail": {
"from": "[email protected]",
"to": [
"[email protected]",
"[email protected]"
]
},
"smtp": {
"host": "mailhost.com",
"user": "[email protected]",
"password": "password",
"port": 25
}
}

0 comments on commit b92b5d4

Please sign in to comment.