summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolaus Gotsche <n@softwarefools.com>2018-02-21 03:25:05 +0100
committerNikolaus Gotsche <n@softwarefools.com>2018-02-21 03:25:05 +0100
commit27b333a73524b9a99145f0ca1f2a3a0181145351 (patch)
tree23f26f7a9a31bd72b3664e684ed7d4a96441e8d3
Mass Mailer - Send an email.html to all recipients in a maillist.csvHEADmaster
-rw-r--r--config.go129
-rw-r--r--crypt.go92
-rw-r--r--main.go113
-rw-r--r--utils.go59
4 files changed, 393 insertions, 0 deletions
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..d371bc9
--- /dev/null
+++ b/config.go
@@ -0,0 +1,129 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "io/ioutil"
+ "strconv"
+ "github.com/BurntSushi/toml"
+)
+
+type Config struct {
+ Mailacc MailAccount `toml:"MailAccount"`
+ Massmail MassMail `toml:"MassMail"`
+}
+type MailAccount struct {
+ Address string //`toml:"address"`
+ Name string //`toml:"name"`
+ Smtpurl string //`toml:"smtpurl"`
+ Port int //`toml:"port"`
+ Accountname string //`toml:"accountname"`
+ Accountpwd string //`toml:"accountpwd"`
+}
+type MassMail struct {
+ Listfile string //`toml:"listfile"`
+ Mailfile string //`toml:"mailfile"`
+ Bannerfile string //`toml:"bannerfile"`
+ Anrede []string //`toml:"anrede"`
+ Subject string //`toml:"subject"`
+}
+
+var config Config
+
+func initConf() {
+ goodconf := false
+ for !goodconf {
+ if _, err := toml.DecodeFile("myconfig.toml", &config); err != nil {
+ fmt.Println(err)
+ makeNewTOML(false)
+ }else{
+ showConfig()
+ //fmt.Println("Loaded Config:\n",config)
+ if isSure("Is this Configuration Correct?") {
+ goodconf = true
+ }else{
+ if isSure("Enter new Configuration?"){
+ makeNewTOML(true)
+ }else{
+ fmt.Println("I Really Dont think I can Help You then...! Goodbye.")
+ os.Exit(0)
+ }
+ }
+
+ }
+ }
+}
+
+func makeNewTOML(gibts bool) {
+ if gibts {
+ fmt.Println("Editing Configuration File\nPress [Enter] to keep the Current setting")
+ }else{
+ fmt.Println("Making new Configuration File")
+
+ arr := []string{"", "", ""}
+ ma0 := MailAccount{"","","",0,"",""}
+ mm0 := MassMail{"","","",arr,""}
+ config = Config{ma0,mm0}
+ }
+ fmt.Println("Enter properties of the Send-account\n")
+ email := getNewInput("Email Account to send from: ",config.Mailacc.Address)
+ mailname := getNewInput("Name for this Account: ",config.Mailacc.Name)
+ smtpurl := getNewInput("URL of the SMTP server: ",config.Mailacc.Smtpurl)
+ port := 0
+ var err error
+ if gibts {
+ fmt.Println("Current:",config.Mailacc.Port)
+ }
+ for{
+ strport := getInput("Port of the SMTP Server: ")
+ port,err = strconv.Atoi(strport)
+ if err != nil {
+ fmt.Println(" Please insert a valid Port number!!!")
+ }else {break}
+ }
+ logname := getNewInput("Login name of the Account: ",config.Mailacc.Accountname)
+ logpwd := Encrypt(getInput("Password of the Account: "))
+
+ ma := MailAccount{email,mailname,smtpurl,port,logname,logpwd}
+
+ fmt.Println("\nEnter properties of the Mass Mail\n")
+ listfile := getNewInput("Which .csv file should be used?: ",config.Massmail.Listfile)
+ mailfile := getNewInput("What .html template to use?: ",config.Massmail.Mailfile)
+ bannerfile := getNewInput("Name of the banner image: ",config.Massmail.Bannerfile)
+ subject := getNewInput("Subject of the Mass Mail: ",config.Massmail.Subject)
+ if gibts {
+ fmt.Println("Current Salutations:",config.Massmail.Anrede)
+ }
+ anredemale := getInput("Salutation for a Male recipient: ")
+ anredeneut := getInput("Salutation for a unknown recipient: ")
+ anredefemale := getInput("Salutation for a Female recipient: ")
+
+ strarr := []string{anredemale, anredeneut, anredefemale}
+ mm := MassMail{listfile, mailfile, bannerfile, strarr, subject}
+ conf := Config{ma,mm}
+
+ buf := new(bytes.Buffer)
+ err = toml.NewEncoder(buf).Encode(conf)
+ if err != nil {
+ panic(err)
+ }else{
+ //fmt.Println("Conffile:\n",buf.String())
+ fmt.Println("Writing Configuration File")
+ err = ioutil.WriteFile("myconfig.toml", buf.Bytes(), 0644)
+ checkErr(err)
+ }
+
+}
+
+func showConfig() {
+ buf := new(bytes.Buffer)
+ err := toml.NewEncoder(buf).Encode(config)
+ if err != nil {
+ panic(err)
+ }else{
+ fmt.Println("Configuration:\n",buf.String())
+ }
+}
+
+
diff --git a/crypt.go b/crypt.go
new file mode 100644
index 0000000..662184c
--- /dev/null
+++ b/crypt.go
@@ -0,0 +1,92 @@
+package main
+
+import (
+ "encoding/base64"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "os"
+ //"strconv"
+)
+
+func cryptexample() {
+ fmt.Println("Testing Cryptics")
+ //key := "123456789012345678901234" // Needs to be 32 bytes long
+ //key := "Have some of the beautiful ideas"
+ plaintext1 := "Hello! You Fool! I Love You"
+ plaintext2 := "Somefancy Password"
+ foo := Encrypt(plaintext1)
+ fook := Decrypt(foo)
+ fmt.Printf("%s -> %s\n",plaintext1,foo)
+ fmt.Printf("%s -> %s\n\n",foo,fook)
+ bar := Encrypt(plaintext2)
+ barn := Decrypt(bar)
+ fmt.Printf("%s -> %s\n",plaintext2,bar)
+ fmt.Printf("%s -> %s\n\n",bar,barn)
+ os.Exit(0)
+}
+
+ //key := "123456789012345678901234" // Needs to be 32 bytes long
+var keystr string = "Have some of the beautiful ideas"
+
+func encodeBase64(inp string) string {
+ b := []byte(inp)
+ return base64.StdEncoding.EncodeToString(b)
+}
+
+func decodeBase64(s string) string {
+ data, err := base64.StdEncoding.DecodeString(s)
+ if err != nil { panic(err) }
+ return string(data)
+}
+
+func Encrypt(textstr string) string {
+ text := []byte(textstr)
+ key := []byte(keystr)
+
+ //fmt.Println(text)
+ block, err := aes.NewCipher([]byte(key))
+ checkErr(err)
+
+ b := base64.StdEncoding.EncodeToString(text)
+ ciphertext := make([]byte, aes.BlockSize+len(b))
+ iv := ciphertext[:aes.BlockSize]
+ _, err = io.ReadFull(rand.Reader, iv)
+ checkErr(err)
+ cfb := cipher.NewCFBEncrypter(block, iv)
+ cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
+ return encodeBase64(string(ciphertext))
+
+}
+
+func Decrypt(textstr string) string {
+
+ text := []byte(decodeBase64(textstr))
+ key := []byte(keystr)
+ //checkErr(err)
+
+ block, err := aes.NewCipher(key)
+ checkErr(err)
+ if len(text) < aes.BlockSize {
+ return "GEEEH SCHIESSEN! ZU Kurz?"
+ //return nil, errors.New("ciphertext too short")
+ }
+ iv := text[:aes.BlockSize]
+ text = text[aes.BlockSize:]
+ cfb := cipher.NewCFBDecrypter(block, iv)
+ cfb.XORKeyStream(text, text)
+ //data, err := base64.StdEncoding.DecodeString(string(text[aes.BlockSize:]))
+ data, err := base64.StdEncoding.DecodeString(string(text))
+ checkErr(err)
+ return string(data)
+ //if err != nil { panic(err) }
+ //ciphertext := decodeBase64(text)
+ //cfb := cipher.NewCFBEncrypter(block, iv)
+ //plaintext := make([]byte, len(ciphertext))
+ //cfb.XORKeyStream(plaintext, ciphertext)
+ //return string(plaintext)
+}
+
+
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..8ee421a
--- /dev/null
+++ b/main.go
@@ -0,0 +1,113 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "os"
+ "encoding/csv"
+ "strconv"
+
+ "gopkg.in/gomail.v2"
+)
+
+type Customer struct {
+ Name string
+ email string
+ Anrede string
+ gender int
+}
+type MailList struct {
+ customers []Customer
+}
+
+var list []Customer
+var filename string = "testlist.csv"
+
+func init() {
+ //cryptexample()
+ fmt.Println(" Starting MassMailer\n ##################################\n")
+ initConf()
+
+ file, err := os.Open(config.Massmail.Listfile)
+ if err != nil {
+ panic(err)
+ }else{
+ fmt.Println("\n",config.Massmail.Listfile, "opened Successfully!")
+ }
+ defer file.Close()
+
+ reader := csv.NewReader(file)
+ reader.Comma = ';'
+ lineCount := 0
+
+
+
+ for {
+ line , erro := reader.Read()
+ if erro == io.EOF {
+ break
+ }else if erro != nil {
+ panic(erro)
+ }
+ gen, err := strconv.Atoi(line[2])
+ if err != nil {
+ panic(err)
+ }
+ anrede := config.Massmail.Anrede[(gen+1)]
+ cn := Customer{Name: line[0], email: line[1], Anrede: anrede, gender: gen}
+ list = append(list, cn)
+ fmt.Println(cn)
+ lineCount += 1
+ }
+ fmt.Println("\n All Customers:",lineCount)
+}
+
+func main() {
+ if isSure("Send the Mail to all Customers?"){
+ for _ , c := range list{
+ err := SendMail(c)
+ if err==nil{
+ fmt.Println("Sending Mail to",c.Anrede,c.Name,"Done Successful")
+ }else{
+ panic(err)
+ }
+ }
+ }else{
+ fmt.Println(" ok... bye then!")
+ }
+}
+
+func SendMail(cust Customer) error {
+ t, err := template.ParseFiles(config.Massmail.Mailfile)
+ if err != nil {
+ return err
+ }
+ buf := new(bytes.Buffer)
+ err = t.Execute(buf, cust)
+ if err != nil {
+ return err
+ }
+ pass := Decrypt(config.Mailacc.Accountpwd)
+
+ m := gomail.NewMessage()
+ m.SetHeader("From", m.FormatAddress(config.Mailacc.Address , config.Mailacc.Name))
+ m.SetHeader("To", cust.email)
+ //m.SetAddressHeader("Cc", "test@mail.com", "Dan")
+ m.SetHeader("Subject", config.Massmail.Subject)
+ m.SetBody("text/html", buf.String())
+ //m.Attach("someimage.jpg", gomail.Rename("logo.jpg"))
+ m.Embed(config.Massmail.Bannerfile)
+
+ d := gomail.NewDialer(config.Mailacc.Smtpurl, config.Mailacc.Port, config.Mailacc.Accountname, pass)
+
+ // Send the email to Bob, Cora and Dan.
+ if err := d.DialAndSend(m); err != nil {
+ fmt.Println("Connecting to Email Server Failed! Check your Accountname and Password\nError:")
+ panic(err)
+ }
+ return nil
+}
+
+
diff --git a/utils.go b/utils.go
new file mode 100644
index 0000000..4daa4fc
--- /dev/null
+++ b/utils.go
@@ -0,0 +1,59 @@
+package main
+
+import (
+ "fmt"
+ "bufio"
+ "os"
+ "strings"
+)
+
+func isSure(quest string) bool {
+ fmt.Printf("%s (type 'y/Y/yes' to confirm) : ",quest)
+ in := bufio.NewReader(os.Stdin)
+ line, err := in.ReadString('\n')
+ line = strings.TrimSuffix(line, "\n")
+ //line = strings.TrimSuffix(line, "\r\n") //for Windows
+ checkErr(err)
+
+ if ( line == "yes" || line == "y" || line == "Y") {
+ return true
+ } else {
+ return false
+ }
+}
+
+func checkErr(err error) {
+ if err != nil {
+ panic(err)
+ }
+}
+
+func getInput(quest string) string {
+ fmt.Print(quest)
+ in := bufio.NewReader(os.Stdin)
+ line, err := in.ReadString('\n')
+ line = strings.TrimSuffix(line, "\n")
+ //line = strings.TrimSuffix(line, "\r\n")//for windows
+ checkErr(err)
+ return line
+}
+
+func getNewInput(quest,old string) string {
+ if old != "" {
+ fmt.Println("Current:",old)
+ }
+ fmt.Print(quest)
+ in := bufio.NewReader(os.Stdin)
+ line, err := in.ReadString('\n')
+ line = strings.TrimSuffix(line, "\n")
+ //line = strings.TrimSuffix(line, "\r\n")//for windows
+ checkErr(err)
+ if line == "" {
+ return old
+ }else{
+ return line
+ }
+}
+
+
+