Releases: nylas/nylas-java
v1.18.0
This release of the Nylas Java SDK comes with new features and a bug fix.
Release Notes
Added
- Added hide participants field for the
Eventclass (#103) - Added support for provider detection (#100)
- Added an enum for all known providers for native authentication (#100)
- Improved webhook notification support with the addition of more notification attributes and event metadata fields (#102)
Changed
- NylasAccount.revokeAccessToken() returns a boolean value now (#97)
Fixed
- Fix error when updating occurrence of a recurring event (#93)
Using New Features
Provider Detection
// Set up your client
NylasClient client = new NylasClient();
NativeAuthentication nativeAuthentication = client.application("CLIENT_ID", "CLIENT_SECRET").nativeAuthentication();
// Detect the provider for an email address
NativeAuthentication.DetectedProvider detectedProvider = nativeAuthentication.detectProvider("test@gmail.com");
// The following fields are made available
detectedProvider.isDetected();
detectedProvider.getProviderName();
detectedProvider.getAuthName();
detectedProvider.getEmailAddress();
detectedProvider.isImap();
// You can use the result from above to get the correct provider settings
ProviderSettings detectedSettings = ProviderSettings.getProviderSettingsByProvider(provider.getAuthName());
// The enum is provided for consistency and equality
if(detectedProvider.getAuthName() == NativeAuthentication.Provider.GMAIL.getName()) {
// do something here for a Gmail case
}v1.17.0
This release of the Nylas Java SDK comes with a new feature and a bug fix.
Release Notes
Added
- Add support for getting a single expanded message and thread (#84)
Fixed
- Fixed issue where
Eventparticipants could never be entirely removed once set (#83)
Using New Features
Getting a single expanded message and thread
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
// Get an expanded message by passing a boolean for the second parameter, indicating an expanded view
Message expandedMessage = account.messages().get("message_id", true);
// Get an expanded thread by passing a boolean for the second parameter, indicating an expanded view
Thread expandedThread = account.threads().get("thread_id", true);v1.16.0
This release of the Nylas Java SDK comes with a couple of additions.
Release Notes
Added
- Add missing event query parameters (#80)
- Add support for Event reminders (#80)
- Add support for additional Event fields (#80)
Using New Features
Event reminders
ZoneId startTz = ZoneId.of("America/Los_Angeles");
ZoneId endTz = ZoneId.of("America/New_York");
ZonedDateTime startTime = ZonedDateTime.now(startTz);
ZonedDateTime endTime = startTime.plusHours(2).withZoneSameInstant(endTz);
Event event = new Event("calendar_id", new Timespan(startTime, endTime));
event.setTitle("Surprise Party");
// Add event reminders
event.setReminders(new Event.Reminders(20, Event.Reminders.ReminderMethod.EMAIL));
// Create the event
Event created = events.create(event, true);v1.15.0
v1.14.0
This release of the Nylas Java SDK comes with a few new features and a fix.
Release Notes
Added
- Add missing fields in Scheduler (#71)
- Add support for collective and group events (#73)
- Add support for calendar free-busy scope (#75)
- Add
redirect_on_errorparameter for Hosted Authentication (#72)
Fixed
- Fixed enum value for
Scheduler.Config.Booking.OpeningHours.Days.Sunday(#74)
New Contributors 🎉
- @maxw-nylas made their first contribution in #72
v1.13.1
This release of the Nylas Java SDK comes with a couple of changes.
Release Notes
Added
- Add missing
orderandemailsfields inAvailabilityandTimeSlot
Fixed
- Fixed
Participantstatus not being sent to the API when set
v1.13.0
This release of the Nylas Java SDK comes with a few new features, changes, and fixes!
Release Notes
Added
- Added support for Delta
- Added support for new (beta) Integrations authentication (Integrations API, Grants API, Hosted Authentication for Integrations)
- Added
authentication_typefield toAccount
Changed
- Bump supported API version to v2.5
Fixed
- Fixed incorrect property name for
Event.Notification.minutes_before_event
Using New Features
Delta
To get the latest cursor:
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Deltas deltas = account.deltas();
String latestCursor = deltas.latestCursor();To return a set of delta cursors since a specific cursor:
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Deltas deltas = account.deltas();
DeltaCursor deltaCursor = deltas.since("{CURSOR}");
// The returned type is of DeltaCursor
String cursorStart = deltaCursor.getCursorStart();
String cursorEnd = deltaCursor.getCursorEnd();
List<Delta<?>> deltas = deltaCursor.getDeltas();
// DeltaCursor.deltas contains a list of Delta objects
Delta<?> delta = deltas[0];
String deltaCursor = delta.getCursor();
String deltaEvent = delta.getEvent();
String deltaId = delta.getId();
String deltaObject = delta.getObject();
// The enclosed Delta.attributes instantiates the object provided in the Delta (Contact, File, etc.)
Event deltaAttributes = delta.attributes();
/**
* You can also pass in other optional arguments through DeltaQueryOptions:
* view: string - This type of view to return within the delta objects
* includeTypes: DeltaQueryOptions.Type... - The list of types to include in the query ('file', 'event', etc.)
* excludeTypes: DeltaQueryOptions.Type... - The list of types to exclude in the query ('file', 'event', etc.)
*/
DeltaQueryOptions options = new DeltaQueryOptions()
.setView("expanded")
.includeTypes(DeltaQueryOptions.Type.EVENT, DeltaQueryOptions.Type.MESSAGE);
DeltaCursor deltaCursor = deltas.since(cursor, options);To stream for delta cursors since a specific cursor:
public class DeltaExample {
public static void main(String[] args) throws RequestFailedException, IOException {
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Deltas deltas = account.deltas();
// By default, the streaming function will listen indefinitely until the connection drops
// and upon reaching the end it will return an array of delta objects captured
List<Delta<?>> streamedDeltas = deltas.stream(latestCursor);
// Optionally you can pass in a class that implements DeltaStreamListener that will invoke
// onDelta(Delta<?>) on each Delta received
DeltaProcessor deltaProcessor = new DeltaProcessor();
streamedDeltas = deltas.stream(latestCursor, deltaProcessor);
/**
* You can also pass in other optional arguments through DeltaQueryOptions:
* view: string - This type of view to return within the delta objects
* includeTypes: DeltaQueryOptions.Type... - The list of types to include in the query ('file', 'event', etc.)
* excludeTypes: DeltaQueryOptions.Type... - The list of types to exclude in the query ('file', 'event', etc.)
*/
DeltaQueryOptions options = new DeltaQueryOptions()
.setView("expanded")
.includeTypes(DeltaQueryOptions.Type.EVENT, DeltaQueryOptions.Type.MESSAGE);
streamedDeltas = deltas.stream(latestCursor, deltaProcessor, options);
}
}
class DeltaProcessor implements DeltaStreamListener {
@Override
public void onDelta(Delta<? extends AccountOwnedModel> delta) {
System.out.println("Delta received! " + delta);
}
}To long-poll for delta cursors since a specific cursor:
public class DeltaExample {
public static void main(String[] args) throws RequestFailedException, IOException {
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Deltas deltas = account.deltas();
// By default, the streaming function will listen until until the timeout is reached
// and upon reaching the end it will return a DeltaCursor object
DeltaCursor longPollDeltas = deltas.longpoll(latestCursor, 30); // timeout is in seconds
// Optionally you can pass in a class that implements DeltaLongPollListener that will invoke
// onDeltaCursor(DeltaCursor) on each DeltaCursor received
DeltaProcessor deltaProcessor = new DeltaProcessor();
longPollDeltas = deltas.longpoll(latestCursor, 30, deltaProcessor);
/**
* You can also pass in other optional arguments through DeltaQueryOptions:
* view: string - This type of view to return within the delta objects
* includeTypes: DeltaQueryOptions.Type... - The list of types to include in the query ('file', 'event', etc.)
* excludeTypes: DeltaQueryOptions.Type... - The list of types to exclude in the query ('file', 'event', etc.)
*/
DeltaQueryOptions options = new DeltaQueryOptions()
.setView("expanded")
.includeTypes(DeltaQueryOptions.Type.EVENT, DeltaQueryOptions.Type.MESSAGE);
longPollDeltas = deltas.longpoll(latestCursor, 30, deltaProcessor, options);
}
}
class DeltaProcessor implements DeltaLongPollListener {
@Override
public void onDeltaCursor(DeltaCursor deltaCursor) {
System.out.println("Delta Cursor received! " + deltaCursor);
}
}Integration Authentication (Beta)
Integrations API
To list all integrations:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Integrations integrations = application.authentication().integrations();
List<Integration> allIntegrations = integrations.list();To get an integration for a specific OAuth Provider:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Integrations integrations = application.authentication().integrations();
Integration zoom = integrations.get(Authentication.Provider.ZOOM);To create a new integration (we will use Zoom for example):
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Integrations integrations = application.authentication().integrations();
Integration integration = new Integration("Test Zoom Integration");
integration.setClientId("zoom.client.id");
integration.setClientSecret("zoom.client.secret");
integration.addRedirectUris("https://www.nylas.com");
integration.setExpiresIn(1209600L);
Integration created = integrations.create(integration, Authentication.Provider.ZOOM);To update an existing integration:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Integrations integrations = application.authentication().integrations();
Integration zoomIntegration = integrations.get(Authentication.Provider.ZOOM);
zoomIntegration.setName("Updated name");
integrations.update(zoomIntegration);To delete an existing integration for a specific OAuth provider:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Integrations integrations = application.authentication().integrations();
integrations.delete(Authentication.Provider.ZOOM);Grants
To list all grants:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
List<Grant> allGrants = grants.list();To get a specific grant:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
Grant grant = grants.get("grant_id");To create a new grant (we will use Zoom for example):
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
Map<String, String> settings = Collections.singletonMap("refresh_token", "zoom_refresh_token"));
Grant grant = new Grant(Authentication.Provider.ZOOM, settings);
grant.setState("test_state");
grant.setScope(Collections.singletonList("meeting:write"));
grant.setMetadata(Collections.singletonMap("sdk", "Java SDK"));
Grant created = grants.create(grant);To update an existing grant:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
Grant grant = integrations.get("grant_id");
grant.setMetadata(Collections.singletonMap("sdk", "Java SDK"));
grants.update(grant);To delete an existing grant:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
grants.delete("grant_id");To trigger a re-sync on a grant:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SECRET");
Grants grants = application.authentication().grants();
Grant resyncedGrant = grants.onDemandSync("grant_id);Hosted Authentication for Authentication
To begin the hosted authentication process and get a login url:
NylasClient nylas = new NylasClient();
NylasApplication application = client.application("CLIENT_ID", "CLIENT_SEC...v1.12.0
This release of the Nylas Java SDK comes with a few new features, changes, and fixes!
Release Notes
Added
- Added Outbox support
- Added support for Component CRUD
- Added support for Neural Categorizer
- Added support for
calendarfield in free-busy, availability, and consecutive availability queries - Added field for
phone_numberinParticipant
Changed
- Bump supported API version to v2.4
Fixed
- Fix null error message when
HostedAuthentication.fetchToken()returns an API error
Deprecated
- Deprecated
checkFreeBusy(Instant, Instant, List<String>)andcheckFreeBusy(Instant, Instant, String)in favour ofcheckFreeBusy(FreeBusyQuery)
Using New Features
Outbox
To send a new message through the outbox:
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
// Create a new outbox message object
OutboxMessage message = new OutboxMessage();
message.setSubject("With Love, From Nylas");
message.setTo(Arrays.asList(new NameEmail("My Nylas Friend", "swag@nylas.com")));
message.setBody("This email was sent using the Nylas email API. Visit https://nylas.com for details.");
message.setReplyTo(new NameEmail("Your Name", "you@example.com"));
message.setFrom(new NameEmail("Your Name", "you@example.com"));
// Set the outbox-specific parameters
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date tomorrow = calendar.getTime();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date dayAfter = calendar.getTime();
message.setSendAt(tomorrow);
message.setRetryLimitDatetime(dayAfter);
// Send the outbox message
OutboxJobStatus jobStatus = outbox.send(outboxMessage);
String outboxJobStatusId = jobStatus.getJobStatusId();
String outboxStatus = jobStatus.getStatus();
OutboxMessage sentMessage = jobStatus.getOriginalData();You can also avoid creating an OutboxMessage type, you can just pass in a draft object to send:
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
// Create a new outbox message object
Draft draft = new Draft();
draft.setSubject("With Love, From Nylas");
draft.setTo(Arrays.asList(new NameEmail("My Nylas Friend", "swag@nylas.com")));
draft.setBody("This email was sent using the Nylas email API. Visit https://nylas.com for details.");
draft.setReplyTo(new NameEmail("Your Name", "you@example.com"));
draft.setFrom(new NameEmail("Your Name", "you@example.com"));
// Prepare the outbox-specific parameters
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date tomorrow = calendar.getTime();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date dayAfter = calendar.getTime();
// Send the outbox message
OutboxJobStatus jobStatus = outbox.send(draft, tomorrow, dayAfter);To update an outbox message after sending it
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
// Create and send the message object
OutboxMessage message = new OutboxMessage();
message.setSubject("With Love, From Nylas");
message.setTo(Arrays.asList(new NameEmail("My Nylas Friend", "swag@nylas.com")));
message.setBody("This email was sent using the Nylas email API. Visit https://nylas.com for details.");
message.setReplyTo(new NameEmail("Your Name", "you@example.com"));
message.setFrom(new NameEmail("Your Name", "you@example.com"));
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date tomorrow = calendar.getTime();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date dayAfter = calendar.getTime();
message.setSendAt(tomorrow);
message.setRetryLimitDatetime(dayAfter);
OutboxJobStatus jobStatus = outbox.send(outboxMessage);
// Modify something in the job status
OutboxMessage sentMessage = jobStatus.getOriginalData();
calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR_OF_DAY, 2);
Date newSendAt = calendar.getTime();
sentMessage.setSendAt(newSendAt);
// Update the outbox job
OutboxJobStatus updatedJobStatus = outbox.update(sentMessage, jobStatus.getJobStatusId());To delete an outbox job
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
outbox.delete("JOB_STATUS_ID");We also support SendGrid operations. To get the authentication and verification status
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
SendGridVerification verification = outbox.sendGridVerificationStatus();
verification.isDomainVerified();
verification.isSenderVerified();To delete a SendGrid user:
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Outbox outbox = account.outbox();
outbox.deleteSendGridSubUser("email_address");Component CRUD
To create a new component:
Component component = new Component();
component.setName("Java Component Test");
component.setType("agenda");
component.setPublicAccountId("ACCOUNT_ID");
component.setAccessToken(conf.get("access.token"));
component = application.components().save(component);To get all components:
RemoteCollection<Component> componentList = application.components().list();To get a specific component:
Component component = application.components().get("{COMPONENT_ID}");To update a component:
Component component = application.components().get("{COMPONENT_ID}");
component.name = "Updated"
application.components().save(component);To delete a component:
application.components().delete("{COMPONENT_ID}")Neural Categorizer
To get the category of a message(s)
import com.nylas.NylasClient;
import com.nylas.NylasAccount;
import com.nylas.Neural;
import com.nylas.NeuralCategorizer;
import java.util.Collections;
import java.util.List;
public class NeuralExample {
public static void main(String[] args) throws RequestFailedException, IOException {
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Neural neural = account.neural();
List<String> messageIds = Collections.singletonList("MESSAGEL_ID");
List<NeuralCategorizer> categorizers = neural.categorize(messageIds);
// The resulting object is an extension of a Message object with a categorize field
NeuralCategorizer categorizer = categorizers.get(0);
String category = categorizer.getCategorizer().getCategory();
String modelVersion = categorizer.getCategorizer().getModelVersion();
Long categorizedAt = categorizer.getCategorizer().getCategorizedAt();
List<String> subcategories = categorizer.getCategorizer().getSubcategories();
}
}To recategorize a single message
import com.nylas.NylasClient;
import com.nylas.NylasAccount;
import com.nylas.Neural;
import com.nylas.NeuralCategorizer.Category;
public class NeuralExample {
public static void main(String[] args) throws RequestFailedException, IOException {
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Neural neural = account.neural();
// NeuralCategorizer.Category options are "CONVERSATION" and "FEED"
neural.reCategorize("MESSAGEL_ID", Category.CONVERSATION);
}
}New calendar field in free-busy, availability, and consecutive availability queries
NylasClient nylas = new NylasClient();
NylasAccount account = nylas.account("{ACCESS_TOKEN}");
Calendars calendars = account.calendars();
// To check free-busy with calendars:
FreeBusyCalendars freeBusyCalendars = new FreeBusyCalendars();
freeBusyCalendars.setAccountId("test_account_id");
freeBusyCalendars.addCalendarIds("example_calendar_id_A", "example_calendar_id_B");
FreeBusyQuery query = new FreeBusyQuery()
.startTime(1590454800)
.endTime(1590780800)
.calendars(freeBusyCalendars);
List<FreeBusy> freeBusyInfo = calendars.checkFreeBusy(query);
// To check availability with calendars:
SingleAvailabilityQuery query = new SingleAvailabilityQuery()
.durationMinutes(30)
.startTime(Instant.now())
.endTime(Instant.now().plus(1, ChronoUnit.HOURS))
.intervalMinutes(10)
.calendars(freeBusyCalendars);
Availability availability = calendars.availability(query);
// To check consecutive availability with calendars:
MultipleAvailabilityQuery consecutiveQuery = new MultipleAvailabilityQuery()
.durationMinutes(30)
.startTime(Instant.now())
.endTime(Instant.now().plus(1, ChronoUnit.HOURS))
.intervalMinutes(10)
.calendars(freeBusyCalendars);
List<List<ConsecutiveAvailability>> consecutiveAvailability = calendars.consecutiveAvailability(consecutiveQuery);v1.11.2
Enhancements
- Remove use of
okhttp3.internallibrary
v1.11.1
Enhancements
- Fixed bug where an
IllegalArgumentExceptionis thrown when deserializingDraftwith `metadata