Help us shape the future of Go! Take the 2026 Go Developer Survey

msgraph

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 15 Imported by: 1

README

msgraph-go

msgraph-go is a small, dependency-free Microsoft Graph REST client for Go. It owns transport concerns that every typed Microsoft SDK in this workspace needs: bearer-token injection, OData query construction, JSON request/response handling, paging, throttling retries, and structured Graph errors.

It deliberately does not import msauth-go. Callers provide a TokenSource, so CLIs can wire Microsoft delegated auth while tests and services can provide their own token source.

Usage

client := msgraph.New(msgraph.TokenSourceFunc(func(ctx context.Context) (string, error) {
    return "access-token", nil
}))

var page msgraph.Page[Message]
_, err := client.Get(ctx, "/me/messages", msgraph.Params{
    Select: []string{"id", "subject", "receivedDateTime"},
    Top:    10,
}, &page)
Transport behavior
  • Retries are enabled for safe methods (GET, HEAD, OPTIONS) on throttling and transient server errors. Mutating methods are not retried unless WithRetryUnsafeMethods(true) is set explicitly.
  • Retry sleeps honor Retry-After and are capped by WithMaxRetryDelay (30s by default).
  • Passing an io.Writer as out streams successful response bodies instead of buffering them first.
  • BatchStrict returns all batch responses plus a BatchError when any subrequest fails.
  • Pages/Items detect repeated nextLink values, and WithMaxPages can cap traversal.

Develop

just ci

Manual live smoke test:

cd cmd/msgraph-live-smoke
go run .
go run . -show-messages # opt in to printing sender/subject metadata
go run . # second run should reuse the msauth-go token cache silently

Documentation

Overview

Package msgraph provides a small Microsoft Graph REST client.

Index

Constants

View Source
const (
	// PreferIDTypeImmutableID asks Graph to return IDs that survive moves.
	PreferIDTypeImmutableID = `IdType="ImmutableId"`

	// PreferBodyContentTypeText asks Outlook mail endpoints to return text bodies.
	PreferBodyContentTypeText = `outlook.body-content-type="text"`

	// PreferBodyContentTypeHTML asks Outlook mail endpoints to return HTML bodies.
	PreferBodyContentTypeHTML = `outlook.body-content-type="html"`

	// ConsistencyLevelEventual enables Graph advanced query capabilities where
	// endpoints require the ConsistencyLevel header.
	ConsistencyLevelEventual = "eventual"
)
View Source
const (
	// GraphResourceAppID is the Microsoft Graph service principal app ID.
	GraphResourceAppID = "00000003-0000-0000-c000-000000000000"

	// GraphCLIClientID is Microsoft's first-party Microsoft Graph Command Line
	// Tools public client app ID.
	GraphCLIClientID = "14d82eec-204b-4c2f-b7e8-296a70dab67e"

	MailReadDelegatedID      = "570282fd-fa5c-430d-a7fd-fc8dc98a9dca"
	MailReadWriteDelegatedID = "024d486e-b451-40bb-833d-3e66d98c5c73"
	MailSendDelegatedID      = "e383f46e-2787-4529-855e-0e479a3ffac0"
	UserReadDelegatedID      = "e1fe6dd8-ba31-4d61-89e7-88639da4683d"
)

Variables

View Source
var (
	ErrPageCycle        = errors.New("msgraph: repeated nextLink")
	ErrMaxPagesExceeded = errors.New("msgraph: max pages exceeded")
)

Pagination errors returned by Pages and Items.

View Source
var CommonPermissions = []Permission{
	{
		Name:                    "Mail.Read",
		ID:                      MailReadDelegatedID,
		Kind:                    "delegated",
		PersonalAccountsAllowed: true,
	},
	{
		Name:                    "Mail.ReadWrite",
		ID:                      MailReadWriteDelegatedID,
		Kind:                    "delegated",
		PersonalAccountsAllowed: true,
	},
	{
		Name:                    "Mail.Send",
		ID:                      MailSendDelegatedID,
		Kind:                    "delegated",
		PersonalAccountsAllowed: true,
	},
	{
		Name:                    "User.Read",
		ID:                      UserReadDelegatedID,
		Kind:                    "delegated",
		PersonalAccountsAllowed: true,
	},
}

CommonPermissions is a hand-curated seed set. The full catalog should be generated from the Graph service principal in a later package.

View Source
var ErrRequestFailed = errors.New("msgraph: request failed")

ErrRequestFailed is wrapped by APIError for non-2xx Graph responses.

Functions

func BodyContentTypePreference

func BodyContentTypePreference(contentType string) string

BodyContentTypePreference returns an Outlook body-content Prefer directive.

func IsForbidden

func IsForbidden(err error) bool

IsForbidden reports whether err is a Graph 403 response.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is a Graph 404 response.

func IsStatus

func IsStatus(err error, statusCode int) bool

IsStatus reports whether err is a Graph response with statusCode.

func IsThrottled

func IsThrottled(err error) bool

IsThrottled reports whether err is a Graph throttling response.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized reports whether err is a Graph 401 response.

func Items

func Items[T any](ctx context.Context, client *Client, path string, params Params, opts ...PageOption) iter.Seq2[T, error]

Items returns an iterator over every item in a Graph collection.

func Pages

func Pages[T any](ctx context.Context, client *Client, path string, params Params, opts ...PageOption) iter.Seq2[Page[T], error]

Pages returns an iterator over Graph collection pages.

Types

type APIError

type APIError struct {
	StatusCode int
	Code       string
	Message    string
	RequestID  string
	Raw        []byte
}

APIError is a structured Microsoft Graph error response.

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

type BatchError

type BatchError struct {
	Responses []BatchResponse
}

BatchError reports one or more failed subresponses from a strict batch call.

func (*BatchError) Error

func (e *BatchError) Error() string

type BatchRequest

type BatchRequest struct {
	ID      string            `json:"id"`
	Method  string            `json:"method"`
	URL     string            `json:"url"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    any               `json:"body,omitempty"`
}

BatchRequest is one request inside a Microsoft Graph JSON batch.

type BatchResponse

type BatchResponse struct {
	ID      string            `json:"id"`
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers,omitempty"`
	Body    json.RawMessage   `json:"body,omitempty"`
}

BatchResponse is one response inside a Microsoft Graph JSON batch.

func FailedBatchResponses

func FailedBatchResponses(responses []BatchResponse) []BatchResponse

FailedBatchResponses returns every subresponse with a non-2xx status.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a small Microsoft Graph REST client.

func New

func New(token TokenSource, opts ...Option) (*Client, error)

New creates a Microsoft Graph client.

func (*Client) Batch

func (c *Client) Batch(ctx context.Context, requests []BatchRequest) ([]BatchResponse, error)

Batch sends a Microsoft Graph JSON batch request.

func (*Client) BatchStrict

func (c *Client) BatchStrict(ctx context.Context, requests []BatchRequest) ([]BatchResponse, error)

BatchStrict sends a JSON batch and returns a BatchError when any subrequest status is outside 2xx. The full response slice is still returned so callers can inspect successes and failures together.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string, params Params, out any) (*Response, error)

Delete sends a Graph DELETE request.

func (*Client) Do

func (c *Client) Do(ctx context.Context, req Request, out any) (*Response, error)

Do sends req and decodes a successful JSON response into out. If out is an io.Writer, the response body is streamed into it instead.

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string, params Params, out any) (*Response, error)

Get sends a Graph GET request.

func (*Client) Patch

func (c *Client) Patch(ctx context.Context, path string, params Params, body, out any) (*Response, error)

Patch sends a Graph PATCH request.

func (*Client) Post

func (c *Client) Post(ctx context.Context, path string, params Params, body, out any) (*Response, error)

Post sends a Graph POST request.

type Option

type Option func(*Client) error

Option configures a Client.

func WithBaseURL

func WithBaseURL(value string) Option

WithBaseURL sets the Graph base URL. It is mostly useful for tests and sovereign clouds.

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

WithHTTPClient sets the HTTP client. A nil client is ignored.

func WithMaxRetries

func WithMaxRetries(value int) Option

WithMaxRetries sets the retry count for throttling and transient server errors. Negative values are clamped to zero.

func WithMaxRetryDelay

func WithMaxRetryDelay(value time.Duration) Option

WithMaxRetryDelay caps retry sleeps, including Retry-After values. A non-positive value disables the cap.

func WithRetryUnsafeMethods

func WithRetryUnsafeMethods(value bool) Option

WithRetryUnsafeMethods allows retries for non-idempotent HTTP methods. It is disabled by default because Graph mutations can have side effects before a transient response or connection failure is observed by the client.

func WithSleeper

func WithSleeper(fn sleepFunc) Option

WithSleeper overrides retry sleeping. It exists for tests.

func WithUserAgent

func WithUserAgent(value string) Option

WithUserAgent sets the User-Agent header.

type Page

type Page[T any] struct {
	Value    []T    `json:"value"`
	NextLink string `json:"@odata.nextLink,omitempty"`
}

Page is the standard Microsoft Graph collection response shape.

type PageOption

type PageOption func(*pageConfig)

PageOption configures collection iteration.

func WithMaxPages

func WithMaxPages(maxPages int) PageOption

WithMaxPages stops iteration after max pages. A non-positive maxPages leaves page count unlimited, though repeated nextLink values are still rejected.

type Params

type Params struct {
	Select  []string
	Expand  []string
	OrderBy []string
	Search  string
	Filter  string
	Top     int
	Skip    int
	Custom  url.Values
}

Params holds common OData query parameters used by Microsoft Graph.

func (Params) Values

func (p Params) Values() url.Values

Values renders p as URL query values.

type Permission

type Permission struct {
	Name                    string
	ID                      string
	Kind                    string
	AdminConsentRequired    bool
	PersonalAccountsAllowed bool
}

Permission describes a known Microsoft Graph permission.

func FindPermission

func FindPermission(nameOrID string) (Permission, bool)

FindPermission returns a known permission by name or ID.

type Request

type Request struct {
	Method           string
	URL              string
	Params           Params
	Query            url.Values
	Header           http.Header
	Prefer           []string
	ConsistencyLevel string
	Body             any
	RawBody          []byte
	ContentType      string
}

Request describes a Microsoft Graph request.

type Response

type Response struct {
	StatusCode int
	Header     http.Header
	RequestID  string
}

Response contains metadata from a successful Graph response.

type TokenSource

type TokenSource interface {
	Token(ctx context.Context) (string, error)
}

TokenSource returns a Microsoft Graph access token. Implementations should refresh tokens before returning expired credentials.

type TokenSourceFunc

type TokenSourceFunc func(ctx context.Context) (string, error)

TokenSourceFunc adapts a function into a TokenSource.

func (TokenSourceFunc) Token

func (fn TokenSourceFunc) Token(ctx context.Context) (string, error)

Token returns fn(ctx).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL