mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-06 04:33:34 +00:00
Multiple updates
This commit is contained in:
@ -137,7 +137,7 @@ gam csv UpdateBrowsers.csv gam update browser ~deviceId updatenotes "~~notes~~\n
|
|||||||
```
|
```
|
||||||
gam move browsers ou|org|orgunit <OrgUnitPath>
|
gam move browsers ou|org|orgunit <OrgUnitPath>
|
||||||
((ids <DeviceIDList>) |
|
((ids <DeviceIDList>) |
|
||||||
(queries <QueryBrowserList> [querytime.* <Time>]) |
|
(queries <QueryBrowserList> [querytime<String> <Time>]) |
|
||||||
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
||||||
<FileSelector> | <CSVFileSelector>)
|
<FileSelector> | <CSVFileSelector>)
|
||||||
[batchsize <Integer>]
|
[batchsize <Integer>]
|
||||||
@ -178,7 +178,7 @@ By default, Gam displays the information as an indented list of keys and values:
|
|||||||
```
|
```
|
||||||
gam show browsers
|
gam show browsers
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
@ -205,7 +205,7 @@ The characters following `querytime` can be any combination of lowercase letters
|
|||||||
```
|
```
|
||||||
gam print browsers [todrive <ToDriveAttribute>*]
|
gam print browsers [todrive <ToDriveAttribute>*]
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
[sortheaders] [formatjson [quotechar <Character>]]
|
[sortheaders] [formatjson [quotechar <Character>]]
|
||||||
@ -372,7 +372,7 @@ gam revoke browsertoken <BrowserTokenPermanentID>
|
|||||||
```
|
```
|
||||||
gam show browsertokens
|
gam show browsertokens
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
@ -395,7 +395,7 @@ By default, Gam displays the information as an indented list of keys and values:
|
|||||||
```
|
```
|
||||||
gam print browsertokens [todrive <ToDriveAttribute>*]
|
gam print browsertokens [todrive <ToDriveAttribute>*]
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
[sortheaders] [formatjson [quotechar <Character>]]
|
[sortheaders] [formatjson [quotechar <Character>]]
|
||||||
|
@ -538,7 +538,7 @@ gam <CrOSTypeEntity> print cros
|
|||||||
|
|
||||||
```
|
```
|
||||||
gam print cros [todrive <ToDriveAttribute>*]
|
gam print cros [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
||||||
@ -691,7 +691,7 @@ gam <CrOSTypeEntity> show count
|
|||||||
|
|
||||||
```
|
```
|
||||||
gam print crosactivity [todrive <ToDriveAttribute>*]
|
gam print crosactivity [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
||||||
|
@ -167,7 +167,7 @@ These two/three columns are used to match current company devices against the CS
|
|||||||
If `preview` is specified, the operations that would be performed are previewed but are not performed; use this to test.
|
If `preview` is specified, the operations that would be performed are previewed but are not performed; use this to test.
|
||||||
```
|
```
|
||||||
gam sync devices
|
gam sync devices
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
csvfile <FileName>
|
csvfile <FileName>
|
||||||
(devicetype_column <String>)|(static_devicetype <DeviceType>)
|
(devicetype_column <String>)|(static_devicetype <DeviceType>)
|
||||||
(serialnumber_column <String>)
|
(serialnumber_column <String>)
|
||||||
@ -190,7 +190,7 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
## Print devices
|
## Print devices
|
||||||
```
|
```
|
||||||
gam print devices [todrive <ToDriveAttribute>*]
|
gam print devices [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
||||||
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
[all|company|personal|nocompanydevices|nopersonaldevices]
|
[all|company|personal|nocompanydevices|nopersonaldevices]
|
||||||
@ -266,7 +266,7 @@ gam info deviceuser <DeviceUserEntity>
|
|||||||
```
|
```
|
||||||
gam print deviceusers [todrive <ToDriveAttribute>*]
|
gam print deviceusers [todrive <ToDriveAttribute>*]
|
||||||
[select <DeviceID>]
|
[select <DeviceID>]
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
|
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
|
||||||
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
|
@ -10,6 +10,27 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
|
|||||||
|
|
||||||
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation
|
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation
|
||||||
|
|
||||||
|
Updated `gam <UserTypeEntity> import|insert message` to allow `replace <Tag> <UserReplacement>` as documented.
|
||||||
|
|
||||||
|
### 6.65.05
|
||||||
|
|
||||||
|
Updated `gam info users <UserTypeEntity>` to make option `grouptree` effective when used
|
||||||
|
with option `formatjson`.
|
||||||
|
|
||||||
|
Added option `[formatjson [quotechar <Character>]]]`
|
||||||
|
to these commands so that event details are displayed in CSV format.
|
||||||
|
```
|
||||||
|
gam print|show grouptree <GroupEntity>
|
||||||
|
gam <UserTypeEntity> print|show grouptree
|
||||||
|
```
|
||||||
|
|
||||||
|
Added option `querytime<String> <Date>` to all commands that process messages.
|
||||||
|
For example, you can identify all messages within a particular time period, in this case, all messages unread
|
||||||
|
in the last 30 days.
|
||||||
|
```
|
||||||
|
gam user user@domain.com print messages querytime30d -30d query "after:#querytime30d# is:unread"
|
||||||
|
```
|
||||||
|
|
||||||
### 6.65.04
|
### 6.65.04
|
||||||
|
|
||||||
Fixed bug where license SKU `1010020031` (Google Workspace Frontline Standard) was improperly entered making it unusable;
|
Fixed bug where license SKU `1010020031` (Google Workspace Frontline Standard) was improperly entered making it unusable;
|
||||||
|
@ -334,7 +334,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||||
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
|
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
|
||||||
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||||
GAMADV-XTD3 6.65.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 6.65.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.10.8 64-bit final
|
Python 3.10.8 64-bit final
|
||||||
MacOS High Sierra 10.13.6 x86_64
|
MacOS High Sierra 10.13.6 x86_64
|
||||||
@ -1002,7 +1002,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
|
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
|
||||||
C:\GAMADV-XTD3>gam version
|
C:\GAMADV-XTD3>gam version
|
||||||
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
||||||
GAMADV-XTD3 6.65.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 6.65.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.0 64-bit final
|
Python 3.12.0 64-bit final
|
||||||
Windows-10-10.0.17134 AMD64
|
Windows-10-10.0.17134 AMD64
|
||||||
|
@ -100,7 +100,7 @@ By default, Gam displays the information as an indented list of keys and values.
|
|||||||
## Print mobile devices
|
## Print mobile devices
|
||||||
```
|
```
|
||||||
gam print mobile [todrive <ToDriveAttribute>*]
|
gam print mobile [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryMobile>)|(queries <QueryMobileList>) (querytime.* <Time>)*]
|
[(query <QueryMobile>)|(queries <QueryMobileList>) (querytime<String> <Time>)*]
|
||||||
[orderby <MobileOrderByFieldName> [ascending|descending]]
|
[orderby <MobileOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
||||||
[delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
[delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
||||||
|
@ -173,6 +173,22 @@
|
|||||||
(gcsdoc|gcshtml <StorageBucketObjectName>)|
|
(gcsdoc|gcshtml <StorageBucketObjectName>)|
|
||||||
(emlfile <FileName>)
|
(emlfile <FileName>)
|
||||||
```
|
```
|
||||||
|
## Message queries with dates
|
||||||
|
```
|
||||||
|
query <QueryGmail> [querytime<String> <Date>]*
|
||||||
|
```
|
||||||
|
* `query "xxx"` - ` xxx` is appended to the current query; you can repeat the query argument to build up a longer query.
|
||||||
|
|
||||||
|
Use the `querytime<String> <Date>` option to allow dates, usually relative, to be substituted into the `query <QueryGmail>` option.
|
||||||
|
The `querytime<String> <Date>` value replaces the string `#querytime<String>#` in any queries.
|
||||||
|
The characters following `querytime` can be any combination of lowercase letters and numbers. This is most useful in scripts
|
||||||
|
where you can specify a relative date without having to change the script.
|
||||||
|
|
||||||
|
For example, query for messages from moree than 5 years ago:
|
||||||
|
```
|
||||||
|
querytime5years -5y query "before:#querytime5years#"
|
||||||
|
```
|
||||||
|
|
||||||
## Subject and label queries
|
## Subject and label queries
|
||||||
Using a query to select messages by subject or label requires some attention in order to achieve the desired effect.
|
Using a query to select messages by subject or label requires some attention in order to achieve the desired effect.
|
||||||
* https://support.google.com/mail/answer/7190
|
* https://support.google.com/mail/answer/7190
|
||||||
@ -316,7 +332,7 @@ Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg
|
|||||||
## Archive messages
|
## Archive messages
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> archive messages <GroupItem>
|
gam <UserTypeEntity> archive messages <GroupItem>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -328,10 +344,10 @@ See below for message selection.
|
|||||||
Export messages in EML format.
|
Export messages in EML format.
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> export message|messages
|
gam <UserTypeEntity> export message|messages
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
||||||
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
gam <UserTypeEntity> export thread|threads
|
gam <UserTypeEntity> export thread|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
||||||
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -354,11 +370,11 @@ See below for message selection.
|
|||||||
## Forward messages/threads
|
## Forward messages/threads
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
||||||
[subject <String>]
|
[subject <String>]
|
||||||
gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
||||||
[subject <String>]
|
[subject <String>]
|
||||||
```
|
```
|
||||||
@ -372,27 +388,27 @@ See below for message selection.
|
|||||||
## Manage messages/threads
|
## Manage messages/threads
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> delete messages|threads
|
gam <UserTypeEntity> delete messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> modify messages|threads
|
gam <UserTypeEntity> modify messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
||||||
(addlabel <LabelName>)* (removelabel <LabelName>)*
|
(addlabel <LabelName>)* (removelabel <LabelName>)*
|
||||||
gam <UserTypeEntity> spam messages|threads
|
gam <UserTypeEntity> spam messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> trash messages|threads
|
gam <UserTypeEntity> trash messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> untrash messages|threads
|
gam <UserTypeEntity> untrash messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
||||||
```
|
```
|
||||||
### Manage a specific set of messages
|
### Manage a specific set of messages
|
||||||
* `ids <MessageIDEntity>` - A list of message ids
|
* `ids <MessageIDEntity>` - A list of message ids
|
||||||
|
|
||||||
### Manage a selected set of messages
|
### Manage a selected set of messages
|
||||||
* `((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
|
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
|
||||||
* `max_to_xxx` - Limit the number of messages that will be processed; use a value of 0 for no limit
|
* `max_to_xxx` - Limit the number of messages that will be processed; use a value of 0 for no limit
|
||||||
* `doit` - No messages are processed unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
|
* `doit` - No messages are processed unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
|
||||||
|
|
||||||
@ -439,7 +455,7 @@ gam config auto_batch_min 1 groups_inde EastOffice delete message query "rfc822m
|
|||||||
## Display messages/threads
|
## Display messages/threads
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> show messages|threads
|
gam <UserTypeEntity> show messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])*
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
|
||||||
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
[countsonly|positivecountsonly] [useronly]
|
[countsonly|positivecountsonly] [useronly]
|
||||||
@ -449,7 +465,7 @@ gam <UserTypeEntity> show messages|threads
|
|||||||
[saveattachments [attachmentnamepattern <RegularExpression>]]
|
[saveattachments [attachmentnamepattern <RegularExpression>]]
|
||||||
[targetfolder <FilePath>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [overwrite [<Boolean>]]
|
||||||
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])*
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
|
||||||
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
[countsonly|positivecountsonly] [useronly]
|
[countsonly|positivecountsonly] [useronly]
|
||||||
@ -467,7 +483,7 @@ By default, Gam displays all messages.
|
|||||||
* `ids <MessageIDEntity>` - A list of message ids
|
* `ids <MessageIDEntity>` - A list of message ids
|
||||||
|
|
||||||
## Display a selected set of messages
|
## Display a selected set of messages
|
||||||
* `((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
|
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
|
||||||
* `max_to_xxx` - Limit the number of messages that will be displayed
|
* `max_to_xxx` - Limit the number of messages that will be displayed
|
||||||
* `includespamtrash` - Include messages in the Spam and Trash folders
|
* `includespamtrash` - Include messages in the Spam and Trash folders
|
||||||
* `labelmatchpattern <RegularExpression>` - Only display messages with some label that matches `<RegularExpression>`
|
* `labelmatchpattern <RegularExpression>` - Only display messages with some label that matches `<RegularExpression>`
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
Print the current version of Gam with details
|
Print the current version of Gam with details
|
||||||
```
|
```
|
||||||
gam version
|
gam version
|
||||||
GAMADV-XTD3 6.65.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 6.65.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.0 64-bit final
|
Python 3.12.0 64-bit final
|
||||||
MacOS Monterey 12.7 x86_64
|
MacOS Monterey 12.7 x86_64
|
||||||
@ -16,7 +16,7 @@ Time: 2023-06-02T21:10:00-07:00
|
|||||||
Print the current version of Gam with details and time offset information
|
Print the current version of Gam with details and time offset information
|
||||||
```
|
```
|
||||||
gam version timeoffset
|
gam version timeoffset
|
||||||
GAMADV-XTD3 6.65.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 6.65.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.0 64-bit final
|
Python 3.12.0 64-bit final
|
||||||
MacOS Monterey 12.7 x86_64
|
MacOS Monterey 12.7 x86_64
|
||||||
@ -28,7 +28,7 @@ Your system time differs from www.googleapis.com by less than 1 second
|
|||||||
Print the current version of Gam with extended details and SSL information
|
Print the current version of Gam with extended details and SSL information
|
||||||
```
|
```
|
||||||
gam version extended
|
gam version extended
|
||||||
GAMADV-XTD3 6.65.04 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 6.65.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.0 64-bit final
|
Python 3.12.0 64-bit final
|
||||||
MacOS Monterey 12.7 x86_64
|
MacOS Monterey 12.7 x86_64
|
||||||
@ -65,7 +65,7 @@ MacOS High Sierra 10.13.6 x86_64
|
|||||||
Path: /Users/Admin/bin/gamadv-xtd3
|
Path: /Users/Admin/bin/gamadv-xtd3
|
||||||
Version Check:
|
Version Check:
|
||||||
Current: 5.35.08
|
Current: 5.35.08
|
||||||
Latest: 6.65.04
|
Latest: 6.65.05
|
||||||
echo $?
|
echo $?
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
@ -73,7 +73,7 @@ echo $?
|
|||||||
Print the current version number without details
|
Print the current version number without details
|
||||||
```
|
```
|
||||||
gam version simple
|
gam version simple
|
||||||
6.65.04
|
6.65.05
|
||||||
```
|
```
|
||||||
In Linux/MacOS you can do:
|
In Linux/MacOS you can do:
|
||||||
```
|
```
|
||||||
@ -83,7 +83,7 @@ echo $VER
|
|||||||
Print the current version of Gam and address of this Wiki
|
Print the current version of Gam and address of this Wiki
|
||||||
```
|
```
|
||||||
gam help
|
gam help
|
||||||
GAM 6.65.04 - https://github.com/taers232c/GAMADV-XTD3
|
GAM 6.65.05 - https://github.com/taers232c/GAMADV-XTD3
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.0 64-bit final
|
Python 3.12.0 64-bit final
|
||||||
MacOS Monterey 12.7 x86_64
|
MacOS Monterey 12.7 x86_64
|
||||||
|
@ -1906,7 +1906,7 @@ gam delete browser <DeviceID>
|
|||||||
gam update browser <BrowserEntity> <BrowserAttibute>+
|
gam update browser <BrowserEntity> <BrowserAttibute>+
|
||||||
gam move browsers ou|org|orgunit <OrgUnitPath>
|
gam move browsers ou|org|orgunit <OrgUnitPath>
|
||||||
((ids <DeviceIDList>) |
|
((ids <DeviceIDList>) |
|
||||||
(queries <QueryBrowserList> [querytime.* <Time>]) |
|
(queries <QueryBrowserList> [querytime<String> <Time>]) |
|
||||||
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
(browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
||||||
<FileSelector> | <CSVFileSelector>)
|
<FileSelector> | <CSVFileSelector>)
|
||||||
[batchsize <Integer>]
|
[batchsize <Integer>]
|
||||||
@ -1916,13 +1916,13 @@ gam info browser <DeviceID>
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
gam show browsers
|
gam show browsers
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam print browsers [todrive <ToDriveAttribute>*]
|
gam print browsers [todrive <ToDriveAttribute>*]
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser>)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
[orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
[basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
[sortheaders]
|
[sortheaders]
|
||||||
@ -1950,13 +1950,13 @@ gam revoke browsertoken <BrowserTokenPermanentID>
|
|||||||
|
|
||||||
gam show browsertokens
|
gam show browsertokens
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam print browsertokens [todrive <ToDriveAttribute>*]
|
gam print browsertokens [todrive <ToDriveAttribute>*]
|
||||||
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)))
|
([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken>)|(queries <QueryBrowserTokenList>)))
|
||||||
[querytime.* <Time>]
|
[querytime<String> <Time>]
|
||||||
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
[orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
[allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
[sortheaders]
|
[sortheaders]
|
||||||
@ -2253,13 +2253,13 @@ gam <CrOSTypeEntity> info
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
|
|
||||||
Print fields for selected CrOS devices; use these options to select CrOS devices:
|
Print fields for selected CrOS devices; use these options to select CrOS devices:
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
If none of these options are chosen, all CrOS devices are selected.
|
If none of these options are chosen, all CrOS devices are selected.
|
||||||
|
|
||||||
gam print cros [todrive <ToDriveAttribute>*]
|
gam print cros [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
||||||
@ -2315,13 +2315,13 @@ Show count of CrOS devices
|
|||||||
gam <CrOSTypeEntity> show count
|
gam <CrOSTypeEntity> show count
|
||||||
|
|
||||||
Print activity for selected CrOS devices; use these options to select CrOS devices:
|
Print activity for selected CrOS devices; use these options to select CrOS devices:
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
If none of these options are chosen, all CrOS devices are selected.
|
If none of these options are chosen, all CrOS devices are selected.
|
||||||
|
|
||||||
gam print crosactivity [todrive <ToDriveAttribute>*]
|
gam print crosactivity [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
[(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
[(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
(cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
[orderby <CrOSOrderByFieldName> [ascending|descending]]
|
||||||
@ -3593,7 +3593,9 @@ gam print groups [todrive <ToDriveAttribute>*]
|
|||||||
|
|
||||||
gam print grouptree <GroupEntity> [todrive <ToDriveAttribute>*]
|
gam print grouptree <GroupEntity> [todrive <ToDriveAttribute>*]
|
||||||
[showparentsaslist [<Boolean>]] [delimiter <Character>]
|
[showparentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
|
[formatjson [quotechar <Character>]]
|
||||||
gam show grouptree <GroupEntity>
|
gam show grouptree <GroupEntity>
|
||||||
|
[formatjson]
|
||||||
|
|
||||||
<MembersFieldName> ::=
|
<MembersFieldName> ::=
|
||||||
delivery|deliverysettings|
|
delivery|deliverysettings|
|
||||||
@ -3807,7 +3809,7 @@ gam wipe device <DeviceEntity> [removeresetlock] [doit]
|
|||||||
|
|
||||||
gam sync devices
|
gam sync devices
|
||||||
<CSVFileSelector>
|
<CSVFileSelector>
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
(devicetype_column <String>)|(static_devicetype <DeviceType>)
|
(devicetype_column <String>)|(static_devicetype <DeviceType>)
|
||||||
(serialnumber_column <String>)
|
(serialnumber_column <String>)
|
||||||
[assettag_column <String>]
|
[assettag_column <String>]
|
||||||
@ -3820,7 +3822,7 @@ gam info device <DeviceEntity>
|
|||||||
[nodeviceusers]
|
[nodeviceusers]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam print devices [todrive <ToDriveAttribute>*]
|
gam print devices [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
<DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
||||||
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
[all|company|personal|nocompanydevices|nopersonaldevices]
|
[all|company|personal|nocompanydevices|nopersonaldevices]
|
||||||
@ -3845,7 +3847,7 @@ gam info deviceuser <DeviceUserEntity>
|
|||||||
[formatjson]
|
[formatjson]
|
||||||
gam print deviceusers [todrive <ToDriveAttribute>*]
|
gam print deviceusers [todrive <ToDriveAttribute>*]
|
||||||
[select <DeviceID>]
|
[select <DeviceID>]
|
||||||
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
[(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
|
<DeviceUserFieldName>* [fields <DeviceUserFieldNameList>]
|
||||||
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
[orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
@ -3986,7 +3988,7 @@ gam info mobile <MobileEntity>
|
|||||||
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam print mobile [todrive <ToDriveAttribute>*]
|
gam print mobile [todrive <ToDriveAttribute>*]
|
||||||
[(query <QueryMobile>)|(queries <QueryMobileList>) (querytime.* <Time>)*]
|
[(query <QueryMobile>)|(queries <QueryMobileList>) (querytime<String> <Time>)*]
|
||||||
[orderby <MobileOrderByFieldName> [ascending|descending]]
|
[orderby <MobileOrderByFieldName> [ascending|descending]]
|
||||||
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
[basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
||||||
[delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
[delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
||||||
@ -6865,43 +6867,43 @@ gam <UserTypeEntity> insert message
|
|||||||
[deleted [<Boolean>]]
|
[deleted [<Boolean>]]
|
||||||
|
|
||||||
gam <UserTypeEntity> archive messages <GroupItem>
|
gam <UserTypeEntity> archive messages <GroupItem>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> delete messages|threads
|
gam <UserTypeEntity> delete messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> modify messages|threads
|
gam <UserTypeEntity> modify messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
||||||
(addlabel <LabelName>)* (removelabel <LabelName>)*
|
(addlabel <LabelName>)* (removelabel <LabelName>)*
|
||||||
gam <UserTypeEntity> spam messages|threads
|
gam <UserTypeEntity> spam messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> trash messages|threads
|
gam <UserTypeEntity> trash messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
||||||
gam <UserTypeEntity> untrash messages|threads
|
gam <UserTypeEntity> untrash messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
||||||
|
|
||||||
gam <UserTypeEntity> export message|messages
|
gam <UserTypeEntity> export message|messages
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
||||||
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
gam <UserTypeEntity> export thread|threads
|
gam <UserTypeEntity> export thread|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
||||||
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
|
|
||||||
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
||||||
[subject <String>] [altcharset <String>]
|
[subject <String>] [altcharset <String>]
|
||||||
gam <UserTypeEntity> forward thread|thtreads recipient|to <RecipientEntity>
|
gam <UserTypeEntity> forward thread|thtreads recipient|to <RecipientEntity>
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
|
||||||
quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
||||||
[subject <String>] [altcharset <String>]
|
[subject <String>] [altcharset <String>]
|
||||||
|
|
||||||
gam <UserTypeEntity> show messages|threads
|
gam <UserTypeEntity> show messages|threads
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])*
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
|
||||||
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
[countsonly|positivecountsonly] [useronly]
|
[countsonly|positivecountsonly] [useronly]
|
||||||
@ -6911,7 +6913,7 @@ gam <UserTypeEntity> show messages|threads
|
|||||||
[saveattachments [attachmentnamepattern <RegularExpression>]]
|
[saveattachments [attachmentnamepattern <RegularExpression>]]
|
||||||
[targetfolder <FilePath>] [overwrite [<Boolean>]]
|
[targetfolder <FilePath>] [overwrite [<Boolean>]]
|
||||||
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
|
||||||
(((query <QueryGmail>) (matchlabel <LabelName>) [or|and])*
|
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
|
||||||
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
[labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
[countsonly|positivecountsonly] [useronly]
|
[countsonly|positivecountsonly] [useronly]
|
||||||
@ -7014,9 +7016,11 @@ gam <UserTypeEntity> print grouptree [todrive <ToDriveAttribute>*]
|
|||||||
[(domain <DomainName>)|(customerid <CustomerID>)]
|
[(domain <DomainName>)|(customerid <CustomerID>)]
|
||||||
[roles <GroupRoleList>]
|
[roles <GroupRoleList>]
|
||||||
[showparentsaslist [<Boolean>]] [delimiter <Character>]
|
[showparentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
|
[formatjson [quotechar <Character>]]
|
||||||
gam <UserTypeEntity> show grouptree
|
gam <UserTypeEntity> show grouptree
|
||||||
[(domain <DomainName>)|(customerid <CustomerID>)]
|
[(domain <DomainName>)|(customerid <CustomerID>)]
|
||||||
[roles <GroupRoleList>]
|
[roles <GroupRoleList>]
|
||||||
|
[formatjson]
|
||||||
gam <UserTypeEntity> print groupslist [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print groupslist [todrive <ToDriveAttribute>*]
|
||||||
[(domain <DomainName>)|(customerid <CustomerID>)]
|
[(domain <DomainName>)|(customerid <CustomerID>)]
|
||||||
[delimiter <Character>] [quotechar <Character>]
|
[delimiter <Character>] [quotechar <Character>]
|
||||||
|
@ -1,3 +1,30 @@
|
|||||||
|
7.00.00
|
||||||
|
|
||||||
|
Merged GAM-Team version
|
||||||
|
|
||||||
|
6.65.05
|
||||||
|
|
||||||
|
Updated `gam info users <UserTypeEntity>` to make option `grouptree` effective when used
|
||||||
|
with option `formatjson`.
|
||||||
|
|
||||||
|
Added option `[formatjson [quotechar <Character>]]]`
|
||||||
|
to these commands so that event details are displayed in CSV format.
|
||||||
|
```
|
||||||
|
gam print|show grouptree <GroupEntity>
|
||||||
|
gam <UserTypeEntity> print|show grouptree
|
||||||
|
```
|
||||||
|
|
||||||
|
Added option `querytime<String> <Date>` to all commands that process messages.
|
||||||
|
For example, you can identify all messages within a particular time period, in this case, all messages unread
|
||||||
|
in the last 30 days.
|
||||||
|
```
|
||||||
|
gam user user@domain.com print messages querytime30d -30d query "after:#querytime30d# is:unread"
|
||||||
|
```
|
||||||
|
|
||||||
|
Updated `gam <UserTypeEntity> import|insert message` to allow `replace <Tag> <UserReplacement>` as documented.
|
||||||
|
|
||||||
|
Updated non-owner permission handling in `gam <UserTypeEntity> copy|move drivefile`.
|
||||||
|
|
||||||
6.65.04
|
6.65.04
|
||||||
|
|
||||||
Fixed bug where license SKU `1010020031` (Google Workspace Frontline Standard) was improperly entered making it unusable;
|
Fixed bug where license SKU `1010020031` (Google Workspace Frontline Standard) was improperly entered making it unusable;
|
||||||
@ -7,10 +34,6 @@ Added support for Google Workspace Additional Storage.
|
|||||||
* ProductID - 101043
|
* ProductID - 101043
|
||||||
* SKUID - 1010430001 | gwas | plusstorage
|
* SKUID - 1010430001 | gwas | plusstorage
|
||||||
|
|
||||||
7.00.00
|
|
||||||
|
|
||||||
Merged GAM-Team version
|
|
||||||
|
|
||||||
6.65.03
|
6.65.03
|
||||||
|
|
||||||
Fixed bug in commands that display calendar events where event start and end times were not properly displayed
|
Fixed bug in commands that display calendar events where event start and end times were not properly displayed
|
||||||
|
@ -2191,6 +2191,7 @@ def getJSON(deleteFields):
|
|||||||
if not Cmd.ArgumentsRemaining():
|
if not Cmd.ArgumentsRemaining():
|
||||||
missingArgumentExit(Cmd.OB_JSON_DATA)
|
missingArgumentExit(Cmd.OB_JSON_DATA)
|
||||||
argstr = Cmd.Current()
|
argstr = Cmd.Current()
|
||||||
|
# argstr = Cmd.Current().replace(r'\\"', r'\"')
|
||||||
Cmd.Advance()
|
Cmd.Advance()
|
||||||
try:
|
try:
|
||||||
if encoding == UTF8:
|
if encoding == UTF8:
|
||||||
@ -4509,17 +4510,26 @@ def runSqliteQuery(db_file, query):
|
|||||||
return curr.fetchone()[0]
|
return curr.fetchone()[0]
|
||||||
|
|
||||||
def refreshCredentialsWithReauth(credentials):
|
def refreshCredentialsWithReauth(credentials):
|
||||||
|
def gcloudError():
|
||||||
|
writeStderr(f'Failed to run gcloud as {admin_email}. Please make sure it\'s setup')
|
||||||
|
e = Msg.REAUTHENTICATION_IS_NEEDED
|
||||||
|
handleOAuthTokenError(e, False)
|
||||||
|
|
||||||
writeStderr(Msg.CALLING_GCLOUD_FOR_REAUTH)
|
writeStderr(Msg.CALLING_GCLOUD_FOR_REAUTH)
|
||||||
if 'termios' in sys.modules:
|
if 'termios' in sys.modules:
|
||||||
old_settings = termios.tcgetattr(sys.stdin)
|
old_settings = termios.tcgetattr(sys.stdin)
|
||||||
|
admin_email = _getAdminEmail()
|
||||||
# First makes sure gcloud has a valid access token and thus
|
# First makes sure gcloud has a valid access token and thus
|
||||||
# should also have a valid RAPT token
|
# should also have a valid RAPT token
|
||||||
try:
|
try:
|
||||||
|
devnull = open(os.devnull, 'w', encoding=UTF8)
|
||||||
subprocess.run(['gcloud',
|
subprocess.run(['gcloud',
|
||||||
'auth',
|
'auth',
|
||||||
'print-identity-token',
|
'print-identity-token',
|
||||||
'--no-user-output-enabled'],
|
'--no-user-output-enabled'],
|
||||||
|
stderr=devnull,
|
||||||
check=False)
|
check=False)
|
||||||
|
devnull.close()
|
||||||
# now determine gcloud's config path and token file
|
# now determine gcloud's config path and token file
|
||||||
gcloud_path_result = subprocess.run(['gcloud',
|
gcloud_path_result = subprocess.run(['gcloud',
|
||||||
'info',
|
'info',
|
||||||
@ -4532,14 +4542,14 @@ def refreshCredentialsWithReauth(credentials):
|
|||||||
printBlankLine()
|
printBlankLine()
|
||||||
raise KeyboardInterrupt from e
|
raise KeyboardInterrupt from e
|
||||||
token_path = gcloud_path_result.stdout.decode().strip()
|
token_path = gcloud_path_result.stdout.decode().strip()
|
||||||
|
if not token_path:
|
||||||
|
gcloudError()
|
||||||
token_file = f'{token_path}/access_tokens.db'
|
token_file = f'{token_path}/access_tokens.db'
|
||||||
admin_email = _getAdminEmail()
|
|
||||||
try:
|
try:
|
||||||
credentials._rapt_token = runSqliteQuery(token_file,
|
credentials._rapt_token = runSqliteQuery(token_file,
|
||||||
f'SELECT rapt_token FROM access_tokens WHERE account_id = "{admin_email}"')
|
f'SELECT rapt_token FROM access_tokens WHERE account_id = "{admin_email}"')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
systemErrorExit(SYSTEM_ERROR_RC,
|
gcloudError()
|
||||||
f'Failed to run gcloud as {admin_email}. Please make sure it\'s setup')
|
|
||||||
if not credentials._rapt_token:
|
if not credentials._rapt_token:
|
||||||
systemErrorExit(SYSTEM_ERROR_RC,
|
systemErrorExit(SYSTEM_ERROR_RC,
|
||||||
'Failed to retrieve reauth token from gcloud. You may need to wait until gcloud is also prompted for reauth.')
|
'Failed to retrieve reauth token from gcloud. You may need to wait until gcloud is also prompted for reauth.')
|
||||||
@ -4792,7 +4802,7 @@ def checkGDataError(e, service):
|
|||||||
reason = error[0].get('reason', '')
|
reason = error[0].get('reason', '')
|
||||||
body = error[0].get('body', '').decode(UTF8)
|
body = error[0].get('body', '').decode(UTF8)
|
||||||
# First check for errors that need special handling
|
# First check for errors that need special handling
|
||||||
if reason in ['Token invalid - Invalid token: Stateless token expired', 'Token invalid - Invalid token: Token not found']:
|
if reason in ['Token invalid - Invalid token: Stateless token expired', 'Token invalid - Invalid token: Token not found', 'gone']:
|
||||||
keep_domain = service.domain
|
keep_domain = service.domain
|
||||||
getGDataOAuthToken(service)
|
getGDataOAuthToken(service)
|
||||||
service.domain = keep_domain
|
service.domain = keep_domain
|
||||||
@ -23302,7 +23312,7 @@ CROS_INDEXED_TITLES = ['activeTimeRanges', 'recentUsers', 'deviceFiles',
|
|||||||
'cpuStatusReports', 'diskVolumeReports', 'lastKnownNetwork', 'screenshotFiles', 'systemRamFreeReports']
|
'cpuStatusReports', 'diskVolumeReports', 'lastKnownNetwork', 'screenshotFiles', 'systemRamFreeReports']
|
||||||
|
|
||||||
# gam print cros [todrive <ToDriveAttribute>*]
|
# gam print cros [todrive <ToDriveAttribute>*]
|
||||||
# [(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
# [(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
# [(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
# [(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
# (cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
# (cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
# gam print cros [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
|
# gam print cros [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
|
||||||
@ -23628,7 +23638,7 @@ CROS_ACTIVITY_LIST_FIELDS_CHOICE_MAP = {
|
|||||||
CROS_ACTIVITY_TIME_OBJECTS = {'createTime'}
|
CROS_ACTIVITY_TIME_OBJECTS = {'createTime'}
|
||||||
|
|
||||||
# gam print crosactivity [todrive <ToDriveAttribute>*]
|
# gam print crosactivity [todrive <ToDriveAttribute>*]
|
||||||
# [(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime.* <Time>]
|
# [(query <QueryCrOS>)|(queries <QueryCrOSList>) [querytime<String> <Time>]
|
||||||
# [(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
# [(limittoou|cros_ou <OrgUnitItem>)|(cros_ou_and_children <OrgUnitItem>)|
|
||||||
# (cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
# (cros_ous <OrgUnitList>)|(cros_ous_and_children <OrgUnitList>)]]
|
||||||
# gam print crosactivity [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
|
# gam print crosactivity [todrive <ToDriveAttribute>*] select <CrOSTypeEntity>
|
||||||
@ -24215,7 +24225,7 @@ def doInfoBrowsers():
|
|||||||
|
|
||||||
# gam move browsers ou|org|orgunit <OrgUnitPath>
|
# gam move browsers ou|org|orgunit <OrgUnitPath>
|
||||||
# ((ids <DeviceIDList>) |
|
# ((ids <DeviceIDList>) |
|
||||||
# (queries <QueryBrowserList> [querytime.* <Time>]) |
|
# (queries <QueryBrowserList> [querytime<String> <Time>]) |
|
||||||
# (browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
# (browserou <OrgUnitItem>) | (browserous <OrgUnitList>) |
|
||||||
# <FileSelector> | <CSVFileSelector>)
|
# <FileSelector> | <CSVFileSelector>)
|
||||||
# [batchsize <Integer>]
|
# [batchsize <Integer>]
|
||||||
@ -24354,13 +24364,13 @@ BROWSER_ORDERBY_CHOICE_MAP = {
|
|||||||
|
|
||||||
# gam show browsers
|
# gam show browsers
|
||||||
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
# [querytime.* <Time>]
|
# [querytime<String> <Time>]
|
||||||
# [orderby <BrowserOrderByFieldName> [ascending|descending]]
|
# [orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
# [basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
# [basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
# [formatjson]
|
# [formatjson]
|
||||||
# gam print browsers [todrive <ToDriveAttribute>*]
|
# gam print browsers [todrive <ToDriveAttribute>*]
|
||||||
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowser)|(queries <QueryBrowserList>))|(select <BrowserEntity>))
|
||||||
# [querytime.* <Time>]
|
# [querytime<String> <Time>]
|
||||||
# [orderby <BrowserOrderByFieldName> [ascending|descending]]
|
# [orderby <BrowserOrderByFieldName> [ascending|descending]]
|
||||||
# [basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
# [basic|full|allfields|annotated] <BrowserFieldName>* [fields <BrowserFieldNameList>]
|
||||||
# [sortheaders] [formatjson [quotechar <Character>]]
|
# [sortheaders] [formatjson [quotechar <Character>]]
|
||||||
@ -24556,13 +24566,13 @@ BROWSER_TOKEN_FIELDS_CHOICE_MAP = {
|
|||||||
|
|
||||||
# gam show browsertokens
|
# gam show browsertokens
|
||||||
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
||||||
# [querytime.* <Time>]
|
# [querytime<String> <Time>]
|
||||||
# [orderby <BrowserTokenFieldName> [ascending|descending]]
|
# [orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
# [allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
# [allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
# [formatjson]
|
# [formatjson]
|
||||||
# gam print browsertokens [todrive <ToDriveAttribute>*]
|
# gam print browsertokens [todrive <ToDriveAttribute>*]
|
||||||
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
# ([ou|org|orgunit|browserou <OrgUnitPath>] [(query <QueryBrowserToken)|(queries <QueryBrowserTokenList>)))
|
||||||
# [querytime.* <Time>]
|
# [querytime<String> <Time>]
|
||||||
# [orderby <BrowserTokenFieldName> [ascending|descending]]
|
# [orderby <BrowserTokenFieldName> [ascending|descending]]
|
||||||
# [allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
# [allfields] <BrowserTokenFieldName>* [fields <BrowserTokenFieldNameList>]
|
||||||
# [sortheaders] [formatjson [quotechar <Character>]]
|
# [sortheaders] [formatjson [quotechar <Character>]]
|
||||||
@ -26677,7 +26687,7 @@ DEVICE_MISSING_ACTION_MAP = {
|
|||||||
|
|
||||||
# gam sync devices
|
# gam sync devices
|
||||||
# <CSVFileSelector>
|
# <CSVFileSelector>
|
||||||
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
# (devicetype_column <String>)|(static_devicetype <DeviceType>)
|
# (devicetype_column <String>)|(static_devicetype <DeviceType>)
|
||||||
# (serialnumber_column <String>)
|
# (serialnumber_column <String>)
|
||||||
# [assettag_column <String>]
|
# [assettag_column <String>]
|
||||||
@ -26976,7 +26986,7 @@ DEVICE_ORDERBY_CHOICE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# gam print devices [todrive <ToDriveAttribute>*]
|
# gam print devices [todrive <ToDriveAttribute>*]
|
||||||
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
# <DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
# <DeviceFieldName>* [fields <DeviceFieldNameList>] [userfields <DeviceUserFieldNameList>]
|
||||||
# [orderby <DeviceOrderByFieldName> [ascending|descending]]
|
# [orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
# [all|company|personal|nocompanydevices|nopersonaldevices]
|
# [all|company|personal|nocompanydevices|nopersonaldevices]
|
||||||
@ -27163,7 +27173,7 @@ def doInfoCIDeviceUser():
|
|||||||
|
|
||||||
# gam print deviceusers [todrive <ToDriveAttribute>*]
|
# gam print deviceusers [todrive <ToDriveAttribute>*]
|
||||||
# [select <DeviceID>]
|
# [select <DeviceID>]
|
||||||
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime.* <Time>)*]
|
# [(query <QueryDevice>)|(queries <QueryDeviceList>) (querytime<String> <Time>)*]
|
||||||
# <DeviceUserFieldName>* [fields <DevieUserFieldNameList>]
|
# <DeviceUserFieldName>* [fields <DevieUserFieldNameList>]
|
||||||
# [orderby <DeviceOrderByFieldName> [ascending|descending]]
|
# [orderby <DeviceOrderByFieldName> [ascending|descending]]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [formatjson [quotechar <Character>]]
|
||||||
@ -28948,7 +28958,7 @@ MOBILE_ORDERBY_CHOICE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# gam print mobile [todrive <ToDriveAttribute>*]
|
# gam print mobile [todrive <ToDriveAttribute>*]
|
||||||
# [(query <QueryMobile>)|(queries <QueryMobileList>) [querytime.* <Time>]]
|
# [(query <QueryMobile>)|(queries <QueryMobileList>) [querytime<String> <Time>]]
|
||||||
# [orderby <MobileOrderByFieldName> [ascending|descending]]
|
# [orderby <MobileOrderByFieldName> [ascending|descending]]
|
||||||
# [basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
# [basic|full|allfields] <MobileFieldName>* [fields <MobileFieldNameList>]
|
||||||
# [delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
# [delimiter <Character>] [appslimit <Number>] [oneappperrow] [listlimit <Number>]
|
||||||
@ -32006,53 +32016,68 @@ def doShowGroupMembers():
|
|||||||
if checkGroupMatchPatterns(groupEmail, group, matchPatterns):
|
if checkGroupMatchPatterns(groupEmail, group, matchPatterns):
|
||||||
_showGroup(groupEmail, 0)
|
_showGroup(groupEmail, 0)
|
||||||
|
|
||||||
|
def getGroupParents(cd, groupParents, groupEmail, groupName, kwargs):
|
||||||
|
groupParents[groupEmail] = {'name': groupName, 'parents': []}
|
||||||
|
_setUserGroupArgs(groupEmail, kwargs)
|
||||||
|
try:
|
||||||
|
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
|
||||||
|
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
|
||||||
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
|
orderBy='email', fields='nextPageToken,groups(email,name)', **kwargs)
|
||||||
|
for parentGroup in entityList:
|
||||||
|
groupParents[groupEmail]['parents'].append(parentGroup['email'])
|
||||||
|
if parentGroup['email'] not in groupParents:
|
||||||
|
getGroupParents(cd, groupParents, parentGroup['email'], parentGroup['name'], kwargs)
|
||||||
|
except (GAPI.invalidMember, GAPI.invalidInput):
|
||||||
|
badRequestWarning(Ent.GROUP, Ent.MEMBER, groupEmail)
|
||||||
|
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
|
||||||
|
accessErrorExit(cd)
|
||||||
|
|
||||||
|
def showGroupParents(groupParents, groupEmail, role, i, count):
|
||||||
|
kvList = [groupEmail, f'{groupParents[groupEmail]["name"]}']
|
||||||
|
if role:
|
||||||
|
kvList.extend([Ent.Singular(Ent.ROLE), role])
|
||||||
|
printKeyValueListWithCount(kvList, i, count)
|
||||||
|
Ind.Increment()
|
||||||
|
for parentEmail in groupParents[groupEmail]['parents']:
|
||||||
|
showGroupParents(groupParents, parentEmail, None, 0, 0)
|
||||||
|
Ind.Decrement()
|
||||||
|
|
||||||
|
def addJsonGroupParents(groupParents, userGroup, groupEmail):
|
||||||
|
userGroup.setdefault('parents', [])
|
||||||
|
for parentEmail in groupParents[groupEmail]['parents']:
|
||||||
|
userGroup['parents'].append({'email': parentEmail, 'name': groupParents[parentEmail]['name'], 'parents': []})
|
||||||
|
addJsonGroupParents(groupParents, userGroup['parents'][-1], parentEmail)
|
||||||
|
|
||||||
|
def printGroupParents(groupParents, groupEmail, row, csvPF, delimiter, showParentsAsList):
|
||||||
|
if groupParents[groupEmail]['parents']:
|
||||||
|
for parentEmail in groupParents[groupEmail]['parents']:
|
||||||
|
row['parents'].append({'email': parentEmail, 'name': groupParents[parentEmail]['name']})
|
||||||
|
printGroupParents(groupParents, parentEmail, row, csvPF, delimiter, showParentsAsList)
|
||||||
|
del row['parents'][-1]
|
||||||
|
else:
|
||||||
|
if not showParentsAsList:
|
||||||
|
csvPF.WriteRowTitles(flattenJSON(row))
|
||||||
|
else:
|
||||||
|
crow = row.copy()
|
||||||
|
if 'Role' in row:
|
||||||
|
crow['Role'] = row['Role']
|
||||||
|
parents = crow.pop('parents')
|
||||||
|
crow['ParentsCount'] = len(parents)
|
||||||
|
crow['Parents'] = delimiter.join([parent['email'] for parent in parents])
|
||||||
|
crow['ParentsName'] = delimiter.join([parent['name'] for parent in parents])
|
||||||
|
csvPF.WriteRow(flattenJSON(crow))
|
||||||
|
|
||||||
# gam print grouptree <GroupEntity> [todrive <ToDriveAttribute>*]
|
# gam print grouptree <GroupEntity> [todrive <ToDriveAttribute>*]
|
||||||
# [showparentsaslist [<Boolean>]] [delimiter <Character>]
|
# [showparentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
|
# [formatjson [quotechar <Character>]]
|
||||||
# gam show grouptree <GroupEntity>
|
# gam show grouptree <GroupEntity>
|
||||||
|
# [formatjson]
|
||||||
def doPrintShowGroupTree():
|
def doPrintShowGroupTree():
|
||||||
def getGroupParents(groupEmail, groupName):
|
|
||||||
groupParents[groupEmail] = {'name': groupName, 'parents': []}
|
|
||||||
_setUserGroupArgs(groupEmail, kwargs)
|
|
||||||
try:
|
|
||||||
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
|
|
||||||
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
|
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
||||||
orderBy='email', fields='nextPageToken,groups(email,name)', **kwargs)
|
|
||||||
for parentGroup in entityList:
|
|
||||||
groupParents[groupEmail]['parents'].append(parentGroup['email'])
|
|
||||||
if parentGroup['email'] not in groupParents:
|
|
||||||
getGroupParents(parentGroup['email'], parentGroup['name'])
|
|
||||||
except (GAPI.invalidMember, GAPI.invalidInput):
|
|
||||||
badRequestWarning(Ent.GROUP, Ent.MEMBER, groupEmail)
|
|
||||||
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
|
|
||||||
accessErrorExit(cd)
|
|
||||||
|
|
||||||
def showGroupParents(groupEmail, i, count):
|
|
||||||
printKeyValueListWithCount([f'{groupEmail}: {groupParents[groupEmail]["name"]}'], i, count)
|
|
||||||
Ind.Increment()
|
|
||||||
for parentEmail in groupParents[groupEmail]['parents']:
|
|
||||||
showGroupParents(parentEmail, 0, 0)
|
|
||||||
Ind.Decrement()
|
|
||||||
|
|
||||||
def printGroupParents(groupEmail, row):
|
|
||||||
if groupParents[groupEmail]['parents']:
|
|
||||||
for parentEmail in groupParents[groupEmail]['parents']:
|
|
||||||
row['parents'].append({'email': parentEmail, 'name': groupParents[parentEmail]['name']})
|
|
||||||
printGroupParents(parentEmail, row)
|
|
||||||
del row['parents'][-1]
|
|
||||||
else:
|
|
||||||
if not showParentsAsList:
|
|
||||||
csvPF.WriteRowTitles(flattenJSON(row))
|
|
||||||
else:
|
|
||||||
crow = {'Group': row['Group'], 'Name': row['Name']}
|
|
||||||
crow['ParentsCount'] = len(row['parents'])
|
|
||||||
crow['Parents'] = delimiter.join([parent['email'] for parent in row['parents']])
|
|
||||||
crow['ParentsName'] = delimiter.join([parent['name'] for parent in row['parents']])
|
|
||||||
csvPF.WriteRow(flattenJSON(crow))
|
|
||||||
|
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
kwargs = {'customer': GC.Values[GC.CUSTOMER_ID]}
|
kwargs = {'customer': GC.Values[GC.CUSTOMER_ID]}
|
||||||
csvPF = CSVPrintFile(['Group', 'Name']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['Group', 'Name']) if Act.csvFormat() else None
|
||||||
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
||||||
showParentsAsList = False
|
showParentsAsList = False
|
||||||
entityList = getEntityList(Cmd.OB_GROUP_ENTITY)
|
entityList = getEntityList(Cmd.OB_GROUP_ENTITY)
|
||||||
@ -32065,8 +32090,8 @@ def doPrintShowGroupTree():
|
|||||||
elif csvPF and myarg == 'showparentsaslist':
|
elif csvPF and myarg == 'showparentsaslist':
|
||||||
showParentsAsList = getBoolean()
|
showParentsAsList = getBoolean()
|
||||||
else:
|
else:
|
||||||
unknownArgumentExit()
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
if csvPF:
|
if csvPF and not FJQC.formatJSON:
|
||||||
if not showParentsAsList:
|
if not showParentsAsList:
|
||||||
csvPF.SetIndexedTitles(['parents'])
|
csvPF.SetIndexedTitles(['parents'])
|
||||||
else:
|
else:
|
||||||
@ -32074,7 +32099,7 @@ def doPrintShowGroupTree():
|
|||||||
groupParents = {}
|
groupParents = {}
|
||||||
i = 0
|
i = 0
|
||||||
count = len(entityList)
|
count = len(entityList)
|
||||||
if not csvPF:
|
if not csvPF and not FJQC.formatJSON:
|
||||||
performActionNumItems(count, Ent.GROUP_TREE)
|
performActionNumItems(count, Ent.GROUP_TREE)
|
||||||
for group in entityList:
|
for group in entityList:
|
||||||
i += 1
|
i += 1
|
||||||
@ -32088,12 +32113,24 @@ def doPrintShowGroupTree():
|
|||||||
GAPI.invalid, GAPI.systemError) as e:
|
GAPI.invalid, GAPI.systemError) as e:
|
||||||
entityActionFailedWarning([Ent.GROUP, groupEmail], str(e), i, count)
|
entityActionFailedWarning([Ent.GROUP, groupEmail], str(e), i, count)
|
||||||
continue
|
continue
|
||||||
getGroupParents(groupEmail, groupName)
|
getGroupParents(cd, groupParents, groupEmail, groupName, kwargs)
|
||||||
if not csvPF:
|
if not FJQC.formatJSON:
|
||||||
showGroupParents(groupEmail, i, count)
|
if not csvPF:
|
||||||
|
showGroupParents(groupParents, groupEmail, None, i, count)
|
||||||
|
else:
|
||||||
|
row = {'Group': groupEmail, 'Name': groupParents[groupEmail]['name'], 'parents': []}
|
||||||
|
printGroupParents(groupParents, groupEmail, row, csvPF, delimiter, showParentsAsList)
|
||||||
else:
|
else:
|
||||||
row = {'Group': groupEmail, 'Name': groupParents[groupEmail]['name'], 'parents': []}
|
groupInfo = {'email': groupEmail, 'name': groupParents[groupEmail]['name'], 'parents': []}
|
||||||
printGroupParents(groupEmail, row)
|
addJsonGroupParents(groupParents, groupInfo, groupEmail)
|
||||||
|
if not csvPF:
|
||||||
|
printLine(json.dumps(cleanJSON(groupInfo), ensure_ascii=False, sort_keys=True))
|
||||||
|
else:
|
||||||
|
row = flattenJSON(groupInfo)
|
||||||
|
if csvPF.CheckRowTitles(row):
|
||||||
|
csvPF.WriteRowNoFilter({'Group': groupEmail, 'Name': groupParents[groupEmail]['name'],
|
||||||
|
'JSON': json.dumps(cleanJSON(groupInfo),
|
||||||
|
ensure_ascii=False, sort_keys=True)})
|
||||||
if csvPF:
|
if csvPF:
|
||||||
csvPF.writeCSVfile('Group Tree')
|
csvPF.writeCSVfile('Group Tree')
|
||||||
|
|
||||||
@ -41513,29 +41550,6 @@ def _formatLanguagesList(propertyValue, delimiter):
|
|||||||
return delimiter.join(languages)
|
return delimiter.join(languages)
|
||||||
|
|
||||||
def infoUsers(entityList):
|
def infoUsers(entityList):
|
||||||
def getGroupParents(groupEmail, groupName):
|
|
||||||
groupParents[groupEmail] = {'name': groupName, 'parents': []}
|
|
||||||
try:
|
|
||||||
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
|
|
||||||
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
|
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
||||||
userKey=groupEmail, orderBy='email', fields='nextPageToken,groups(email,name)')
|
|
||||||
for parentGroup in entityList:
|
|
||||||
groupParents[groupEmail]['parents'].append(parentGroup['email'])
|
|
||||||
if parentGroup['email'] not in groupParents:
|
|
||||||
getGroupParents(parentGroup['email'], parentGroup['name'])
|
|
||||||
except (GAPI.invalidMember, GAPI.invalidInput):
|
|
||||||
badRequestWarning(Ent.GROUP, Ent.MEMBER, groupEmail)
|
|
||||||
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
|
|
||||||
accessErrorExit(cd)
|
|
||||||
|
|
||||||
def showGroupParents(groupEmail):
|
|
||||||
printKeyValueList([groupEmail, f'{groupParents[groupEmail]["name"]}'])
|
|
||||||
Ind.Increment()
|
|
||||||
for parentEmail in groupParents[groupEmail]['parents']:
|
|
||||||
showGroupParents(parentEmail)
|
|
||||||
Ind.Decrement()
|
|
||||||
|
|
||||||
def printUserCIGroupMap(parent, group_name_mappings, seen_group_count, edges, direction):
|
def printUserCIGroupMap(parent, group_name_mappings, seen_group_count, edges, direction):
|
||||||
for a_parent, a_child in edges:
|
for a_parent, a_child in edges:
|
||||||
if a_parent == parent:
|
if a_parent == parent:
|
||||||
@ -41662,8 +41676,14 @@ def infoUsers(entityList):
|
|||||||
getCIGroupsTree = False
|
getCIGroupsTree = False
|
||||||
licenses = getUserLicenses(lic, user, skus) if getLicenses else []
|
licenses = getUserLicenses(lic, user, skus) if getLicenses else []
|
||||||
if FJQC.formatJSON:
|
if FJQC.formatJSON:
|
||||||
if getGroups:
|
if getGroups or getGroupsTree:
|
||||||
user['groups'] = groups
|
user['groups'] = groups
|
||||||
|
if getGroupsTree:
|
||||||
|
for group in user['groups']:
|
||||||
|
groupEmail = group['email']
|
||||||
|
if groupEmail not in groupParents:
|
||||||
|
getGroupParents(cd, groupParents, groupEmail, group['name'], {})
|
||||||
|
addJsonGroupParents(groupParents, group, groupEmail)
|
||||||
if getLicenses:
|
if getLicenses:
|
||||||
user['licenses'] = [SKU.formatSKUIdDisplayName(u_license) for u_license in licenses]
|
user['licenses'] = [SKU.formatSKUIdDisplayName(u_license) for u_license in licenses]
|
||||||
if not getAliases:
|
if not getAliases:
|
||||||
@ -41901,8 +41921,8 @@ def infoUsers(entityList):
|
|||||||
for group in groups:
|
for group in groups:
|
||||||
groupEmail = group['email']
|
groupEmail = group['email']
|
||||||
if groupEmail not in groupParents:
|
if groupEmail not in groupParents:
|
||||||
getGroupParents(groupEmail, group['name'])
|
getGroupParents(cd, groupParents, groupEmail, group['name'], {})
|
||||||
showGroupParents(groupEmail)
|
showGroupParents(groupParents, groupEmail, None, 0, 0)
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
elif getCIGroupsTree:
|
elif getCIGroupsTree:
|
||||||
printEntity([Ent.GROUP_MEMBERSHIP_TREE, ''])
|
printEntity([Ent.GROUP_MEMBERSHIP_TREE, ''])
|
||||||
@ -52092,7 +52112,7 @@ FILECOUNT_SUMMARY_CHOICE_MAP = {
|
|||||||
FILECOUNT_SUMMARY_USER = 'Summary'
|
FILECOUNT_SUMMARY_USER = 'Summary'
|
||||||
|
|
||||||
# gam <UserTypeEntity> print filelist [todrive <ToDriveAttribute>*]
|
# gam <UserTypeEntity> print filelist [todrive <ToDriveAttribute>*]
|
||||||
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime.* <Time>)*]
|
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
||||||
# [choose <DriveFileNameEntity>|<DriveFileEntityShortcut>]
|
# [choose <DriveFileNameEntity>|<DriveFileEntityShortcut>]
|
||||||
# [corpora <CorporaAttribute>]
|
# [corpora <CorporaAttribute>]
|
||||||
# [select <DriveFileEntity> [selectsubquery <QueryDriveFile>]
|
# [select <DriveFileEntity> [selectsubquery <QueryDriveFile>]
|
||||||
@ -52822,7 +52842,7 @@ def printShowFilePaths(users):
|
|||||||
csvPF.writeCSVfile('Drive File Paths')
|
csvPF.writeCSVfile('Drive File Paths')
|
||||||
|
|
||||||
# gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
# gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
||||||
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime.* <Time>)*]
|
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
||||||
# [corpora <CorporaAttribute>]
|
# [corpora <CorporaAttribute>]
|
||||||
# [select <SharedDriveEntity>]
|
# [select <SharedDriveEntity>]
|
||||||
# [anyowner|(showownedby any|me|others)]
|
# [anyowner|(showownedby any|me|others)]
|
||||||
@ -52832,7 +52852,7 @@ def printShowFilePaths(users):
|
|||||||
# [excludetrashed]
|
# [excludetrashed]
|
||||||
# [summary none|only|plus] [summaryuser <String>] [showsize]
|
# [summary none|only|plus] [summaryuser <String>] [showsize]
|
||||||
# gam <UserTypeEntity> show filecounts
|
# gam <UserTypeEntity> show filecounts
|
||||||
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime.* <Time>)*]
|
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
||||||
# [corpora <CorporaAttribute>]
|
# [corpora <CorporaAttribute>]
|
||||||
# [select <SharedDriveEntity>]
|
# [select <SharedDriveEntity>]
|
||||||
# [anyowner|(showownedby any|me|others)]
|
# [anyowner|(showownedby any|me|others)]
|
||||||
@ -54765,7 +54785,8 @@ def _getUniqueFilename(destFilename, mimeType, targetChildren):
|
|||||||
|
|
||||||
def _copyPermissions(drive, user, i, count, j, jcount,
|
def _copyPermissions(drive, user, i, count, j, jcount,
|
||||||
entityType, fileId, fileTitle, newFileId, newFileTitle,
|
entityType, fileId, fileTitle, newFileId, newFileTitle,
|
||||||
statistics, stat, copyMoveOptions, atTop, copyInherited, copyNonInherited):
|
statistics, stat, copyMoveOptions, atTop, copyInherited, copyNonInherited,
|
||||||
|
updateOwner):
|
||||||
def getPermissions(fid):
|
def getPermissions(fid):
|
||||||
permissions = {}
|
permissions = {}
|
||||||
try:
|
try:
|
||||||
@ -54800,12 +54821,14 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|||||||
|
|
||||||
def isPermissionCopyable(kvList, permission):
|
def isPermissionCopyable(kvList, permission):
|
||||||
role = permission['role']
|
role = permission['role']
|
||||||
|
if permission['type'] in {'group', 'user'}:
|
||||||
|
emailAddress = permission.get('emailAddress', '')
|
||||||
domain = ''
|
domain = ''
|
||||||
if copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains']:
|
if copyMoveOptions['excludePermissionsFromDomains'] or copyMoveOptions['includePermissionsFromDomains']:
|
||||||
if permission['type'] in {'group', 'user'}:
|
if permission['type'] in {'group', 'user'}:
|
||||||
atLoc = permission.get('emailAddress', '').find('@')
|
atLoc = emailAddress.find('@')
|
||||||
if atLoc > 0:
|
if atLoc > 0:
|
||||||
domain = permission['emailAddress'][atLoc+1:]
|
domain = emailAddress[atLoc+1:]
|
||||||
elif permission['type'] == 'domain':
|
elif permission['type'] == 'domain':
|
||||||
domain = permission.get('domain', '')
|
domain = permission.get('domain', '')
|
||||||
if permission['inherited'] and not copyMoveOptions[copyInherited]:
|
if permission['inherited'] and not copyMoveOptions[copyInherited]:
|
||||||
@ -54813,7 +54836,13 @@ def _copyPermissions(drive, user, i, count, j, jcount,
|
|||||||
elif not permission['inherited'] and copyMoveOptions[copyNonInherited] == COPY_NONINHERITED_PERMISSIONS_NEVER:
|
elif not permission['inherited'] and copyMoveOptions[copyNonInherited] == COPY_NONINHERITED_PERMISSIONS_NEVER:
|
||||||
notCopiedMessage = 'noninherited not selected'
|
notCopiedMessage = 'noninherited not selected'
|
||||||
elif role == 'owner':
|
elif role == 'owner':
|
||||||
notCopiedMessage = f'role {role} copy not required/appropriate'
|
if emailAddress == user or copyMoveOptions['destDriveId'] or not updateOwner:
|
||||||
|
notCopiedMessage = f'role {role} copy not required/appropriate'
|
||||||
|
else:
|
||||||
|
permission['role'] = 'writer'
|
||||||
|
return True
|
||||||
|
elif updateOwner and emailAddress == user:
|
||||||
|
notCopiedMessage = 'user is now owner'
|
||||||
elif domain and domain in copyMoveOptions['excludePermissionsFromDomains']:
|
elif domain and domain in copyMoveOptions['excludePermissionsFromDomains']:
|
||||||
notCopiedMessage = f'domain {domain} excluded'
|
notCopiedMessage = f'domain {domain} excluded'
|
||||||
elif domain and copyMoveOptions['includePermissionsFromDomains'] and domain not in copyMoveOptions['includePermissionsFromDomains']:
|
elif domain and copyMoveOptions['includePermissionsFromDomains'] and domain not in copyMoveOptions['includePermissionsFromDomains']:
|
||||||
@ -55301,7 +55330,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, True,
|
copyMoveOptions, True,
|
||||||
'copyTopFolderInheritedPermissions',
|
'copyTopFolderInheritedPermissions',
|
||||||
copyFolderNonInheritedPermissions)
|
copyFolderNonInheritedPermissions,
|
||||||
|
True)
|
||||||
return (newParentId, newParentName, True)
|
return (newParentId, newParentName, True)
|
||||||
# Merge parent folders
|
# Merge parent folders
|
||||||
if copyMoveOptions['duplicateFolders'] == DUPLICATE_FOLDER_MERGE:
|
if copyMoveOptions['duplicateFolders'] == DUPLICATE_FOLDER_MERGE:
|
||||||
@ -55330,7 +55360,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, atTop,
|
copyMoveOptions, atTop,
|
||||||
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
||||||
copyFolderNonInheritedPermissions)
|
copyFolderNonInheritedPermissions,
|
||||||
|
False)
|
||||||
return (newFolderId, newFolderName, True)
|
return (newFolderId, newFolderName, True)
|
||||||
entityActionFailedWarning(kvList+[Ent.DRIVE_FOLDER, newParentNameId], Msg.NOT_WRITABLE, j, jcount)
|
entityActionFailedWarning(kvList+[Ent.DRIVE_FOLDER, newParentNameId], Msg.NOT_WRITABLE, j, jcount)
|
||||||
_incrStatistic(statistics, STAT_FOLDER_NOT_WRITABLE)
|
_incrStatistic(statistics, STAT_FOLDER_NOT_WRITABLE)
|
||||||
@ -55375,7 +55406,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
||||||
['copySubFolderNonInheritedPermissions', 'copyTopFolderNonInheritedPermissions'][atTop])
|
['copySubFolderNonInheritedPermissions', 'copyTopFolderNonInheritedPermissions'][atTop],
|
||||||
|
True)
|
||||||
return (newFolderId, newFolderName, False)
|
return (newFolderId, newFolderName, False)
|
||||||
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
|
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
|
||||||
GAPI.internalError, GAPI.storageQuotaExceeded, GAPI.teamDriveHierarchyTooDeep, GAPI.badRequest) as e:
|
GAPI.internalError, GAPI.storageQuotaExceeded, GAPI.teamDriveHierarchyTooDeep, GAPI.badRequest) as e:
|
||||||
@ -55570,7 +55602,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
'copySheetProtectedRangesInheritedPermissions',
|
'copySheetProtectedRangesInheritedPermissions',
|
||||||
'copySheetProtectedRangesNonInheritedPermissions')
|
'copySheetProtectedRangesNonInheritedPermissions',
|
||||||
|
True)
|
||||||
_updateSheetProtectedRanges(sheet, user, i, count, k, kcount, result['id'], result['name'], protectedSheetRanges,
|
_updateSheetProtectedRanges(sheet, user, i, count, k, kcount, result['id'], result['name'], protectedSheetRanges,
|
||||||
statistics, STAT_FILE_PROTECTEDRANGES_FAILED)
|
statistics, STAT_FILE_PROTECTEDRANGES_FAILED)
|
||||||
elif copyMoveOptions['copyFilePermissions']:
|
elif copyMoveOptions['copyFilePermissions']:
|
||||||
@ -55579,7 +55612,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
'copyFileInheritedPermissions',
|
'copyFileInheritedPermissions',
|
||||||
'copyFileNonInheritedPermissions')
|
'copyFileNonInheritedPermissions',
|
||||||
|
True)
|
||||||
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
|
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
|
||||||
GAPI.insufficientParentPermissions, GAPI.unknownError,
|
GAPI.insufficientParentPermissions, GAPI.unknownError,
|
||||||
GAPI.invalid, GAPI.cannotCopyFile, GAPI.badRequest, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
|
GAPI.invalid, GAPI.cannotCopyFile, GAPI.badRequest, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
|
||||||
@ -55830,7 +55864,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
'copySheetProtectedRangesInheritedPermissions',
|
'copySheetProtectedRangesInheritedPermissions',
|
||||||
'copySheetProtectedRangesNonInheritedPermissions')
|
'copySheetProtectedRangesNonInheritedPermissions',
|
||||||
|
True)
|
||||||
_updateSheetProtectedRanges(sheet, user, i, count, j, jcount, result['id'], result['name'], protectedSheetRanges,
|
_updateSheetProtectedRanges(sheet, user, i, count, j, jcount, result['id'], result['name'], protectedSheetRanges,
|
||||||
statistics, STAT_FILE_PROTECTEDRANGES_FAILED)
|
statistics, STAT_FILE_PROTECTEDRANGES_FAILED)
|
||||||
elif copyMoveOptions['copyFilePermissions']:
|
elif copyMoveOptions['copyFilePermissions']:
|
||||||
@ -55839,7 +55874,8 @@ def copyDriveFile(users):
|
|||||||
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
statistics, STAT_FILE_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
'copyFileInheritedPermissions',
|
'copyFileInheritedPermissions',
|
||||||
'copyFileNonInheritedPermissions')
|
'copyFileNonInheritedPermissions',
|
||||||
|
True)
|
||||||
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
|
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions,
|
||||||
GAPI.insufficientParentPermissions, GAPI.unknownError,
|
GAPI.insufficientParentPermissions, GAPI.unknownError,
|
||||||
GAPI.invalid, GAPI.badRequest, GAPI.cannotCopyFile, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
|
GAPI.invalid, GAPI.badRequest, GAPI.cannotCopyFile, GAPI.responsePreparationFailure, GAPI.fileNeverWritable, GAPI.fieldNotWritable,
|
||||||
@ -56072,7 +56108,8 @@ def moveDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, True,
|
copyMoveOptions, True,
|
||||||
'copyTopFolderInheritedPermissions',
|
'copyTopFolderInheritedPermissions',
|
||||||
copyFolderNonInheritedPermissions)
|
copyFolderNonInheritedPermissions,
|
||||||
|
False)
|
||||||
source.pop('oldparents', None)
|
source.pop('oldparents', None)
|
||||||
return (newParentId, newParentName, True)
|
return (newParentId, newParentName, True)
|
||||||
# Merge parent folders
|
# Merge parent folders
|
||||||
@ -56101,7 +56138,8 @@ def moveDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, atTop,
|
copyMoveOptions, atTop,
|
||||||
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
||||||
copyFolderNonInheritedPermissions)
|
copyFolderNonInheritedPermissions,
|
||||||
|
False)
|
||||||
return (newFolderId, newFolderName, True)
|
return (newFolderId, newFolderName, True)
|
||||||
entityActionFailedWarning(kvList+[Ent.DRIVE_FOLDER, newParentNameId], Msg.NOT_WRITABLE, j, jcount)
|
entityActionFailedWarning(kvList+[Ent.DRIVE_FOLDER, newParentNameId], Msg.NOT_WRITABLE, j, jcount)
|
||||||
_incrStatistic(statistics, STAT_FOLDER_NOT_WRITABLE)
|
_incrStatistic(statistics, STAT_FOLDER_NOT_WRITABLE)
|
||||||
@ -56187,7 +56225,8 @@ def moveDriveFile(users):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, False,
|
copyMoveOptions, False,
|
||||||
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
['copySubFolderInheritedPermissions', 'copyTopFolderInheritedPermissions'][atTop],
|
||||||
['copySubFolderNonInheritedPermissions', 'copyTopFolderNonInheritedPermissions'][atTop])
|
['copySubFolderNonInheritedPermissions', 'copyTopFolderNonInheritedPermissions'][atTop],
|
||||||
|
True)
|
||||||
return (newFolderId, newFolderName, False)
|
return (newFolderId, newFolderName, False)
|
||||||
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
|
except (GAPI.forbidden, GAPI.insufficientFilePermissions, GAPI.insufficientParentPermissions,
|
||||||
GAPI.internalError, GAPI.storageQuotaExceeded, GAPI.teamDriveHierarchyTooDeep,
|
GAPI.internalError, GAPI.storageQuotaExceeded, GAPI.teamDriveHierarchyTooDeep,
|
||||||
@ -59575,7 +59614,7 @@ def doInfoDriveFileACLs():
|
|||||||
infoDriveFileACLs([_getAdminEmail()], True)
|
infoDriveFileACLs([_getAdminEmail()], True)
|
||||||
|
|
||||||
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
|
DRIVEFILE_BASIC_PERMISSION_FIELDS = [
|
||||||
'id', 'emailAddress', 'domain', 'role', 'type',
|
'displayName', 'id', 'emailAddress', 'domain', 'role', 'type',
|
||||||
'allowFileDiscovery', 'expirationTime', 'deleted'
|
'allowFileDiscovery', 'expirationTime', 'deleted'
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -60929,7 +60968,8 @@ def copySyncSharedDriveACLs(users, useDomainAdminAccess=False):
|
|||||||
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
statistics, STAT_FOLDER_PERMISSIONS_FAILED,
|
||||||
copyMoveOptions, True,
|
copyMoveOptions, True,
|
||||||
'copyTopFolderInheritedPermissions',
|
'copyTopFolderInheritedPermissions',
|
||||||
'copyTopFolderNonInheritedPermissions')
|
'copyTopFolderNonInheritedPermissions',
|
||||||
|
False)
|
||||||
|
|
||||||
def doCopySyncSharedDriveACLs():
|
def doCopySyncSharedDriveACLs():
|
||||||
copySyncSharedDriveACLs([_getAdminEmail()], True)
|
copySyncSharedDriveACLs([_getAdminEmail()], True)
|
||||||
@ -62162,58 +62202,16 @@ def printShowUserGroups(users):
|
|||||||
# [(domain <DomainName>)|(customerid <CustomerID>)]
|
# [(domain <DomainName>)|(customerid <CustomerID>)]
|
||||||
# [roles <GroupRoleList>]
|
# [roles <GroupRoleList>]
|
||||||
# [showparentsaslist [<Boolean>]] [delimiter <Character>]
|
# [showparentsaslist [<Boolean>]] [delimiter <Character>]
|
||||||
|
# [formatjson [quotechar <Character>]]
|
||||||
# gam <UserTypeEntity> show grouptree
|
# gam <UserTypeEntity> show grouptree
|
||||||
# [(domain <DomainName>)|(customerid <CustomerID>)]
|
# [(domain <DomainName>)|(customerid <CustomerID>)]
|
||||||
# [roles <GroupRoleList>]
|
# [roles <GroupRoleList>]
|
||||||
|
# [formatjson]
|
||||||
def printShowGroupTree(users):
|
def printShowGroupTree(users):
|
||||||
def getGroupParents(groupEmail, groupName):
|
|
||||||
groupParents[groupEmail] = {'name': groupName, 'parents': []}
|
|
||||||
_setUserGroupArgs(groupEmail, kwargs)
|
|
||||||
try:
|
|
||||||
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
|
|
||||||
throwReasons=GAPI.GROUP_LIST_USERKEY_THROW_REASONS,
|
|
||||||
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
||||||
orderBy='email', fields='nextPageToken,groups(email,name)', **kwargs)
|
|
||||||
for parentGroup in entityList:
|
|
||||||
groupParents[groupEmail]['parents'].append(parentGroup['email'])
|
|
||||||
if parentGroup['email'] not in groupParents:
|
|
||||||
getGroupParents(parentGroup['email'], parentGroup['name'])
|
|
||||||
except (GAPI.invalidMember, GAPI.invalidInput):
|
|
||||||
badRequestWarning(Ent.GROUP, Ent.MEMBER, groupEmail)
|
|
||||||
except (GAPI.resourceNotFound, GAPI.domainNotFound, GAPI.forbidden, GAPI.badRequest):
|
|
||||||
accessErrorExit(cd)
|
|
||||||
|
|
||||||
def showGroupParents(groupEmail, role, i, count):
|
|
||||||
kvList = [groupEmail, f'{groupParents[groupEmail]["name"]}']
|
|
||||||
if role:
|
|
||||||
kvList.extend([Ent.Singular(Ent.ROLE), role])
|
|
||||||
printKeyValueListWithCount(kvList, i, count)
|
|
||||||
Ind.Increment()
|
|
||||||
for parentEmail in groupParents[groupEmail]['parents']:
|
|
||||||
showGroupParents(parentEmail, None, 0, 0)
|
|
||||||
Ind.Decrement()
|
|
||||||
|
|
||||||
def printGroupParents(groupEmail, row):
|
|
||||||
if groupParents[groupEmail]['parents']:
|
|
||||||
for parentEmail in groupParents[groupEmail]['parents']:
|
|
||||||
row['parents'].append({'email': parentEmail, 'name': groupParents[parentEmail]['name']})
|
|
||||||
printGroupParents(parentEmail, row)
|
|
||||||
del row['parents'][-1]
|
|
||||||
else:
|
|
||||||
if not showParentsAsList:
|
|
||||||
csvPF.WriteRowTitles(flattenJSON(row))
|
|
||||||
else:
|
|
||||||
crow = {'User': row['User'], 'Group': row['Group'], 'Name': row['Name']}
|
|
||||||
if rolesSet:
|
|
||||||
crow['Role'] = row['Role']
|
|
||||||
crow['ParentsCount'] = len(row['parents'])
|
|
||||||
crow['Parents'] = delimiter.join([parent['email'] for parent in row['parents']])
|
|
||||||
crow['ParentsName'] = delimiter.join([parent['name'] for parent in row['parents']])
|
|
||||||
csvPF.WriteRow(flattenJSON(crow))
|
|
||||||
|
|
||||||
cd = buildGAPIObject(API.DIRECTORY)
|
cd = buildGAPIObject(API.DIRECTORY)
|
||||||
kwargs = {'customer': GC.Values[GC.CUSTOMER_ID]}
|
kwargs = {'customer': GC.Values[GC.CUSTOMER_ID]}
|
||||||
csvPF = CSVPrintFile(['User', 'Group', 'Name']) if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['User', 'Group', 'Name']) if Act.csvFormat() else None
|
||||||
|
FJQC = FormatJSONQuoteChar(csvPF)
|
||||||
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
|
||||||
showParentsAsList = False
|
showParentsAsList = False
|
||||||
rolesSet = set()
|
rolesSet = set()
|
||||||
@ -62234,14 +62232,19 @@ def printShowGroupTree(users):
|
|||||||
elif csvPF and myarg == 'showparentsaslist':
|
elif csvPF and myarg == 'showparentsaslist':
|
||||||
showParentsAsList = getBoolean()
|
showParentsAsList = getBoolean()
|
||||||
else:
|
else:
|
||||||
unknownArgumentExit()
|
FJQC.GetFormatJSONQuoteChar(myarg, False)
|
||||||
if csvPF:
|
if csvPF:
|
||||||
if rolesSet:
|
if rolesSet:
|
||||||
csvPF.AddTitles('Role')
|
csvPF.AddTitles('Role')
|
||||||
if not showParentsAsList:
|
if not FJQC.formatJSON:
|
||||||
csvPF.SetIndexedTitles(['parents'])
|
if not showParentsAsList:
|
||||||
|
csvPF.SetIndexedTitles(['parents'])
|
||||||
|
else:
|
||||||
|
csvPF.AddTitles(['ParentsCount', 'Parents', 'ParentsName'])
|
||||||
else:
|
else:
|
||||||
csvPF.AddTitles(['ParentsCount', 'Parents', 'ParentsName'])
|
if rolesSet:
|
||||||
|
csvPF.AddJSONTitles('Role')
|
||||||
|
csvPF.AddJSONTitles('JSON')
|
||||||
allRoles = rolesSet == ALL_GROUP_ROLES
|
allRoles = rolesSet == ALL_GROUP_ROLES
|
||||||
groupParents = {}
|
groupParents = {}
|
||||||
i, count, users = getEntityArgument(users)
|
i, count, users = getEntityArgument(users)
|
||||||
@ -62259,7 +62262,7 @@ def printShowGroupTree(users):
|
|||||||
continue
|
continue
|
||||||
j = 0
|
j = 0
|
||||||
jcount = len(groups)
|
jcount = len(groups)
|
||||||
if not csvPF:
|
if not csvPF and not FJQC.formatJSON:
|
||||||
if allRoles:
|
if allRoles:
|
||||||
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.GROUP_TREE, i, count)
|
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.GROUP_TREE, i, count)
|
||||||
else:
|
else:
|
||||||
@ -62269,7 +62272,7 @@ def printShowGroupTree(users):
|
|||||||
j += 1
|
j += 1
|
||||||
groupEmail = group['email']
|
groupEmail = group['email']
|
||||||
if groupEmail not in groupParents:
|
if groupEmail not in groupParents:
|
||||||
getGroupParents(groupEmail, group['name'])
|
getGroupParents(cd, groupParents, groupEmail, group['name'], kwargs)
|
||||||
if rolesSet:
|
if rolesSet:
|
||||||
try:
|
try:
|
||||||
result = callGAPI(cd.members(), 'get',
|
result = callGAPI(cd.members(), 'get',
|
||||||
@ -62287,13 +62290,30 @@ def printShowGroupTree(users):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
role = None
|
role = None
|
||||||
if not csvPF:
|
if not FJQC.formatJSON:
|
||||||
showGroupParents(groupEmail, role, j, jcount)
|
if not csvPF:
|
||||||
|
showGroupParents(groupParents, groupEmail, role, j, jcount)
|
||||||
|
else:
|
||||||
|
row = {'User': user, 'Group': groupEmail, 'Name': group['name'], 'parents': []}
|
||||||
|
if role is not None:
|
||||||
|
row['Role'] = role
|
||||||
|
printGroupParents(groupParents, groupEmail, row, csvPF, delimiter, showParentsAsList)
|
||||||
else:
|
else:
|
||||||
row = {'User': user, 'Group': groupEmail, 'Name': group['name'], 'parents': []}
|
groupInfo = {'email': groupEmail, 'name': group['name'], 'parents': []}
|
||||||
if rolesSet:
|
if role is not None:
|
||||||
row['Role'] = role
|
groupInfo['role'] = role
|
||||||
printGroupParents(groupEmail, row)
|
addJsonGroupParents(groupParents, groupInfo, groupEmail)
|
||||||
|
if not csvPF:
|
||||||
|
printLine(json.dumps(cleanJSON(groupInfo), ensure_ascii=False, sort_keys=True))
|
||||||
|
else:
|
||||||
|
row = flattenJSON(groupInfo)
|
||||||
|
if csvPF.CheckRowTitles(row):
|
||||||
|
row = {'User': user, 'Group': groupEmail, 'Name': group['name']}
|
||||||
|
if rolesSet:
|
||||||
|
row['Role'] = role
|
||||||
|
row['JSON'] = json.dumps(cleanJSON(groupInfo),
|
||||||
|
ensure_ascii=False, sort_keys=True)
|
||||||
|
csvPF.WriteRowNoFilter(row)
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
if csvPF:
|
if csvPF:
|
||||||
csvPF.writeCSVfile('User Group Trees')
|
csvPF.writeCSVfile('User Group Trees')
|
||||||
@ -64599,7 +64619,8 @@ MESSAGES_MAX_TO_KEYWORDS = {
|
|||||||
|
|
||||||
def _initMessageThreadParameters(entityType, doIt, maxToProcess):
|
def _initMessageThreadParameters(entityType, doIt, maxToProcess):
|
||||||
listType = 'messages' if entityType == Ent.MESSAGE else 'threads'
|
listType = 'messages' if entityType == Ent.MESSAGE else 'threads'
|
||||||
return {'currLabelOp': 'and', 'prevLabelOp': 'and', 'labelGroupOpen': False, 'query': '',
|
return {'currLabelOp': 'and', 'prevLabelOp': 'and', 'labelGroupOpen': False,
|
||||||
|
'query': '', 'queryTimes': {},
|
||||||
'entityType': entityType, 'messageEntity': None, 'doIt': doIt, 'quick': True,
|
'entityType': entityType, 'messageEntity': None, 'doIt': doIt, 'quick': True,
|
||||||
'labelMatchPattern': None, 'senderMatchPattern': None,
|
'labelMatchPattern': None, 'senderMatchPattern': None,
|
||||||
'maxToProcess': maxToProcess, 'maxItems': 0,
|
'maxToProcess': maxToProcess, 'maxItems': 0,
|
||||||
@ -64611,6 +64632,8 @@ LABEL_QUERY_REPLACEMENT_CHARACTERS = ' &()"|{}/'
|
|||||||
def _getMessageSelectParameters(myarg, parameters):
|
def _getMessageSelectParameters(myarg, parameters):
|
||||||
if myarg == 'query':
|
if myarg == 'query':
|
||||||
parameters['query'] += f' ({getString(Cmd.OB_QUERY)})'
|
parameters['query'] += f' ({getString(Cmd.OB_QUERY)})'
|
||||||
|
elif myarg.startswith('querytime'):
|
||||||
|
parameters['queryTimes'][myarg] = getDateOrDeltaFromNow().replace('-', '/')
|
||||||
elif myarg == 'matchlabel':
|
elif myarg == 'matchlabel':
|
||||||
labelTemp = getString(Cmd.OB_LABEL_NAME).lower()
|
labelTemp = getString(Cmd.OB_LABEL_NAME).lower()
|
||||||
labelName = ''
|
labelName = ''
|
||||||
@ -64667,6 +64690,9 @@ def _finalizeMessageSelectParameters(parameters, queryOrIdsRequired):
|
|||||||
if parameters['query']:
|
if parameters['query']:
|
||||||
if parameters['labelGroupOpen']:
|
if parameters['labelGroupOpen']:
|
||||||
parameters['query'] += ')'
|
parameters['query'] += ')'
|
||||||
|
if parameters['queryTimes']:
|
||||||
|
for queryTimeName, queryTimeValue in iter(parameters['queryTimes'].items()):
|
||||||
|
parameters['query'] = parameters['query'].replace(f'#{queryTimeName}#', queryTimeValue)
|
||||||
_mapMessageQueryDates(parameters)
|
_mapMessageQueryDates(parameters)
|
||||||
elif queryOrIdsRequired and parameters['messageEntity'] is None:
|
elif queryOrIdsRequired and parameters['messageEntity'] is None:
|
||||||
missingArgumentExit('query|matchlabel|ids')
|
missingArgumentExit('query|matchlabel|ids')
|
||||||
@ -64675,7 +64701,7 @@ def _finalizeMessageSelectParameters(parameters, queryOrIdsRequired):
|
|||||||
parameters['maxItems'] = parameters['maxToProcess'] if parameters['quick'] and not parameters['labelMatchPattern'] else 0
|
parameters['maxItems'] = parameters['maxToProcess'] if parameters['quick'] and not parameters['labelMatchPattern'] else 0
|
||||||
|
|
||||||
# gam <UserTypeEntity> archive messages <GroupItem>
|
# gam <UserTypeEntity> archive messages <GroupItem>
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
|
||||||
def archiveMessages(users):
|
def archiveMessages(users):
|
||||||
entityType = Ent.MESSAGE
|
entityType = Ent.MESSAGE
|
||||||
parameters = _initMessageThreadParameters(entityType, False, 0)
|
parameters = _initMessageThreadParameters(entityType, False, 0)
|
||||||
@ -64905,30 +64931,30 @@ def _processMessagesThreads(users, entityType):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
|
|
||||||
# gam <UserTypeEntity> delete message|messages
|
# gam <UserTypeEntity> delete message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
|
||||||
# gam <UserTypeEntity> modify message|messages
|
# gam <UserTypeEntity> modify message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
|
||||||
# (addlabel <LabelName>)* (removelabel <LabelName>)*
|
# (addlabel <LabelName>)* (removelabel <LabelName>)*
|
||||||
# gam <UserTypeEntity> spam message|messages
|
# gam <UserTypeEntity> spam message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
|
||||||
# gam <UserTypeEntity> trash message|messages
|
# gam <UserTypeEntity> trash message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
||||||
# gam <UserTypeEntity> untrash message|messages
|
# gam <UserTypeEntity> untrash message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
|
||||||
def processMessages(users):
|
def processMessages(users):
|
||||||
_processMessagesThreads(users, Ent.MESSAGE)
|
_processMessagesThreads(users, Ent.MESSAGE)
|
||||||
|
|
||||||
# gam <UserTypeEntity> delete thread|threads
|
# gam <UserTypeEntity> delete thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_delete <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_delete <Number>])|(ids <ThreadIDEntity>)
|
||||||
# gam <UserTypeEntity> modify thread|threads
|
# gam <UserTypeEntity> modify thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_modify <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_modify <Number>])|(ids <ThreadIDEntity>)
|
||||||
# (addlabel <LabelName>)* (removelabel <LabelName>)*
|
# (addlabel <LabelName>)* (removelabel <LabelName>)*
|
||||||
# gam <UserTypeEntity> spam thread|threads
|
# gam <UserTypeEntity> spam thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_spam <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_spam <Number>])|(ids <ThreadIDEntity>)
|
||||||
# gam <UserTypeEntity> trash thread|threads
|
# gam <UserTypeEntity> trash thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
|
||||||
# gam <UserTypeEntity> untrash thread|threads
|
# gam <UserTypeEntity> untrash thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <ThreadIDEntity>)
|
||||||
def processThreads(users):
|
def processThreads(users):
|
||||||
_processMessagesThreads(users, Ent.THREAD)
|
_processMessagesThreads(users, Ent.THREAD)
|
||||||
|
|
||||||
@ -65038,13 +65064,13 @@ def exportMessagesThreads(users, entityType):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
|
|
||||||
# gam <UserTypeEntity> export message|messages
|
# gam <UserTypeEntity> export message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
|
||||||
# [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
# [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
def exportMessages(users):
|
def exportMessages(users):
|
||||||
exportMessagesThreads(users, Ent.MESSAGE)
|
exportMessagesThreads(users, Ent.MESSAGE)
|
||||||
|
|
||||||
# gam <UserTypeEntity> export thread|threads
|
# gam <UserTypeEntity> export thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
|
||||||
# [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
# [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
|
||||||
def exportThreads(users):
|
def exportThreads(users):
|
||||||
exportMessagesThreads(users, Ent.THREAD)
|
exportMessagesThreads(users, Ent.THREAD)
|
||||||
@ -65064,10 +65090,10 @@ def _decodeHeader(header):
|
|||||||
return header
|
return header
|
||||||
|
|
||||||
# gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
# gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
||||||
# [subject <String>] [altcharset <String>]
|
# [subject <String>] [altcharset <String>]
|
||||||
# gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
# gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
||||||
# [subject <String>] [altcharset <String>]
|
# [subject <String>] [altcharset <String>]
|
||||||
def forwardMessagesThreads(users, entityType):
|
def forwardMessagesThreads(users, entityType):
|
||||||
def getRecipients():
|
def getRecipients():
|
||||||
@ -65371,7 +65397,7 @@ def _draftImportInsertMessage(users, operation):
|
|||||||
emlFile = True
|
emlFile = True
|
||||||
internalDateSource = 'dateHeader'
|
internalDateSource = 'dateHeader'
|
||||||
elif myarg == 'replace':
|
elif myarg == 'replace':
|
||||||
_getTagReplacement(tagReplacements, False)
|
_getTagReplacement(tagReplacements, True)
|
||||||
elif operation in IMPORT_INSERT and myarg == 'addlabel':
|
elif operation in IMPORT_INSERT and myarg == 'addlabel':
|
||||||
addLabelNames.append(getString(Cmd.OB_LABEL_NAME, minLen=1))
|
addLabelNames.append(getString(Cmd.OB_LABEL_NAME, minLen=1))
|
||||||
elif operation in IMPORT_INSERT and myarg == 'labels':
|
elif operation in IMPORT_INSERT and myarg == 'labels':
|
||||||
@ -66184,7 +66210,7 @@ def printShowMessagesThreads(users, entityType):
|
|||||||
csvPF.writeCSVfile('Message Counts' if not show_labels else 'Message Label Counts')
|
csvPF.writeCSVfile('Message Counts' if not show_labels else 'Message Label Counts')
|
||||||
|
|
||||||
# gam <UserTypeEntity> print message|messages
|
# gam <UserTypeEntity> print message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
# [labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
# [labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
||||||
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
||||||
@ -66192,7 +66218,7 @@ def printShowMessagesThreads(users, entityType):
|
|||||||
# [convertcrnl] [delimiter <Character>] [todrive <ToDriveAttribute>*]
|
# [convertcrnl] [delimiter <Character>] [todrive <ToDriveAttribute>*]
|
||||||
# [countsonly|positivecountsonly] [useronly]
|
# [countsonly|positivecountsonly] [useronly]
|
||||||
# gam <UserTypeEntity> show message|messages
|
# gam <UserTypeEntity> show message|messages
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
|
||||||
# [labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
# [labelmatchpattern <RegularExpression>] [sendermatchpattern <RegularExpression>]
|
||||||
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
||||||
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
||||||
@ -66203,7 +66229,7 @@ def printShowMessages(users):
|
|||||||
printShowMessagesThreads(users, Ent.MESSAGE)
|
printShowMessagesThreads(users, Ent.MESSAGE)
|
||||||
|
|
||||||
# gam <UserTypeEntity> print thread|threads
|
# gam <UserTypeEntity> print thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <ThreadIDEntity>)
|
||||||
# [labelmatchpattern <RegularExpression>]
|
# [labelmatchpattern <RegularExpression>]
|
||||||
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
||||||
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
||||||
@ -66211,7 +66237,7 @@ def printShowMessages(users):
|
|||||||
# [convertcrnl] [delimiter <Character>] [todrive <ToDriveAttribute>*]
|
# [convertcrnl] [delimiter <Character>] [todrive <ToDriveAttribute>*]
|
||||||
# [countsonly|positivecountsonly] [useronly]
|
# [countsonly|positivecountsonly] [useronly]
|
||||||
# gam <UserTypeEntity> show thread|threads
|
# gam <UserTypeEntity> show thread|threads
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <ThreadIDEntity>)
|
||||||
# [labelmatchpattern <RegularExpression>]
|
# [labelmatchpattern <RegularExpression>]
|
||||||
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
# [headers all|<SMTPHeaderList>] [dateheaderformat iso|rfc2822|<String>] [dateheaderconverttimezone [<Boolean>]]
|
||||||
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
# [showlabels] [showbody] [showdate] [showsize] [showsnippet]
|
||||||
@ -67169,10 +67195,10 @@ EMAILSETTINGS_FORWARD_POP_ACTION_CHOICE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
# gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
|
||||||
# [subject <String>]
|
# [subject <String>]
|
||||||
# gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
# gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
|
||||||
# (((query <QueryGmail>) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
# (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
|
||||||
# [subject <String>]
|
# [subject <String>]
|
||||||
# gam <UserTypeEntity> forward <FalseValues>
|
# gam <UserTypeEntity> forward <FalseValues>
|
||||||
# gam <UserTypeEntity> forward <TrueValues> keep|leaveininbox|archive|delete|trash|markread <EmailAddress>
|
# gam <UserTypeEntity> forward <TrueValues> keep|leaveininbox|archive|delete|trash|markread <EmailAddress>
|
||||||
|
@ -438,6 +438,7 @@ STRING_LENGTH = 'string length'
|
|||||||
SUBKEY_FIELD_MISMATCH = 'subkeyfield {0} does not match saved subkeyfield {1}'
|
SUBKEY_FIELD_MISMATCH = 'subkeyfield {0} does not match saved subkeyfield {1}'
|
||||||
SUBSCRIPTION_NOT_FOUND = 'Could not find subscription'
|
SUBSCRIPTION_NOT_FOUND = 'Could not find subscription'
|
||||||
SUFFIX_NOT_ALLOWED_WITH_CUSTOMLANGUAGE = 'Suffix {0} not allowed with customLanguage {1}'
|
SUFFIX_NOT_ALLOWED_WITH_CUSTOMLANGUAGE = 'Suffix {0} not allowed with customLanguage {1}'
|
||||||
|
TASKLIST_TITLE_NOT_FOUND = 'Task list title not found'
|
||||||
THREAD = 'thread'
|
THREAD = 'thread'
|
||||||
THREADS = 'threads'
|
THREADS = 'threads'
|
||||||
TO = 'To'
|
TO = 'To'
|
||||||
|
Reference in New Issue
Block a user