Blog
Custom GPT Experiment: Building an M365 Email Assistant
TL;DR
Created a custom GPT that connects directly to Microsoft 365 email via GPT Actions
Allows managing email through natural language commands like "show me unread emails" or "draft a reply to Sarah"
Only requires a ChatGPT Plus subscription and basic Microsoft Azure app registration
Solves the "folder confusion" problem - when I say "check my inbox," it only shows Inbox folder messages, not all mailbox items
Eliminates constant re-authentication prompts by using application permissions with mailbox-specific access policies
Makes email management significantly more efficient with minimal setup
Biggest challenge was teaching it to respect folder boundaries and correctly interpret complex commands
The Challenge: Email Overload
As a technology executive, my inbox is constantly flooded with messages. Managing emails efficiently has become a critical productivity challenge - one that I suspect many professionals can relate to. Traditional email interfaces often require multiple clicks and navigation steps to perform simple tasks, and the mental overhead of switching between different folders and views can be draining.
I wanted a solution that would allow me to interact with my email in a more natural, conversational way. Something that would understand exactly what I mean when I say "show me my emails" (and not pull messages from every folder in my account).
Enter Custom GPTs
When OpenAI introduced the ability to create custom GPTs, I immediately saw the potential to build an assistant specifically designed for email management. Custom GPTs allow you to create specialized AI assistants with specific knowledge, capabilities, and behaviors tailored to particular use cases.
Requirements
The beauty of this implementation is its simplicity. Here's all you need to build a similar solution:
Basic Requirements
Accounts and Subscriptions:
ChatGPT Plus subscription (to access Custom GPT capabilities)
Microsoft 365 account with mailbox access
Custom GPT Setup:
Knowledge of creating Custom GPTs in the ChatGPT interface
Understanding of effective prompt engineering
Ability to write clear instructions for email management tasks
Microsoft 365 Integration:
App Registration in Microsoft Azure AD
Basic understanding of OAuth permissions for Microsoft Graph API
That's really it! No complex development environment, no hosting infrastructure, and no extensive coding required.
App Registration in Azure AD
The only "technical" part is setting up the Microsoft connection:
Register an application in the Azure Portal
Create a simple App Registration
Configure redirect URI (usually provided by the Custom GPT action)
Generate a client secret
Configure these API permissions:
Mail.Read
Mail.ReadWrite
Mail.Send
Set up authentication:
Configure the OAuth settings
Use the provided client ID and secret in your Custom GPT action
Authentication Types and Security Considerations:
Delegated Permissions (default): The app acts on behalf of the logged-in user, but requires re-authentication frequently
Application Permissions: Eliminates re-authentication prompts, but grants access to all mailboxes in your organization by default
Enhancing Security: Use Application Access Policies to limit application permissions to specific mailboxes:
This approach provides the convenience of application permissions without over-privileging the integration
The Custom GPT handles the complex interaction patterns, natural language processing, and email command interpretation, while the direct connection to Microsoft Graph API allows it to securely access and manage your emails.
With these minimal requirements satisfied, let's look at how I built the M365 Email Assistant GPT experiment.
The M365 Email Assistant Experiment
I set out to create a custom GPT that would:
Understand natural language commands for email management
Focus specifically on Microsoft 365 email integration
Learn my preferences and communication style
Respect proper folder organization (a big pain point with other solutions)
Key Features
My M365 Email Assistant GPT can:
Read and manage emails from my Inbox folder (and only that folder when requested)
Compose and send professional messages that match my communication style
Find specific messages quickly without having to remember complex search syntax
Handle attachments and draft processing
Organize emails across folders with simple commands
The Technical Setup
The assistant connects to the Microsoft Graph API with appropriate OAuth scopes to:
Read emails (Mail.Read)
Modify messages (Mail.ReadWrite)
Send messages (Mail.Send)
I've implemented several optimizations to make it perform efficiently:
Requesting minimal fields in list operations
Using specific filters to narrow results
Only retrieving full message bodies when necessary
Deep Dive: Technical Implementation
For those interested in the technical details of how this integration works, let's explore the architecture and setup process.
OAuth Authentication Flow
The integration relies on Azure AD OAuth 2.0 to authenticate securely with Microsoft Graph. Here's what the authentication flow looks like:
App Registration: I registered an application in the Azure Portal to get:
Application (client) ID
Directory (tenant) ID
Client secret
Permission Configuration: I configured the following permissions:
Redirect URI Setup: I configured the redirect URI to safely receive the authentication code:
Web redirect URI:
https://example.com/auth/callback
Mobile/desktop URI format:
msauth://your-app-name/callback
Authorization Code Flow: The actual authentication follows these steps:
User is directed to Microsoft login (
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize
)After successful login, the authorization code is sent to the redirect URI
The code is exchanged for access and refresh tokens
Tokens are securely stored and refreshed as needed
Custom GPT Connection
The custom GPT connects to my Microsoft 365 account through an API layer I built. This required:
Secure Secrets Management:
Client secret and tokens are stored in a secure vault
No credentials are ever exposed to the GPT itself
API Schema: Here's a simplified version of the API schema that powers the integration:
Rate Limiting & Security:
Implemented token-based rate limiting (100 requests per minute)
All API requests are logged for security auditing
Automated alerts for suspicious activity patterns
Microsoft Graph Queries
The integration uses specific Microsoft Graph queries to efficiently retrieve only the necessary data:
Error Handling and Resilience
To ensure the system remains reliable:
Exponential Backoff: Implemented for API call retries
Token Refresh Logic: Automatic refresh when tokens expire
Graceful Degradation: Fallback options when specific features are unavailable
Verbose Logging: Detailed logs for troubleshooting integration issues
The integration is containerized using Docker and deployed on Azure, making it easily portable and scalable as needed.
Appendix: Full Implementation Resources
For those who want to implement something similar, here are the complete resources I used for my implementation, which you can adapt to your needs.
Complete Custom GPT Instructions (Anonymized)
Below are the full instructions I provided to my Custom GPT. You should customize these based on your personal preferences and email management style:
Complete OpenAPI Schema (Anonymized)
Below is the full OpenAPI schema I used for the Microsoft Graph API integration. You can adapt this to include additional endpoints as needed for your implementation:
Implementation Tips
When adapting these resources for your own use:
Modify the User Profile: Update the signature and user details to match your own
Custom Commands: Add specific command interpretations that match your email workflow
Folder Structure: Adjust the folder logic to match your Microsoft 365 organization
API Endpoints: Add or remove endpoints from the OpenAPI schema based on your needs
Security Stance: Consider the tradeoffs between delegated and application permissions, using Application Access Policies if you choose the latter
By providing these full resources, I hope to make it easier for others to create their own email management GPTs that respect their folder organization and workflow preferences.
Troubleshooting: Lessons From the Trenches
Building this integration wasn't without challenges. Here are some of the major issues I encountered and how I resolved them:
Authentication Failures
Issue: The GPT would frequently lose connection to Microsoft Graph after about an hour of usage, requiring re-authentication.
Root Cause: The default token expiration was set to 1 hour, and the refresh token flow wasn't properly implemented.
Solution: Implemented a proper token refresh mechanism that automatically detects expired tokens and refreshes them before making API calls. Added a token validation check before each request:
Alternative Solution: Switched from delegated permissions to application permissions to eliminate re-authentication prompts entirely. To maintain security:
Used Application Access Policies to restrict access to only my specific mailbox:
Implemented strict auditing and monitoring for the application credentials
Set shorter expiration times for client secrets with automated rotation
This approach provided a seamless experience without constant re-authentication prompts while maintaining proper security boundaries.
Folder Confusion
Issue: When asking to "check my inbox," the GPT would search across all mail folders, returning confusing results.
Root Cause: The Microsoft Graph API defaults to searching across all folders if not explicitly told otherwise. The GPT instructions weren't specific enough about folder scope.
Solution:
Modified Graph API calls to explicitly specify the Inbox folder ID:
Refined the GPT's instructions to be extremely explicit about folder scope:
Permission Scopes
Issue: Certain commands like "move this email" would fail with 403 Forbidden errors.
Root Cause: The initial OAuth scope configuration only included Mail.Read and Mail.Send, but not Mail.ReadWrite which is required for modifying messages.
Solution: Re-registered the application with the complete set of required permissions and implemented a permission check function:
Rate Limiting
Issue: During heavy usage, the integration would hit Microsoft Graph API rate limits.
Root Cause: Multiple rapid requests without proper throttling management.
Solution: Implemented an adaptive throttling mechanism:
Tracked the remaining request quota from response headers
Added automatic request queuing when approaching limits
Implemented a circuit breaker pattern for API stability:
Handling Large Attachments
Issue: The system would crash when trying to process emails with large attachments.
Root Cause: Memory limitations when trying to load entire attachments into memory.
Solution: Implemented streaming attachment processing:
Created a streaming API endpoint for attachment retrieval
Added chunked processing for large files:
Natural Language Processing Challenges
Issue: The GPT sometimes misunderstood complex commands like "forward the second email from John to Sarah with a note saying I'll review this tomorrow."
Root Cause: The GPT struggled to parse complex commands with multiple actions and parameters.
Solution: Implemented a command parser that breaks down complex requests:
Added a pre-processing layer to identify command components
Created a structured format for command interpretation
Implemented a clarification system for ambiguous requests:
These challenges and solutions reflect the real-world complexity of building a reliable, user-friendly AI email assistant. Each issue uncovered helped refine both the technical implementation and the GPT's instruction set.
Solving the "Inbox" Problem
One particular challenge was getting the assistant to understand that when I say "check my inbox" or "show me emails," I specifically mean messages in my Inbox folder - not emails spread across my entire mailbox.
The solution was to explicitly instruct the GPT that:
"Inbox" refers specifically to the Inbox folder
It should NEVER show emails from other folders when asked to check the inbox
Any search should default to the Inbox folder unless I explicitly specify another location
Real-World Usage Examples
Here are some commands I use regularly with my assistant:
The assistant handles these conversationally, confirming details when needed and providing clear summaries of actions taken.
Benefits and Outcomes
Since implementing this custom GPT:
Time savings: I spend significantly less time managing email
Reduced mental load: No more context switching between various email views
Better organization: Emails end up in the right folders with minimal effort
Consistency: My communications maintain a professional tone even when I'm rushed
Future Improvements
I'm continuing to refine the assistant with:
More sophisticated priority detection
Enhanced draft management
Better handling of complex email threads
Calendar integration for scheduling references
Try It Yourself
Creating a custom GPT might sound technical, but OpenAI has made the process surprisingly accessible. If you're facing similar challenges with email management, consider creating your own specialized assistant. The key is to be extremely specific in your instructions about what you want it to do and how it should interpret various commands.
The most important lesson I've learned is that clear, detailed instructions make all the difference in creating a truly useful custom GPT. Small details (like specifying exactly what "inbox" means) can dramatically improve the experience.
Have you experimented with custom GPTs for productivity? I'd love to hear about your experiences in the comments!
The author is a technology executive focused on helping businesses secure and optimize their cloud infrastructure.