func ReadLblFixturesJSON(name string) []*gmail.Label {
	log.Printf("reading labels from %s instead of fetching from Gmail", name)
	f, err := os.Open(name)
	if err != nil {
		log.Fatalf("Unable to read label fixtures: %v", err)
	}
	defer f.Close()
	msgs := []*gmail.Label{}
	json.NewDecoder(f).Decode(&msgs)
	return msgs
}
ReadLblFixturesJSON reads Gmail labels from a given JSON file.
package gmailutils
import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
	"time"
	"unicode"
	"unicode/utf8"
	"github.com/bzz/scholar-alert-digest/gmailutils/token"
	"github.com/cheggaaa/pb/v3"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/gmail/v1"
)
const Instructions = `Please follow https: 
in order to:
 - create a new "Quickstart" API project under your account
 - enable GMail API on it
 - download OAuth 2.0 credentials
`
func NewClient(needWriteAccess bool) *http.Client {
	b, err := ioutil.ReadFile("credentials.json")
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v\n%s", err, Instructions)
	}
	scopes := []string{gmail.GmailReadonlyScope}
	token := "token.json"
	if needWriteAccess {
		scopes = append(scopes, gmail.GmailModifyScope)
		token = "token_rw.json"
	}
	config, err := google.ConfigFromJSON(b, scopes...)
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}
	return getClient(config, token)
}
func getClient(config *oauth2.Config, tokFile string) *http.Client {
	tok, err := token.FromFile(tokFile)
	if err != nil {
		tok = token.FromWeb(config)
		token.Save(tokFile, tok)
	}
	return config.Client(context.Background(), tok)
}
func FetchLabels(ctx context.Context, client *http.Client) (
	*gmail.ListLabelsResponse, error) {  
	srv, err := gmail.New(client)
	if err != nil {
		return nil, err
	}
	labelsResp, err := srv.Users.Labels.List("me").Do()
	if err != nil {
		return nil, err
	}
	return labelsResp, nil
}
func PrintAllLabels(srv *gmail.Service, user string) []*gmail.Label {
	log.Printf("Listing all Gmail labels")
	labelsResp, err := srv.Users.Labels.List(user).Do()
	if err != nil {
		log.Fatalf("Unable to retrieve all labels: %v", err)
	}
	log.Printf("%d labels found", len(labelsResp.Labels))
	for _, l := range labelsResp.Labels {
		fmt.Println(FormatAsID(l.Name))
	}
	return labelsResp.Labels
}
func FetchConcurent(ctx context.Context, srv *gmail.Service, user, query string, concurentReq int) ([]*gmail.Message, error) {
	log.Printf("searching and fetching messages from Gmail: %q", query)
	start := time.Now()
	msgs, err := searchAndFetchConcurent(ctx, srv, user, query, concurentReq)
	if err != nil {
		return nil, err
	}
	log.Printf("%d messages found&fetched with (took %.0f sec)", len(msgs), time.Since(start).Seconds())
	return msgs, nil
}
func searchAndFetchConcurent(ctx context.Context, srv *gmail.Service, user, query string, concurentReq int) ([]*gmail.Message, error) {
	log.Printf("searching messages from Gmail: %q", query)
	start := time.Now()
	var msgIDs []string
	err := srv.Users.Messages.List(user).Q(query).Pages(ctx, func(mr *gmail.ListMessagesResponse) error {
		for _, msg := range mr.Messages {
			msgIDs = append(msgIDs, msg.Id)
		}
		return nil
	})
	if err != nil {
		log.Printf("Unable to list messages for query:%q - %v", query, err)
		return nil, err
	}
	log.Printf("%d messages found (took %.0f sec)", len(msgIDs), time.Since(start).Seconds())
	start = time.Now()
	bar := pb.Full.Start(len(msgIDs))
	bar.SetMaxWidth(100)
	var (
		throttle = make(chan int, concurentReq)
		wg       sync.WaitGroup
		msgs     []*gmail.Message
	)
	for i := range msgIDs {
		msgID := msgIDs[i]
		wg.Add(1)
		go func() {
			throttle <- 1
			defer func() { <-throttle; wg.Done() }()
			bar.Increment()
			msg, err := srv.Users.Messages.Get(user, msgID).Do()
			if err != nil {  
				log.Printf("Unable to fetch message by ID:%q", msgID)
			}
			msgs = append(msgs, msg)
		}()
	}
	wg.Wait()
	bar.Finish()
	log.Printf("%d messages fetched (took %.0f sec)", len(msgIDs), time.Since(start).Seconds())
	return msgs, nil
}
func ReadMsgFixturesJSON(name string) []*gmail.Message {
	log.Printf("reading messages from %s instead of fetching from Gmail", name)
	f, err := os.Open(name)
	if err != nil {
		log.Fatalf("Unable to read messages fixtures: %v", err)
	}
	defer f.Close()
	msgs := []*gmail.Message{}
	json.NewDecoder(f).Decode(&msgs)
	return msgs
}