README.md in inbox-1.1.0 vs README.md in inbox-1.2.1
- old
+ new
@@ -1,6 +1,6 @@
-# Nylas REST API Ruby bindings
+# Nylas REST API Ruby bindings ![Travis build status](https://travis-ci.org/nylas/nylas-ruby.svg?branch=master)
## Installation
Add this line to your application's Gemfile:
@@ -8,18 +8,27 @@
And then execute:
bundle
-You don't need to use this repo unless you're planning to modify the gem. If you just want to use the Inbox SDK with Ruby bindings, you should run:
+You don't need to use this repo unless you're planning to modify the gem. If you just want to use the Nylas SDK with Ruby bindings, you should run:
gem install nylas
+### MacOS 10.11 (El Capitan) note
+Apple stopped bundling openssl with MacOS 10.11. However, one of the dependencies of this gem (EventMachine) requires it. If you're on El Capitan and are unable to install the gem, try running the following commands in a terminal:
+
+```
+sudo brew install openssl
+sudo brew link openssl --force
+gem install nylas
+```
+
##Requirements
-- Ruby 1.8.7 or above. (Ruby 1.8.6 may work if you load ActiveSupport.)
+- Ruby 1.9.3 or above.
- rest-client, json, yajl-ruby, em-http-request
## Examples
@@ -35,17 +44,21 @@
### Rails App
A small example Rails app is included in the `examples/rails` directory. You can run the sample app to see how an authentication flow might be implemented.
+**Note:** To use the sample app you will need to
+
+1. Replace the Nylas App ID and Secret in `config/environments/development.rb`
+2. Add the Callback URL `http://localhost:3000/login_callback` to your app in the [developer console](https://developer.nylas.com/console)
+
```
cd examples/rails
+bundle install
RESTCLIENT_LOG=stdout rails s
```
-**Note:** *You will need to replace the Nylas App ID and Secret in `config/environments/development.rb` to use the sample app.*
-
## Usage
### App ID and Secret
Before you can interact with the Nylas API, you need to register for the Nylas Developer Program at [https://www.nylas.com/](https://www.nylas.com/). After you've created a developer account, you can create a new application to generate an App ID / Secret pair.
@@ -99,28 +112,29 @@
# Your Nylas API token will be revoked, you will not be charged
```
### Account Status
-````ruby
+```ruby
# Query the status of every account linked to the app
nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nylas_token)
accounts = nylas.accounts
- accounts.each { |a| [a.account_id, a.sync_state] } # Available fields are: account_id, sync_state, trial, trial_expires and billing_state. See lib/account.rb for more details.
+ accounts.each { |a| [a.account_id, a.sync_state] }
+ # Available fields are: account_id, sync_state, trial, trial_expires and billing_state.
+ # See lib/account.rb for more details.
```
### Fetching Accounts
```ruby
nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nylas_token)
-# Print out the email address and provider (Gmail, Exchange)
-puts nylas.account.email_address
-puts nylas.account.provider
+puts nylas.account.email_address #=> 'alice@example.com'
+puts nylas.account.provider #=> 'gmail'
+puts nylas.account.sync_state #=> 'running'
```
-
### Fetching Threads
```ruby
# Fetch the first thread
thread = nylas.threads.first
@@ -153,11 +167,10 @@
# Collect all threads with 'ben@nylas.com' into an array.
# Note: for large numbers of threads, this is not advised.
threads = nylas.threads.where(:any_email => 'ben@nylas.com').all
```
-
### Working with Threads
```ruby
# List thread participants
thread.participants.each do |participant|
@@ -190,23 +203,27 @@
# List messages
thread.messages.each do |message|
puts message.subject
end
+
+# List all messages sent by Ben where Helena was cc'ed:
+thread.messages.where(:from => 'ben@nylas.com').each.select { |t|
+ t.cc.any? {|p| p['email'] == 'helena@nylas.com' }
+}
```
-
### Working with Files
```ruby
# List files
nylas.files.each do |file|
puts file.filename
end
# Create a new file
-file = nylas.files.build(:file => File.new("./public/favicon.ico", 'rb'))
+file = nylas.files.build(:file => File.new('./public/favicon.ico', 'rb'))
file.save!
# Download a file's contents
content = file.download
```
@@ -214,11 +231,10 @@
### Working with Labels/Folders
The new folders and labels API replaces the now deprecated Tags API. It allows you to apply Gmail labels to whole threads or individual messages and, for providers other than Gmail, to move threads and messages between folders.
```ruby
-
# List labels
nylas.labels.each do |label|
puts label.display_name, label.id
end
@@ -237,25 +253,65 @@
#
# Note that you can not rename folders like INBOX, Trash, etc.
fld = nylas.folders.first
fld.display_name = 'Renamed folder'
fld.save!
-
```
### Working with Messages, Contacts, etc.
+#### Filtering
+
Each of the primary collections (contacts, messages, etc.) behave the same way as `threads`. For example, finding messages with a filter is similar to finding threads:
```ruby
-messages = nylas.messages.where(:to => 'ben@nylas.com`).all
+# Let's get all the attachments Ben sent me.
+messages = nylas.messages.where(:to => 'ben@nylas.com')
+
+messages.each do |msg|
+ puts msg.subject
+
+ if msg.files? # => returns true if the message has attachments.
+ # Download them all.
+ msg.files.each |file| do
+ puts file.download
+ end
+ end
+end
```
-The `where` method accepts a hash of filters, as documented in the [Filters Documentation](https://nylas.com/docs/platform#filters).
+The `#where` method accepts a hash of filters, as documented in the [Filters Documentation](https://nylas.com/docs/platform#filters).
-### Getting a message's Message-Id, References and In-Reply-To headers
+#### Enumerator methods
+Every object API object has an `each` method which returns an `Enumerator` if you don't pass it a block.
+This allows you to do leverage all that Ruby's `Enumerable` has to offer.
+For example, this is the previous example rewritten to use an `Enumerator`:
+
+```ruby
+messages_with_files = messages.each.select(&:files?)
+to_download = messages_with_files.flat_map(&:files)
+to_download.map { |file| puts file.download }
+```
+
+#### Accessing an object's raw JSON
+
+Sometimes you really need to access the JSON object the API returned. You can use the `#raw_json` property for this:
+
+```ruby
+puts contact.raw_json #=>
+# {
+# "name": "Ben Bitdiddle",
+# "email": "ben.bitdiddle@mit.edu",
+# "id": "8pjz8oj4hkfwgtb46furlh77",
+# "account_id": "aqau8ta87ndh6cwv0o3ajfoo2",
+# "object": "contact"
+# }
+```
+
+#### Getting a message's Message-Id, References and In-Reply-To headers
+
If you've building your own threading solution, you'll probably need access to a handful of headers like
`Message-Id`, `In-Reply-To` and `References`. Here's how to access them:
```ruby
msg = nylas.messages.first
@@ -263,27 +319,26 @@
puts expanded_message.message_id
puts expanded_message.references
puts expanded_message.in_reply_to
```
-### Getting the raw contents of a message
+#### Getting the raw contents of a message
It's possible to access the unprocessed contents of a message using the raw method:
```ruby
raw_contents = message.raw
```
-
### Creating and Sending Drafts
```ruby
# Create a new draft
draft = nylas.drafts.build(
:to => [{:name => 'Ben Gotow', :email => 'ben@nylas.com'}],
- :subject => "Sent by Ruby",
- :body => "Hi there!<strong>This is HTML</strong>"
+ :subject => 'Sent by Ruby',
+ :body => 'Hi there!<strong>This is HTML</strong>'
)
# Modify attributes as necessary
draft.cc = [{:name => 'Michael', :email => 'mg@nylas.com'}]
@@ -297,30 +352,30 @@
draft.send!
# Sometimes sending isn't possible --- handle the exception and
# print the error message returned by the SMTP server:
begin
- draft.send!
+ draft.send!
rescue Nylas::APIError => e
- puts "Failed with error: #{e.message}"
- if not e.server_error.nil?
- puts "The SMTP server replied: #{e.server_error}"
- end
+ puts "Failed with error: #{e.message}"
+ if not e.server_error.nil?
+ puts "The SMTP server replied: #{e.server_error}"
+ end
end
```
### Creating an event
-````ruby
+```ruby
# Every event is attached to a calendar -- get the id of the first calendar
calendar_id = nylas.calendars.first.id
new_event = nylas.events.build(:calendar_id => calendar_id, :title => 'Coffee?')
# Modify attributes as necessary
new_event.location = "L'excelsior"
-# Dates are expressed by the Inbox API as UTC timestamps
+# Dates are expressed by the Nylas API as UTC timestamps
new_event.when = {:start_time => 1407542195, :end_time => 1407543195}
# Persist the event --- it's automatically synced back to the Google or Exchange calendar
new_event.save!
@@ -332,33 +387,34 @@
emailed_invite.rsvp!(status='yes', comment='I will come')
```
## Using the Delta sync API
-The delta sync API allows fetching all the changes that occured after a specific time. [Read this](https://nylas.com/docs/platform/#deltas) for more details about the API.
+The delta sync API allows fetching all the changes that occurred after a specific time.
+[Read this](https://nylas.com/docs/platform/#deltas) for more details about the API.
-````ruby
+```ruby
# Get an API cursor. Cursors are API objects identifying an individual change.
# The latest cursor is the id of the latest change which was applied
# to an API object (e.g: a message got read, an event got created, etc.)
cursor = nylas.latest_cursor
last_cursor = nil
nylas.deltas(cursor) do |event, object|
- if event == "create" or event == "modify"
- if object.is_a?(Nylas::Contact)
- puts "#{object.name} - #{object.email}"
- elsif object.is_a?(Nylas::Event)
- puts "Event!"
- end
- elsif event == "delete"
- # In the case of a deletion, the API only returns the ID of the object.
- # In this case, the Ruby SDK returns a dummy object with only the id field
- # set.
- puts "Deleting from collection #{object.class.name}, id: #{object}"
+ if event == "create" or event == "modify"
+ if object.is_a?(Nylas::Contact)
+ puts "#{object.name} - #{object.email}"
+ elsif object.is_a?(Nylas::Event)
+ puts "Event!"
end
- last_cursor = object.cursor
+ elsif event == "delete"
+ # In the case of a deletion, the API only returns the ID of the object.
+ # In this case, the Ruby SDK returns a dummy object with only the id field
+ # set.
+ puts "Deleting from collection #{object.class.name}, id: #{object}"
+ end
+ last_cursor = object.cursor
end
# Don't forget to save the last cursor so that we can pick up changes
# from where we left.
save_to_db(last_cursor)
@@ -366,85 +422,84 @@
### Using the Delta sync streaming API
The streaming API will receive deltas in real time, without needing to repeatedly poll. It uses EventMachine for async IO.
-````ruby
+```ruby
cursor = nylas.latest_cursor
last_cursor = nil
nylas.delta_stream(cursor) do |event, object|
- if event == "create" or event == "modify"
- if object.is_a?(Inbox::Contact)
- puts "#{object.name} - #{object.email}"
- elsif object.is_a?(Inbox::Event)
- puts "Event!"
- end
- elsif event == "delete"
- # In the case of a deletion, the API only returns the ID of the object.
- # In this case, the Ruby SDK returns a dummy object with only the id field
- # set.
- puts "Deleting from collection #{object.class.name}, id: #{object}"
+ if event == "create" or event == "modify"
+ if object.is_a?(Nylas::Contact)
+ puts "#{object.name} - #{object.email}"
+ elsif object.is_a?(Nylas::Event)
+ puts "Event!"
end
- last_cursor = object.cursor
+ elsif event == "delete"
+ # In the case of a deletion, the API only returns the ID of the object.
+ # In this case, the Ruby SDK returns a dummy object with only the id field
+ # set.
+ puts "Deleting from collection #{object.class.name}, id: #{object}"
+ end
+ last_cursor = object.cursor
- # This will loop indefintely
+ # This will loop indefintely
end
-
```
-
### Exclude changes from a specific type --- get only messages
-````ruby
+
+```ruby
nylas.deltas(cursor, exclude=[Nylas::Contact,
Nylas::Event,
Nylas::File,
Nylas::Tag,
Nylas::Thread]) do |event, object|
-if event == 'create' or event == 'modify'
- puts object.subject
- end
+ if ['create', 'modify'].include? event
+ puts object.subject
+ end
end
```
### Expand Messages from the Delta stream
It's possible to ask the Deltas and delta stream API to return [expanded messages](https://nylas.com/docs/platform#expanded_message_view) directly:
-````ruby
+
+```ruby
nylas.deltas(cursor, exclude=[Nylas::Contact,
Nylas::Event,
Nylas::File,
Nylas::Tag,
Nylas::Thread], expanded_view=true) do |event, object|
-if event == 'create' or event == 'modify'
- if obj.is_a?(Inbox::Message)
+ if ['create', 'modify'].include? event
+ if obj.is_a?(Nylas::Message)
puts obj.subject
puts obj.message_id
+ end
end
end
```
### Handling Errors
The Nylas API uses conventional HTTP response codes to indicate success or failure of an API request. The ruby gem raises these as native exceptions.
Code | Error Type | Description
--- | --- | ---
-400 | InvalidRequest | Your request has invalid parameters.
-403 | AccessDenied | You don't have authorization to access the requested resource or perform the requested action. You may need to re-authenticate the user.
-404 | ResourceNotFound | The requested resource doesn't exist.
-500 | APIError | There was an internal error with the Nylas server.
+400 | `InvalidRequest` | Your request has invalid parameters.
+403 | `AccessDenied` | You don't have authorization to access the requested resource or perform the requested action. You may need to re-authenticate the user.
+404 | `ResourceNotFound` | The requested resource doesn't exist.
+500 | `APIError` | There was an internal error with the Nylas server.
A few additional exceptions are raised by the `draft.send!` method if your draft couldn't be sent.
Code | Error Type | Description
--- | --- | ---
-402 | MessageRejected| The message was syntactically valid, but rejected for delivery by the mail server.
-429 | SendingQuotaExceeded | The user has exceeded their daily sending quota.
-503 | ServiceUnavailable | There was a temporary error establishing a connection to the user's mail server.
+402 | `MessageRejected` | The message was syntactically valid, but rejected for delivery by the mail server.
+429 | `SendingQuotaExceeded` | The user has exceeded their daily sending quota.
+503 | `ServiceUnavailable` | There was a temporary error establishing a connection to the user's mail server.
-
-
## Open-Source Sync Engine
The [Nylas Sync Engine](http://github.com/nylas/sync-engine) is open source, and you can also use the Ruby gem with the open source API. Since the open source API provides no authentication or security, connecting to it is simple. When you instantiate the Nylas object, provide `nil` for the App ID and App Secret, and set the API Token to the id of the account you're going to access. Finally, don't forget to pass the fully-qualified address to your copy of the sync engine:
```ruby
@@ -489,7 +544,10 @@
## API self-tests
Because it's critical that we don't break the SDK for our customers, we require releasers to run some tests before releasing a new version of the gem. The test programs are located in the test/ directory. To set up them up, you'll need to copy `tests/credentials.rb.templates` as `test/credentials.rb` and edit the `APP_ID` and `APP_SECRET` with a working Nylas API app id and secret. You also need to set up a `/callback` URL in the Nylas admin panel.
You can run the programs like this:
-`cd tests && ruby -I../lib auth.rb`
-`cd tests && ruby -I../lib system.rb`
+
+```shell
+cd tests && ruby -I../lib auth.rb
+cd tests && ruby -I../lib system.rb
+```