mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 08:01:16 +00:00
48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
package msgraph
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"github.com/warmbly/warmbly/internal/errx"
|
|
)
|
|
|
|
// graphErrorEnvelope is Graph's standard error shape.
|
|
type graphErrorEnvelope struct {
|
|
Error struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
} `json:"error"`
|
|
}
|
|
|
|
// HandleError maps a non-2xx Graph response to a MailError. It classifies by
|
|
// HTTP status so the send/sync retry loop can tell transient (retryable) from
|
|
// critical (needs re-auth / stop) failures:
|
|
// - 401 -> authentication failed (token expired/revoked, re-consent)
|
|
// - 403 -> authorization failed (missing scope / mailbox disabled)
|
|
// - 429 -> sending too fast (throttled; Retry-After honored by the caller loop)
|
|
// - 5xx / other -> server unreachable (retry)
|
|
func HandleError(resp *http.Response) *errx.MailError {
|
|
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<16))
|
|
var env graphErrorEnvelope
|
|
_ = json.Unmarshal(body, &env)
|
|
|
|
switch resp.StatusCode {
|
|
case http.StatusUnauthorized:
|
|
return errx.ErrMailAuthenticationFailed
|
|
case http.StatusForbidden:
|
|
return errx.ErrMailAuthorizationFailed
|
|
case http.StatusTooManyRequests:
|
|
return errx.ErrMailSendingTooFast
|
|
default:
|
|
log.Debug().
|
|
Int("status", resp.StatusCode).
|
|
Str("code", env.Error.Code).
|
|
Str("message", env.Error.Message).
|
|
Msg("Graph API error")
|
|
return errx.ErrMailServerUnreachable
|
|
}
|
|
}
|