Added replaceregex <RegularExpression> <ReplacementString> <Tag> <String>
Some checks are pending
Build and test GAM / build (Win64, build, 10, VC-WIN64A, windows-2022) (push) Waiting to run
Build and test GAM / build (aarch64, build, 3, linux-aarch64, ubuntu-24.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 4, linux-aarch64, ubuntu-22.04-arm) (push) Waiting to run
Build and test GAM / build (aarch64, build, 6, linux-aarch64, ubuntu-22.04-arm, yes) (push) Waiting to run
Build and test GAM / build (aarch64, build, 8, darwin64-arm64, macos-14) (push) Waiting to run
Build and test GAM / build (aarch64, build, 9, darwin64-arm64, macos-15) (push) Waiting to run
Build and test GAM / build (x86_64, build, 1, linux-x86_64, ubuntu-22.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 2, linux-x86_64, ubuntu-24.04) (push) Waiting to run
Build and test GAM / build (x86_64, build, 5, linux-x86_64, ubuntu-22.04, yes) (push) Waiting to run
Build and test GAM / build (x86_64, build, 7, darwin64-x86_64, macos-13) (push) Waiting to run
Build and test GAM / build (x86_64, test, 11, ubuntu-24.04, 3.10) (push) Waiting to run
Build and test GAM / build (x86_64, test, 12, ubuntu-24.04, 3.11) (push) Waiting to run
Build and test GAM / build (x86_64, test, 13, ubuntu-24.04, 3.12) (push) Waiting to run
Build and test GAM / merge (push) Blocked by required conditions
Build and test GAM / publish (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Check for Google Root CA Updates / check-apis (push) Waiting to run

This commit is contained in:
Ross Scroggs
2025-03-31 13:26:04 -07:00
parent d308ad1271
commit defac7d9a8
4 changed files with 184 additions and 67 deletions

View File

@@ -1908,7 +1908,7 @@ gam calendar|calendars <CalendarEntity> modify <CalendarSettings>+
<ChatContent> ::= <ChatContent> ::=
((text <String>)| ((text <String>)|
(textfile <FileName> [charset <CharSet>])| (textfile <FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
@@ -4735,8 +4735,10 @@ gam sendemail [recipient|to] <RecipientEntity>
[from <EmailAddress>] [mailbox <EmailAddress>] [replyto <EmailAddress>] [from <EmailAddress>] [mailbox <EmailAddress>] [replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>] [subject <String>]
[<MessageContent>] (replace <Tag> <String>)* [<MessageContent>]
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])* (replace <Tag> <String>)*
(replaceregex <RegularExpression> <String> <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
@@ -4744,8 +4746,10 @@ gam <UserTypeEntity> sendemail recipient|to <RecipientEntity>
[replyto <EmailAddress>] [replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>] [subject <String>]
[<MessageContent>] (replace <Tag> <String>)* [<MessageContent>]
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])* (replace <Tag> <String>)*
(replaceregex <RegularExpression> <String> <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
@@ -4753,8 +4757,10 @@ gam <UserTypeEntity> sendemail from <EmailAddress>
[replyto <EmailAddress>] [replyto <EmailAddress>]
[cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
[subject <String>] [subject <String>]
[<MessageContent>] (replace <Tag> <String>)* [<MessageContent>]
[html [<Boolean>]] (attach <FileName> [charset <CharSet>])* (replace <Tag> <String>)*
(replaceregex <RegularExpression> <String> <Tag> <String>)*
[html [<Boolean>]] (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
[newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
@@ -5560,7 +5566,9 @@ gam create|add user <EmailAddress> [ignorenullpassword] <UserAttribute>*
[mailbox <EmailAaddress>] [mailbox <EmailAaddress>]
[replyto <EmailAaddress>] [replyto <EmailAaddress>]
[<NotifyMessageContent>] [<NotifyMessageContent>]
(replace <Tag> <UserReplacement>)*] (replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
]
[logpassword <FileName>] [logpassword <FileName>]
[addnumericsuffixonduplicate <Number>] [addnumericsuffixonduplicate <Number>]
@@ -5569,7 +5577,7 @@ gam <UserTypeEntity> waitformailbox [retries <Number>]
gam update user <UserItem> [ignorenullpassword] <UserAttribute>* gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable|alwaysevict] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <Charset>]
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[immutableous <OrgUnitEntity>]| [immutableous <OrgUnitEntity>]|
@@ -5581,10 +5589,12 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[subject <String>] [subject <String>]
[notifypassword <String>] [notifypassword <String>]
[from <EmailAaddress>] [from <EmailAaddress>]
[mailbox <EmailAaddress>] [mailbox <EmailAddress>]
[replyto <EmailAaddress>] [replyto <EmailAddress>]
[<NotifyMessageContent>] [<NotifyMessageContent>]
(replace <Tag> <UserReplacement>)*] (replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
]
[notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]] [notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]]
[logpassword <FileName>] [logpassword <FileName>]
gam delete user <UserItem> [noactionifalias] gam delete user <UserItem> [noactionifalias]
@@ -5603,9 +5613,9 @@ gam info user [<UserItem>]
[formatjson] [formatjson]
gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>* gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <Charset>]
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>|<SchemaNameField>] [clearschema <SchemaName>|<SchemaNameField>]
@@ -5615,13 +5625,15 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[notify <EmailAddressList> [notify <EmailAddressList>
[subject <String>] [subject <String>]
[notifypassword <String>] [notifypassword <String>]
[from <EmailAaddress>] [from <EmailAddress>]
[mailbox <EmailAaddress>] [mailbox <EmailAddress>]
[replyto <EmailAaddress>]
[<NotifyMessageContent>] [<NotifyMessageContent>]
(replace <Tag> <UserReplacement>)*] (replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
]
[notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]] [notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]]
[logpassword <FileName>] [logpassword <FileName>]
[verifynotinvitable]
gam delete users <UserTypeEntity> [noactionifalias] gam delete users <UserTypeEntity> [noactionifalias]
gam undelete users <UserEntity> [ou|org|orgunit <OrgUnitPath>] gam undelete users <UserEntity> [ou|org|orgunit <OrgUnitPath>]
gam suspend users <UserTypeEntity> [noactionifalias] gam suspend users <UserTypeEntity> [noactionifalias]
@@ -5638,9 +5650,11 @@ gam info users <UserTypeEntity>
[formatjson] [formatjson]
gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>* gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
[verifynotinvitable] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <CSVFileInput> [keyfield <FieldName>] [datafield <FieldName>]] [updateoufromgroup <FileName> [charset <Charset>]
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>|<SchemaNameField>] [clearschema <SchemaName>|<SchemaNameField>]
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>] [createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)* (groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
@@ -5649,12 +5663,14 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
[subject <String>] [subject <String>]
[notifypassword <String>] [notifypassword <String>]
[from <EmailAaddress>] [from <EmailAaddress>]
[mailbox <EmailAaddress>] [mailbox <EmailAddress>]
[replyto <EmailAddress>]
[<NotifyMessageContent>] [<NotifyMessageContent>]
(replace <Tag> <UserReplacement>)*] (replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
]
[notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]] [notifyonupdate [<Boolean>]] [setchangepasswordoncreate [<Boolean>]]
[logpassword <FileName>] [logpassword <FileName>]
[verifynotinvitable]
gam <UserTypeEntity> delete users [noactionifalias] gam <UserTypeEntity> delete users [noactionifalias]
gam <UserEntity> undelete users [ou|org|orgunit <OrgUnitPath>] gam <UserEntity> undelete users [ou|org|orgunit <OrgUnitPath>]
gam <UserTypeEntity> suspend users [noactionifalias] gam <UserTypeEntity> suspend users [noactionifalias]
@@ -6165,7 +6181,7 @@ gam <UserTypeEntity> print focustime|outofoffice|workinglocation
<ChatContent> ::= <ChatContent> ::=
((text <String>)| ((text <String>)|
(textfile <FileName> [charset <CharSet>])| (textfile <FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
@@ -6527,7 +6543,7 @@ gam <UserTypeEntity> update drivefile <DriveFileEntity> [copy] [returnidonly|ret
[timestamp [<Boolean>]] [timeformat <String>] [timestamp [<Boolean>]] [timeformat <String>]
<DriveFileUpdateAttribute>* <DriveFileUpdateAttribute>*
[(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)] [(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
[charset <CharSet>] [columndelimiter <Character>] [charset <Charset>] [columndelimiter <Character>]
<DriveFileCopyAttribute> ::= <DriveFileCopyAttribute> ::=
(contentrestrictions (readonly false)|(readonly true [reason <String>]) [ownerrestricted [<Boolean>]])| (contentrestrictions (readonly false)|(readonly true [reason <String>]) [ownerrestricted [<Boolean>]])|
@@ -7532,22 +7548,28 @@ gam <UserTypeEntity> print labels|label [todrive <ToDriveAttribute>*]
(emlfile <FileName> [charset <Charset>]) (emlfile <FileName> [charset <Charset>])
gam <UserTypeEntity> draft message gam <UserTypeEntity> draft message
<MessageContent> (replace <Tag> <UserReplacement>)* <MessageContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
(attach <FileName> [charset <CharSet>])* (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
gam <UserTypeEntity> import message gam <UserTypeEntity> import message
<MessageContent> (replace <Tag> <UserReplacement>)* <MessageContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
(addlabel <LabelName>)* [labels <LabelNameList>] (addlabel <LabelName>)* [labels <LabelNameList>]
(attach <FileName> [charset <CharSet>])* (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
[deleted [<Boolean>]] [checkspam|nevermarkspam [<Boolean>]] [processforcalendar [<Boolean>]] [deleted [<Boolean>]] [checkspam|nevermarkspam [<Boolean>]] [processforcalendar [<Boolean>]]
gam <UserTypeEntity> insert message gam <UserTypeEntity> insert message
<MessageContent> (replace <Tag> <UserReplacement>)* <MessageContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
(<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
(addlabel <LabelName>)* [labels <LabelNameList>] (addlabel <LabelName>)* [labels <LabelNameList>]
(attach <FileName> [charset <CharSet>])* (attach <FileName> [charset <Charset>])*
(embedimage <FileName> <String>)* (embedimage <FileName> <String>)*
[deleted [<Boolean>]] [deleted [<Boolean>]]
@@ -7626,13 +7648,17 @@ gam <UserTypeEntity> print gmailprofile [todrive <ToDriveAttribute>*]
# Users - Gmail - Send As/Signature/Vacation # Users - Gmail - Send As/Signature/Vacation
gam <UserTypeEntity> [create|add] sendas <EmailAddress> [name] <String> gam <UserTypeEntity> [create|add] sendas <EmailAddress> [name] <String>
[<SendAsContent> (replace <Tag> <UserReplacement>)*] [<SendAsContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
[html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
[smtpmsa.host <SMTPHostName> smtpmsa.port 25|465|587 [smtpmsa.host <SMTPHostName> smtpmsa.port 25|465|587
smtpmsa.username <UserName> smtpmsa.password <Password> smtpmsa.username <UserName> smtpmsa.password <Password>
[smtpmsa.securitymode none|ssl|starttls]] [smtpmsa.securitymode none|ssl|starttls]]
gam <UserTypeEntity> update sendas <EmailAddress> [name <String>] gam <UserTypeEntity> update sendas <EmailAddress> [name <String>]
[<SendAsContent> (replace <Tag> <UserReplacement>)*] [<SendAsContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
[html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
gam <UserTypeEntity> delete sendas <EmailAddressEntity> gam <UserTypeEntity> delete sendas <EmailAddressEntity>
gam <UserTypeEntity> info sendas <EmailAddressEntity> [compact|format|html] gam <UserTypeEntity> info sendas <EmailAddressEntity> [compact|format|html]
@@ -7642,7 +7668,9 @@ gam <UserTypeEntity> print sendas [compact]
[primary|default] [verifyonly] [todrive <ToDriveAttribute>*] [primary|default] [verifyonly] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> signature|sig gam <UserTypeEntity> signature|sig
<SignatureContent> (replace <Tag> <UserReplacement>)* <SignatureContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
[html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
[name <String>] [name <String>]
[primary] [primary]
@@ -7652,7 +7680,9 @@ gam <UserTypeEntity> print signature [compact]
[primary|default] [verifyonly] [todrive <ToDriveAttribute>*] [primary|default] [verifyonly] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> vacation [<Boolean>] [subject <String>] gam <UserTypeEntity> vacation [<Boolean>] [subject <String>]
[<VacationMessageContent> (replace <Tag> <UserReplacement>)*] [<VacationMessageContent>
(replace <Tag> <UserReplacement>)*
(replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
[html [<Boolean>]] [contactsonly [<Boolean>]] [domainonly [<Boolean>]] [html [<Boolean>]] [contactsonly [<Boolean>]] [domainonly [<Boolean>]]
[start|startdate <Date>|Started] [end|enddate <Date>|NotSpecified] [start|startdate <Date>|Started] [end|enddate <Date>|NotSpecified]
gam <UserTypeEntity> show vacation [compact|format|html] [enabledonly] gam <UserTypeEntity> show vacation [compact|format|html] [enabledonly]
@@ -7779,7 +7809,7 @@ gam <UserTypeEntity> check isinvitable [todrive <ToDriveAttribute>*]
<NoteContent> ::= <NoteContent> ::=
((text <String>)| ((text <String>)|
(textfile <FileName> [charset <CharSet>])| (textfile <FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>)| (gcsdoc <StorageBucketObjectName>)|
<JSONData>) <JSONData>)

View File

@@ -1,3 +1,41 @@
7.05.19
Added `replaceregex <RegularExpression> <ReplacementString> <Tag> <String>` to the following commands:
```
gam sendemail subject <String> <MessageContent>
gam <UserTypeEntity> sendemail subject <String> <MessageContent>
```
The `<RegularExpression>` is used as a match pattern against `<String>` to produce `<ReplacementString>`.
Instances of `{Tag}` will be replaced by `<ReplacementString>` in the message subject and body.
Added `replaceregex <RegularExpression> <ReplacementString> <Tag> <UserReplacement>` to the following commands:
```
gam create user <NotifyMessageContent>
gam update user <NotifyMessageContent>
gam update users <NotifyMessageContent>
gam <UserTypeEntity> update users <NotifyMessageContent>
gam <UserTypeEntity> draft message <MessageContent>
gam <UserTypeEntity> import message <MessageContent>
gam <UserTypeEntity> insert messageo <MessageContent>
gam <UserTypeEntity> create sendas <SendAsContent>
gam <UserTypeEntity> update sendas <SendAsContent>
gam <UserTypeEntity> signature <SignatureContent>
gam <UserTypeEntity> vacation subject <String> <VacationMessageContent>
```
The `<RegularExpression>` is used as a match pattern against `<UserReplacement>` to produce `<ReplacementString>`.
Instances of `{Tag}` will be replaced by `<ReplacementString>` in the indicated items.
For example, when adding a phone number to a signature, an unformatted number can be formatted:
```
replaceregex "(\d{3})(\d{3})(\d{4})" "(\1) \2-\3" Phone "9876543210"
replaces 9876543210 with (987) 654-3210
replaceregex "(\+\d{2})(\d{3})(\d{3})(\d{3})" "\1 \2 \3 \4" Phone "+61987654321"
replaces +61421221506 with +61 987 654 321
```
7.05.18 7.05.18
Updated `gam calendars <CalendarEntity> show events` and `gam <UserTypeEntity> show events` Updated `gam calendars <CalendarEntity> show events` and `gam <UserTypeEntity> show events`

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.05.18' __version__ = '7.05.19'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -14517,7 +14517,13 @@ def _initTagReplacements():
'fieldsSet': set(), 'fields': '', 'fieldsSet': set(), 'fields': '',
'schemasSet': set(), 'customFieldMask': None} 'schemasSet': set(), 'customFieldMask': None}
def _getTagReplacement(tagReplacements, allowSubs): def _getTagReplacement(myarg, tagReplacements, allowSubs):
if myarg == 'replace':
trregex = None
elif myarg == 'replaceregex':
trregex = (getREPattern(re.IGNORECASE), getString(Cmd.OB_STRING, minLen=0))
else:
return False
matchTag = getString(Cmd.OB_TAG) matchTag = getString(Cmd.OB_TAG)
matchReplacement = getString(Cmd.OB_STRING, minLen=0) matchReplacement = getString(Cmd.OB_STRING, minLen=0)
if matchReplacement.startswith('field:'): if matchReplacement.startswith('field:'):
@@ -14562,7 +14568,8 @@ def _getTagReplacement(tagReplacements, allowSubs):
tagReplacements['fieldsSet'].add(field) tagReplacements['fieldsSet'].add(field)
tagReplacements['fields'] = ','.join(tagReplacements['fieldsSet']) tagReplacements['fields'] = ','.join(tagReplacements['fieldsSet'])
tagReplacements['tags'][matchTag] = {'field': field, 'subfield': subfield, tagReplacements['tags'][matchTag] = {'field': field, 'subfield': subfield,
'matchfield': matchfield, 'matchvalue': matchvalue, 'value': ''} 'matchfield': matchfield, 'matchvalue': matchvalue, 'value': '',
'trregex': trregex}
if field == 'locations' and subfield == 'buildingName': if field == 'locations' and subfield == 'buildingName':
_makeBuildingIdNameMap() _makeBuildingIdNameMap()
elif matchReplacement.startswith('schema:'): elif matchReplacement.startswith('schema:'):
@@ -14580,15 +14587,24 @@ def _getTagReplacement(tagReplacements, allowSubs):
tagReplacements['fields'] = ','.join(tagReplacements['fieldsSet']) tagReplacements['fields'] = ','.join(tagReplacements['fieldsSet'])
tagReplacements['schemasSet'].add(schemaName) tagReplacements['schemasSet'].add(schemaName)
tagReplacements['customFieldMask'] = ','.join(tagReplacements['schemasSet']) tagReplacements['customFieldMask'] = ','.join(tagReplacements['schemasSet'])
tagReplacements['tags'][matchTag] = {'schema': schemaName, 'schemafield': schemaField, 'value': ''} tagReplacements['tags'][matchTag] = {'schema': schemaName, 'schemafield': schemaField, 'value': '',
'trregex': trregex}
elif ((matchReplacement.find('#') >= 0) and elif ((matchReplacement.find('#') >= 0) and
(matchReplacement.find('#user#') >= 0) or (matchReplacement.find('#email#') >= 0) or (matchReplacement.find('#username#') >= 0)): (matchReplacement.find('#user#') >= 0) or (matchReplacement.find('#email#') >= 0) or (matchReplacement.find('#username#') >= 0)):
if not allowSubs: if not allowSubs:
usageErrorExit(Msg.USER_SUBS_NOT_ALLOWED_TAG_REPLACEMENT) usageErrorExit(Msg.USER_SUBS_NOT_ALLOWED_TAG_REPLACEMENT)
tagReplacements['subs'] = True tagReplacements['subs'] = True
tagReplacements['tags'][matchTag] = {'template': matchReplacement, 'value': ''} tagReplacements['tags'][matchTag] = {'template': matchReplacement, 'value': '',
'trregex': trregex}
else: else:
tagReplacements['tags'][matchTag] = {'value': matchReplacement} if trregex is None:
tagReplacements['tags'][matchTag] = {'value': matchReplacement}
else:
try:
tagReplacements['tags'][matchTag] = {'value': re.sub(trregex[0], trregex[1], matchReplacement)}
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(trregex[1], str(e)))
return True
def _getTagReplacementFieldValues(user, i, count, tagReplacements, results=None): def _getTagReplacementFieldValues(user, i, count, tagReplacements, results=None):
if results is None: if results is None:
@@ -14670,6 +14686,12 @@ def _getTagReplacementFieldValues(user, i, count, tagReplacements, results=None)
tag['value'] = str(results.get('customSchemas', {}).get(tag['schema'], {}).get(tag['schemafield'], '')) tag['value'] = str(results.get('customSchemas', {}).get(tag['schema'], {}).get(tag['schemafield'], ''))
elif tag.get('template'): elif tag.get('template'):
tag['value'] = _substituteForUser(tag['template'], user, userName) tag['value'] = _substituteForUser(tag['template'], user, userName)
trregex = tag.get('trregex', None)
if trregex is not None:
try:
tag['value'] = re.sub(trregex[0], trregex[1], tag['value'])
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(trregex[1], str(e)))
RTL_PATTERN = re.compile(r'(?s){RTL}.*?{/RTL}') RTL_PATTERN = re.compile(r'(?s){RTL}.*?{/RTL}')
RT_PATTERN = re.compile(r'(?s){RT}.*?{/RT}') RT_PATTERN = re.compile(r'(?s){RT}.*?{/RT}')
@@ -14922,7 +14944,9 @@ def getRecipients():
# gam sendemail [recipient|to] <RecipientEntity> [from <EmailAddress>] [mailbox <EmailAddress>] [replyto <EmailAddress>] # gam sendemail [recipient|to] <RecipientEntity> [from <EmailAddress>] [mailbox <EmailAddress>] [replyto <EmailAddress>]
# [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] # [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
# [subject <String>] # [subject <String>]
# [<MessageContent>] (replace <Tag> <String>)* # [<MessageContent>]
# (replace <Tag> <String>)*
# (replaceregex <RegularExpression> <String> <Tag> <String>)*
# [html [<Boolean>]] (attach <FileName> [charset <CharSet>])* # [html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
# (embedimage <FileName> <String>)* # (embedimage <FileName> <String>)*
# [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] # [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
@@ -14930,7 +14954,9 @@ def getRecipients():
# gam <UserTypeEntity> sendemail recipient <RecipientEntity> [replyto <EmailAddress>] # gam <UserTypeEntity> sendemail recipient <RecipientEntity> [replyto <EmailAddress>]
# [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] # [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
# [subject <String>] # [subject <String>]
# [<MessageContent>] (replace <Tag> <String>)* # [<MessageContent>]
# (replace <Tag> <String>)*
# (replaceregex <RegularExpression> <String> <Tag> <String>)*
# [html [<Boolean>]] (attach <FileName> [charset <CharSet>])* # [html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
# (embedimage <FileName> <String>)* # (embedimage <FileName> <String>)*
# [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] # [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
@@ -14938,7 +14964,9 @@ def getRecipients():
# gam <UserTypeEntity> sendemail from <EmailAddress> [replyto <EmailAddress>] # gam <UserTypeEntity> sendemail from <EmailAddress> [replyto <EmailAddress>]
# [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage] # [cc <RecipientEntity>] [bcc <RecipientEntity>] [singlemessage]
# [subject <String>] # [subject <String>]
# [<MessageContent>] (replace <Tag> <String>)* # [<MessageContent>]
# (replace <Tag> <String>)*
# (replaceregex <RegularExpression> <String> <Tag> <String>)*
# [html [<Boolean>]] (attach <FileName> [charset <CharSet>])* # [html [<Boolean>]] (attach <FileName> [charset <CharSet>])*
# (embedimage <FileName> <String>)* # (embedimage <FileName> <String>)*
# [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>] # [newuser <EmailAddress> firstname|givenname <String> lastname|familyname <string> password <Password>]
@@ -15001,8 +15029,8 @@ def doSendEmail(users=None):
body['name']['familyName'] = getString(Cmd.OB_STRING, minLen=0, maxLen=60) body['name']['familyName'] = getString(Cmd.OB_STRING, minLen=0, maxLen=60)
elif myarg in {'password', 'notifypassword'}: elif myarg in {'password', 'notifypassword'}:
body['password'] = notify['password'] = getString(Cmd.OB_PASSWORD, maxLen=100) body['password'] = notify['password'] = getString(Cmd.OB_PASSWORD, maxLen=100)
elif myarg == 'replace': elif _getTagReplacement(myarg, tagReplacements, False):
_getTagReplacement(tagReplacements, False) pass
elif myarg == 'attach': elif myarg == 'attach':
attachments.append((getFilename(), getCharSet())) attachments.append((getFilename(), getCharSet()))
elif myarg == 'embedimage': elif myarg == 'embedimage':
@@ -39081,7 +39109,10 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
if 'description' in updateFieldList and 'description' in event: if 'description' in updateFieldList and 'description' in event:
body['description'] = event['description'] body['description'] = event['description']
for replacement in parameters['replaceDescription']: for replacement in parameters['replaceDescription']:
body['description'] = re.sub(replacement[0], replacement[1], body['description']) try:
body['description'] = re.sub(replacement[0], replacement[1], body['description'])
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(replacement[1], str(e)))
if 'attendees' in updateFieldList: if 'attendees' in updateFieldList:
if not parameters['clearAttendees']: if not parameters['clearAttendees']:
if 'attendees' in event: if 'attendees' in event:
@@ -42835,8 +42866,8 @@ def getUserAttributes(cd, updateCmd, noUid=False):
notify['mailbox'] = getString(Cmd.OB_EMAIL_ADDRESS) notify['mailbox'] = getString(Cmd.OB_EMAIL_ADDRESS)
elif PwdOpts.ProcessArgument(myarg, notify, notFoundBody): elif PwdOpts.ProcessArgument(myarg, notify, notFoundBody):
pass pass
elif myarg == 'replace': elif _getTagReplacement(myarg, tagReplacements, True):
_getTagReplacement(tagReplacements, True) pass
elif myarg == 'admin': elif myarg == 'admin':
value = getBoolean() value = getBoolean()
if updateCmd or value: if updateCmd or value:
@@ -43253,9 +43284,9 @@ def createUserAddAliases(cd, user, aliasList, i, count):
# [from <EmailAaddress>] # [from <EmailAaddress>]
# [replyto <EmailAaddress>] # [replyto <EmailAaddress>]
# [<NotifyMessageContent>] # [<NotifyMessageContent>]
# (replace <Tag> <UserReplacement>)*] # (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
# [logpassword <FileName>] [ignorenullpassword] # [logpassword <FileName>] [ignorenullpassword]
# [verifynotinvitable]
# [addnumericsuffixonduplicate <Number>] # [addnumericsuffixonduplicate <Number>]
def doCreateUser(): def doCreateUser():
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
@@ -43354,8 +43385,9 @@ def verifyUserPrimaryEmail(cd, user, createIfNotFound, i, count):
# [notifypassword <String>] # [notifypassword <String>]
# [from <EmailAaddress>] # [from <EmailAaddress>]
# [replyto <EmailAaddress>] # [replyto <EmailAaddress>]
# [<NotifyMessageContent>] # [<NotifyMessageContent>
# (replace <Tag> <UserReplacement>)*] # (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
# [notifyonupdate [<Boolean>]] # [notifyonupdate [<Boolean>]]
# [logpassword <FileName>] [ignorenullpassword] # [logpassword <FileName>] [ignorenullpassword]
def updateUsers(entityList): def updateUsers(entityList):
@@ -57348,7 +57380,10 @@ def writeReturnIdLink(returnIdLink, mimeType, result):
def processFilenameReplacements(name, replacements): def processFilenameReplacements(name, replacements):
for replacement in replacements: for replacement in replacements:
name = re.sub(replacement[0], replacement[1], name) try:
name = re.sub(replacement[0], replacement[1], name)
except re.error as e:
systemErrorExit(ACTION_FAILED_RC, Msg.REGEX_REPLACEMENT_ERROR.format(replacement[1], str(e)))
return name return name
def addTimestampToFilename(parameters, body): def addTimestampToFilename(parameters, body):
@@ -69991,8 +70026,8 @@ def _draftImportInsertMessage(users, operation):
internalDateSource = 'dateHeader' internalDateSource = 'dateHeader'
if checkArgumentPresent('emlutf8'): if checkArgumentPresent('emlutf8'):
emlEncoding = UTF8 emlEncoding = UTF8
elif myarg == 'replace': elif _getTagReplacement(myarg, tagReplacements, True):
_getTagReplacement(tagReplacements, True) pass
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':
@@ -70127,7 +70162,9 @@ def _draftImportInsertMessage(users, operation):
userGmailServiceNotEnabledWarning(user, i, count) userGmailServiceNotEnabledWarning(user, i, count)
# gam <UserTypeEntity> draft message # gam <UserTypeEntity> draft message
# <MessageContent> (replace <Tag> <UserReplacement>)* # <MessageContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
# (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* # (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
# (attach <FileName> [charset <CharSet>])* # (attach <FileName> [charset <CharSet>])*
# (embedimage <FileName> <String>)* # (embedimage <FileName> <String>)*
@@ -70135,7 +70172,9 @@ def draftMessage(users):
_draftImportInsertMessage(users, 'draft') _draftImportInsertMessage(users, 'draft')
# gam <UserTypeEntity> import message # gam <UserTypeEntity> import message
# <MessageContent> (replace <Tag> <UserReplacement>)* # <MessageContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
# (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* # (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
# (addlabel <LabelName>)* [labels <LabelNameList>] # (addlabel <LabelName>)* [labels <LabelNameList>]
# (attach <FileName> [charset <CharSet>])* # (attach <FileName> [charset <CharSet>])*
@@ -70145,7 +70184,9 @@ def importMessage(users):
_draftImportInsertMessage(users, 'import') _draftImportInsertMessage(users, 'import')
# gam <UserTypeEntity> insert message # gam <UserTypeEntity> insert message
# <MessageContent> (replace <Tag> <UserReplacement>)* # <MessageContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*
# (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)* # (<SMTPDateHeader> <Time>)* (<SMTPHeader> <String>)* (header <String> <String>)*
# (addlabel <LabelName>)* [labels <LabelNameList>] # (addlabel <LabelName>)* [labels <LabelNameList>]
# (attach <FileName> [charset <CharSet>])* # (attach <FileName> [charset <CharSet>])*
@@ -72432,8 +72473,8 @@ def _processSendAs(user, i, count, entityType, emailAddress, j, jcount, gmail, f
return userDefined return userDefined
def getSendAsAttributes(myarg, body, tagReplacements): def getSendAsAttributes(myarg, body, tagReplacements):
if myarg == 'replace': if _getTagReplacement(myarg, tagReplacements, True):
_getTagReplacement(tagReplacements, True) pass
elif myarg == 'name': elif myarg == 'name':
body['displayName'] = getString(Cmd.OB_NAME, minLen=0) body['displayName'] = getString(Cmd.OB_NAME, minLen=0)
elif myarg == 'replyto': elif myarg == 'replyto':
@@ -72452,13 +72493,17 @@ SMTPMSA_SECURITY_MODES = ['none', 'ssl', 'starttls']
SMTPMSA_REQUIRED_FIELDS = ['host', 'port', 'username', 'password'] SMTPMSA_REQUIRED_FIELDS = ['host', 'port', 'username', 'password']
# gam <UserTypeEntity> [create] sendas <EmailAddress> [name] <String> # gam <UserTypeEntity> [create] sendas <EmailAddress> [name] <String>
# [<SendAsContent> (replace <Tag> <UserReplacement>)*] # [<SendAsContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
# [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] # [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
# [smtpmsa.host <SMTPHostName> smtpmsa.port 25|465|587 # [smtpmsa.host <SMTPHostName> smtpmsa.port 25|465|587
# smtpmsa.username <UserName> smtpmsa.password <Password> # smtpmsa.username <UserName> smtpmsa.password <Password>
# [smtpmsa.securitymode none|ssl|starttls]] # [smtpmsa.securitymode none|ssl|starttls]]
# gam <UserTypeEntity> update sendas <EmailAddress> [name <String>] # gam <UserTypeEntity> update sendas <EmailAddress> [name <String>]
# [<SendAsContent> (replace <Tag> <UserReplacement>)*] # [<SendAsContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
# [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] # [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
def createUpdateSendAs(users): def createUpdateSendAs(users):
updateCmd = Act.Get() == Act.UPDATE updateCmd = Act.Get() == Act.UPDATE
@@ -73295,6 +73340,7 @@ def printShowCSEKeyPairs(users):
# gam <UserTypeEntity> signature|sig # gam <UserTypeEntity> signature|sig
# <SignatureContent> # <SignatureContent>
# (replace <Tag> <String>)* # (replace <Tag> <String>)*
# (replaceregex <RegularExpression> <String> <Tag> <String>)*
# [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>] # [html [<Boolean>]] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
# [name <String>] # [name <String>]
# [primary] # [primary]
@@ -73388,7 +73434,9 @@ def _showVacation(user, i, count, result, showDisabled, sigReplyFormat):
Ind.Decrement() Ind.Decrement()
# gam <UserTypeEntity> vacation [<Boolean>] [subject <String>] # gam <UserTypeEntity> vacation [<Boolean>] [subject <String>]
# [<VacationMessageContent> (replace <Tag> <UserReplacement>)*] # [<VacationMessageContent>
# (replace <Tag> <UserReplacement>)*
# (replaceregex <RegularExpression> <String> <Tag> <UserReplacement>)*]
# [html [<Boolean>]] [contactsonly [<Boolean>]] [domainonly [<Boolean>]] # [html [<Boolean>]] [contactsonly [<Boolean>]] [domainonly [<Boolean>]]
# [start|startdate <Date>|Started] [end|enddate <Date>|NotSpecified] # [start|startdate <Date>|Started] [end|enddate <Date>|NotSpecified]
def setVacation(users): def setVacation(users):
@@ -73406,8 +73454,8 @@ def setVacation(users):
message, _, html = getStringOrFile(myarg) message, _, html = getStringOrFile(myarg)
if html: if html:
responseBodyType = 'responseBodyHtml' responseBodyType = 'responseBodyHtml'
elif myarg == 'replace': elif _getTagReplacement(myarg, tagReplacements, True):
_getTagReplacement(tagReplacements, True) pass
elif myarg == 'html': elif myarg == 'html':
if getBoolean(): if getBoolean():
responseBodyType = 'responseBodyHtml' responseBodyType = 'responseBodyHtml'

View File

@@ -465,6 +465,7 @@ REASON_ONLY_VALID_WITH_CONTENTRESTRICTIONS_READONLY_TRUE = 'reason only valid wi
REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create' REAUTHENTICATION_IS_NEEDED = 'Reauthentication is needed, please run\n\ngam oauth create'
RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n' RECOMMEND_RUNNING_GAM_ROTATE_SAKEY = 'Recommend running "gam rotate sakey" to get a new key\n'
REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.' REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because acknowledge_device_touch_requirement not specified.\nDeprovisioning a device means the device will have to be physically wiped and re-enrolled to be managed by your domain again.\nThis requires physical access to the device and is very time consuming to perform for each device.\nPlease add "acknowledge_device_touch_requirement" to the GAM command if you understand this and wish to proceed with the deprovision.\nPlease also be aware that deprovisioning can have an effect on your device license count.\nSee https://support.google.com/chrome/a/answer/3523633 for full details.'
REGEX_REPLACEMENT_ERROR = 'Regular expression replacement string "{0}" error: {1}'
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>' REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again' REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}' REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'