Files
gmail/main.go
2025-07-28 03:03:24 +03:00

173 lines
3.9 KiB
Go

package main
import (
"context"
"encoding/csv"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strings"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/gmail/v1"
"google.golang.org/api/option"
)
type EmailInfo struct {
Sender string `json:"sender"`
Subject string `json:"subject"`
Date string `json:"date"`
ID string `json:"id"`
}
func main() {
if len(os.Args) < 4 {
fmt.Println("Usage: go run main.go <client_id> <client_secret> <output_format>")
fmt.Println(" client_id: Your Google OAuth2 client ID")
fmt.Println(" client_secret: Your Google OAuth2 client secret")
fmt.Println(" output_format: csv or json")
os.Exit(1)
}
clientID := os.Args[1]
clientSecret := os.Args[2]
outputFormat := strings.ToLower(os.Args[3])
if outputFormat != "csv" && outputFormat != "json" {
log.Fatal("Output format must be 'csv' or 'json'")
}
ctx := context.Background()
config := &oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
Scopes: []string{gmail.GmailReadonlyScope},
Endpoint: google.Endpoint,
}
client := getClient(config)
srv, err := gmail.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
log.Fatalf("Unable to retrieve Gmail client: %v", err)
}
fmt.Printf("Connected to Gmail API successfully\n")
fmt.Printf("Fetching emails from inbox...\n")
emails := fetchEmails(srv)
fmt.Printf("Generating %s output...\n", outputFormat)
switch outputFormat {
case "csv":
outputCSV(emails)
case "json":
outputJSON(emails)
}
fmt.Printf("Complete! Fetched %d emails\n", len(emails))
}
func getClient(config *oauth2.Config) *http.Client {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Visit this URL in your browser: %v\n\n", authURL)
fmt.Print("Paste the authorization code here: ")
var authCode string
if _, err := fmt.Scanln(&authCode); err != nil {
log.Fatalf("Unable to read authorization code: %v", err)
}
tok, err := config.Exchange(context.TODO(), authCode)
if err != nil {
log.Fatalf("Unable to retrieve token: %v", err)
}
return config.Client(context.Background(), tok)
}
func fetchEmails(srv *gmail.Service) []EmailInfo {
var emails []EmailInfo
pageCount := 0
req := srv.Users.Messages.List("me").Q("in:inbox")
for {
pageCount++
fmt.Printf("Fetching page %d...\n", pageCount)
r, err := req.Do()
if err != nil {
log.Fatalf("Unable to retrieve messages: %v", err)
}
fmt.Printf("Processing %d messages from page %d...\n", len(r.Messages), pageCount)
for i, m := range r.Messages {
if (i+1)%50 == 0 {
fmt.Printf(" Processed %d/%d messages on this page\n", i+1, len(r.Messages))
}
msg, err := srv.Users.Messages.Get("me", m.Id).Do()
if err != nil {
log.Printf("Unable to retrieve message %s: %v", m.Id, err)
continue
}
email := parseMessage(msg)
emails = append(emails, email)
}
fmt.Printf("Completed page %d. Total emails collected: %d\n", pageCount, len(emails))
if r.NextPageToken == "" {
fmt.Printf("Reached end of inbox. Processing complete.\n")
break
}
req.PageToken(r.NextPageToken)
}
return emails
}
func parseMessage(msg *gmail.Message) EmailInfo {
email := EmailInfo{
ID: msg.Id,
}
for _, header := range msg.Payload.Headers {
switch header.Name {
case "From":
email.Sender = header.Value
case "Subject":
email.Subject = header.Value
case "Date":
email.Date = header.Value
}
}
return email
}
func outputCSV(emails []EmailInfo) {
writer := csv.NewWriter(os.Stdout)
defer writer.Flush()
writer.Write([]string{"Sender", "Subject", "Date", "ID"})
for _, email := range emails {
writer.Write([]string{email.Sender, email.Subject, email.Date, email.ID})
}
}
func outputJSON(emails []EmailInfo) {
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
encoder.Encode(emails)
}