Downloading inbox messages

Next, we need to set up the client from the credentials file that has been saved (in the current directory). We add a new function to parse the data, set up the authentication, and configure *gmail.Service using the following code:

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

config, err := google.ConfigFromJSON(b, gmail.GmailReadonlyScope,
gmail.GmailComposeScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
client := getClient(config)

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

return srv
}

The service returned from this function will be used for each subsequent call to the Gmail API as it contains the authentication configuration and credentials. Next, we need to prepare the email list by downloading all of the messages in the user's inbox. The INBOX LabelID is used to filter messages that haven't been archived. This function requests the message list and iterates through the metadata to initiate the full download of each message. For a full implementation, we would need to add paging support (the response contains nextPageToken, which indicates when more data is available), but this example will handle up to 100 messages:

func downloadMessages(srv *gmail.Service) {
req := srv.Users.Messages.List(user)
req.LabelIds("INBOX")
resp, err := req.Do()
if err != nil {
log.Fatalf("Unable to retrieve Inbox items: %v", err)
}

var emails []*EmailMessage
for _, message := range resp.Messages {
email := downloadMessage(srv, message)
emails = append(emails, email)
}
}

To download each individual message, we need to implement the downloadMessage() function referenced previously. For the specified message, we download the full content using the Gmail Go API. From the resulting data, we extract the information we need from the message headers. As well as parsing the Date header, we need to decode the message body, which is in a serialized, Base64 encoded format:

func downloadMessage(srv *gmail.Service, message *gmail.Message) *EmailMessage {
mail, err := srv.Users.Messages.Get(user, message.Id).Do()
if err != nil {
log.Fatalf("Unable to retrieve message payload: %v", err)
}

var subject string
var to, from Email
var date time.Time

content := decodeBody(mail.Payload)
for _, header := range mail.Payload.Headers {
switch header.Name {
case "Subject":
subject = header.Value
case "To":
to = Email(header.Value)
case "From":
from = Email(header.Value)
case "Date":
value := strings.Replace(header.Value, "(UTC)", "", -1)
date, err = time.Parse("Mon, _2 Jan 2006 15:04:05 -0700",
strings.TrimSpace(value))
if err != nil {
log.Println("Error: Could not parse date", value)
date = time.Now()
} else {
log.Println("date", header.Value)
}
}
}

return NewMessage(subject, content, to, from, date)
}

The decodeBody() function is as shown in the following. For plain text emails, the content is in the Body.Data field. For multi-part messages (where the body is empty), we access the first of the multiple parts and decode that instead. Decoding the Base64 content is handled by the standard library decoder:

func decodeBody(payload *gmail.MessagePart) string {
data := payload.Body.Data
if data == "" {
data = payload.Parts[0].Body.Data
}
content, err := base64.StdEncoding.DecodeString(data)
if err != nil {
fmt.Println("Failed to decode body", err)
}

return string(content)
}

The final step in preparing this code is to complete the EmailServer interface methods. The ListMessages() function will return the result of downloadMessages(), and we can set up CurrentMessage() to return the email at the top of the list. Full implementation is in this book's code repository.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.72.15