nylas_v2 5.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/lib/nylas_v2/account.rb +56 -0
  3. data/lib/nylas_v2/api.rb +244 -0
  4. data/lib/nylas_v2/application_details.rb +13 -0
  5. data/lib/nylas_v2/calendar.rb +46 -0
  6. data/lib/nylas_v2/calendar_collection.rb +144 -0
  7. data/lib/nylas_v2/categorize.rb +14 -0
  8. data/lib/nylas_v2/collection.rb +175 -0
  9. data/lib/nylas_v2/component.rb +35 -0
  10. data/lib/nylas_v2/component_collection.rb +10 -0
  11. data/lib/nylas_v2/constraints.rb +56 -0
  12. data/lib/nylas_v2/contact.rb +53 -0
  13. data/lib/nylas_v2/contact_group.rb +23 -0
  14. data/lib/nylas_v2/current_account.rb +23 -0
  15. data/lib/nylas_v2/delta.rb +56 -0
  16. data/lib/nylas_v2/deltas.rb +19 -0
  17. data/lib/nylas_v2/deltas_collection.rb +40 -0
  18. data/lib/nylas_v2/draft.rb +100 -0
  19. data/lib/nylas_v2/email_address.rb +12 -0
  20. data/lib/nylas_v2/errors.rb +111 -0
  21. data/lib/nylas_v2/event.rb +141 -0
  22. data/lib/nylas_v2/event_collection.rb +15 -0
  23. data/lib/nylas_v2/event_conferencing.rb +12 -0
  24. data/lib/nylas_v2/event_conferencing_autocreate.rb +10 -0
  25. data/lib/nylas_v2/event_conferencing_details.rb +14 -0
  26. data/lib/nylas_v2/event_notification.rb +17 -0
  27. data/lib/nylas_v2/file.rb +75 -0
  28. data/lib/nylas_v2/filter_attributes.rb +25 -0
  29. data/lib/nylas_v2/folder.rb +26 -0
  30. data/lib/nylas_v2/free_busy.rb +13 -0
  31. data/lib/nylas_v2/free_busy_collection.rb +48 -0
  32. data/lib/nylas_v2/http_client.rb +279 -0
  33. data/lib/nylas_v2/im_address.rb +11 -0
  34. data/lib/nylas_v2/job_status.rb +27 -0
  35. data/lib/nylas_v2/job_status_collection.rb +21 -0
  36. data/lib/nylas_v2/label.rb +27 -0
  37. data/lib/nylas_v2/logging.rb +41 -0
  38. data/lib/nylas_v2/message.rb +98 -0
  39. data/lib/nylas_v2/message_headers.rb +27 -0
  40. data/lib/nylas_v2/message_tracking.rb +13 -0
  41. data/lib/nylas_v2/model/attributable.rb +89 -0
  42. data/lib/nylas_v2/model/attribute_definition.rb +24 -0
  43. data/lib/nylas_v2/model/attributes.rb +97 -0
  44. data/lib/nylas_v2/model/list_attribute_definition.rb +39 -0
  45. data/lib/nylas_v2/model/transferable.rb +53 -0
  46. data/lib/nylas_v2/model.rb +217 -0
  47. data/lib/nylas_v2/native_authentication.rb +39 -0
  48. data/lib/nylas_v2/neural.rb +87 -0
  49. data/lib/nylas_v2/neural_categorizer.rb +29 -0
  50. data/lib/nylas_v2/neural_clean_conversation.rb +33 -0
  51. data/lib/nylas_v2/neural_contact_link.rb +11 -0
  52. data/lib/nylas_v2/neural_contact_name.rb +11 -0
  53. data/lib/nylas_v2/neural_message_options.rb +35 -0
  54. data/lib/nylas_v2/neural_ocr.rb +16 -0
  55. data/lib/nylas_v2/neural_sentiment_analysis.rb +17 -0
  56. data/lib/nylas_v2/neural_signature_contact.rb +81 -0
  57. data/lib/nylas_v2/neural_signature_extraction.rb +18 -0
  58. data/lib/nylas_v2/new_message.rb +39 -0
  59. data/lib/nylas_v2/nylas_date.rb +25 -0
  60. data/lib/nylas_v2/open_hours.rb +15 -0
  61. data/lib/nylas_v2/outbox.rb +116 -0
  62. data/lib/nylas_v2/outbox_job_status.rb +19 -0
  63. data/lib/nylas_v2/outbox_message.rb +17 -0
  64. data/lib/nylas_v2/participant.rb +13 -0
  65. data/lib/nylas_v2/phone_number.rb +11 -0
  66. data/lib/nylas_v2/physical_address.rb +17 -0
  67. data/lib/nylas_v2/raw_message.rb +25 -0
  68. data/lib/nylas_v2/recurrence.rb +11 -0
  69. data/lib/nylas_v2/registry.rb +42 -0
  70. data/lib/nylas_v2/room_resource.rb +19 -0
  71. data/lib/nylas_v2/rsvp.rb +24 -0
  72. data/lib/nylas_v2/scheduler.rb +51 -0
  73. data/lib/nylas_v2/scheduler_booking_confirmation.rb +24 -0
  74. data/lib/nylas_v2/scheduler_booking_request.rb +17 -0
  75. data/lib/nylas_v2/scheduler_collection.rb +104 -0
  76. data/lib/nylas_v2/scheduler_config.rb +20 -0
  77. data/lib/nylas_v2/scheduler_time_slot.rb +14 -0
  78. data/lib/nylas_v2/search_collection.rb +10 -0
  79. data/lib/nylas_v2/send_grid_verified_status.rb +12 -0
  80. data/lib/nylas_v2/thread.rb +66 -0
  81. data/lib/nylas_v2/time_slot.rb +16 -0
  82. data/lib/nylas_v2/time_slot_capacity.rb +13 -0
  83. data/lib/nylas_v2/timespan.rb +20 -0
  84. data/lib/nylas_v2/token_info.rb +20 -0
  85. data/lib/nylas_v2/types.rb +168 -0
  86. data/lib/nylas_v2/version.rb +5 -0
  87. data/lib/nylas_v2/web_page.rb +11 -0
  88. data/lib/nylas_v2/webhook.rb +98 -0
  89. data/lib/nylas_v2/when.rb +75 -0
  90. data/lib/nylas_v2.rb +162 -0
  91. metadata +415 -0
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # An enumerable for working with index and search endpoints
5
+ class Collection
6
+ attr_accessor :model, :api, :constraints
7
+
8
+ extend Forwardable
9
+ def_delegators :each, :map, :select, :reject, :to_a, :take
10
+ def_delegators :to_a, :first, :last, :[]
11
+
12
+ def initialize(model:, api:, constraints: nil)
13
+ self.constraints = Constraints.from_constraints(constraints)
14
+ self.model = model
15
+ self.api = api
16
+ end
17
+
18
+ # Instantiates a new model
19
+ def new(**attributes)
20
+ model.new(**attributes.merge(api: api))
21
+ end
22
+
23
+ def create(**attributes)
24
+ instance = model.new(**attributes.merge(api: api))
25
+ instance.save
26
+ instance
27
+ end
28
+
29
+ # Merges in additional filters when querying the collection
30
+ # @return [Collection<Model>]
31
+ def where(filters)
32
+ raise ModelNotFilterableError, model unless model.filterable?
33
+
34
+ self.class.new(model: model, api: api, constraints: constraints.merge(where: filters))
35
+ end
36
+
37
+ def search(query)
38
+ raise ModelNotSearchableError, model unless model.searchable?
39
+
40
+ SearchCollection.new(model: model, api: api, constraints: constraints.merge(where: { q: query }))
41
+ end
42
+
43
+ # The collection now returns a string representation of the model in a particular mime type instead of
44
+ # Model objects
45
+ # @return [Collection<String>]
46
+ def raw
47
+ raise ModelNotAvailableAsRawError, model unless model.exposable_as_raw?
48
+
49
+ self.class.new(model: model, api: api, constraints: constraints.merge(accept: model.raw_mime_type))
50
+ end
51
+
52
+ # @return [Integer]
53
+ def count
54
+ collection = self.class.new(model: model, api: api, constraints: constraints)
55
+
56
+ if model.countable
57
+ collection.constraints = collection.constraints.merge(view: "count")
58
+ collection.execute[:count]
59
+ else
60
+ collection.find_each.map.count
61
+ end
62
+ end
63
+
64
+ # @return [Collection<Model>]
65
+ def expanded
66
+ self.class.new(model: model, api: api, constraints: constraints.merge(view: "expanded"))
67
+ end
68
+
69
+ # @return [Array<String>]
70
+ def ids
71
+ collection = self.class.new(model: model, api: api, constraints: constraints)
72
+
73
+ if model.id_listable
74
+ collection.constraints = collection.constraints.merge(view: "ids")
75
+ collection.execute
76
+ else
77
+ collection.find_each.map(&:id)
78
+ end
79
+ end
80
+
81
+ # Iterates over a single page of results based upon current pagination settings
82
+ def each
83
+ return enum_for(:each) unless block_given?
84
+
85
+ execute.each do |result|
86
+ yield(model.new(**result.merge(api: api)))
87
+ end
88
+ end
89
+
90
+ def limit(quantity)
91
+ self.class.new(model: model, api: api, constraints: constraints.merge(limit: quantity))
92
+ end
93
+
94
+ def offset(start)
95
+ self.class.new(model: model, api: api, constraints: constraints.merge(offset: start))
96
+ end
97
+
98
+ # Iterates over every result that meets the filters, retrieving a page at a time
99
+ def find_each
100
+ return enum_for(:find_each) unless block_given?
101
+
102
+ query = self
103
+ accumulated = 0
104
+
105
+ while query
106
+ results = query.each do |instance|
107
+ yield(instance)
108
+ end
109
+
110
+ accumulated += results.length
111
+ query = query.next_page(accumulated: accumulated, current_page: results)
112
+ end
113
+ end
114
+
115
+ def next_page(accumulated:, current_page:)
116
+ return nil unless more_pages?(accumulated, current_page)
117
+
118
+ self.class.new(model: model, api: api, constraints: constraints.next_page)
119
+ end
120
+
121
+ def more_pages?(accumulated, current_page)
122
+ return false if current_page.empty?
123
+ return false if constraints.limit && accumulated >= constraints.limit
124
+ return false if constraints.per_page && current_page.length < constraints.per_page
125
+
126
+ true
127
+ end
128
+
129
+ # Retrieves a record. Nylas doesn't support where filters on GET so this will not take into
130
+ # consideration other query constraints, such as where clauses.
131
+ def find(id)
132
+ constraints.accept == "application/json" ? find_model(id) : find_raw(id)
133
+ end
134
+
135
+ def find_raw(id)
136
+ api.execute(**to_be_executed.merge(path: "#{resources_path}/#{id}")).to_s
137
+ end
138
+
139
+ def resources_path
140
+ model.resources_path(api: api)
141
+ end
142
+
143
+ def find_model(id)
144
+ response = api.execute(
145
+ **to_be_executed.merge(
146
+ path: "#{resources_path}/#{id}",
147
+ query: view_query
148
+ )
149
+ )
150
+ model.from_hash(response, api: api)
151
+ end
152
+
153
+ # @return [Hash] Specification for request to be passed to {API#execute}
154
+ def to_be_executed
155
+ { method: :get, path: resources_path, query: constraints.to_query,
156
+ headers: constraints.to_headers, auth_method: model.auth_method }
157
+ end
158
+
159
+ # Retrieves the data from the API for the particular constraints
160
+ # @return [Hash,Array]
161
+ def execute
162
+ api.execute(**to_be_executed)
163
+ end
164
+
165
+ private
166
+
167
+ def view_query
168
+ if constraints.view
169
+ { view: constraints.view }
170
+ else
171
+ {}
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent a the Component Schema.
5
+ class Component
6
+ include Model
7
+ self.creatable = true
8
+ self.listable = true
9
+ self.showable = true
10
+ self.filterable = true
11
+ self.updatable = true
12
+ self.destroyable = true
13
+ self.auth_method = HttpClient::AuthMethod::BASIC
14
+
15
+ attribute :id, :string, read_only: true
16
+ attribute :account_id, :string
17
+ attribute :name, :string
18
+ attribute :type, :string
19
+ attribute :action, :integer
20
+ attribute :active, :boolean
21
+ attribute :settings, :hash
22
+ attribute :public_account_id, :string
23
+ attribute :public_token_id, :string
24
+ attribute :public_application_id, :string, read_only: true
25
+ attribute :access_token, :string
26
+ attribute :created_at, :date, read_only: true
27
+ attribute :updated_at, :date, read_only: true
28
+
29
+ has_n_of_attribute :allowed_domains, :string
30
+
31
+ def resources_path(*)
32
+ "/component/#{api.client.app_id}"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Additional configuration for the Component CRUD API
5
+ class ComponentCollection < Collection
6
+ def resources_path
7
+ "/component/#{api.client.app_id}"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # The constraints a particular GET request will include in their query params
5
+ class Constraints
6
+ attr_accessor :where, :limit, :offset, :view, :per_page, :accept
7
+
8
+ def initialize(where: {}, limit: nil, offset: 0, view: nil, per_page: 100, accept: "application/json")
9
+ self.where = where
10
+ self.limit = limit
11
+ self.offset = offset
12
+ self.view = view
13
+ self.per_page = per_page
14
+ self.accept = accept
15
+ end
16
+
17
+ def merge(where: {}, limit: nil, offset: nil, view: nil, per_page: nil, accept: nil)
18
+ Constraints.new(where: self.where.merge(where),
19
+ limit: limit || self.limit,
20
+ per_page: per_page || self.per_page,
21
+ offset: offset || self.offset,
22
+ view: view || self.view,
23
+ accept: accept || self.accept)
24
+ end
25
+
26
+ def next_page
27
+ merge(offset: offset + per_page)
28
+ end
29
+
30
+ def to_query
31
+ query = where.each_with_object({}) do |(name, value), result|
32
+ result[name] = value
33
+ end
34
+ query[:limit] = limit_for_query
35
+ query[:offset] = offset unless offset.nil?
36
+ query[:view] = view unless view.nil?
37
+ query
38
+ end
39
+
40
+ def to_headers
41
+ accept == "application/json" ? {} : { "Accept" => accept, "Content-types" => accept }
42
+ end
43
+
44
+ def limit_for_query
45
+ !limit.nil? && limit < per_page ? limit : per_page
46
+ end
47
+
48
+ def self.from_constraints(constraints = Constraints.new)
49
+ return constraints if constraints.is_a?(Constraints)
50
+ return new(**constraints) if constraints.respond_to?(:key?)
51
+ return new if constraints.nil?
52
+
53
+ raise TypeError, "passed in constraints #{constraints} cannot be cast to a set of constraints"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # ActiveModel compliant interface for interacting with the Contacts API
5
+ # @see https://docs.nylas.com/reference#contacts
6
+ class Contact
7
+ include Model
8
+ self.resources_path = "/contacts"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.filterable = true
13
+ self.updatable = true
14
+ self.destroyable = true
15
+
16
+ attribute :id, :string, read_only: true
17
+ attribute :object, :string, default: "contact"
18
+ attribute :account_id, :string, read_only: true
19
+
20
+ attribute :given_name, :string
21
+ attribute :middle_name, :string
22
+ attribute :picture_url, :string
23
+ attribute :surname, :string
24
+ attribute :birthday, :string
25
+ attribute :suffix, :string
26
+ attribute :nickname, :string
27
+ attribute :company_name, :string
28
+ attribute :job_title, :string
29
+ attribute :manager_name, :string
30
+ attribute :office_location, :string
31
+ attribute :notes, :string
32
+ attribute :source, :string
33
+ attribute :job_status_id, :string, read_only: true
34
+
35
+ has_n_of_attribute :groups, :contact_group
36
+ has_n_of_attribute :emails, :email_address
37
+ has_n_of_attribute :im_addresses, :im_address
38
+ has_n_of_attribute :physical_addresses, :physical_address
39
+ has_n_of_attribute :phone_numbers, :phone_number
40
+ has_n_of_attribute :web_pages, :web_page
41
+
42
+ # @returns [Tempfile] path to the retrieved picture. It is preferrable to cache this in your system than
43
+ # to retrieve it from nylas every time.
44
+ def picture
45
+ return @picture_tempfile if @picture_tempfile
46
+
47
+ @picture_tempfile = Tempfile.new
48
+ @picture_tempfile.write(api.get(path: "#{resource_path}/picture"))
49
+ @picture_tempfile.close
50
+ @picture_tempfile
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent the Contact Group schema
5
+ # @see https://docs.nylas.com/reference#contactsid
6
+ class ContactGroup
7
+ include Model
8
+ self.resources_path = "/contacts/groups"
9
+
10
+ self.creatable = false
11
+ self.destroyable = false
12
+ self.filterable = false
13
+ self.listable = true
14
+ self.showable = false
15
+ self.updatable = false
16
+
17
+ attribute :id, :string
18
+ attribute :object, :string
19
+ attribute :account_id, :string
20
+ attribute :name, :string
21
+ attribute :path, :string
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby representation of the Nylas /account API
5
+ # @see https://docs.nylas.com/reference#account
6
+ class CurrentAccount
7
+ include Model
8
+ self.showable = true
9
+
10
+ self.resources_path = "/account"
11
+
12
+ attribute :id, :string
13
+ attribute :object, :string, default: "account"
14
+
15
+ attribute :account_id, :string
16
+ attribute :email_address, :string
17
+ attribute :name, :string
18
+ attribute :organization_unit, :string
19
+ attribute :provider, :string
20
+ attribute :sync_state, :string
21
+ attribute :linked_at, :unix_timestamp
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby object to represent a single change. Used both when receiving a webhook, as well as the deltas API.
5
+ # @see https://docs.nylas.com/reference#receiving-notifications
6
+ # @see https://docs.nylas.com/reference#deltas
7
+ class Delta
8
+ include Model::Attributable
9
+
10
+ attribute :id, :string
11
+ attribute :type, :string
12
+ attribute :object, :string
13
+ attribute :event, :string
14
+ attribute :cursor, :string
15
+ attribute :namespace_id, :string
16
+ attribute :account_id, :string
17
+
18
+ attribute :headers, :message_headers
19
+
20
+ attribute :date, :unix_timestamp
21
+ attribute :metadata, :hash
22
+ attribute :object_attributes, :hash
23
+
24
+ def model
25
+ return nil if object.nil?
26
+
27
+ @model ||= Types.registry[object.to_sym].cast(object_attributes_with_ids)
28
+ end
29
+
30
+ private
31
+
32
+ def object_attributes_with_ids
33
+ (object_attributes || {}).merge(id: id, account_id: account_id)
34
+ end
35
+ end
36
+
37
+ # Casts Delta data from either a webhook or a delta stream to a Delta
38
+ class DeltaType < Types::ModelType
39
+ def initialize
40
+ super(model: Delta)
41
+ end
42
+
43
+ def cast(data)
44
+ data = if data.key?(:object_data)
45
+ object_data = data.delete(:object_data)
46
+ data.merge(object_data)
47
+ else
48
+ data
49
+ end
50
+
51
+ data = data.merge(data[:attributes]) if data[:attributes]
52
+ data[:object_attributes] = data.delete(:attributes)
53
+ super(**data)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby object to represent a collection of changes. Used both when receiving a webhook, as well as the
5
+ # deltas API.
6
+ # @see https://docs.nylas.com/reference#receiving-notifications
7
+ # @see https://docs.nylas.com/reference#deltas
8
+ class Deltas
9
+ include Model
10
+ self.resources_path = "/delta"
11
+ self.filterable = true
12
+ has_n_of_attribute :deltas, :delta
13
+ attribute :cursor_start, :string
14
+ attribute :cursor_end, :string
15
+
16
+ extend Forwardable
17
+ def_delegators :deltas, :count, :length, :each, :map, :first, :last, :to_a, :empty?
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Special collection for delta objects
5
+ class DeltasCollection < Collection
6
+ attr_accessor :deltas
7
+
8
+ extend Forwardable
9
+ def_delegators :execute, :cursor_start, :cursor_end,
10
+ :count, :each, :to_h, :to_a, :empty?
11
+
12
+ def initialize(api:, constraints: nil, model: Deltas)
13
+ super(api: api, model: model, constraints: constraints)
14
+ end
15
+
16
+ def latest_cursor
17
+ api.execute(method: :post, path: "#{resources_path}/latest_cursor")[:cursor]
18
+ end
19
+
20
+ def latest
21
+ since(latest_cursor)
22
+ end
23
+
24
+ def since(cursor)
25
+ where(cursor: cursor)
26
+ end
27
+
28
+ def next_page(*)
29
+ return nil if empty?
30
+
31
+ where(cursor: cursor_end)
32
+ end
33
+
34
+ # Retrieves the data from the API for the particular constraints
35
+ # @return [Detlas]
36
+ def execute
37
+ self.deltas ||= Deltas.new(**api.execute(**to_be_executed))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby representatin of a Nylas Draft object
5
+ # @see https://docs.nylas.com/reference#drafts
6
+ class Draft
7
+ include Model
8
+ self.resources_path = "/drafts"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.updatable = true
13
+ self.destroyable = true
14
+ self.id_listable = true
15
+ self.countable = true
16
+
17
+ attribute :id, :string
18
+ attribute :object, :string
19
+ attribute :version, :integer
20
+ attribute :account_id, :string
21
+ attribute :thread_id, :string
22
+ attribute :reply_to_message_id, :string
23
+
24
+ has_n_of_attribute :to, :email_address
25
+ has_n_of_attribute :from, :email_address
26
+ has_n_of_attribute :cc, :email_address
27
+ has_n_of_attribute :bcc, :email_address
28
+ has_n_of_attribute :reply_to, :email_address
29
+
30
+ attribute :date, :unix_timestamp
31
+ attribute :subject, :string
32
+ attribute :snippet, :string
33
+ attribute :body, :string
34
+ attribute :starred, :boolean
35
+ attribute :unread, :boolean
36
+ attribute :metadata, :hash
37
+
38
+ has_n_of_attribute :events, :event
39
+ has_n_of_attribute :files, :file, read_only: true
40
+ has_n_of_attribute :file_ids, :string
41
+ attribute :folder, :folder
42
+ has_n_of_attribute :labels, :label
43
+
44
+ attribute :tracking, :message_tracking
45
+ attribute :job_status_id, :string, read_only: true
46
+
47
+ transfer :api, to: %i[events files folder labels]
48
+
49
+ def update(**data)
50
+ # If files are provided, replace files with file IDs
51
+ self.files = data[:files] if data[:files]
52
+ extract_file_ids!
53
+ data[:file_ids] = file_ids
54
+ # If version is not provided, add version or request will fail
55
+ data[:version] = version unless data[:version]
56
+
57
+ super
58
+ end
59
+
60
+ def create
61
+ extract_file_ids!
62
+
63
+ super
64
+ end
65
+
66
+ def send!
67
+ return execute(method: :post, path: "/send", payload: to_json) unless id
68
+
69
+ data = { draft_id: id, version: version }
70
+ data[:tracking] = tracking.to_h if tracking
71
+ execute(method: :post, path: "/send", payload: JSON.dump(data))
72
+ end
73
+
74
+ def starred?
75
+ starred
76
+ end
77
+
78
+ def unread?
79
+ unread
80
+ end
81
+
82
+ def destroy
83
+ execute(method: :delete, path: resource_path, payload: attributes.serialize_for_api(keys: [:version]))
84
+ end
85
+
86
+ def save
87
+ extract_file_ids!
88
+
89
+ super
90
+ end
91
+
92
+ private
93
+
94
+ def extract_file_ids!
95
+ files = self.files || []
96
+
97
+ self.file_ids ||= files.map(&:id)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent the Email Address Schema
5
+ # @see https://docs.nylas.com/reference#contactsid
6
+ class EmailAddress
7
+ include Model::Attributable
8
+ attribute :type, :string
9
+ attribute :email, :string
10
+ attribute :name, :string
11
+ end
12
+ end