Fix email encoding

This commit is contained in:
Glenn Y. Rolland 2018-08-22 18:57:50 +02:00
parent fc301b48ef
commit e88250a913
4 changed files with 73 additions and 39 deletions

View file

@ -1,21 +1,35 @@
package main package main
// TODO: use https://github.com/domodwyer/mailyak as a base lib
import ( import (
"bytes" "bytes"
"encoding/base64"
"fmt" "fmt"
"github.com/davecgh/go-spew/spew" // "github.com/davecgh/go-spew/spew"
"strings" "strings"
// "log" // "log"
// "strconv" // "strconv"
"math/rand"
"net/mail" "net/mail"
) )
type EmailHeaders map[string]string type EmailHeaders map[string]string
type EmailBody string
type EmailCtx struct { type EmailCtx struct {
Headers EmailHeaders Headers EmailHeaders
Body EmailBody BodyPlain string
BodyHtml string
}
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func RandStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
} }
func (headers EmailHeaders) String() string { func (headers EmailHeaders) String() string {
@ -26,14 +40,6 @@ func (headers EmailHeaders) String() string {
return buffer.String() return buffer.String()
} }
func (body EmailBody) String() string {
res := string(body)
if false {
spew.Dump(res)
}
return res
}
func NewEmail() *EmailCtx { func NewEmail() *EmailCtx {
email := EmailCtx{} email := EmailCtx{}
email.Headers = make(EmailHeaders) email.Headers = make(EmailHeaders)
@ -46,23 +52,57 @@ func encodeRFC2047(text string) string {
return strings.Trim(addr.String(), " \"<@>") return strings.Trim(addr.String(), " \"<@>")
} }
func (email *EmailCtx) MakeHeaders(config EmailConfig) { func (email *EmailCtx) SetHeaders(config EmailConfig) {
email.Headers["Return-Path"] = config.From email.Headers["Return-Path"] = config.From
email.Headers["From"] = config.From email.Headers["From"] = config.From
email.Headers["To"] = config.To email.Headers["To"] = config.To
email.Headers["Subject"] = encodeRFC2047(config.Subject) email.Headers["Subject"] = encodeRFC2047(config.Subject)
// email.Headers["Content-Type"] = "text/plain; charset=\"us-ascii\";" email.Headers["Content-Transfer-Encoding"] = "quoted-printable"
email.Headers["Content-Type"] = "text/plain; charset=\"utf-8\";"
email.Headers["Content-Transfer-Encoding"] = "base64"
email.Headers["MIME-Version"] = "1.0" email.Headers["MIME-Version"] = "1.0"
return return
} }
func (email *EmailCtx) MakeBody(content string) { func (email *EmailCtx) SetBody(html string, plain string) {
email.Body = EmailBody(content) email.BodyPlain = plain
if false { email.BodyHtml = html
spew.Dump(email.Body)
}
return return
} }
func (email *EmailCtx) String() string {
var buffer bytes.Buffer
mixBoundary := RandStringBytes(16)
altBoundary := RandStringBytes(16)
buffer.WriteString(email.Headers.String())
buffer.WriteString(fmt.Sprintf("Content-Type: multipart/mixed;\r\n boundary=\"%s\"\r\n", mixBoundary))
buffer.WriteString("\r\n")
buffer.WriteString(fmt.Sprintf("--%s\r\n", mixBoundary))
buffer.WriteString(fmt.Sprintf("Content-Type: multipart/alternative;\r\n boundary=\"%s\"\r\n", altBoundary))
buffer.WriteString("\r\n")
buffer.WriteString(fmt.Sprintf("--%s\r\n", altBoundary))
buffer.WriteString(fmt.Sprintf("Content-Type: text/plain; charset=\"utf-8\"\r\n"))
buffer.WriteString(fmt.Sprintf("Content-Transfer-Encoding: base64\r\n"))
buffer.WriteString("\r\n")
buffer.WriteString(base64.StdEncoding.EncodeToString([]byte(email.BodyPlain)))
buffer.WriteString("\r\n")
buffer.WriteString("\r\n")
buffer.WriteString(fmt.Sprintf("--%s\r\n", altBoundary))
buffer.WriteString(fmt.Sprintf("Content-Type: text/html; charset=\"utf-8\"\r\n"))
buffer.WriteString(fmt.Sprintf("Content-Transfer-Encoding: base64\r\n"))
buffer.WriteString("\r\n")
buffer.WriteString(base64.StdEncoding.EncodeToString([]byte(email.BodyHtml)))
buffer.WriteString("\r\n")
buffer.WriteString("\r\n")
buffer.WriteString(fmt.Sprintf("--%s--\r\n", altBoundary))
buffer.WriteString("\r\n")
buffer.WriteString(fmt.Sprintf("--%s--\r\n", mixBoundary))
buffer.WriteString("\r\n")
return buffer.String()
}

View file

@ -1,8 +1,9 @@
package main package main
import ( import (
// "gopkg.in/russross/blackfriday.v2" "fmt"
// "github.com/davecgh/go-spew/spew" // "gopkg.in/russross/blackfriday.v2"
// "github.com/davecgh/go-spew/spew"
) )
func main() { func main() {
@ -14,11 +15,13 @@ func main() {
trelloCtx := NewTrello(config.Trello.Token) trelloCtx := NewTrello(config.Trello.Token)
trelloBoard := trelloCtx.GetBoard(config.Trello.Url) trelloBoard := trelloCtx.GetBoard(config.Trello.Url)
trelloMarkdown := trelloBoard.ExportToMarkdown() trelloMarkdown := trelloBoard.ExportToMarkdown()
trelloHtml := trelloBoard.ExportToHtml()
config.Email.Subject = fmt.Sprintf("Daily mail for %s", trelloBoard.Name)
// Create email enveloppe // Create email enveloppe
email := NewEmail() email := NewEmail()
email.MakeHeaders(config.Email) email.SetHeaders(config.Email)
email.MakeBody(trelloMarkdown) email.SetBody(trelloHtml, trelloMarkdown)
// Connect and send email // Connect and send email
transport := NewTransport(config.Smtp) transport := NewTransport(config.Smtp)

View file

@ -3,7 +3,6 @@ package main
import ( import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"encoding/base64"
"fmt" "fmt"
"log" "log"
"net/smtp" "net/smtp"
@ -122,11 +121,7 @@ func (ctx *TransportCtx) Send(email *EmailCtx) {
} }
defer wc.Close() defer wc.Close()
var buffer bytes.Buffer buffer := bytes.NewBufferString(email.String())
buffer.WriteString(email.Headers.String())
buffer.WriteString("\r\n")
buffer.WriteString(base64.StdEncoding.EncodeToString([]byte(email.Body.String())))
if _, err = buffer.WriteTo(wc); err != nil { if _, err = buffer.WriteTo(wc); err != nil {
log.Panic(err) log.Panic(err)
} }

View file

@ -4,8 +4,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/adlio/trello" "github.com/adlio/trello"
// "github.com/davecgh/go-spew/spew"
"gopkg.in/russross/blackfriday.v2" "gopkg.in/russross/blackfriday.v2"
"log" "log"
"net/url" "net/url"
@ -24,8 +22,9 @@ type TrelloCtx struct {
} }
type TrelloBoard struct { type TrelloBoard struct {
Ctx *TrelloCtx Ctx *TrelloCtx
Ptr *trello.Board Ptr *trello.Board
Name string
} }
func runcmd(command string) string { func runcmd(command string) string {
@ -75,10 +74,8 @@ func (ctx *TrelloCtx) GetBoard(boardUrl string) TrelloBoard {
} }
boardId := strings.Split(parsedUrl.Path, "/")[2] boardId := strings.Split(parsedUrl.Path, "/")[2]
// spew.Dump(boardId)
board, err := ctx.Client.GetBoard(boardId, trello.Defaults()) board, err := ctx.Client.GetBoard(boardId, trello.Defaults())
// spew.Dump(board) return TrelloBoard{Ctx: ctx, Ptr: board, Name: board.Name}
return TrelloBoard{Ctx: ctx, Ptr: board}
} }
func (board *TrelloBoard) ExportToMarkdown() string { func (board *TrelloBoard) ExportToMarkdown() string {
@ -108,7 +105,6 @@ func (board *TrelloBoard) ExportToMarkdown() string {
for _, card := range cards { for _, card := range cards {
text := fmt.Sprintf("* %s\n", card.Name) text := fmt.Sprintf("* %s\n", card.Name)
markdown.WriteString(text) markdown.WriteString(text)
// spew.Dump(card)
} }
} }
return markdown.String() return markdown.String()