nylas 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md DELETED
@@ -1,599 +0,0 @@
1
- # Nylas REST API Ruby bindings ![Travis build status](https://travis-ci.org/nylas/nylas-ruby.svg?branch=master)
2
-
3
- ## Installation
4
-
5
- Add this line to your application's Gemfile:
6
-
7
- gem 'nylas'
8
-
9
- And then execute:
10
-
11
- bundle
12
-
13
- 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:
14
-
15
- gem install nylas
16
-
17
- ### MacOS 10.11 (El Capitan) note
18
-
19
- 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:
20
-
21
- ```
22
- sudo brew install openssl
23
- sudo brew link openssl --force
24
- gem install nylas
25
- ```
26
-
27
- ##Requirements
28
-
29
- - Ruby 1.9.3 or above.
30
-
31
- - rest-client, json, yajl-ruby, em-http-request
32
-
33
-
34
- ## Examples
35
-
36
- ### Sinatra App
37
-
38
- A small example of a Sintra app is included in the `examples/sinatra` directory. You can check-out the `README.md` in the sinatra folder to learn more about the example
39
-
40
- ```
41
- cd examples/sinatra
42
- ruby index.rb
43
- ```
44
-
45
- ### Rails App
46
-
47
- 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.
48
-
49
- **Note:** To use the sample app you will need to
50
-
51
- 1. Replace the Nylas App ID and Secret in `config/environments/development.rb`
52
- 2. Add the Callback URL `http://localhost:3000/login_callback` to your app in the [developer console](https://developer.nylas.com/console)
53
-
54
- ```
55
- cd examples/rails
56
- bundle install
57
- RESTCLIENT_LOG=stdout rails s
58
- ```
59
-
60
- ## Usage
61
-
62
- ### App ID and Secret
63
-
64
- 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.
65
-
66
- Generally, you should store your App ID and Secret into environment variables to avoid adding them to source control. That said, in the example project and code snippets below, the values were added to `config/environments/development.rb` for convenience.
67
-
68
-
69
- ### Authentication
70
-
71
- The Nylas REST API uses server-side (three-legged) OAuth, and the Ruby gem provides convenience methods that simplify the OAuth process. For more information about authenticating with Nylas, visit the [Developer Documentation](https://nylas.com/docs/platform#authentication).
72
-
73
- **Step 1: Redirect the user to Nylas:**
74
-
75
- ```ruby
76
- require 'nylas'
77
-
78
- def login
79
- nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nil)
80
- # The email address of the user you want to authenticate
81
- user_email = 'ben@nylas.com'
82
-
83
- # This URL must be registered with your application in the developer portal
84
- callback_url = url_for(:action => 'login_callback')
85
-
86
- # You can also optionally pass state, an optional arbitrary string that
87
- # will be passed back to us at the end of the auth flow.
88
- redirect_to nylas.url_for_authentication(callback_url, user_email, {:state => 'ben auth'})
89
- end
90
- ```
91
-
92
- **Step 2: Handle the Authentication Response:**
93
-
94
- ```ruby
95
- def login_callback
96
- nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nil)
97
- nylas_token = nylas.token_for_code(params[:code])
98
-
99
- # Save the nylas_token to the current session, save it to the user model, etc.
100
- end
101
- ```
102
-
103
- ### Managing Billing
104
-
105
- If you're using the open-source version of the Nylas Sync Engine or have fewer than 10 accounts associated with your developer app, you don't need to worry about billing. However, if you've requested production access to the Sync Engine, you are billed monthly based on the number of email accounts you've connected to Nylas.
106
-
107
- **Cancelling an Account**
108
-
109
- ```ruby
110
- nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nil)
111
- account = nylas.accounts.find(account_id)
112
- account.downgrade!
113
-
114
- # Your Nylas API token will be revoked, you will not be charged
115
- ```
116
-
117
- ### Account Status
118
-
119
- ```ruby
120
- # Query the status of every account linked to the app
121
- nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nylas_token)
122
- accounts = nylas.accounts
123
- accounts.each { |a| [a.account_id, a.sync_state] }
124
- # Available fields are: account_id, sync_state, trial, trial_expires and billing_state.
125
- # See lib/account.rb for more details.
126
- ```
127
-
128
- ### Fetching Accounts
129
-
130
- ```ruby
131
- nylas = Nylas::API.new(config.nylas_app_id, config.nylas_app_secret, nylas_token)
132
-
133
- puts nylas.account.email_address #=> 'alice@example.com'
134
- puts nylas.account.provider #=> 'gmail'
135
- puts nylas.account.sync_state #=> 'running'
136
- ```
137
-
138
- ### Fetching Threads
139
-
140
- ```ruby
141
- # Fetch the first thread
142
- thread = nylas.threads.first
143
-
144
- # Fetch a specific thread
145
- thread = nylas.threads.find('ac123acd123ef123')
146
-
147
- # List all threads in the inbox
148
- # (paginating 50 at a time until no more are returned.)
149
- nylas.threads.where(:in => 'inbox').each do |thread|
150
- puts thread.subject
151
- end
152
-
153
- # List the 5 most recent unread threads
154
- nylas.threads.where(:unread => true).range(0,4).each do |thread|
155
- puts thread.subject
156
- end
157
-
158
- # List all threads with 'ben@nylas.com'
159
- nylas.threads.where(:any_email => 'ben@nylas.com').each do |thread|
160
- puts thread.subject
161
- end
162
-
163
- # Get number of all threads
164
- count = nylas.threads.count
165
-
166
- # Get number of threads with 'ben@inboxapp.com'
167
- count = nylas.threads.where(:any_email => 'ben@inboxapp.com').count
168
-
169
- # Collect all threads with 'ben@nylas.com' into an array.
170
- # Note: for large numbers of threads, this is not advised.
171
- threads = nylas.threads.where(:any_email => 'ben@nylas.com').all
172
- ```
173
-
174
- ### Working with Threads
175
-
176
- ```ruby
177
- # List thread participants
178
- thread.participants.each do |participant|
179
- puts participant['email']
180
- end
181
-
182
- # Mark as read
183
- thread.mark_as_read!
184
-
185
- # Mark as unread
186
- thread.mark_as_unread!
187
-
188
- # Star
189
- thread.star!
190
-
191
- # Remove star
192
- thread.unstar!
193
-
194
- # Adding a new label to a thread
195
-
196
- # First, find the id of the important label.
197
- #
198
- # A note here: all labels have a display_name
199
- # property, which contains a label's name.
200
- # Some very specific labels (e.g: Inbox, Trash, etc.)
201
- # also have a name property, which is a canonical name
202
- # for the label. This is important because folder names
203
- # can change depending the user's locale (e.g: "Boîte de réception"
204
- # means "Inbox" in french). See https://nylas.com/docs/platform#labels
205
- # for more details.
206
- important = nil
207
- nylas.labels.each do |label|
208
- if label.name == 'important'
209
- important = label
210
- end
211
- end
212
-
213
- # Then, add it to the thread.
214
- thread = nylas.threads.where(:from => "helena@nylas.com").first
215
- thread.labels.push(important)
216
- thread.save!
217
-
218
- # List messages
219
- thread.messages.each do |message|
220
- puts message.subject
221
- end
222
-
223
- # List all messages sent by Ben where Helena was cc'ed:
224
- thread.messages.where(:from => 'ben@nylas.com').each.select { |t|
225
- t.cc.any? {|p| p['email'] == 'helena@nylas.com' }
226
- }
227
- ```
228
-
229
- ### Working with Files
230
-
231
- ```ruby
232
- # List files
233
- nylas.files.each do |file|
234
- puts file.filename
235
- end
236
-
237
- # Create a new file
238
- file = nylas.files.build(:file => File.new('./public/favicon.ico', 'rb'))
239
- file.save!
240
-
241
- # Download a file's contents
242
- content = file.download
243
- ```
244
-
245
- ### Working with Labels/Folders
246
-
247
- 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.
248
-
249
- ```ruby
250
- # List labels
251
- nylas.labels.each do |label|
252
- puts label.display_name, label.id
253
- end
254
-
255
- # Create a label
256
- label = nylas.folders.build(:display_name => 'Test label', :name => 'test name')
257
- label.save!
258
-
259
- # Create a folder
260
- #
261
- # Note that Folders and Labels are absolutely identical from the standpoint of the SDK.
262
- # The only difference is that a message can have many labels but only a single folder.
263
- fld = nylas.folders.build(:display_name => 'Test folder', :name => 'test name')
264
- fld.save!
265
-
266
- # Rename a folder
267
- #
268
- # Note that you can not rename folders like INBOX, Trash, etc.
269
- fld = nylas.folders.first
270
- fld.display_name = 'Renamed folder'
271
- fld.save!
272
- ```
273
-
274
- ### Working with Messages
275
-
276
- ```ruby
277
- puts msg.subject
278
- puts msg.from
279
-
280
- # Mark as read
281
- msg.mark_as_read!
282
-
283
- # Mark as unread
284
- msg.mark_as_unread!
285
-
286
- # Star
287
- msg.star!
288
-
289
- # Remove star
290
- msg.unstar!
291
- ```
292
-
293
- ### Working with API Objects
294
-
295
- #### Filtering
296
-
297
- 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:
298
-
299
- ```ruby
300
- # Let's get all the attachments Ben sent me.
301
- messages = nylas.messages.where(:to => 'ben@nylas.com')
302
-
303
- messages.each do |msg|
304
- puts msg.subject
305
-
306
- if msg.files? # => returns true if the message has attachments.
307
- # Download them all.
308
- msg.files.each |file| do
309
- puts file.download
310
- end
311
- end
312
- end
313
- ```
314
-
315
- The `#where` method accepts a hash of filters, as documented in the [Filters Documentation](https://nylas.com/docs/platform#filters).
316
-
317
- #### Enumerator methods
318
-
319
- Every object API object has an `each` method which returns an `Enumerator` if you don't pass it a block.
320
- This allows you to leverage all that Ruby's `Enumerable` has to offer.
321
- For example, this is the previous example rewritten to use an `Enumerator`:
322
-
323
- ```ruby
324
- messages_with_files = messages.each.select(&:files?)
325
- to_download = messages_with_files.flat_map(&:files)
326
- to_download.map { |file| puts file.download }
327
- ```
328
-
329
- #### Accessing an object's raw JSON
330
-
331
- Sometimes you really need to access the JSON object the API returned. You can use the `#raw_json` property for this:
332
-
333
- ```ruby
334
- puts contact.raw_json #=>
335
- # {
336
- # "name": "Ben Bitdiddle",
337
- # "email": "ben.bitdiddle@mit.edu",
338
- # "id": "8pjz8oj4hkfwgtb46furlh77",
339
- # "account_id": "aqau8ta87ndh6cwv0o3ajfoo2",
340
- # "object": "contact"
341
- # }
342
- ```
343
-
344
- #### Getting a message's Message-Id, References and In-Reply-To headers
345
-
346
- If you've building your own threading solution, you'll probably need access to a handful of headers like
347
- `Message-Id`, `In-Reply-To` and `References`. Here's how to access them:
348
-
349
- ```ruby
350
- msg = nylas.messages.first
351
- expanded_message = msg.expanded
352
- puts expanded_message.message_id
353
- puts expanded_message.references
354
- puts expanded_message.in_reply_to
355
- ```
356
-
357
- #### Getting the raw contents of a message
358
-
359
- It's possible to access the unprocessed contents of a message using the raw method:
360
-
361
- ```ruby
362
- raw_contents = message.raw
363
- ```
364
-
365
- ### Creating and Sending Drafts
366
-
367
- ```ruby
368
- # Create a new draft
369
- draft = nylas.drafts.build(
370
- :to => [{:name => 'Ben Gotow', :email => 'ben@nylas.com'}],
371
- :subject => 'Sent by Ruby',
372
- :body => 'Hi there!<strong>This is HTML</strong>'
373
- )
374
-
375
- # Modify attributes as necessary
376
- draft.cc = [{:name => 'Michael', :email => 'mg@nylas.com'}]
377
-
378
- # Add the file we uploaded as an attachment
379
- draft.attach(file)
380
-
381
- # Save the draft
382
- draft.save!
383
-
384
- # Send the draft.
385
- draft.send!
386
-
387
- # Sometimes sending isn't possible --- handle the exception and
388
- # print the error message returned by the SMTP server:
389
- begin
390
- draft.send!
391
- rescue Nylas::APIError => e
392
- puts "Failed with error: #{e.message}"
393
- if not e.server_error.nil?
394
- puts "The SMTP server replied: #{e.server_error}"
395
- end
396
- end
397
- ```
398
-
399
- ### Creating an event
400
-
401
- ```ruby
402
- # Every event is attached to a calendar -- get the id of the first calendar
403
- calendar_id = nylas.calendars.first.id
404
- new_event = nylas.events.build(:calendar_id => calendar_id, :title => 'Coffee?')
405
-
406
- # Modify attributes as necessary
407
- new_event.location = "L'excelsior"
408
-
409
- # Dates are expressed by the Nylas API as UTC timestamps
410
- new_event.when = {:start_time => 1407542195, :end_time => 1407543195}
411
-
412
- # Persist the event --- it's automatically synced back to the Google or Exchange calendar
413
- new_event.save!
414
-
415
- # Send an invite/update message to the participants
416
- new_event.save!(:notify_participants => true)
417
-
418
- # RSVP to an invite (Note: this only works for the events in the 'Emailed events' calendar)
419
- # possible statuses are 'yes', 'no' and 'maybe'.
420
- emailed_invite.rsvp!(status='yes', comment='I will come')
421
- ```
422
-
423
- ## Using the Delta sync API
424
-
425
- The delta sync API allows fetching all the changes that occurred after a specific time.
426
- [Read this](https://nylas.com/docs/platform/#deltas) for more details about the API.
427
-
428
- ```ruby
429
- # Get an API cursor. Cursors are API objects identifying an individual change.
430
- # The latest cursor is the id of the latest change which was applied
431
- # to an API object (e.g: a message got read, an event got created, etc.)
432
- cursor = nylas.latest_cursor
433
-
434
- last_cursor = nil
435
- nylas.deltas(cursor) do |event, object|
436
- if event == "create" or event == "modify"
437
- if object.is_a?(Nylas::Contact)
438
- puts "#{object.name} - #{object.email}"
439
- elsif object.is_a?(Nylas::Event)
440
- puts "Event!"
441
- end
442
- elsif event == "delete"
443
- # In the case of a deletion, the API only returns the ID of the object.
444
- # In this case, the Ruby SDK returns a dummy object with only the id field
445
- # set.
446
- puts "Deleting from collection #{object.class.name}, id: #{object}"
447
- end
448
- last_cursor = object.cursor
449
- end
450
-
451
- # Don't forget to save the last cursor so that we can pick up changes
452
- # from where we left.
453
- save_to_db(last_cursor)
454
- ```
455
-
456
- ### Using the Delta sync streaming API
457
-
458
- The streaming API will receive deltas in real time, without needing to repeatedly poll. It uses EventMachine for async IO.
459
-
460
- ```ruby
461
- cursor = nylas.latest_cursor
462
-
463
- EventMachine.run do
464
- nylas.delta_stream(cursor) do |event, object|
465
- if event == "create" or event == "modify"
466
- if object.is_a?(Nylas::Contact)
467
- puts "#{object.name} - #{object.email}"
468
- elsif object.is_a?(Nylas::Event)
469
- puts "Event!"
470
- end
471
- elsif event == "delete"
472
- # In the case of a deletion, the API only returns the ID of the object.
473
- # In this case, the Ruby SDK returns a dummy object with only the id field
474
- # set.
475
- puts "Deleting from collection #{object.class.name}, id: #{object}"
476
- end
477
- end
478
- end
479
- ```
480
-
481
- To receive streams from multiple accounts, call `delta_stream` for each of them inside an `EventMachine.run` block.
482
-
483
- ```ruby
484
- api_handles = [] # a list of Nylas::API objects
485
-
486
- EventMachine.run do
487
- api_handles.each do |a|
488
- cursor = a.latest_cursor()
489
- a.delta_stream(cursor) do |event, object|
490
- puts object
491
- end
492
- end
493
- end
494
- ```
495
-
496
- ### Exclude changes from a specific type --- get only messages
497
-
498
- ```ruby
499
- nylas.deltas(cursor, exclude=[Nylas::Contact,
500
- Nylas::Event,
501
- Nylas::File,
502
- Nylas::Tag,
503
- Nylas::Thread]) do |event, object|
504
- if ['create', 'modify'].include? event
505
- puts object.subject
506
- end
507
- end
508
- ```
509
-
510
- ### Expand Messages from the Delta stream
511
-
512
- It's possible to ask the Deltas and delta stream API to return [expanded messages](https://nylas.com/docs/platform#expanded_message_view) directly:
513
-
514
- ```ruby
515
- nylas.deltas(cursor, exclude=[Nylas::Contact,
516
- Nylas::Event,
517
- Nylas::File,
518
- Nylas::Tag,
519
- Nylas::Thread], expanded_view=true) do |event, object|
520
- if ['create', 'modify'].include? event
521
- if obj.is_a?(Nylas::Message)
522
- puts obj.subject
523
- puts obj.message_id
524
- end
525
- end
526
- end
527
- ```
528
-
529
- ### Handling Errors
530
- 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.
531
-
532
- Code | Error Type | Description
533
- --- | --- | ---
534
- 400 | `InvalidRequest` | Your request has invalid parameters.
535
- 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.
536
- 404 | `ResourceNotFound` | The requested resource doesn't exist.
537
- 500 | `APIError` | There was an internal error with the Nylas server.
538
-
539
- A few additional exceptions are raised by the `draft.send!` method if your draft couldn't be sent.
540
-
541
- Code | Error Type | Description
542
- --- | --- | ---
543
- 402 | `MessageRejected` | The message was syntactically valid, but rejected for delivery by the mail server.
544
- 429 | `SendingQuotaExceeded` | The user has exceeded their daily sending quota.
545
- 503 | `ServiceUnavailable` | There was a temporary error establishing a connection to the user's mail server.
546
-
547
- ## Open-Source Sync Engine
548
-
549
- 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:
550
-
551
- ```ruby
552
- require 'nylas'
553
- nylas = Nylas::API.new(nil, nil, nil, 'http://localhost:5555/')
554
-
555
- # Get the id of the first account -- this is the access token we're
556
- # going to use.
557
- account_id = nylas.accounts.first.id
558
-
559
- # Display the body of the first message for the first account
560
- nylas = Nylas::API.new(nil, nil, account_id, 'http://localhost:5555/')
561
- puts nylas.messages.first.body
562
- ```
563
-
564
-
565
- ## Contributing
566
-
567
- We'd love your help making the Nylas ruby gem better. Join the Google Group for project updates and feature discussion. We also have a [Slack community](nylas-slack-invite.heroku.com) where we provide support, or you can email [support@nylas.com](mailto:support@nylas.com).
568
-
569
- Please sign the [Contributor License Agreement](https://www.nylas.com/cla.html) before submitting pull requests. (It's similar to other projects, like NodeJS or Meteor.)
570
-
571
- Tests can be run with:
572
-
573
- rspec spec
574
-
575
-
576
- ## Deployment
577
-
578
- The Nylas ruby gem uses [Jeweler](https://github.com/technicalpickles/jeweler) for release management. Jeweler should be installed automatically when you call `bundle`, and extends `rake` to include a few more commands. When you're ready to release a new version, edit `lib/version.rb` and then build:
579
-
580
- rake inbox_build
581
- rake nylas_build
582
-
583
- Test your new version (found in `pkg/`) locally, and then release with:
584
-
585
- rake inbox_release
586
- rake nylas_release
587
-
588
- If it's your first time updating the ruby gems, you may be prompted for the username/password for rubygems.org. Members of the Nylas team can find that by doing `fetch-password rubygems`.
589
-
590
- ## API self-tests
591
-
592
- 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.
593
-
594
- You can run the programs like this:
595
-
596
- ```shell
597
- cd tests && ruby -I../lib auth.rb
598
- cd tests && ruby -I../lib system.rb
599
- ```