Fix email encoding
This commit is contained in:
parent
fc301b48ef
commit
e88250a913
4 changed files with 73 additions and 39 deletions
|
@ -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()
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
// "gopkg.in/russross/blackfriday.v2"
|
// "gopkg.in/russross/blackfriday.v2"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -26,6 +24,7 @@ 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()
|
||||||
|
|
Loading…
Reference in a new issue