summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/rsc/google/gmailsend/send.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/rsc/google/gmailsend/send.go')
-rw-r--r--vendor/github.com/mattermost/rsc/google/gmailsend/send.go370
1 files changed, 370 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/rsc/google/gmailsend/send.go b/vendor/github.com/mattermost/rsc/google/gmailsend/send.go
new file mode 100644
index 000000000..ace6eb12b
--- /dev/null
+++ b/vendor/github.com/mattermost/rsc/google/gmailsend/send.go
@@ -0,0 +1,370 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "flag"
+ "fmt"
+ "io"
+ "net/smtp"
+ "os"
+ "regexp"
+ "strings"
+
+ "github.com/mattermost/rsc/google"
+)
+
+func enc(s string) string {
+ // TODO =? .. ?=
+ return s
+}
+
+type Addr struct {
+ Name string
+ Email string
+}
+
+func (a Addr) enc() string {
+ if a.Name == "" {
+ return "<" + a.Email + ">"
+ }
+ if a.Email == "" {
+ return enc(a.Name) + ":;"
+ }
+ return enc(a.Name) + " <" + a.Email + ">"
+}
+
+type Addrs []Addr
+
+func (a *Addrs) String() string {
+ return "[addrlist]"
+}
+
+func (a Addrs) has(s string) bool {
+ for _, aa := range a {
+ if aa.Email == s {
+ return true
+ }
+ }
+ return false
+}
+
+func (a *Addrs) Set(s string) bool {
+ s = strings.TrimSpace(s)
+ if strings.HasSuffix(s, ">") {
+ j := strings.LastIndex(s, "<")
+ if j >= 0 {
+ *a = append(*a, Addr{strings.TrimSpace(s[:j]), s[j+1 : len(s)-1]})
+ return true
+ }
+ }
+
+ if strings.Contains(s, " ") {
+ fmt.Fprintf(os.Stderr, "invalid address: %s", s)
+ os.Exit(2)
+ }
+ *a = append(*a, Addr{"", s})
+ return true
+}
+
+func (a *Addrs) parseLine(s string) {
+ for _, f := range strings.Split(s, ",") {
+ f = strings.TrimSpace(f)
+ if f != "" {
+ a.Set(f)
+ }
+ }
+}
+
+func (a Addrs) fixDomain() {
+ i := strings.Index(acct.Email, "@")
+ if i < 0 {
+ return
+ }
+ dom := acct.Email[i:]
+ for i := range a {
+ if a[i].Email != "" && !strings.Contains(a[i].Email, "@") {
+ a[i].Email += dom
+ }
+ }
+}
+
+var from, to, cc, bcc, replyTo Addrs
+var inReplyTo, subject string
+var appendFile = flag.String("append", "", "file to append to end of body")
+
+var acct google.Account
+var acctName = flag.String("a", "", "account to use")
+var inputHeader = flag.Bool("i", false, "read additional header lines from stdin")
+
+func holdmode() {
+ if os.Getenv("TERM") == "9term" {
+ // forgive me
+ os.Stdout.WriteString("\x1B];*9term-hold+\x07")
+ }
+}
+
+func match(line, prefix string, arg *string) bool {
+ if len(line) < len(prefix) || !strings.EqualFold(line[:len(prefix)], prefix) {
+ return false
+ }
+ *arg = strings.TrimSpace(line[len(prefix):])
+ return true
+}
+
+func main() {
+ flag.StringVar(&inReplyTo, "in-reply-to", "", "In-Reply-To")
+ flag.StringVar(&subject, "s", "", "Subject")
+ flag.Var(&from, "from", "From (can repeat)")
+ flag.Var(&to, "to", "To (can repeat)")
+ flag.Var(&cc, "cc", "CC (can repeat)")
+ flag.Var(&bcc, "bcc", "BCC (can repeat)")
+ flag.Var(&replyTo, "replyTo", "Reply-To (can repeat)")
+
+ flag.Parse()
+ if flag.NArg() != 0 && !*inputHeader {
+ flag.Usage()
+ }
+
+ var body bytes.Buffer
+ input := bufio.NewReader(os.Stdin)
+ if *inputHeader {
+ holdmode()
+ Loop:
+ for {
+ s, err := input.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break Loop
+ }
+ fmt.Fprintf(os.Stderr, "reading stdin: %s\n", err)
+ os.Exit(2)
+ }
+ var arg string
+ switch {
+ default:
+ if ok, _ := regexp.MatchString(`^\S+:`, s); ok {
+ fmt.Fprintf(os.Stderr, "unknown header line: %s", s)
+ os.Exit(2)
+ }
+ body.WriteString(s)
+ break Loop
+ case match(s, "from:", &arg):
+ from.parseLine(arg)
+ case match(s, "to:", &arg):
+ to.parseLine(arg)
+ case match(s, "cc:", &arg):
+ cc.parseLine(arg)
+ case match(s, "bcc:", &arg):
+ bcc.parseLine(arg)
+ case match(s, "reply-to:", &arg):
+ replyTo.parseLine(arg)
+ case match(s, "subject:", &arg):
+ subject = arg
+ case match(s, "in-reply-to:", &arg):
+ inReplyTo = arg
+ }
+ }
+ }
+
+ acct = google.Acct(*acctName)
+ from.fixDomain()
+ to.fixDomain()
+ cc.fixDomain()
+ bcc.fixDomain()
+ replyTo.fixDomain()
+
+ smtpTo := append(append(to, cc...), bcc...)
+
+ if len(from) == 0 {
+ // TODO: Much better
+ name := ""
+ email := acct.Email
+ if email == "rsc@swtch.com" || email == "rsc@google.com" {
+ name = "Russ Cox"
+ }
+ if email == "rsc@google.com" && (smtpTo.has("go@googlecode.com") || smtpTo.has("golang-dev@googlegroups.com") || smtpTo.has("golang-nuts@googlegroups.com")) {
+ from = append(from, Addr{name, "rsc@golang.org"})
+ } else {
+ from = append(from, Addr{name, email})
+ }
+ }
+
+ if len(from) > 1 {
+ fmt.Fprintf(os.Stderr, "missing -from\n")
+ os.Exit(2)
+ }
+
+ if len(to)+len(cc)+len(bcc) == 0 {
+ fmt.Fprintf(os.Stderr, "missing destinations\n")
+ os.Exit(2)
+ }
+
+ if !*inputHeader {
+ holdmode()
+ }
+ _, err := io.Copy(&body, input)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "reading stdin: %s\n", err)
+ os.Exit(2)
+ }
+
+ if *appendFile != "" {
+ f, err := os.Open(*appendFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "append: %s\n", err)
+ os.Exit(2)
+ }
+ _, err = io.Copy(&body, f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "append: %s\n", err)
+ os.Exit(2)
+ }
+ }
+
+ var msg bytes.Buffer
+ fmt.Fprintf(&msg, "MIME-Version: 1.0\n")
+ if len(from) > 0 {
+ fmt.Fprintf(&msg, "From: ")
+ for i, a := range from {
+ if i > 0 {
+ fmt.Fprintf(&msg, ", ")
+ }
+ fmt.Fprintf(&msg, "%s", a.enc())
+ }
+ fmt.Fprintf(&msg, "\n")
+ }
+ if len(to) > 0 {
+ fmt.Fprintf(&msg, "To: ")
+ for i, a := range to {
+ if i > 0 {
+ fmt.Fprintf(&msg, ", ")
+ }
+ fmt.Fprintf(&msg, "%s", a.enc())
+ }
+ fmt.Fprintf(&msg, "\n")
+ }
+ if len(cc) > 0 {
+ fmt.Fprintf(&msg, "CC: ")
+ for i, a := range cc {
+ if i > 0 {
+ fmt.Fprintf(&msg, ", ")
+ }
+ fmt.Fprintf(&msg, "%s", a.enc())
+ }
+ fmt.Fprintf(&msg, "\n")
+ }
+ if len(replyTo) > 0 {
+ fmt.Fprintf(&msg, "Reply-To: ")
+ for i, a := range replyTo {
+ if i > 0 {
+ fmt.Fprintf(&msg, ", ")
+ }
+ fmt.Fprintf(&msg, "%s", a.enc())
+ }
+ fmt.Fprintf(&msg, "\n")
+ }
+ if inReplyTo != "" {
+ fmt.Fprintf(&msg, "In-Reply-To: %s\n", inReplyTo)
+ }
+ if subject != "" {
+ fmt.Fprintf(&msg, "Subject: %s\n", enc(subject))
+ }
+ fmt.Fprintf(&msg, "Date: xxx\n")
+ fmt.Fprintf(&msg, "Content-Type: text/plain; charset=\"utf-8\"\n")
+ fmt.Fprintf(&msg, "Content-Transfer-Encoding: base64\n")
+ fmt.Fprintf(&msg, "\n")
+ enc64 := base64.StdEncoding.EncodeToString(body.Bytes())
+ for len(enc64) > 72 {
+ fmt.Fprintf(&msg, "%s\n", enc64[:72])
+ enc64 = enc64[72:]
+ }
+ fmt.Fprintf(&msg, "%s\n\n", enc64)
+
+ auth := smtp.PlainAuth(
+ "",
+ acct.Email,
+ acct.Password,
+ "smtp.gmail.com",
+ )
+ var smtpToEmail []string
+ for _, a := range smtpTo {
+ if a.Email != "" {
+ smtpToEmail = append(smtpToEmail, a.Email)
+ }
+ }
+
+ if err := sendMail("smtp.gmail.com:587", auth, from[0].Email, smtpToEmail, msg.Bytes()); err != nil {
+ fmt.Fprintf(os.Stderr, "sending mail: %s\n", err)
+ os.Exit(2)
+ }
+}
+
+/*
+ MIME-Version: 1.0
+Subject: commit/plan9port: rsc: 9term: hold mode back door
+From: Bitbucket <commits-noreply@bitbucket.org>
+To: plan9port-dev@googlegroups.com
+Date: Tue, 11 Oct 2011 13:34:30 -0000
+Message-ID: <20111011133430.31146.55070@bitbucket13.managed.contegix.com>
+Reply-To: commits-noreply@bitbucket.org
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+1 new changeset in plan9port:
+
+http://bitbucket.org/rsc/plan9port/changeset/8735d7708a1b/
+changeset: 8735d7708a1b
+user: rsc
+date: 2011-10-11 15:34:25
+summary: 9term: hold mode back door
+
+R=3Drsc
+http://codereview.appspot.com/5248056
+affected #: 2 files (-1 bytes)
+
+Repository URL: https://bitbucket.org/rsc/plan9port/
+
+--
+
+This is a commit notification from bitbucket.org. You are receiving
+this because you have the service enabled, addressing the recipient of
+this email.
+
+*/
+
+func sendMail(addr string, a smtp.Auth, from string, to []string, msg []byte) error {
+ c, err := smtp.Dial(addr)
+ if err != nil {
+ return err
+ }
+ if err = c.StartTLS(nil); err != nil {
+ return err
+ }
+ if err = c.Auth(a); err != nil {
+ return err
+ }
+ if err = c.Mail(from); err != nil {
+ return err
+ }
+ for _, addr := range to {
+ if err = c.Rcpt(addr); err != nil {
+ return err
+ }
+ }
+ w, err := c.Data()
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(msg)
+ if err != nil {
+ return err
+ }
+ err = w.Close()
+ if err != nil {
+ return err
+ }
+ return c.Quit()
+}