Skip to content

indikaimk/ms_graph_lite

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MsGraphLite

A lightweight, modular Ruby wrapper for the Microsoft Graph API.

Designed for developers who need a simple, robust way to send emails (and eventually handle Teams/OneDrive) without the overhead of the massive official SDK.

Features

  • πŸš€ Lightweight: Zero bloat. Only what you need.
  • ⚑ High Performance: Built-in Token Caching. It reuses OAuth tokens until they expire, preventing rate-limiting and reducing latency.
  • πŸ“§ Advanced Email: Supports HTML bodies and Inline Images (CIDs) out of the box.
  • πŸ›‘οΈ Robust Error Handling: Maps complex Microsoft JSON errors to standard Ruby exceptions (e.g., RateLimitError with retry headers).
  • πŸ”Œ Modular: Architecture designed to easily extend to Teams, Calendar, and Drive in the future.

Installation

Add this line to your application's Gemfile:

gem 'ms_graph_lite'

And then execute:

$ bundle install

Prerequisites: Azure Setup

Before using this gem, you need credentials from the Microsoft Azure Portal:

  1. Create a new App Registration.
  2. Go to API Permissions and add Mail.Send (Application Permission).
  3. Grant Admin Consent for the permission.
  4. Generate a Client Secret.

Configuration

Configure the gem in an initializer (e.g., config/initializers/ms_graph_lite.rb for Rails):

MsGraphLite.configure do |config|
  config.tenant_id     = ENV['AZURE_TENANT_ID']
  config.client_id     = ENV['AZURE_CLIENT_ID']
  config.client_secret = ENV['AZURE_CLIENT_SECRET']
end

Usage

1. Sending a Simple Email

mailer = MsGraphLite::Resources::Mail.new

mailer.send(
  from_email: 'notifications@yourcompany.com',
  to_recipients: ['user@example.com', 'admin@example.com'],
  subject: 'Welcome to the Platform',
  content: '<h1>Hello!</h1><p>Welcome aboard.</p>'
)

2. Sending Attachments

To send regular files (PDFs, CSVs, etc.):

attachments = [
  { path: '/tmp/report.pdf' },
  { path: '/tmp/invoice.csv' }
]

mailer.send(
  from_email: 'bot@yourcompany.com',
  to_recipients: 'finance@example.com',
  subject: 'Weekly Report',
  content: 'Please find the attached report.',
  attachments: attachments
)

3. Sending Inline Images (Advanced)

To embed an image inside the email body (like a logo or banner), you must provide a cid (Content ID) in the attachment hash and reference it in your HTML using src="cid:...".

# 1. Prepare the HTML with a CID reference
html_body = <<~HTML
  <h2>Weekly Update</h2>
  <p>Here is our performance chart:</p>
  <img src="cid:performance_chart" alt="Chart" width="500">
  <p>Regards, Team.</p>
HTML

# 2. Attach the image with the matching CID
attachments = [
  { 
    path: './assets/chart.png', 
    cid: 'performance_chart' # Matches the src above
  }
]

# 3. Send
mailer.send(
  from_email: 'bot@yourcompany.com',
  to_recipients: 'manager@example.com',
  subject: 'Performance Update',
  content: html_body,
  attachments: attachments
)

4. Receiving Emails via Polling for Changes (Delta Query)

The most efficient way to check for new emails periodically (e.g., every 5 minutes). It only returns what changed.

# 1. Load the last "Delta Link" from your DB/File (nil if first run)
# You need to implement the MyDB class to read the link from a text file or database.
# Checkout the examples/read_emails.rb for a working example with Ruby pstore.
last_link = MyDb.get_link

# 2. Call Delta
response = mailer.delta(user_email: "support@yourcompany.com", delta_link: last_link)

# 3. Process Changes
response['value'].each do |msg|
  if msg['@removed']
    puts "πŸ—‘οΈ Email Deleted: #{msg['id']}"
  else
    puts "πŸ“© New/Updated: #{msg['subject']}"
  end
end

# 4. Save the new link for next time
new_link = response['@odata.deltaLink'] || response['@odata.nextLink']
MyDb.save_link(new_link)

🧠 Cheat Sheet: Email Fields

When iterating through emails, use these keys to access data:

Field Accessor
Subject email['subject']
Body (HTML) email['body']['content']
Preview Text email['bodyPreview']
Sender Email email['from']['emailAddress']['address']
Sender Name email['from']['emailAddress']['name']
Recipients (To) email['toRecipients'] (Array)
Has Attachments? email['hasAttachments'] (Boolean)
Is Read? email['isRead'] (Boolean)
Message ID email['id']
Received Time email['receivedDateTime']

Error Handling

Stop guessing why your API calls failed. MsGraphLite maps Microsoft errors to specific Ruby exceptions.

begin
  mailer.send(...)
  
rescue MsGraphLite::RateLimitError => e
  # Microsoft is throttling us. The exception knows when we can retry.
  puts "Too many requests! Sleeping for #{e.retry_after} seconds."
  sleep(e.retry_after)
  retry
  
rescue MsGraphLite::AuthenticationError
  # Your Client Secret likely expired or Tenant ID is wrong.
  AdminNotifier.alert("Azure Auth Failed!")
  
rescue MsGraphLite::ResourceNotFoundError
  # The 'from_email' user might not exist in your Azure Tenant.
  puts "The sender email address does not exist."

rescue MsGraphLite::Error => e
  # Handle generic API errors
  puts "Graph API Error: #{e.message} (Code: #{e.code})"
end

Development

After checking out the repo, run bin/setup to install dependencies.

Running Tests

We use RSpec and WebMock to test without hitting real Microsoft servers.

bundle exec rspec

Contributing

Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration.

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

The gem is available as open source under the terms of the MIT License.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors