This article explains how to send an email as the logged-in user from an SPFx web part using Microsoft Graph. It covers permission configuration (package-solution), admin consent, code examples (TypeScript + SPFx MSGraphClient), attachments, troubleshooting, and alternatives (application permissions). Ready-to-use code snippets are included.
Why use Microsoft Graph from SPFx?
Graph is the unified API for Microsoft 365 — it exposes
me/sendMailto send mail as the currently authenticated user.In SPFx you can call Graph with the built-in
MSGraphClient(orAadHttpClient/GraphHttpClient), which handles auth as the current user so you don’t need to manage tokens client-side.Typical use case: web part sends notification, confirmation, or formatted email using the identity of the user interacting with the page.
High-level steps
Add the required delegated Graph permission (
Mail.Send) to your SPFx solution.Package and request admin consent in SharePoint Admin (tenant admin must approve the permission).
In your web part, get an
MSGraphClientinstance and callPOST /me/sendMailwith the message payload.Handle success and errors, and optionally include attachments and
saveToSentItems.
Permission setup (package-solution.json)
Add a webApiPermissionRequests entry to config/package-solution.json so your solution requests delegated permission to send mail:
{
"solution": {
"name": "send-mail-solution",
"id": "00000000-0000-0000-0000-000000000000",
"version": "1.0.0.0",
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "Mail.Send"
}
]
}
}
After you deploy the package to the App Catalog, a tenant admin must go to the SharePoint admin center → API access and grant the requested permission.
The permission requested above is delegated (mail is sent as the signed-in user). The tenant admin consent is required only once per tenant for that permission request.
Using MSGraphClient in SPFx (TypeScript example)
Below is a simple React + SPFx example that sends an email using /me/sendMail. This assumes you're in a web part and have access to this.context.msGraphClientFactory.
// imports
import * as React from 'react';
import { MSGraphClient } from '@microsoft/sp-http';
import { PrimaryButton, TextField } from '@fluentui/react';
// Example component props
interface ISendMailProps {
context: any; // the web part context
}
export const SendMailComponent: React.FC<ISendMailProps> = ({ context }) => {
const [to, setTo] = React.useState('');
const [subject, setSubject] = React.useState('');
const [body, setBody] = React.useState('');
const [loading, setLoading] = React.useState(false);
const [status, setStatus] = React.useState<string | null>(null);
const sendMail = async (): Promise<void> => {
setLoading(true);
setStatus(null);
try {
const client: MSGraphClient = await context.msGraphClientFactory.getClient();
// Build message payload
const message = {
subject: subject || '(no subject)',
body: {
contentType: 'HTML',
content: body || ''
},
toRecipients: to.split(';').map((addr: string) => ({ emailAddress: { address: addr.trim() } }))
};
// POST /me/sendMail
await client.api('/me/sendMail').post({
message,
saveToSentItems: true
});
setStatus('Email sent successfully.');
} catch (error) {
console.error('sendMail error', error);
// Example error handling
if (error && error.status === 403) {
setStatus('Permission denied — Mail.Send may not be consented for this tenant.');
} else {
setStatus(`Failed to send email: ${error?.message || JSON.stringify(error)}`);
}
} finally {
setLoading(false);
}
};
return (
<div>
<TextField label="To (separate multiple with ; )" value={to} onChange={(_, v) => setTo(v || '')} />
<TextField label="Subject" value={subject} onChange={(_, v) => setSubject(v || '')} />
<TextField label="Body (HTML allowed)" multiline value={body} onChange={(_, v) => setBody(v || '')} />
<PrimaryButton text={loading ? 'Sending...' : 'Send email'} onClick={sendMail} disabled={loading} />
{status && <div style={{ marginTop: 8 }}>{status}</div>}
</div>
);
};
Notes
Use
context.msGraphClientFactory.getClient()to get anMSGraphClientalready authenticated as the current user.If you’re writing in a Web Part class (not a React separate component),
this.context.msGraphClientFactoryis available from the web part's context.
Message payload details
Example minimal Graph payload:
{
"message": {
"subject": "Hello from SPFx",
"body": {
"contentType": "HTML",
"content": "<p>Hi there — this email was sent from an SPFx web part.</p>"
},
"toRecipients": [
{
"emailAddress": {
"address": "[email protected]"
}
}
]
},
"saveToSentItems": true
}

Join the conversation! Your thoughts help the community grow.