# GoogleMail Class ## Overview `GoogleMail` is the Gmail API client within 4D NetKit. It provides send, append, read, delete, label management, and change-notification operations. Both JMAP (4D mail object) and MIME (raw RFC 2822) formats are supported, controlled by the `mailType` property set when creating the [Google](./Google.md) object. A `GoogleMail` object is accessed via the `mail` property of a [Google](./Google.md) object: `$google.mail`. ## Table of Contents ### Mails * [.append()](#append) * [.delete()](#delete) * [.getMail()](#getmail) * [.getMailIds()](#getmailids) * [.getMails()](#getmails) * [.send()](#send) * [.untrash()](#untrash) * [.update()](#update) ### Labels * [.createLabel()](#createlabel) * [.deleteLabel()](#deletelabel) * [.getLabel()](#getlabel) * [.getLabelList()](#getlabellist) * [.updateLabel()](#updatelabel) ### Notifications * [.notifier()](#notifier) ## Properties A `GoogleMail` object exposes the following properties: | Property | Type | Description | |---|---|---| | mailType | Text | (read-only) Mail type used to send and receive emails. Can be `"MIME"` or `"JMAP"`. Set via the `mailType` option in [`cs.NetKit.Google.new()`](./Google.md#csnetkitgooglenew). | | userId | Text | User identifier used to identify the user in Service mode. Can be the `id` or the `userPrincipalName`. | ## Mails ### .append() **.append**( *mail* : Text { ; *labelIds* : Collection } ) : Object
**.append**( *mail* : Blob { ; *labelIds* : Collection } ) : Object
**.append**( *mail* : Object { ; *labelIds* : Collection } ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mail | Text \| Blob \| Object | -> | Email to store. BLOB or Text for MIME format; Object (JMAP) for JMAP format. | | labelIds | Collection | -> | Collection of label IDs to apply. Defaults to `["DRAFT"]` when omitted or empty. | | Result | Object | <- | [Status object](#status-object) with an additional `id` property. | #### Description `.append()` stores a mail message in the user's mailbox without sending it. Useful for importing existing messages or saving drafts with custom labels. > If `labelIds` is passed and the mail has a `from` or `sender` header, the Gmail server automatically adds the `SENT` label. #### Returned object The method returns a [status object](#status-object) with an additional `id` property: | Property | Type | Description | |---|---|---| | id | Text | ID of the email created on the server. | | success | Boolean | See [status object](#status-object). | | statusText | Text | See [status object](#status-object). | | errors | Collection | See [status object](#status-object). | #### Example ```4d // Append a mail as a draft (default) $status:=$google.mail.append($mail) // Append a mail directly to the inbox $status:=$google.mail.append($mail; ["INBOX"]) ``` ### .delete() **.delete**( *mailID* : Text { ; *permanently* : Boolean } ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mailID | Text | -> | ID of the mail to delete. | | permanently | Boolean | -> | If `true`, deletes permanently. If `false` (default), moves the message to Trash. | | Result | Object | <- | [Status object](#status-object). | #### Description `.delete()` deletes the specified message from the user's mailbox, either permanently or by moving it to Trash. #### Returned object The method returns a standard [status object](#status-object). #### Permissions This method requires one of the following OAuth scopes: ``` https://mail.google.com/ https://www.googleapis.com/auth/gmail.modify ``` #### Example ```4d // Delete permanently $status:=$google.mail.delete($mailId; True) ``` ### .getMail() **.getMail**( *mailID* : Text { ; *param* : Object } ) : Object
**.getMail**( *mailID* : Text { ; *param* : Object } ) : Blob #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mailID | Text | -> | ID of the message to retrieve. | | param | Object | -> | Options for the message to retrieve (optional). | | Result | Object \| Blob | <- | Downloaded mail; `Null` on error. | #### Description `.getMail()` gets the specified message from the user's mailbox. In *param*, you can pass the following properties: | Property | Type | Description | |---|---|---| | format | Text | The format to return the message in. Can be: `"raw"` (default, full email), `"minimal"` (ID and labels only), `"metadata"` (ID, labels, and headers only). | | headers | Collection | Collection of header names to return. Only used when `format` is `"metadata"`. | | mailType | Text | Override the instance `mailType` for this call. Can be `"MIME"` or `"JMAP"`. | #### Returned object The method returns a mail in one of the following formats depending on `mailType`: | Format | Type | Comment | |---|---|---| | MIME | Blob | | | JMAP | Object | Contains an `id` attribute. | ### .getMailIds() **.getMailIds**( { *param* : Object } ) : [cs.NetKit.GoogleMailIdList](./GoogleMailIdList.md) #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | param | Object | -> | Options for filtering messages (optional). | | Result | [cs.NetKit.GoogleMailIdList](./GoogleMailIdList.md) | <- | Paginated list of Gmail message IDs. Use `next()` / `previous()` to navigate pages. | #### Description `.getMailIds()` returns an object containing a collection of message IDs in the user's mailbox. In *param*, you can pass the following properties: | Property | Type | Description | |---|---|---| | top | Integer | Maximum number of messages to return. Default is 100, maximum is 500. | | search | Text | Only return messages matching the specified query. Supports Gmail search syntax. See [Gmail search operators](https://support.google.com/mail/answer/7190). | | labelIds | Collection | Only return messages that have all the specified label IDs. | | includeSpamTrash | Boolean | Include messages from SPAM and TRASH. Default is `false`. | #### Returned object The method returns a [GoogleMailIdList](./GoogleMailIdList.md) object with the following properties: | Property | Type | Description | |---|---|---| | mailIds | Collection | Collection of objects, each with `id` (Text) and `threadId` (Text). Empty if no mail is returned. | | isLastPage | Boolean | `true` if the last page is reached. | | page | Integer | Current page number. Starts at `1`. Default page size is 10 (configurable via `top`). | | next() | 4D.Function | Loads the next page. Returns `true` if successful, `false` otherwise. | | previous() | 4D.Function | Loads the previous page. Returns `true` if successful, `false` otherwise. | | success | Boolean | See [status object](#status-object). | | statusText | Text | See [status object](#status-object). | | errors | Collection | See [status object](#status-object). | #### Permissions This method requires one of the following OAuth scopes: ``` https://www.googleapis.com/auth/gmail.modify https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.metadata ``` ### .getMails() **.getMails**( *mailIDs* : Collection { ; *param* : Object } ) : Collection #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mailIDs | Collection | -> | Collection of mail IDs (Text), or collection of objects each with an `id` property. | | param | Object | -> | Options (same properties as `.getMail()`) (optional). | | Result | Collection | <- | Collection of mails (JMAP objects or Blobs depending on `mailType`). `Null` on error. | #### Description `.getMails()` gets a collection of emails based on the specified `mailIDs` collection. > The maximum number of IDs supported is 100. For more than 100 mails, call the function multiple times. In *param*, you can pass the following properties: | Property | Type | Description | |---|---|---| | format | Text | The format to return the messages in. Can be: `"raw"` (default), `"minimal"`, or `"metadata"`. | | headers | Collection | Collection of header names to return. Only used when `format` is `"metadata"`. | | mailType | Text | Override the instance `mailType` for this call. Can be `"MIME"` or `"JMAP"`. | #### Returned value The method returns a collection of mails in one of the following formats depending on `mailType`: | Format | Type | Comment | |---|---|---| | MIME | Blob | | | JMAP | Object | Contains an `id` attribute. | ### .send() **.send**( *email* : Text ) : Object
**.send**( *email* : Object ) : Object
**.send**( *email* : Blob ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | email | Text \| Blob \| Object | -> | Email to be sent. | | Result | Object | <- | [Status object](#status-object). | #### Description `.send()` sends an email using the MIME or JMAP format. In *email*, pass the email to send: - **Text or Blob**: sent using MIME format. - **Object**: sent using JMAP format, following the [4D email object format](https://developer.4d.com/docs/API/EmailObjectClass.html#email-object). The data type passed in `email` must be compatible with the `mailType` property. > To avoid authentication errors, ensure your application has appropriate authorizations. One of the following OAuth scopes is required: [`gmail.modify`](https://www.googleapis.com/auth/gmail.modify), [`gmail.compose`](https://www.googleapis.com/auth/gmail.compose), or [`gmail.send`](https://www.googleapis.com/auth/gmail.send). #### Returned object The method returns a standard [status object](#status-object). #### Example ```4d var $oAuth2 : cs.NetKit.OAuth2Provider var $credential:={} $credential.name:="Google" $credential.permission:="signedIn" $credential.clientId:="your-client-id" $credential.clientSecret:="your-client-secret" $credential.redirectURI:="http://127.0.0.1:50993/authorize/" $credential.scope:="https://www.googleapis.com/auth/gmail.send" $oAuth2:=cs.NetKit.OAuth2Provider.new($credential) var $email:={} $email.from:="noreply.mail@gmail.com" $email.to:="address1@mail.com,address2@mail.com" $email.cc:={name: "Stephen"; email: "address3@mail.com"} $email.subject:="Hello world" $email.textBody:="Test mail \r\n This is just a test e-mail \r\n Please ignore it" $email.attachments:=[MAIL New attachment($filePath)] var $Google:=cs.NetKit.Google.new($oAuth2; {mailType: "JMAP"}) var $status:=$Google.mail.send($email) ``` ### .untrash() **.untrash**( *mailID* : Text ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mailID | Text | -> | ID of the message to remove from Trash. | | Result | Object | <- | [Status object](#status-object). | #### Description `.untrash()` removes the specified message from Trash. #### Returned object The method returns a standard [status object](#status-object). #### Permissions This method requires one of the following OAuth scopes: ``` https://mail.google.com/ https://www.googleapis.com/auth/gmail.modify ``` ### .update() **.update**( *mailIDs* : Collection ; *param* : Object ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | mailIDs | Collection | -> | Collection of mail IDs (Text), or collection of objects each with an `id` property. Limited to 1000 IDs per request. | | param | Object | -> | Modification options. | | Result | Object | <- | [Status object](#status-object). | #### Description `.update()` adds or removes labels on the specified messages to help categorize emails. Labels can be system labels (e.g., `INBOX`, `SPAM`, `TRASH`, `UNREAD`, `STARRED`, `IMPORTANT`) or custom labels. Multiple labels can be applied simultaneously. In *param*, you can pass the following properties: | Property | Type | Description | |---|---|---| | addLabelIds | Collection | Collection of label IDs to add to the messages. | | removeLabelIds | Collection | Collection of label IDs to remove from the messages. | #### Returned object The method returns a standard [status object](#status-object). #### Example ```4d // Mark a collection of emails as unread $result:=$google.mail.update($mailIds; {addLabelIds: ["UNREAD"]}) ``` ## Labels ### .createLabel() **.createLabel**( *labelInfo* : Object ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | labelInfo | Object | -> | [labelInfo object](#labelinfo-object) containing label properties to create. | | Result | Object | <- | [Status object](#status-object) with an additional `label` property. | #### Description `.createLabel()` creates a new label. #### Returned object The method returns a [status object](#status-object) with an additional `label` property: | Property | Type | Description | |---|---|---| | label | Object | Newly created label instance (see [labelInfo object](#labelinfo-object)). | | success | Boolean | See [status object](#status-object). | | statusText | Text | See [status object](#status-object). | | errors | Collection | See [status object](#status-object). | #### Example ```4d $status:=$google.mail.createLabel({name: "Backup"}) $labelId:=$status.label.id ``` ### .deleteLabel() **.deleteLabel**( *labelId* : Text ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | labelId | Text | -> | ID of the label to delete. | | Result | Object | <- | [Status object](#status-object). | #### Description `.deleteLabel()` immediately and permanently deletes the specified label and removes it from any messages and threads it is applied to. > This method is only available for labels with `type="user"`. #### Returned object The method returns a standard [status object](#status-object). #### Example ```4d $status:=$google.mail.deleteLabel($labelId) ``` ### .getLabel() **.getLabel**( *labelId* : Text ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | labelId | Text | -> | ID of the label to retrieve. | | Result | Object | <- | [labelInfo object](#labelinfo-object) with additional counter properties. | #### Description `.getLabel()` returns the information of a label. #### Returned object The returned [labelInfo object](#labelinfo-object) includes the following additional properties: | Property | Type | Description | |---|---|---| | messagesTotal | Integer | Total number of messages with this label. | | messagesUnread | Integer | Number of unread messages with this label. | | threadsTotal | Integer | Total number of threads with this label. | | threadsUnread | Integer | Number of unread threads with this label. | #### Example ```4d $info:=$google.mail.getLabel($labelId) $name:=$info.name $emailNumber:=$info.messagesTotal $unread:=$info.messagesUnread ``` ### .getLabelList() **.getLabelList**() : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | Result | Object | <- | [Status object](#status-object) with an additional `labels` property. | #### Description `.getLabelList()` returns an object containing the collection of all labels in the user's mailbox. #### Returned object The method returns a [status object](#status-object) with an additional `labels` property: | Property | Type | Description | |---|---|---| | labels | Collection | Collection of [`mailLabel` objects](#maillabel-object). | | success | Boolean | See [status object](#status-object). | | statusText | Text | See [status object](#status-object). | | errors | Collection | See [status object](#status-object). | #### mailLabel object A `mailLabel` object contains the following properties: | Property | Type | Description | |---|---|---| | name | Text | Display name of the label. | | id | Text | Immutable ID of the label. | | messageListVisibility | Text | Visibility in the message list. Can be `"show"` or `"hide"`. | | labelListVisibility | Text | Visibility in the label list. Can be `"labelShow"`, `"labelShowIfUnread"`, or `"labelHide"`. | | type | Text | Owner type: `"user"` (custom, modifiable) or `"system"` (created by Gmail, cannot be modified or deleted). | ### .updateLabel() **.updateLabel**( *labelId* : Text ; *labelInfo* : Object ) : Object #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | labelId | Text | -> | ID of the label to update. | | labelInfo | Object | -> | [labelInfo object](#labelinfo-object) containing updated label properties. | | Result | Object | <- | [Status object](#status-object) with an additional `label` property. | #### Description `.updateLabel()` updates the specified label. > This method is only available for labels with `type="user"`. #### Returned object The method returns a [status object](#status-object) with an additional `label` property: | Property | Type | Description | |---|---|---| | label | Object | Updated label instance (see [labelInfo object](#labelinfo-object)). | | success | Boolean | See [status object](#status-object). | | statusText | Text | See [status object](#status-object). | | errors | Collection | See [status object](#status-object). | #### Example ```4d $status:=$google.mail.updateLabel($labelId; {name: "Backup January"}) ``` ## Notifications ### .notifier() **.notifier**( *param* : Object { ; *labelId* : Text } ) : [cs.NetKit.GoogleNotification](./GoogleNotification.md) #### Parameters | Parameter | Type | | Description | |---|---|:---:|---| | param | Object | -> | Callback and mode definitions (see below). | | labelId | Text | -> | *(optional)* Subscribe only to changes of items in this label. If omitted, subscribe to changes in all labels. | | Result | [cs.NetKit.GoogleNotification](./GoogleNotification.md) | <- | Notification object with `start()`, `stop()`, `expiration`, and `isStarted`. Call `start()` to begin monitoring. | #### Description `.notifier()` creates and returns a [GoogleNotification](./GoogleNotification.md) object allowing you to configure, start, and stop subscriptions to mail change notifications. Two modes are available: - **Push** (webhook): Real-time notifications via HTTP callbacks. Requires a publicly accessible HTTPS endpoint. The webhook URL is derived as `{endPoint}/4dnk-google-notification?state={uuid}`. - **Pull** (polling): Periodic polling of change APIs. No external endpoint needed. Polls the Gmail history API at the configured interval. When a resource changes, user-defined callbacks are dispatched in the 4D worker where the notifier's `start()` function was originally called. The subscription is automatically closed when the notifier object is destroyed. In *param*, you can pass the following properties: | Property | Type | Description | |---|---|---| | endPoint | Text | Webhook URL for **push** mode. If omitted, uses **pull** mode. Must be a publicly accessible HTTPS endpoint. See [endPoint management](./GoogleCalendar.md#endpoint-management). | | onCreate | 4D.Function | Callback for a mail creation *(optional)*. | | onDelete | 4D.Function | Callback for a mail deletion *(optional)*. | | onModify | 4D.Function | Callback for a mail modification *(optional)*. | | timer | Integer | Polling interval in seconds for pull mode (default: 30) *(optional)*. | |topicName|Text|Google Cloud Pub/Sub topic used by the Gmail API to [push mailbox change notifications](https://developers.google.com/workspace/gmail/api/guides/push). The subscription must be created with the delivery type "Push", and the `endPoint` URL must include the "4dnk-google-notification" endpoint: "https://mydomain/4dnk-google-notification". Required when `endPoint` is specified. | Callback functions receive two parameters: | Parameter | Type | Description | |---|---|---| | google | cs.NetKit.Google | The current [Google](./Google.md) object. | | event | Object | Object with `type` (Text: `"mailCreated"`, `"mailDeleted"`, or `"mailModified"`) and `ids` (Collection of affected mail IDs). | #### Returned object The returned [GoogleNotification](./GoogleNotification.md) object contains the following properties: | Property | Type | Description | |---|---|---| | endPoint | Text | Publicly accessible HTTPS endpoint that receives notifications. | | expiration | Text | Expiration date and time (timestamp). Read-only. | | isStarted | Boolean | `true` when notifications are active, `false` when stopped. Read-only. | | start() | 4D.Function | Starts the subscription. Returns a status object (`success`, `statusText`, `errors`). | | stop() | 4D.Function | Stops the subscription. Returns a status object (`success`, `statusText`, `errors`). | | timer | Integer | Interval in seconds between delta query checks (pull mode). | #### Example Mail notifications via webhook (push mode): ```4d var $notif:=$google.mail.notifier({ \ endPoint: "https://myserver.com"; \ onCreate: Formula(ALERT("New mail: "+String($2.ids))); \ onDelete: Formula(ALERT("Mail deleted: "+String($2.ids))) \ }) $status:=$notif.start() ``` ## labelInfo object Several `.GoogleMail` label management methods use a `labelInfo` object, containing the following properties: | Property | Type | Description | |---|---|---| | id | Text | ID of the label. | | name | Text | Display name of the label. **Mandatory** when creating a label. | | messageListVisibility | Text | Visibility in the message list. Can be `"show"` or `"hide"`. | | labelListVisibility | Text | Visibility in the label list. Can be `"labelShow"`, `"labelShowIfUnread"`, or `"labelHide"`. | | [color](https://developers.google.com/gmail/api/reference/rest/v1/users.labels?hl=en#color) | Object | Color for the label (only available for `type="user"` labels). Contains `textColor` (Text, hex) and `backgroundColor` (Text, hex, e.g., `"#000000"`). | | type | Text | Owner type: `"system"` (Gmail-created) or `"user"` (custom, modifiable). | ## Status object Several `GoogleMail` functions return a `status` object containing the following properties: | Property | Type | Description | |---|---|---| | success | Boolean | `true` if the operation was successful. | | statusText | Text | Status message returned by the Gmail server or last error from the 4D error stack. | | errors | Collection | Collection of 4D error items (not returned if a server response is received): `errcode`, `message`, `componentSignature`. | ## See also * [GoogleMailIdList](./GoogleMailIdList.md) * [GoogleNotification](./GoogleNotification.md) * [Google](./Google.md)