How do I send email through the Gmail Go SDK?

I am trying to send a new email via the gmail package . However, the Message type that send requires is poorly documented. Most of the fields appear to be used for parsing or reading emails. The only field that makes sense (to some extent) for the dispatch method is the payload of type MessagePart , although I can't figure out how to generate the MessagePartBody as it seems to be a kind of mime type. Below is the code I have.

func (em *Email) SendMessage(cl *Client) error {
    config.ClientId = cl.Username
    config.ClientSecret = cl.Password

    t := &oauth.Transport{

        Config:    config,
        Transport: http.DefaultTransport,
    }
    var tk oauth.Token
    err := json.Unmarshal([]byte(cl.Meta), &tk)
    t.Token = &tk
    if err != nil {
        log.Errorf("meta %v, err %v", cl.Meta, err)
        return err
    }
    gmailService, err := gmail.New(t.Client())
    if err != nil {
        log.Error(err)
        return err
    }

    p := gmail.MessagePart{}
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "From",
        Value: em.FromEmail,
    })
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "To",
        Value: em.ToEmail,
    })
    p.Headers = append(p.Headers, &gmail.MessagePartHeader{
        Name:  "Subject",
        Value: em.Subject,
    })

    emsg := base64.StdEncoding.EncodeToString(em.Message)
    log.Info(emsg)
    msg := gmail.Message{
        Payload: &p,
        Raw:     "",
    }
    _, err = gmailService.Users.Messages.Send("me", &msg).Do()
    if err != nil {
        log.Error(err)
        return err
    }
    return err
}

      

The "REST" API is even more confusing. This requires a parameter uploadType

(WTF to load) and a field raw

, which I assume is a raw message, which requires the format provided by messages.get. Why are you sending a message from your inbox that will literally "resend" as indicated on the list of receipts? Am I the only one who thinks this API (or at least the documentation) is just crap?

+5


source to share


2 answers


It was a little tricky, but this is how you can send emails via the GMAIL API



import(
    "code.google.com/p/goauth2/oauth"
    "code.google.com/p/google-api-go-client/gmail/v1"
    log "github.com/golang/glog"

    "encoding/base64"
    "encoding/json"
    "net/mail"
    "strings"
    )


type Email struct {
    FromName, FromEmail, ToName, ToEmail, Subject string
    Message                                       string
}

func (em *Email) SendMessage(cl *Client) error {
    config.ClientId = cl.Username //oauth clientID
    config.ClientSecret = cl.Password  //oauth client secret 

    t := &oauth.Transport{
        Config:    config,
        Transport: http.DefaultTransport,
    }
    var tk oauth.Token
    err := json.Unmarshal([]byte(cl.Meta), &tk)
    t.Token = &tk
    if err != nil {
        log.Errorf("meta %v, err %v", cl.Meta, err)
        return err
    }
    gmailService, err := gmail.New(t.Client())
    if err != nil {
        log.Error(err)
        return err
    }

    from := mail.Address{em.FromName, em.FromEmail}
    to := mail.Address{em.ToName, em.ToEmail}

    header := make(map[string]string)
    header["From"] = from.String()
    header["To"] = to.String()
    header["Subject"] = encodeRFC2047(em.Subject)
    header["MIME-Version"] = "1.0"
    header["Content-Type"] = "text/html; charset=\"utf-8\""
    header["Content-Transfer-Encoding"] = "base64"

    var msg string
    for k, v := range header {
        msg += fmt.Sprintf("%s: %s\r\n", k, v)
    }
    msg += "\r\n" + em.Message

    gmsg := gmail.Message{
        Raw: encodeWeb64String([]byte(msg)),
    }

    _, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
    if err != nil {
        log.Errorf("em %v, err %v", gmsg, err)
        return err
    }
    return err
}



func encodeRFC2047(s string) string {
    // use mail rfc2047 to encode any string
    addr := mail.Address{s, ""}
    return strings.Trim(addr.String(), " <>")
}

func encodeWeb64String(b []byte) string {

    s := base64.URLEncoding.EncodeToString(b)

    var i = len(s) - 1
    for s[i] == '=' {
        i--
    }

    return s[0 : i+1]
}

      

+5


source


Similar to @hey's answer, but I removed it and allowed the email to insert new lines in the email body through \n

and display correctly in the email client. Also, @hey doesn't use the new supported Gmail API . Here's the final code:

import (
    "encoding/base64"
    "golang.org/x/net/context"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/gmail/v1"
    "encoding/json"
    "net/mail"
)

type Email struct {
    FromName  string
    FromEmail string
    ToName    string
    ToEmail   string
    Subject   string
    Message   string
}


func (em *Email) sendMailFromEmail() error {
b, err := ioutil.ReadFile("credentials.json")
if err != nil {
    log.Fatalf("Unable to read client secret file: %v", err)
}

// If modifying these scopes, delete your previously saved token.json.
config, err := google.ConfigFromJSON(b, gmail.GmailSendScope)
if err != nil {
    log.Fatalf("Unable to parse client secret file to config: %v", err)
}
cl := getClientMail(config)

gmailService, err := gmail.New(cl)
if err != nil {
    log.Fatalf("Unable to retrieve Gmail client: %v", err)
}

from := mail.Address{em.FromName, em.FromEmail}
to := mail.Address{em.ToName, em.ToEmail}

header := make(map[string]string)
header["From"] = from.String()
header["To"] = to.String()
header["Subject"] = em.Subject
header["MIME-Version"] = "1.0"
header["Content-Type"] = "text/plain; charset=\"utf-8\""
header["Content-Transfer-Encoding"] = "base64"

var msg string
for k, v := range header {
    msg += fmt.Sprintf("%s: %s\r\n", k, v)
}
msg += "\r\n" + em.Message

gmsg := gmail.Message{
    Raw: base64.RawURLEncoding.EncodeToString([]byte(msg)),
}

_, err = gmailService.Users.Messages.Send("me", &gmsg).Do()
if err != nil {
    log.Printf("em %v, err %v", gmsg, err)
    return err
}
return err
}

      



I have not included the following features: getClient, getTokenFromWeb, tokenFromFile and saveToken. You can find them and learn how to enable the Gmail API using this tutorial from Google.

+1


source







All Articles