Skip to the documentation
Go

client.Calendar

Every method in this namespace: its signature, its parameters, what it returns and an example.

Methods

Calendar events found in mail, expanded into occurrences.

Calendar.ListEvents

List one page of event occurrences inside a time window

Scopescalendar:readPages through results
Signature
ListEvents(ctx context.Context, from time.Time, to time.Time, opts ...nextmail.RequestOption) (*nextmail.Page, error)

Expands your events into their occurrences between from and to and returns one page of them, sorted by start time and then by event id. A recurring series gives one row per instance in the window, with its excluded dates left out, and every row points back to its event through eventId. The window is required because a repeating series has no end to list up to. Follow NextCursor while HasMore is true, with the same from, to and timezone, to read every occurrence, or let ListAllEvents and IterateEvents do that walk.

to must be after from and at most 366 days later. A missing from or to is a 422 invalid_parameter, while a value that does not parse, a reversed or overlong window, or an unknown zone is a 400 invalid_parameter naming the field. Both bounds take a time.Time or an ISO 8601 string.

timezone is an IANA zone and defaults to UTC on the server. It is used to expand any event stored without a zone of its own, which is what decides the day an all day event lands on.

Parameters

fromtime.TimeRequired

Start of the window.

totime.TimeRequired

End of the window, after from and at most 366 days later.

nextmail.WithTimezonestring

IANA zone such as Europe/London, at most 64 characters. Defaults to UTC.

nextmail.WithIncludeTeambool

true adds the events of the rest of the workspace, apart from the ones marked private. Only a key of the workspace owner sees more with it. Defaults to false.

nextmail.WithQstring

Words to look for in the title, the place and the organiser, at most 200 characters. Only events that hold every word come back, so pass a long window to find an event by name.

nextmail.WithLimitint

Occurrences per page, a whole number from 1 to 100. The server defaults to 25.

nextmail.WithCursorstring

The NextCursor of the previous page, sent with the same window. It is opaque, so never build one yourself.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The *nextmail.Page with Items, HasMore and NextCursor. Each item has eventId, uid, start, end, allDay, summary, location, status, transparency, isOrganizer, organizerEmail, recurring, myPartstat and attendeeCount.

Example

page, err := client.Calendar.ListEvents(	ctx,	time.Now().Add(24*time.Hour),	time.Now().Add(24*time.Hour),	nextmail.WithTimezone("Europe/London"),	nextmail.WithLimit(50),)if err != nil {	return err} for _, occurrence := range page.Items {	fmt.Println(occurrence.String("start"), occurrence.String("summary"), occurrence.String("myPartstat"))} fmt.Println(page.HasMore, page.NextCursor)

Notes

  • The list holds your own events: the ones you made and the ones an address of yours organises or attends. For the workspace owner and their keys, an address counts as theirs unless it was given to a teammate, and nextmail.WithIncludeTeam(true) adds the rest of the workspace, apart from events somebody marked private. A member's app and a narrowed key always get their own view.

  • myPartstat is the response recorded for one of your own addresses, or for the addresses a narrowed key covers, and null when none of them is an attendee.

  • A narrowed key only sees occurrences whose organiser is one of the addresses it covers or where one of them is an attendee.

  • Cancelled events are not filtered out. Check status for CANCELLED.

  • Nothing in the window is dropped. A series repeats at most once a day, so one series gives at most one row per day of the window, and every one of them is reachable through the pages.

  • The cursor holds the start time and event id of the last row, so an event deleted or moved between pages never breaks the walk. A cursor this list did not hand out is a 400 invalid_cursor.

Also available in

API
GET /calendar/events
TypeScript
nextmail.calendar.listEvents()
Python
calendar.list_events()
Ruby
calendar.list_events
PHP
calendar->listEvents
Java
calendar().listEvents
C#
Calendar.ListEventsAsync
CLI
nextmail calendar list-events

Calendar.ListAllEvents

Collect every occurrence inside a time window into one slice

Scopescalendar:readPages through results
Signature
ListAllEvents(ctx context.Context, from time.Time, to time.Time, opts ...nextmail.RequestOption) ([]nextmail.Object, error)

Walks every page of ListEvents for one window and returns with all of its occurrences, sorted by start time and then by event id. It follows NextCursor until HasMore is false, sending the same from, to and timezone with each request.

A window of up to 366 days of a busy calendar can hold thousands of occurrences, so prefer IterateEvents when you can stop early.

Parameters

fromtime.TimeRequired

Start of the window.

totime.TimeRequired

End of the window, after from and at most 366 days later.

nextmail.WithTimezonestring

IANA zone such as Europe/London, at most 64 characters. Defaults to UTC.

nextmail.WithIncludeTeambool

true adds the events of the rest of the workspace, apart from the ones marked private. Only a key of the workspace owner sees more with it. Defaults to false.

nextmail.WithQstring

Words to look for in the title, the place and the organiser, at most 200 characters. Only events that hold every word come back, so pass a long window to find an event by name.

nextmail.WithLimitint

Page size for each request, 1 to 100. The server defaults to 25.

nextmail.WithCursorstring

Starts the walk from this cursor instead of the start of the window.

nextmail.WithAPIKeystring

Overrides the client API key for every page of this walk.

Returns

A []nextmail.Object holding every occurrence in the window, earliest first.

Example

occurrences, err := client.Calendar.ListAllEvents(	ctx,	time.Date(2026, time.October, 1, 0, 0, 0, 0, time.UTC),	time.Date(2026, time.November, 1, 0, 0, 0, 0, time.UTC),	nextmail.WithLimit(100),)if err != nil {	return err} for _, occurrence := range occurrences {	fmt.Println(occurrence.String("transparency"))}

Notes

  • If any page fails the call fails and the occurrences already fetched are discarded.

Also available in

API
GET /calendar/events
TypeScript
nextmail.calendar.listAllEvents()
Python
calendar.list_all_events()
Ruby
calendar.list_all_events
PHP
calendar->listAllEvents
Java
calendar().listAllEvents
C#
Calendar.ListAllEventsAsync

Calendar.IterateEvents

Stream the occurrences inside a time window one at a time

Scopescalendar:readPages through results
Signature
IterateEvents(ctx context.Context, from time.Time, to time.Time, opts ...nextmail.RequestOption) *nextmail.Iterator

Returns an iterator over the occurrences in one window that yields them individually, earliest first, and fetches the next page only when the current one is drained. Nothing is requested until you consume it, and breaking out of the loop stops further requests, which makes it the way to find the next free slot or the next meeting without reading the whole window.

The walk ends when HasMore is false, when the server stops offering a cursor, or when it repeats one.

Parameters

fromtime.TimeRequired

Start of the window.

totime.TimeRequired

End of the window, after from and at most 366 days later.

nextmail.WithTimezonestring

IANA zone such as Europe/London, at most 64 characters. Defaults to UTC.

nextmail.WithIncludeTeambool

true adds the events of the rest of the workspace, apart from the ones marked private. Only a key of the workspace owner sees more with it. Defaults to false.

nextmail.WithQstring

Words to look for in the title, the place and the organiser, at most 200 characters. Only events that hold every word come back, so pass a long window to find an event by name.

nextmail.WithLimitint

Page size per request, 1 to 100. The server defaults to 25.

nextmail.WithCursorstring

Starts the walk from this cursor instead of the start of the window.

nextmail.WithAPIKeystring

Overrides the client API key for every page of this walk.

Returns

The *nextmail.Iterator yielding one occurrence per step.

Example

for occurrence, err := range client.Calendar.IterateEvents(ctx, time.Now().Add(24*time.Hour), time.Now().Add(24*time.Hour)).All() {	if err != nil {		return err	} 	fmt.Println(occurrence.String("myPartstat"), occurrence.String("start"), occurrence.String("summary"))}

Notes

  • A cancelled context fails the pending page request, and the loop ends with that error.

Also available in

API
GET /calendar/events
TypeScript
nextmail.calendar.iterateEvents()
Python
calendar.iterate_events()
Ruby
calendar.iterate_events
PHP
calendar->iterateEvents
Java
calendar().iterateEvents
C#
Calendar.IterateEventsAsync

Calendar.GetEvent

Read an event with its attendees

Scopescalendar:read
Signature
GetEvent(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Returns a stored event with its attendees and their responses. What the server understood from the iCalendar data is structured here: recurrence holds the RRULE text, exdates the excluded instances, organizer the organiser and alarms the reminders as a map with minutesBefore and action. The raw iCalendar source is not included, and GetEventIcs serves the event as a document.

id is the event id, the eventId on an occurrence, and not the iCalendar uid. A recurring series is one event however many occurrences it has, so start and end describe its first instance. messageId and threadId link the event to mail in the mailbox when there is any.

Attendees come back in the order they were added, each with partstat, role, rsvp, cutype and respondedAt. A narrowed key gets a 404 unless one of the addresses it covers organises the event or is on the attendee list, and a key that holds a whole domain covers every address on it.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with id, uid, sequence, summary, description, location, url, start, end, allDay, timezone, recurrence, exdates, status, transparency, visibility, organizer, isOrganizer, source, messageId, threadId, alarms, attendees, createdAt and updatedAt.

Example

event, err := client.Calendar.GetEvent(ctx, "cal_8d3f0a2b9c4e41f7a6b5c2d1")if err != nil {	return err} fmt.Println(event.String("summary"), event.String("recurrence"))

Notes

  • status, transparency and visibility carry iCalendar values, and default to CONFIRMED, OPAQUE and PUBLIC.

  • An attendee's partstat defaults to NEEDS-ACTION and role to REQ-PARTICIPANT until a response is recorded.

Also available in

API
GET /calendar/events/{id}
TypeScript
nextmail.calendar.getEvent()
Python
calendar.get_event()
Ruby
calendar.get_event
PHP
calendar->getEvent
Java
calendar().getEvent
C#
Calendar.GetEventAsync
CLI
nextmail calendar get-event

Calendar.GetEventIcs

Download an event as an iCalendar document

Scopescalendar:read
Signature
GetEventIcs(ctx context.Context, id string, opts ...nextmail.RequestOption) (string, error)

Returns the event serialised as an .ics document, as a raw string rather than parsed JSON. The server sends it as text/calendar; charset=utf-8 with a download filename built from the event's uid, and the SDK requests that type and returns the body untouched.

The document declares METHOD:PUBLISH, and the content type carries no method parameter. That is deliberate: a REQUEST document makes a calendar client offer accept and decline and reply to the organiser, and this endpoint has no authority to invite anyone. Import it to show what the event currently is, not to send an invitation.

It holds one VEVENT with the attendees and their participation status, the recurrence rule, excluded dates and alarms. Lines end in CRLF and long lines are folded. DTSTAMP is the time of the request, so two downloads of an unchanged event differ on that line.

Parameters

idstringRequired

Event id, the eventId of an occurrence.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

A string, the iCalendar text from BEGIN:VCALENDAR to END:VCALENDAR.

Example

text, err := client.Calendar.GetEventIcs(ctx, "cal_8d3f0a2b9c4e41f7a6b5c2d1")if err != nil {	return err} fmt.Println(text)

Notes

  • Errors still come back as JSON and return *nextmail.Error, so a failure is never returned as text.

  • Timed events are written in the zone they were created in, as local times with a TZID and a VTIMEZONE that carries the rules of that zone, and all day events as DATE values.

  • A narrowed key gets a 404 on the same terms as GetEvent.

Also available in

API
GET /calendar/events/{id}/ics
TypeScript
nextmail.calendar.getEventIcs()
Python
calendar.get_event_ics()
Ruby
calendar.get_event_ics
PHP
calendar->getEventIcs
Java
calendar().getEventIcs
C#
Calendar.GetEventIcsAsync
CLI
nextmail calendar get-event-ics

Calendar.CreateEvent

Put an event on the calendar

Scopescalendar:write
Signature
CreateEvent(ctx context.Context, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Creates an event, as New event on the Calendar page of the app does. start and end take a time.Time or ISO 8601 with a zone, and timezone is the IANA zone the event belongs to, which decides what an all-day event means.

With attendees, an invitation goes to each of them by email from from, which has to be an address the key may send as, so the call also needs emails:send. Send sendInvites: false to keep it to your own calendar.

Parameters

summarystringRequired

The title, 1 to 255 characters.

starttime.Time | stringRequired

When it starts, a time.Time or ISO 8601 with a zone.

endtime.Time | stringRequired

When it ends, after start and at most two years later.

descriptionstring

Notes about the event, up to 8,000 characters.

locationstring

Where it is: a room, an address or a link.

urlstring

A link that belongs to the event.

meetingUrlstring

The link to the video call, such as a Zoom, Meet or Teams address. The invitation carries it, so guests get a Join button in their calendar too.

allDaybool

Whether it fills whole days. start and end then mark the days.

timezonestring

The IANA zone the event belongs to, UTC unless you say.

recurrencestring

An RRULE such as FREQ=WEEKLY;BYDAY=MO when it repeats.

attendees[]nextmail.Body

Up to 200 people to invite, each a map with email and optionally name and optional.

reminders[]nextmail.Body

Up to five reminders, each a map with minutesBefore and optionally action.

transparencystring

OPAQUE shows you busy and TRANSPARENT free.

visibilitystring

PUBLIC, PRIVATE or CONFIDENTIAL.

sendInvitesbool

False keeps the change to your own calendar, and sends nothing.

fromstring

The address the invitations come from. It has to be one the key may send as.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object for the new event, with its attendees and their responses.

Example

event, err := client.Calendar.CreateEvent(ctx, nextmail.Body{	"summary": "Planning",	"start":   "2026-10-12T09:00:00Z",	"end":     "2026-10-12T09:30:00Z",	"attendees": []nextmail.Body{		{"email": "ada@example.com"},	},	"from": "team@acme.com",})if err != nil {	return err} fmt.Println(event.String("id"))

Notes

  • The SDK does not retry it, because a second call makes a second event and invites everybody again.

  • A key that may not send as from is refused with 403 from_address_forbidden, and an event with attendees and no from with 422 invalid_parameter. Invitations without emails:send are a 403 insufficient_scope.

Also available in

API
POST /calendar/events
TypeScript
nextmail.calendar.createEvent()
Python
calendar.create_event()
Ruby
calendar.create_event
PHP
calendar->createEvent
Java
calendar().createEvent
C#
Calendar.CreateEventAsync
CLI
nextmail calendar create-event

Calendar.UpdateEvent

Change an event

Scopescalendar:write
Signature
UpdateEvent(ctx context.Context, id string, patch nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Changes an event you organise. A field you leave out keeps its value, and attendees replaces the whole list. Everyone invited gets the updated invitation by email from from, so a change to an event with attendees needs emails:send too, unless sendInvites is false.

For a repeating event, scope says which dates change, as the app asks when you edit one date: occurrence changes only the date that starts at occurrenceStart, following that date and every one after it, and series all of them. With following the later dates become a new series with its own id, which is what comes back, and the old one ends the day before.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

summarystring

The title, 1 to 255 characters.

starttime.Time | string

When it starts, a time.Time or ISO 8601 with a zone.

endtime.Time | string

When it ends, after start and at most two years later.

descriptionstring

Notes about the event, up to 8,000 characters.

locationstring

Where it is: a room, an address or a link.

urlstring

A link that belongs to the event.

meetingUrlstring

The link to the video call. An empty string takes it off.

allDaybool

Whether it fills whole days. start and end then mark the days.

timezonestring

The IANA zone the event belongs to, UTC unless you say.

recurrencestring

An RRULE such as FREQ=WEEKLY;BYDAY=MO when it repeats.

attendees[]nextmail.Body

Up to 200 people to invite, each a map with email and optionally name and optional. It replaces the whole list.

reminders[]nextmail.Body

Up to five reminders, each a map with minutesBefore and optionally action.

transparencystring

OPAQUE shows you busy and TRANSPARENT free.

visibilitystring

PUBLIC, PRIVATE or CONFIDENTIAL.

sendInvitesbool

False keeps the change to your own calendar, and sends nothing.

fromstring

The address the invitations come from. It has to be one the key may send as.

scopestring

occurrence, following or series: which dates of a repeating event change. Left out, the change reaches the event or date the id names.

occurrenceStarttime.Time | string

The start of the date you mean, as ListEvents gives it. Needed with occurrence and following.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object as it stands after the change, with sequence one higher.

Example

event, err := client.Calendar.UpdateEvent(	ctx,	"cal_3f9a1c7e5b2d48a06c1e9f4b",	nextmail.Body{"start": "2026-10-12T10:00:00Z", "end": "2026-10-12T10:30:00Z"},)if err != nil {	return err} fmt.Println(event.String("start"), event.Int("sequence"))

Notes

  • The SDK does not retry it, because a retry after a lost response sends the update to everybody again.

  • An event organised by somebody else is refused with 403 not_organizer: answer it with RespondToEvent instead. An event the key does not reach is a 404.

Also available in

API
PATCH /calendar/events/{id}
TypeScript
nextmail.calendar.updateEvent()
Python
calendar.update_event()
Ruby
calendar.update_event
PHP
calendar->updateEvent
Java
calendar().updateEvent
C#
Calendar.UpdateEventAsync
CLI
nextmail calendar update-event

Calendar.DeleteEvent

Remove an event from the calendar

Scopescalendar:write
Signature
DeleteEvent(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Removes an event for good, as Remove does in the app. Nobody else is told, so call off a meeting with others in it with CancelEvent instead. For a repeating event, nextmail.WithScope("occurrence") with nextmail.WithOccurrenceStart removes one date, and following that date and every one after it.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

nextmail.WithScopestring

occurrence, following or series: which dates of a repeating event go.

nextmail.WithOccurrenceStarttime.Time

The start of the date you mean, as ListEvents gives it. Needed with occurrence and following.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with object, id and deleted set to true.

Example

event, err := client.Calendar.DeleteEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b",	nextmail.WithScope("occurrence"),	nextmail.WithOccurrenceStart(time.Date(2026, time.October, 19, 9, 0, 0, 0, time.UTC)),)if err != nil {	return err} fmt.Println(event.String("id"), event.String("object"))

Notes

  • An event organised by somebody else is refused with 403 not_organizer, and an event that is gone or that the key does not reach is a 404. An event you may not remove can still be taken off your own calendar with HideEvent.

Also available in

API
DELETE /calendar/events/{id}
TypeScript
nextmail.calendar.deleteEvent()
Python
calendar.delete_event()
Ruby
calendar.delete_event
PHP
calendar->deleteEvent
Java
calendar().deleteEvent
C#
Calendar.DeleteEventAsync
CLI
nextmail calendar delete-event

Calendar.CancelEvent

Call off a meeting

Scopescalendar:write
Signature
CancelEvent(ctx context.Context, id string, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Cancels a meeting you organise, as Cancel meeting does in the app. It stays on the calendar with status CANCELLED, and everyone invited is told it is off by email from from, so a meeting with attendees also needs emails:send.

For a repeating meeting, scope occurrence with occurrenceStart calls off one date, and following that date and every one after it. Guests get the matching update.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

fromstring

The address the cancellation comes from. It has to be one the key may send as.

scopestring

occurrence, following or series: which dates of a repeating meeting are called off.

occurrenceStarttime.Time | string

The start of the date you mean, as ListEvents gives it. Needed with occurrence and following.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with status CANCELLED.

Example

event, err := client.Calendar.CancelEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b", nextmail.Body{"from": "team@acme.com"})if err != nil {	return err} fmt.Println(event.String("status"))

Notes

  • The SDK does not retry it, because a retry sends the cancellation again.

  • An event organised by somebody else is refused with 403 not_organizer.

Also available in

API
POST /calendar/events/{id}/cancel
TypeScript
nextmail.calendar.cancelEvent()
Python
calendar.cancel_event()
Ruby
calendar.cancel_event
PHP
calendar->cancelEvent
Java
calendar().cancelEvent
C#
Calendar.CancelEventAsync
CLI
nextmail calendar cancel-event

Calendar.RespondToEvent

Answer an invitation

Scopescalendar:writeemails:send
Signature
RespondToEvent(ctx context.Context, id string, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Accepts, declines or tentatively accepts an invitation, as the buttons of an invitation do in the app. The answer goes to the organiser by email from the invited address the key may send as, or from respondingAs when the invitation went to more than one of yours, so it needs emails:send as well.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

responsestringRequired

ACCEPTED, DECLINED or TENTATIVE.

respondingAsstring

Which of your invited addresses answers, when there is more than one.

proposedStarttime.Time | string

A new start to propose with your answer, sent together with proposedEnd.

proposedEndtime.Time | string

The end of the proposed time.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with your answer on your attendee row.

Example

event, err := client.Calendar.RespondToEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b", nextmail.Body{"response": "ACCEPTED"})if err != nil {	return err} fmt.Println(event.String("id"), event.String("status"))

Notes

  • An event that invited none of the addresses the key may send as is refused with 403 not_invited, and a cancelled meeting with 409 event_cancelled.

  • When the organiser cannot be reached, nothing changes and the call is a 409 reply_not_sent.

  • With proposedStart and proposedEnd the organiser gets a counter-proposal, as Propose a new time sends from Google Calendar and Outlook, and decides whether to move the meeting.

Also available in

API
POST /calendar/events/{id}/respond
TypeScript
nextmail.calendar.respondToEvent()
Python
calendar.respond_to_event()
Ruby
calendar.respond_to_event
PHP
calendar->respondToEvent
Java
calendar().respondToEvent
C#
Calendar.RespondToEventAsync
CLI
nextmail calendar respond-to-event

Calendar.DeclineProposal

Decline a proposed time

Scopescalendar:writeemails:send
Signature
DeclineProposal(ctx context.Context, id string, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Keeps the original time of a meeting you organise after a guest proposed another one, as Decline in the proposal on the event does in the app. The guest is told by email from from, or from the organising address, so it needs emails:send as well. To take the proposed time instead, change the event with UpdateEvent.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

attendeestringRequired

The guest whose proposal you decline, by email address.

fromstring

The address the answer is sent from, when it is not the organising address.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with the guest's proposedStart and proposedEnd cleared.

Example

event, err := client.Calendar.GetEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} for _, attendee := range event.Objects("attendees") {	if !attendee.Has("proposedStart") {		continue	} 	if _, err := client.Calendar.DeclineProposal(ctx, event.ID(), nextmail.Body{"attendee": attendee.String("email")}); err != nil {		return err	} 	break}

Notes

Also available in

API
POST /calendar/events/{id}/decline-proposal
TypeScript
nextmail.calendar.declineProposal()
Python
calendar.decline_proposal()
Ruby
calendar.decline_proposal
PHP
calendar->declineProposal
Java
calendar().declineProposal
C#
Calendar.DeclineProposalAsync
CLI
nextmail calendar decline-proposal

Calendar.HideEvent

Hide an event from your calendar

Scopescalendar:write
Signature
HideEvent(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Takes an event off your own calendar and leaves it for everyone else, as Hide from my calendar does in the app. Use it for an invitation that reached you through a shared address, or an event you may not remove. It hides every date of a repeating event, and stops its reminders for you. UnhideEvent brings it back.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with object, id, uid and hidden set to true.

Example

hidden, err := client.Calendar.HideEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(hidden.String("id"), hidden.Bool("hidden"))

Notes

  • Hiding an event that is already hidden changes nothing, so it is safe to repeat. An event the key does not reach is a 404.

  • It hides the event for the person the key or app acts for, and nobody else. ListEvents leaves it out from then on, and GetEvent still finds it, with hidden true.

Also available in

API
POST /calendar/events/{id}/hide
TypeScript
nextmail.calendar.hideEvent()
Python
calendar.hide_event()
Ruby
calendar.hide_event
PHP
calendar->hideEvent
Java
calendar().hideEvent
C#
Calendar.HideEventAsync
CLI
nextmail calendar hide-event

Calendar.UnhideEvent

Show a hidden event again

Scopescalendar:write
Signature
UnhideEvent(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Puts an event you hid back on your calendar, as Show on my calendar does on the invitation in the app.

Parameters

idstringRequired

Event id, the eventId of an occurrence, such as cal_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with object, id, uid and hidden set to false.

Example

shown, err := client.Calendar.UnhideEvent(ctx, "cal_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(shown.String("id"), shown.Bool("hidden"))

Notes

  • An event that was not hidden stays as it was, so it is safe to repeat.

Also available in

API
POST /calendar/events/{id}/unhide
TypeScript
nextmail.calendar.unhideEvent()
Python
calendar.unhide_event()
Ruby
calendar.unhide_event
PHP
calendar->unhideEvent
Java
calendar().unhideEvent
C#
Calendar.UnhideEventAsync
CLI
nextmail calendar unhide-event

Calendar.FreeBusy

Free and busy times

Scopescalendar:read
Signature
FreeBusy(ctx context.Context, emails []string, from time.Time, to time.Time, opts ...nextmail.RequestOption) (nextmail.Object, error)

When the people you name are busy, as Find a time in the event editor of the app shows it. An address of the workspace shows the busy times of the person who holds it, from their events, the invitations they have not declined, their subscribed calendars and their bookings, without any detail. Any other address comes back with known false.

With nextmail.WithDurationMinutes, suggestions lists up to five times when everyone known is free, on weekdays between 09:00 and 17:00 in the zone of nextmail.WithTimezone. from and to may be at most 31 days apart.

Parameters

emails[]stringRequired

The addresses to look up, at most 20.

fromtime.TimeRequired

The start of the window.

totime.TimeRequired

The end of the window, at most 31 days after from.

nextmail.WithTimezonestring

The IANA zone the suggested times keep to working hours in, UTC unless you say.

nextmail.WithDurationMinutesint

The length of the meeting, 5 to 480 minutes. Send it to get suggestions.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with people, each with email, known and busy, its busy times as objects with start and end, and suggestions in the same shape.

Example

from := time.Now() times, err := client.Calendar.FreeBusy(ctx, []string{"ana@acme.com", "ben@acme.com"}, from, from.Add(7*24*time.Hour),	nextmail.WithTimezone("Europe/London"),	nextmail.WithDurationMinutes(30),)if err != nil {	return err} for _, suggestion := range times.Objects("suggestions") {	fmt.Println("Free:", suggestion.String("start"))}

Notes

  • A key or an app limited to particular addresses or domains is refused with 422 capability_unsupported, because the answer reads whole calendars.

  • It reads the calendars as they are now and holds nothing, so a suggested time can be gone a moment later.

Also available in

API
GET /calendar/free-busy
TypeScript
nextmail.calendar.freeBusy()
Python
calendar.free_busy()
Ruby
calendar.free_busy
PHP
calendar->freeBusy
Java
calendar().freeBusy
C#
Calendar.FreeBusyAsync
CLI
nextmail calendar free-busy

Calendar.ListFeeds

List calendar links

Scopescalendar:read
Signature
ListFeeds(ctx context.Context, opts ...nextmail.RequestOption) ([]nextmail.Object, error)

Returns the secret links that publish your calendar to other calendar apps, as Share in the calendar settings of the app lists them. Anyone with a link can read what it shows, so treat url and webcalUrl like passwords.

Parameters

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

A []nextmail.Object, each with id, name, mode, url, webcalUrl and when calendar apps last read it.

Example

feeds, err := client.Calendar.ListFeeds(ctx)if err != nil {	return err} for _, feed := range feeds {	fmt.Println(feed.String("name"), feed.String("mode"), feed.String("url"))}

Notes

  • A key limited to particular addresses or domains is refused with 422 capability_unsupported, because a link covers the whole calendar.

Also available in

API
GET /calendar/feeds
TypeScript
nextmail.calendar.listFeeds()
Python
calendar.list_feeds()
Ruby
calendar.list_feeds
PHP
calendar->listFeeds
Java
calendar().listFeeds
C#
Calendar.ListFeedsAsync
CLI
nextmail calendar list-feeds

Calendar.CreateFeed

Create a calendar link

Scopescalendar:write
Signature
CreateFeed(ctx context.Context, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Makes a secret link that publishes your calendar as an iCalendar feed, for Google Calendar (From URL), Outlook (Subscribe from web) or Apple Calendar (New subscription). full shows every detail, busy only the times you are busy. The calendar app reads the link again on its own schedule, usually every few hours.

Parameters

namestringRequired

The name calendar apps show for the calendar, up to 100 characters.

modestringRequired

full for every detail, busy for busy times only.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with the new url and webcalUrl.

Example

feed, err := client.Calendar.CreateFeed(ctx, nextmail.Body{"name": "Work (busy)", "mode": "busy"})if err != nil {	return err} fmt.Println(feed.String("url"))

Notes

Also available in

API
POST /calendar/feeds
TypeScript
nextmail.calendar.createFeed()
Python
calendar.create_feed()
Ruby
calendar.create_feed
PHP
calendar->createFeed
Java
calendar().createFeed
C#
Calendar.CreateFeedAsync
CLI
nextmail calendar create-feed

Calendar.ResetFeed

Reset a calendar link

Scopescalendar:write
Signature
ResetFeed(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Replaces the secret in a calendar link, so the old address stops working everywhere it was shared. Paste the new address into the calendar apps you still want to update.

Parameters

idstringRequired

Calendar link id, cfd_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with its new url and webcalUrl.

Example

feed, err := client.Calendar.ResetFeed(ctx, "cfd_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(feed.String("url"))

Notes

Also available in

API
POST /calendar/feeds/{id}/reset
TypeScript
nextmail.calendar.resetFeed()
Python
calendar.reset_feed()
Ruby
calendar.reset_feed
PHP
calendar->resetFeed
Java
calendar().resetFeed
C#
Calendar.ResetFeedAsync
CLI
nextmail calendar reset-feed

Calendar.DeleteFeed

Delete a calendar link

Scopescalendar:write
Signature
DeleteFeed(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Turns a calendar link off for good. Calendar apps that subscribed to it stop getting updates.

Parameters

idstringRequired

Calendar link id, cfd_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with deleted: true.

Example

feed, err := client.Calendar.DeleteFeed(ctx, "cfd_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(feed.String("id"), feed.String("object"))

Notes

Also available in

API
DELETE /calendar/feeds/{id}
TypeScript
nextmail.calendar.deleteFeed()
Python
calendar.delete_feed()
Ruby
calendar.delete_feed
PHP
calendar->deleteFeed
Java
calendar().deleteFeed
C#
Calendar.DeleteFeedAsync
CLI
nextmail calendar delete-feed

Calendar.ListSubscriptions

List calendar subscriptions

Scopescalendar:read
Signature
ListSubscriptions(ctx context.Context, opts ...nextmail.RequestOption) ([]nextmail.Object, error)

Returns the other calendars you subscribe to by link, such as a Google or Outlook calendar address, a team rota or public holidays, as Other calendars in the app lists them. Their events show on your calendar, read-only.

Parameters

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

A []nextmail.Object, each with name, url, color, status, lastError and how many events it holds.

Example

subscriptions, err := client.Calendar.ListSubscriptions(ctx)if err != nil {	return err} for _, subscription := range subscriptions {	fmt.Println(subscription.String("name"), subscription.String("status"), subscription.Int("eventCount"))}

Notes

  • status is failing while reads fail and are retried, and stopped after ten failures in a row until you refresh it.

Also available in

API
GET /calendar/subscriptions
TypeScript
nextmail.calendar.listSubscriptions()
Python
calendar.list_subscriptions()
Ruby
calendar.list_subscriptions
PHP
calendar->listSubscriptions
Java
calendar().listSubscriptions
C#
Calendar.ListSubscriptionsAsync
CLI
nextmail calendar list-subscriptions

Calendar.CreateSubscription

Subscribe to a calendar

Scopescalendar:write
Signature
CreateSubscription(ctx context.Context, body nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Adds a calendar by its iCalendar link: an https, http or webcal address, such as the secret address of a Google calendar or a published Outlook calendar. It is read at once, then again about every half hour. name defaults to the name the calendar gives itself.

Parameters

urlstringRequired

The calendar link, https, http or webcal.

namestring

The name to show, up to 100 characters.

colorstring

The colour of its events, from CALENDAR_COLORS.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with its first events read.

Example

holidays, err := client.Calendar.CreateSubscription(ctx, nextmail.Body{"url": "webcal://example.com/holidays.ics", "color": "green"})if err != nil {	return err} fmt.Println(holidays.String("name"), holidays.Int("eventCount"))

Notes

Also available in

API
POST /calendar/subscriptions
TypeScript
nextmail.calendar.createSubscription()
Python
calendar.create_subscription()
Ruby
calendar.create_subscription
PHP
calendar->createSubscription
Java
calendar().createSubscription
C#
Calendar.CreateSubscriptionAsync
CLI
nextmail calendar create-subscription

Calendar.UpdateSubscription

Change a calendar subscription

Scopescalendar:write
Signature
UpdateSubscription(ctx context.Context, id string, patch nextmail.Body, opts ...nextmail.RequestOption) (nextmail.Object, error)

Renames a subscription or gives it another colour.

Parameters

idstringRequired

Subscription id, csb_ followed by 24 hex characters.

namestring

The new name, up to 100 characters.

colorstring

The new colour, from CALENDAR_COLORS.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object as it stands now.

Example

subscription, err := client.Calendar.UpdateSubscription(ctx, "csb_3f9a1c7e5b2d48a06c1e9f4b", nextmail.Body{"name": "Team rota", "color": "purple"})if err != nil {	return err} fmt.Println(subscription.String("id"), subscription.String("status"))

Notes

Also available in

API
PATCH /calendar/subscriptions/{id}
TypeScript
nextmail.calendar.updateSubscription()
Python
calendar.update_subscription()
Ruby
calendar.update_subscription
PHP
calendar->updateSubscription
Java
calendar().updateSubscription
C#
Calendar.UpdateSubscriptionAsync
CLI
nextmail calendar update-subscription

Calendar.RefreshSubscription

Refresh a calendar subscription

Scopescalendar:write
Signature
RefreshSubscription(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Reads a subscribed calendar again now instead of waiting for the next half-hourly read, and restarts one that stopped after repeated failures.

Parameters

idstringRequired

Subscription id, csb_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object after the read, with status and lastError.

Example

subscription, err := client.Calendar.RefreshSubscription(ctx, "csb_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(subscription.String("lastError"))

Notes

Also available in

API
POST /calendar/subscriptions/{id}/refresh
TypeScript
nextmail.calendar.refreshSubscription()
Python
calendar.refresh_subscription()
Ruby
calendar.refresh_subscription
PHP
calendar->refreshSubscription
Java
calendar().refreshSubscription
C#
Calendar.RefreshSubscriptionAsync
CLI
nextmail calendar refresh-subscription

Calendar.DeleteSubscription

Unsubscribe from a calendar

Scopescalendar:write
Signature
DeleteSubscription(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Removes a subscription and every event it brought onto your calendar.

Parameters

idstringRequired

Subscription id, csb_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client's API key for this call only.

Returns

The nextmail.Object with deleted: true.

Example

subscription, err := client.Calendar.DeleteSubscription(ctx, "csb_3f9a1c7e5b2d48a06c1e9f4b")if err != nil {	return err} fmt.Println(subscription.String("id"), subscription.String("object"))

Notes

Also available in

API
DELETE /calendar/subscriptions/{id}
TypeScript
nextmail.calendar.deleteSubscription()
Python
calendar.delete_subscription()
Ruby
calendar.delete_subscription
PHP
calendar->deleteSubscription
Java
calendar().deleteSubscription
C#
Calendar.DeleteSubscriptionAsync
CLI
nextmail calendar delete-subscription

Calendar.ImportIcs

Import a calendar file

Scopescalendar:write
Signature
ImportIcs(ctx context.Context, data io.Reader, opts ...nextmail.RequestOption) (nextmail.Object, error)

Sends an iCalendar (.ics) file as the request body and queues it. Its events become events of your own that you can edit, and nobody on them is sent anything, now or when you change them later, unless you ask for that on the change. Poll GetImport until status is completed.

The file may be 10 MB and hold 25,000 events. Several calendars in one file are merged, and the report keeps their names. An event whose UID is already in the workspace is skipped and counted, never overwritten, so sending the same file twice adds nothing.

data is an io.Reader, and it goes out as text/calendar.

Parameters

dataio.ReaderRequired

The .ics file: an io.Reader.

nextmail.WithFilenamestring

The name to show for the file in the list of imports, at most 255 characters.

nextmail.WithAPIKeystring

Overrides the client API key for this call only.

Returns

The nextmail.Object with status: queued.

Example

source, err := os.Open("work.ics")if err != nil {	return err} defer source.Close() queued, err := client.Calendar.ImportIcs(ctx, source, nextmail.WithFilename("work.ics"))if err != nil {	return err} fmt.Println(queued.ID(), queued.String("status"))

Notes

  • A body that is not an iCalendar file is a 400 not_a_calendar_file, an empty one a 400 item_import_empty, and one holding more than 25,000 events a 400 too_many_events.

  • A file over 10 MB is a 413 item_import_too_large.

  • To send text you already hold, such as what GetEventIcs returns, wrap it in strings.NewReader(text).

  • An upload that outlasts the client timeout fails as a network error, so raise it on the client for a large file on a slow connection.

  • Not retried automatically.

Also available in

API
POST /calendar/imports
TypeScript
nextmail.calendar.importIcs()
Python
calendar.import_ics()
Ruby
calendar.import_ics
PHP
calendar->importIcs
Java
calendar().importIcs
C#
Calendar.ImportIcsAsync
CLI
nextmail calendar import-ics

Calendar.ListImports

List calendar imports

Scopescalendar:readPages through results
Signature
ListImports(ctx context.Context, opts ...nextmail.RequestOption) (*nextmail.Page, error)

Returns one page of the calendar files and calendars brought in, newest first, each with what it added and what it left out. Beside the files sent with ImportIcs it lists the calendars that came with a mailbox import, and those carry the id of that import in parentImportId.

Paging is keyset. nextmail.WithLimit takes 1 to 100 and defaults to 25, and NextCursor goes back as nextmail.WithCursor while HasMore is true. ListAllImports and IterateImports do that walk for you.

Parameters

nextmail.WithLimitint

Imports per page, a whole number from 1 to 100. The server defaults to 25.

nextmail.WithCursorstring

The NextCursor from the previous page. Never build one yourself.

nextmail.WithAPIKeystring

Overrides the client API key for this call only.

Returns

The *nextmail.Page with Items, HasMore and NextCursor.

Example

page, err := client.Calendar.ListImports(ctx, nextmail.WithLimit(50))if err != nil {	return err} for _, job := range page.Items {	fmt.Println(job.String("fileName"), job.String("status"), job.Object("counts").Int("imported"), job.Object("counts").Int("skipped"))} fmt.Println(page.HasMore, page.NextCursor)

Notes

  • source is file for an upload. takeout, caldav and microsoft came with a mailbox import.

  • A cursor that names no import is a 400 invalid_cursor.

  • A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's nextmail.WithMaxRetries, and on a 429 only when it carries a Retry-After of a minute or less.

Also available in

API
GET /calendar/imports
TypeScript
nextmail.calendar.listImports()
Python
calendar.list_imports()
Ruby
calendar.list_imports
PHP
calendar->listImports
Java
calendar().listImports
C#
Calendar.ListImportsAsync
CLI
nextmail calendar list-imports

Calendar.ListAllImports

Collect every calendar import into one slice

Scopescalendar:readPages through results
Signature
ListAllImports(ctx context.Context, opts ...nextmail.RequestOption) ([]nextmail.Object, error)

Follows NextCursor from page to page and returns with every calendar import, newest first.

Everything is held in memory before the call returns. Prefer IterateImports when you can stop early. limit sets the page size of each request, not the total.

Parameters

nextmail.WithLimitint

Page size per request, from 1 to 100, defaulting to 25 on the server.

nextmail.WithCursorstring

A cursor from an earlier page to start after.

nextmail.WithAPIKeystring

Overrides the client API key for every page of this walk.

Returns

A []nextmail.Object holding every import across all pages.

Example

imports, err := client.Calendar.ListAllImports(ctx)if err != nil {	return err} added := 0 for _, job := range imports {	added += job.Object("counts").Int("imported")} fmt.Println(added, "events came from", len(imports), "imports")

Notes

  • A failure on any page fails the whole call, and the imports already fetched are discarded.

Also available in

API
GET /calendar/imports
TypeScript
nextmail.calendar.listAllImports()
Python
calendar.list_all_imports()
Ruby
calendar.list_all_imports
PHP
calendar->listAllImports
Java
calendar().listAllImports
C#
Calendar.ListAllImportsAsync

Calendar.IterateImports

Stream calendar imports one at a time

Scopescalendar:readPages through results
Signature
IterateImports(ctx context.Context, opts ...nextmail.RequestOption) *nextmail.Iterator

Returns an iterator that yields calendar imports one by one, newest first, and requests the next page only once the current one is drained. Nothing is fetched until you consume it, and breaking out of the loop stops the requests.

Parameters

nextmail.WithLimitint

Page size per request, from 1 to 100, defaulting to 25 on the server.

nextmail.WithCursorstring

A cursor from an earlier page to start after.

nextmail.WithAPIKeystring

Overrides the client API key for every page of this walk.

Returns

The *nextmail.Iterator yielding one import per step.

Example

for job, err := range client.Calendar.IterateImports(ctx).All() {	if err != nil {		return err	} 	if job.String("status") != "running" {		continue	} 	fmt.Println("still running", job.ID(), job.Object("counts").Int("total")) 	break}

Notes

  • The iterator is lazy, so an abandoned loop costs only the pages you consumed.

Also available in

API
GET /calendar/imports
TypeScript
nextmail.calendar.iterateImports()
Python
calendar.iterate_imports()
Ruby
calendar.iterate_imports
PHP
calendar->iterateImports
Java
calendar().iterateImports
C#
Calendar.IterateImportsAsync

Calendar.GetImport

Get a calendar import

Scopescalendar:read
Signature
GetImport(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Returns one calendar import with its counts and its report: the calendars it read, how many events it left out and why, and up to 20 of the events it left out. Poll it after ImportIcs until status is completed or failed.

counts.imported is what was added and counts.skipped what was left out, which report.skipped breaks down by reason: uid-taken for an event that was already here, no-start for one with no start time, invalid for one that could not be read and empty for a file or calendar that held no events.

Parameters

idstringRequired

Calendar import id, iimp_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client API key for this call only.

Returns

The nextmail.Object with status, counts, report, undoable and when it started, finished and was undone.

Example

item, err := client.Calendar.GetImport(ctx, "iimp_3f9c2a7b1e4d8f60a5c7b92d")if err != nil {	return err} counts := item.Object("counts") fmt.Println(item.String("status"), counts.Int("imported"), counts.Int("skipped")) for _, sample := range item.Object("report").Objects("samples") {	fmt.Println(sample.String("name"), sample.String("reason"))}

Notes

  • An id that names no calendar import is a 404 item_import_not_found.

  • A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's nextmail.WithMaxRetries, and on a 429 only when it carries a Retry-After of a minute or less.

Also available in

API
GET /calendar/imports/{id}
TypeScript
nextmail.calendar.getImport()
Python
calendar.get_import()
Ruby
calendar.get_import
PHP
calendar->getImport
Java
calendar().getImport
C#
Calendar.GetImportAsync
CLI
nextmail calendar get-import

Calendar.UndoImport

Remove what a calendar import added

Scopescalendar:write
Signature
UndoImport(ctx context.Context, id string, opts ...nextmail.RequestOption) (nextmail.Object, error)

Deletes every event the import added, changed since or not, and marks the import undone. Nobody is told. Events that were skipped because they were already here are not touched.

Parameters

idstringRequired

Calendar import id, iimp_ followed by 24 hex characters.

nextmail.WithAPIKeystring

Overrides the client API key for this call only.

Returns

The nextmail.Object with status: undone and undoneAt set.

Example

undone, err := client.Calendar.UndoImport(ctx, "iimp_3f9c2a7b1e4d8f60a5c7b92d")if err != nil {	return err} fmt.Println(undone.String("status"), undone.String("undoneAt"), undone.Object("counts").Int("imported"))

Notes

  • An import that is still running, or was already removed, is a 409 item_import_not_undoable. undoable on the import says whether the call would remove anything.

  • An id that names no calendar import is a 404 item_import_not_found.

  • Not retried automatically.

Also available in

API
POST /calendar/imports/{id}/undo
TypeScript
nextmail.calendar.undoImport()
Python
calendar.undo_import()
Ruby
calendar.undo_import
PHP
calendar->undoImport
Java
calendar().undoImport
C#
Calendar.UndoImportAsync
CLI
nextmail calendar undo-import