Files
gpt-plus-gpt/tools/test_outlook.go
2026-03-15 20:48:19 +08:00

162 lines
4.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
"strings"
"time"
)
const (
msTokenURL = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
outlookMailURL = "https://outlook.office.com/api/v2.0/me/mailFolders/inbox/messages"
)
func main() {
clientID := "9e5f94bc-e8a4-4e73-b8be-63364c29d753"
refreshToken := "M.C502_SN1.0.U.-Crvsmbp5ATQIkZ3hocv9p7Z2X5!OXVJHdHa72LcvvI0vL89DBJ3O6CU!j07BU3A9kAJlFQcYVE*wmp!riMOJXBdeMvgB9xuF0duYbb8*M8qCnYGkX196K0z5CMhkHOOSahXbHkWN0cI685XA4z27rPYPOcGylHZdax1K0wF6N4kSxe*eoXn0dYL9wMPe1oC3vQ62B1EYECpaqqpfIKfKqhBpkbQ74up272uhiMvlRkYiD6ZCxL1aSeHg*aRiXGP4XfWWojKHN5rBqcXCXTRTGqw4r1Zij!RDXSBPBucjlL2uUSgPUu4H!UzEIQntGU2DeTGqecwk*XiJhLiic*RbrQliU9wQ!8J36Cc2grdSbeF9TeCHp!H6FC!qS40rekL31ZPFSunD8sJ*dQTOxPH9qC9ErHeoHvREFh0ypy4pa!!h5!15vvtwAPZgEcxcg2qSiA$$"
email := "frher9601@outlook.com"
fmt.Printf("=== Outlook REST API - No-Filter Strategy Test ===\n")
fmt.Printf("Account: %s\n\n", email)
// Step 1: Get access token
fmt.Println("[1] Exchanging refresh token...")
accessToken, err := exchangeToken(clientID, refreshToken)
if err != nil {
fmt.Printf(" FAILED: %v\n", err)
return
}
fmt.Printf(" OK: access_token (%d chars)\n\n", len(accessToken))
// Step 2: Fetch recent emails WITHOUT any filter (the fix)
fmt.Println("[2] Fetching recent 10 emails (no $filter)...")
reqURL := fmt.Sprintf("%s?$top=10&$orderby=ReceivedDateTime+desc&$select=Subject,BodyPreview,ReceivedDateTime,From",
outlookMailURL)
req, _ := http.NewRequest("GET", reqURL, nil)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil {
fmt.Printf(" FAILED: %v\n", err)
return
}
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
if resp.StatusCode != 200 {
fmt.Printf(" FAILED (HTTP %d): %s\n", resp.StatusCode, string(body)[:min(len(body), 300)])
return
}
var result struct {
Value []struct {
Subject string `json:"Subject"`
BodyPreview string `json:"BodyPreview"`
ReceivedDateTime string `json:"ReceivedDateTime"`
From struct {
EmailAddress struct {
Address string `json:"Address"`
} `json:"EmailAddress"`
} `json:"From"`
} `json:"value"`
}
json.Unmarshal(body, &result)
fmt.Printf(" OK: %d emails returned\n\n", len(result.Value))
// Step 3: Client-side filter simulation
fmt.Println("[3] Client-side filtering (simulating fixed code)...")
notBefore := time.Now().Add(-48 * time.Hour) // last 48h
otpRegexp := regexp.MustCompile(`\b(\d{6})\b`)
foundOTP := ""
for i, e := range result.Value {
sender := strings.ToLower(e.From.EmailAddress.Address)
preview := e.BodyPreview
if len(preview) > 80 {
preview = preview[:80] + "..."
}
fmt.Printf(" [%d] from=%-45s subj=%q\n", i, sender, e.Subject)
// Filter: must be from OpenAI
if !strings.Contains(sender, "openai") {
fmt.Printf(" -> SKIP (not openai)\n")
continue
}
// Filter: time check
if e.ReceivedDateTime != "" {
if t, err := time.Parse("2006-01-02T15:04:05Z", e.ReceivedDateTime); err == nil {
if t.Before(notBefore) {
fmt.Printf(" -> SKIP (too old: %s)\n", e.ReceivedDateTime)
continue
}
}
}
// Extract OTP
if m := otpRegexp.FindStringSubmatch(e.Subject); len(m) >= 2 {
foundOTP = m[1]
fmt.Printf(" -> OTP from subject: %s\n", foundOTP)
break
}
if m := otpRegexp.FindStringSubmatch(e.BodyPreview); len(m) >= 2 {
foundOTP = m[1]
fmt.Printf(" -> OTP from body: %s\n", foundOTP)
break
}
fmt.Printf(" -> OpenAI email but no OTP found\n")
}
fmt.Println()
if foundOTP != "" {
fmt.Printf("=== SUCCESS: OTP = %s ===\n", foundOTP)
} else {
fmt.Println("=== No OTP found (no recent OpenAI email in inbox) ===")
}
}
func exchangeToken(clientID, refreshToken string) (string, error) {
data := url.Values{
"client_id": {clientID},
"grant_type": {"refresh_token"},
"refresh_token": {refreshToken},
}
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.PostForm(msTokenURL, data)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 200 {
cut := len(body)
if cut > 300 {
cut = 300
}
return "", fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body)[:cut])
}
var tokenResp struct {
AccessToken string `json:"access_token"`
}
json.Unmarshal(body, &tokenResp)
if tokenResp.AccessToken == "" {
return "", fmt.Errorf("no access_token in response")
}
return tokenResp.AccessToken, nil
}
func min(a, b int) int {
if a < b {
return a
}
return b
}