mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-06 22:01:36 +00:00
Add smtpMsa options to create sendas; update license commands (#814)
* Add smtpMsa options to create sendas This allows sendas addresses outside of your domain * Update licenses commands Add gam show licenses Add countsonly option to gam print licenses Add allskus and gsuite selection options
This commit is contained in:
@@ -212,6 +212,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
<Section> ::= <String>
|
<Section> ::= <String>
|
||||||
<SerialNumber> ::= <String>
|
<SerialNumber> ::= <String>
|
||||||
<S/MIMEID> ::= <String>
|
<S/MIMEID> ::= <String>
|
||||||
|
<SMTPHostName> ::= <String>
|
||||||
<StudentItem> ::= <EmailAddress>|<UniqueID>|<String>
|
<StudentItem> ::= <EmailAddress>|<UniqueID>|<String>
|
||||||
<TeamDriveID> ::= <String>
|
<TeamDriveID> ::= <String>
|
||||||
<Timezone> ::= <String>
|
<Timezone> ::= <String>
|
||||||
@@ -219,6 +220,7 @@ If an item contains spaces, it should be surrounded by ".
|
|||||||
<URI> ::= <String>
|
<URI> ::= <String>
|
||||||
<URL> ::= <String>
|
<URL> ::= <String>
|
||||||
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
|
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
|
||||||
|
<UserName> ::= <<String>
|
||||||
|
|
||||||
<CourseFieldName> ::=
|
<CourseFieldName> ::=
|
||||||
alternatelink|
|
alternatelink|
|
||||||
@@ -984,7 +986,8 @@ gam print group-members|groups-members [todrive]
|
|||||||
([domain <DomainName>] ([member <UserItem>]|[query <QueryGroup>]))|[group|group_ns|group_susp <GroupItem>] [notsuspended|suspended]
|
([domain <DomainName>] ([member <UserItem>]|[query <QueryGroup>]))|[group|group_ns|group_susp <GroupItem>] [notsuspended|suspended]
|
||||||
[roles <GroupRoleList>] [membernames] [fields <MembersFieldNameList>]
|
[roles <GroupRoleList>] [membernames] [fields <MembersFieldNameList>]
|
||||||
|
|
||||||
gam print license|licenses|licence|licences [todrive] [(products|product <ProductIDList>)|(skus|sku <SKUIDList>)]
|
gam print licenses [todrive] [(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite] [countsonly]
|
||||||
|
gam show license|licenses|licence|licences [(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite]
|
||||||
|
|
||||||
gam update notification|notifications [(id all)|(id <NotificationID>)*] unread|read
|
gam update notification|notifications [(id all)|(id <NotificationID>)*] unread|read
|
||||||
gam delete notification|notifications [(id all)|(id <NotificationID>)*]
|
gam delete notification|notifications [(id all)|(id <NotificationID>)*]
|
||||||
@@ -1230,6 +1233,7 @@ gam <UserTypeEntity> pop|pop3 <Boolean> [for allmail|newmail|mailfromnowon|fromn
|
|||||||
gam <UserTypeEntity> show pop|pop3
|
gam <UserTypeEntity> show pop|pop3
|
||||||
|
|
||||||
gam <UserTypeEntity> [create|add] sendas <EmailAddress> <Name> [signature|sig <String>|(file <FileName> [charset <Charset>]) (replace <Tag> <String>)*] [html] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
|
gam <UserTypeEntity> [create|add] sendas <EmailAddress> <Name> [signature|sig <String>|(file <FileName> [charset <Charset>]) (replace <Tag> <String>)*] [html] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
|
||||||
|
[smtpmsa.host <SMTPHostName> smtpmsa.port 25|465|587 smtpmsa.username <UserName> smtpmsa.password <Password> [smtpmsa.securitymode none|ssl|starttls]]
|
||||||
gam <UserTypeEntity> update sendas <EmailAddress> [name <Name>] [signature|sig <String>|(file <FileName> [charset <Charset>]) (replace <Tag> <String>)*] [html] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
|
gam <UserTypeEntity> update sendas <EmailAddress> [name <Name>] [signature|sig <String>|(file <FileName> [charset <Charset>]) (replace <Tag> <String>)*] [html] [replyto <EmailAddress>] [default] [treatasalias <Boolean>]
|
||||||
gam <UserTypeEntity> delete sendas <EmailAddress>
|
gam <UserTypeEntity> delete sendas <EmailAddress>
|
||||||
gam <UserTypeEntity> show sendas [format]
|
gam <UserTypeEntity> show sendas [format]
|
||||||
|
|||||||
104
src/gam.py
104
src/gam.py
@@ -5029,6 +5029,8 @@ def getPop(users):
|
|||||||
else:
|
else:
|
||||||
print u'User: {0}, POP Enabled: {1} ({2}/{3})'.format(user, enabled, i, count)
|
print u'User: {0}, POP Enabled: {1} ({2}/{3})'.format(user, enabled, i, count)
|
||||||
|
|
||||||
|
SMTPMSA_DISPLAY_FIELDS = [u'host', u'port', u'securityMode']
|
||||||
|
|
||||||
def _showSendAs(result, j, jcount, formatSig):
|
def _showSendAs(result, j, jcount, formatSig):
|
||||||
if result[u'displayName']:
|
if result[u'displayName']:
|
||||||
print utils.convertUTF8(u'SendAs Address: {0} <{1}>{2}'.format(result[u'displayName'], result[u'sendAsEmail'], currentCount(j, jcount)))
|
print utils.convertUTF8(u'SendAs Address: {0} <{1}>{2}'.format(result[u'displayName'], result[u'sendAsEmail'], currentCount(j, jcount)))
|
||||||
@@ -5040,7 +5042,12 @@ def _showSendAs(result, j, jcount, formatSig):
|
|||||||
print u' Default: {0}'.format(result.get(u'isDefault', False))
|
print u' Default: {0}'.format(result.get(u'isDefault', False))
|
||||||
if not result.get(u'isPrimary', False):
|
if not result.get(u'isPrimary', False):
|
||||||
print u' TreatAsAlias: {0}'.format(result.get(u'treatAsAlias', False))
|
print u' TreatAsAlias: {0}'.format(result.get(u'treatAsAlias', False))
|
||||||
print u' Verification Status: {0}'.format(result.get(u'verificationStatus', u'unspecified'))
|
if u'smtpMsa' in result:
|
||||||
|
for field in SMTPMSA_DISPLAY_FIELDS:
|
||||||
|
if field in result[u'smtpMsa']:
|
||||||
|
print u' smtpMsa.{0}: {1}'.format(field, result[u'smtpMsa'][field])
|
||||||
|
if u'verificationStatus' in result:
|
||||||
|
print u' Verification Status: {0}'.format(result[u'verificationStatus'])
|
||||||
sys.stdout.write(u' Signature:\n ')
|
sys.stdout.write(u' Signature:\n ')
|
||||||
signature = result.get(u'signature')
|
signature = result.get(u'signature')
|
||||||
if not signature:
|
if not signature:
|
||||||
@@ -5098,6 +5105,10 @@ def getSendAsAttributes(i, myarg, body, tagReplacements, command):
|
|||||||
systemErrorExit(2, '%s is not a valid argument for "gam <users> %s"' % (sys.argv[i], command))
|
systemErrorExit(2, '%s is not a valid argument for "gam <users> %s"' % (sys.argv[i], command))
|
||||||
return i
|
return i
|
||||||
|
|
||||||
|
SMTPMSA_PORTS = [u'25', u'465', u'587']
|
||||||
|
SMTPMSA_SECURITY_MODES = [u'none', u'ssl', u'starttls']
|
||||||
|
SMTPMSA_REQUIRED_FIELDS = [u'host', u'port', u'username', u'password']
|
||||||
|
|
||||||
def addUpdateSendAs(users, i, addCmd):
|
def addUpdateSendAs(users, i, addCmd):
|
||||||
emailAddress = normalizeEmailAddressOrUID(sys.argv[i], noUid=True)
|
emailAddress = normalizeEmailAddressOrUID(sys.argv[i], noUid=True)
|
||||||
i += 1
|
i += 1
|
||||||
@@ -5109,6 +5120,7 @@ def addUpdateSendAs(users, i, addCmd):
|
|||||||
command = u'update sendas'
|
command = u'update sendas'
|
||||||
body = {}
|
body = {}
|
||||||
signature = None
|
signature = None
|
||||||
|
smtpMsa = {}
|
||||||
tagReplacements = {}
|
tagReplacements = {}
|
||||||
html = False
|
html = False
|
||||||
while i < len(sys.argv):
|
while i < len(sys.argv):
|
||||||
@@ -5123,10 +5135,39 @@ def addUpdateSendAs(users, i, addCmd):
|
|||||||
elif myarg == u'html':
|
elif myarg == u'html':
|
||||||
html = True
|
html = True
|
||||||
i += 1
|
i += 1
|
||||||
|
elif addCmd and myarg.startswith(u'smtpmsa.'):
|
||||||
|
if myarg == u'smtpmsa.host':
|
||||||
|
smtpMsa[u'host'] = sys.argv[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == u'smtpmsa.port':
|
||||||
|
value = sys.argv[i+1].lower()
|
||||||
|
if value not in SMTPMSA_PORTS:
|
||||||
|
systemErrorExit(2, '{0} must be {1}; got {2}'.format(myarg, u', '.join(SMTPMSA_PORTS), value))
|
||||||
|
smtpMsa[u'port'] = int(value)
|
||||||
|
i += 2
|
||||||
|
elif myarg == u'smtpmsa.username':
|
||||||
|
smtpMsa[u'username'] = sys.argv[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == u'smtpmsa.password':
|
||||||
|
smtpMsa[u'password'] = sys.argv[i+1]
|
||||||
|
i += 2
|
||||||
|
elif myarg == u'smtpmsa.securitymode':
|
||||||
|
value = sys.argv[i+1].lower()
|
||||||
|
if value not in SMTPMSA_SECURITY_MODES:
|
||||||
|
systemErrorExit(2, '{0} must be {1}; got {2}'.format(myarg, u', '.join(SMTPMSA_SECURITY_MODES), value))
|
||||||
|
smtpMsa[u'securityMode'] = value
|
||||||
|
i += 2
|
||||||
|
else:
|
||||||
|
systemErrorExit(2, '%s is not a valid argument for "gam <users> %s"' % (sys.argv[i], command))
|
||||||
else:
|
else:
|
||||||
i = getSendAsAttributes(i, myarg, body, tagReplacements, command)
|
i = getSendAsAttributes(i, myarg, body, tagReplacements, command)
|
||||||
if signature is not None:
|
if signature is not None:
|
||||||
body[u'signature'] = _processSignature(tagReplacements, signature, html)
|
body[u'signature'] = _processSignature(tagReplacements, signature, html)
|
||||||
|
if smtpMsa:
|
||||||
|
for field in SMTPMSA_REQUIRED_FIELDS:
|
||||||
|
if field not in smtpMsa:
|
||||||
|
systemErrorExit(2, 'smtpmsa.{0} is required.'.format(field))
|
||||||
|
body[u'smtpMsa'] = smtpMsa
|
||||||
kwargs = {u'body': body}
|
kwargs = {u'body': body}
|
||||||
if not addCmd:
|
if not addCmd:
|
||||||
kwargs[u'sendAsEmail'] = emailAddress
|
kwargs[u'sendAsEmail'] = emailAddress
|
||||||
@@ -5313,9 +5354,17 @@ def printShowSendAs(users, csvFormat):
|
|||||||
for sendas in result[u'sendAs']:
|
for sendas in result[u'sendAs']:
|
||||||
row = {u'User': user, u'isPrimary': False}
|
row = {u'User': user, u'isPrimary': False}
|
||||||
for item in sendas:
|
for item in sendas:
|
||||||
|
if item != u'smtpMsa':
|
||||||
if item not in titles:
|
if item not in titles:
|
||||||
titles.append(item)
|
titles.append(item)
|
||||||
row[item] = sendas[item]
|
row[item] = sendas[item]
|
||||||
|
else:
|
||||||
|
for field in SMTPMSA_DISPLAY_FIELDS:
|
||||||
|
if field in sendas[item]:
|
||||||
|
title = u'smtpMsa.{0}'.format(field)
|
||||||
|
if title not in titles:
|
||||||
|
titles.append(title)
|
||||||
|
row[title] = sendas[item][field]
|
||||||
csvRows.append(row)
|
csvRows.append(row)
|
||||||
if csvFormat:
|
if csvFormat:
|
||||||
writeCSVfile(csvRows, titles, u'SendAs', todrive)
|
writeCSVfile(csvRows, titles, u'SendAs', todrive)
|
||||||
@@ -11629,18 +11678,18 @@ def doPrintCrosDevices():
|
|||||||
sortCSVTitles([u'deviceId',], titles)
|
sortCSVTitles([u'deviceId',], titles)
|
||||||
writeCSVfile(csvRows, titles, u'CrOS', todrive)
|
writeCSVfile(csvRows, titles, u'CrOS', todrive)
|
||||||
|
|
||||||
def doPrintLicenses(returnFields=None, skus=None):
|
def doPrintLicenses(returnFields=None, skus=None, countsOnly=False, returnCounts=False):
|
||||||
lic = buildGAPIObject(u'licensing')
|
lic = buildGAPIObject(u'licensing')
|
||||||
products = []
|
products = []
|
||||||
licenses = []
|
licenses = []
|
||||||
|
licenseCounts = []
|
||||||
if not returnFields:
|
if not returnFields:
|
||||||
titles = [u'userId', u'productId', u'skuId']
|
|
||||||
csvRows = []
|
csvRows = []
|
||||||
todrive = False
|
todrive = False
|
||||||
i = 3
|
i = 3
|
||||||
while i < len(sys.argv):
|
while i < len(sys.argv):
|
||||||
myarg = sys.argv[i].lower()
|
myarg = sys.argv[i].lower()
|
||||||
if myarg == u'todrive':
|
if not returnCounts and myarg == u'todrive':
|
||||||
todrive = True
|
todrive = True
|
||||||
i += 1
|
i += 1
|
||||||
elif myarg in [u'products', u'product']:
|
elif myarg in [u'products', u'product']:
|
||||||
@@ -11649,9 +11698,29 @@ def doPrintLicenses(returnFields=None, skus=None):
|
|||||||
elif myarg in [u'sku', u'skus']:
|
elif myarg in [u'sku', u'skus']:
|
||||||
skus = sys.argv[i+1].split(u',')
|
skus = sys.argv[i+1].split(u',')
|
||||||
i += 2
|
i += 2
|
||||||
|
elif myarg == u'allskus':
|
||||||
|
skus = sorted(SKUS.keys())
|
||||||
|
products = []
|
||||||
|
i += 1
|
||||||
|
elif myarg == u'gsuite':
|
||||||
|
skus = [skuId for skuId in SKUS if SKUS[skuId][u'product'] in [u'Google-Apps', u'101031']]
|
||||||
|
products = []
|
||||||
|
i += 1
|
||||||
|
elif myarg == u'countsonly':
|
||||||
|
countsOnly = True
|
||||||
|
i += 1
|
||||||
else:
|
else:
|
||||||
systemErrorExit(2, '%s is not a valid argument for "gam print licenses"' % sys.argv[i])
|
systemErrorExit(2, '%s is not a valid argument for "gam print licenses"' % sys.argv[i])
|
||||||
|
if not countsOnly:
|
||||||
fields = u'nextPageToken,items(productId,skuId,userId)'
|
fields = u'nextPageToken,items(productId,skuId,userId)'
|
||||||
|
titles = [u'userId', u'productId', u'skuId']
|
||||||
|
else:
|
||||||
|
fields = u'nextPageToken,items(userId)'
|
||||||
|
if not returnCounts:
|
||||||
|
if skus:
|
||||||
|
titles = [u'productId', u'skuId', u'licenses']
|
||||||
|
else:
|
||||||
|
titles = [u'productId', u'licenses']
|
||||||
else:
|
else:
|
||||||
fields = u'nextPageToken,items({0})'.format(returnFields)
|
fields = u'nextPageToken,items({0})'.format(returnFields)
|
||||||
if skus:
|
if skus:
|
||||||
@@ -11661,6 +11730,9 @@ def doPrintLicenses(returnFields=None, skus=None):
|
|||||||
try:
|
try:
|
||||||
licenses += callGAPIpages(lic.licenseAssignments(), u'listForProductAndSku', u'items', throw_reasons=[GAPI_INVALID, GAPI_FORBIDDEN], page_message=page_message,
|
licenses += callGAPIpages(lic.licenseAssignments(), u'listForProductAndSku', u'items', throw_reasons=[GAPI_INVALID, GAPI_FORBIDDEN], page_message=page_message,
|
||||||
customerId=GC_Values[GC_DOMAIN], productId=product, skuId=sku, fields=fields)
|
customerId=GC_Values[GC_DOMAIN], productId=product, skuId=sku, fields=fields)
|
||||||
|
if countsOnly:
|
||||||
|
licenseCounts.append([u'Product', product, u'SKU', sku, u'Licenses', len(licenses)])
|
||||||
|
licenses = []
|
||||||
except (GAPI_invalid, GAPI_forbidden):
|
except (GAPI_invalid, GAPI_forbidden):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -11674,8 +11746,22 @@ def doPrintLicenses(returnFields=None, skus=None):
|
|||||||
try:
|
try:
|
||||||
licenses += callGAPIpages(lic.licenseAssignments(), u'listForProduct', u'items', throw_reasons=[GAPI_INVALID, GAPI_FORBIDDEN], page_message=page_message,
|
licenses += callGAPIpages(lic.licenseAssignments(), u'listForProduct', u'items', throw_reasons=[GAPI_INVALID, GAPI_FORBIDDEN], page_message=page_message,
|
||||||
customerId=GC_Values[GC_DOMAIN], productId=productId, fields=fields)
|
customerId=GC_Values[GC_DOMAIN], productId=productId, fields=fields)
|
||||||
|
if countsOnly:
|
||||||
|
licenseCounts.append([u'Product', productId, u'Licenses', len(licenses)])
|
||||||
|
licenses = []
|
||||||
except (GAPI_invalid, GAPI_forbidden):
|
except (GAPI_invalid, GAPI_forbidden):
|
||||||
pass
|
pass
|
||||||
|
if countsOnly:
|
||||||
|
if returnCounts:
|
||||||
|
return licenseCounts
|
||||||
|
if skus:
|
||||||
|
for u_license in licenseCounts:
|
||||||
|
csvRows.append({u'productId': u_license[1], u'skuId': u_license[3], u'licenses': u_license[5]})
|
||||||
|
else:
|
||||||
|
for u_license in licenseCounts:
|
||||||
|
csvRows.append({u'productId': u_license[1], u'licenses': u_license[3]})
|
||||||
|
writeCSVfile(csvRows, titles, u'Licenses', todrive)
|
||||||
|
return
|
||||||
if returnFields:
|
if returnFields:
|
||||||
if returnFields == u'userId':
|
if returnFields == u'userId':
|
||||||
userIds = []
|
userIds = []
|
||||||
@@ -11700,6 +11786,14 @@ def doPrintLicenses(returnFields=None, skus=None):
|
|||||||
u'skuId': _skuIdToDisplayName(skuId)})
|
u'skuId': _skuIdToDisplayName(skuId)})
|
||||||
writeCSVfile(csvRows, titles, u'Licenses', todrive)
|
writeCSVfile(csvRows, titles, u'Licenses', todrive)
|
||||||
|
|
||||||
|
def doShowLicenses():
|
||||||
|
licenseCounts = doPrintLicenses(countsOnly=True, returnCounts=True)
|
||||||
|
for u_license in licenseCounts:
|
||||||
|
line = u''
|
||||||
|
for i in xrange(0, len(u_license), 2):
|
||||||
|
line += u'{0}: {1}, '.format(u_license[i], u_license[i+1])
|
||||||
|
print line[:-2]
|
||||||
|
|
||||||
RESCAL_DFLTFIELDS = [u'id', u'name', u'email',]
|
RESCAL_DFLTFIELDS = [u'id', u'name', u'email',]
|
||||||
RESCAL_ALLFIELDS = [u'id', u'name', u'email', u'description', u'type', u'buildingid', u'category', u'capacity',
|
RESCAL_ALLFIELDS = [u'id', u'name', u'email', u'description', u'type', u'buildingid', u'category', u'capacity',
|
||||||
u'features', u'floor', u'floorsection', u'generatedresourcename', u'uservisibledescription',]
|
u'features', u'floor', u'floorsection', u'generatedresourcename', u'uservisibledescription',]
|
||||||
@@ -12868,6 +12962,8 @@ def ProcessGAMCommand(args):
|
|||||||
doPrintShowUserSchemas(False)
|
doPrintShowUserSchemas(False)
|
||||||
elif argument in [u'guardian', u'guardians']:
|
elif argument in [u'guardian', u'guardians']:
|
||||||
doPrintShowGuardians(False)
|
doPrintShowGuardians(False)
|
||||||
|
elif argument in [u'license', u'licenses', u'licence', u'licences']:
|
||||||
|
doShowLicenses()
|
||||||
else:
|
else:
|
||||||
systemErrorExit(2, '%s is not a valid argument for "gam show"' % argument)
|
systemErrorExit(2, '%s is not a valid argument for "gam show"' % argument)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ SKUS = {
|
|||||||
u'1010050001': {
|
u'1010050001': {
|
||||||
u'product': u'101005', u'aliases': [u'identitypremium', u'cloudidentitypremium'], u'displayName': 'Cloud Identity Premium'},
|
u'product': u'101005', u'aliases': [u'identitypremium', u'cloudidentitypremium'], u'displayName': 'Cloud Identity Premium'},
|
||||||
u'1010310002': {
|
u'1010310002': {
|
||||||
u'product': u'101031', u'aliases': [u'gsefe', u'e4e'], u'displayName': u'G Suite Enterprise for Education'},
|
u'product': u'101031', u'aliases': [u'gsefe', u'e4e', u'gsuiteenterpriseeducation'], u'displayName': u'G Suite Enterprise for Education'},
|
||||||
u'Google-Apps': {
|
u'Google-Apps': {
|
||||||
u'product': u'Google-Apps', u'aliases': [u'standard', u'free'], u'displayName': u'G Suite Free/Standard'},
|
u'product': u'Google-Apps', u'aliases': [u'standard', u'free'], u'displayName': u'G Suite Free/Standard'},
|
||||||
u'Google-Apps-For-Business': {
|
u'Google-Apps-For-Business': {
|
||||||
|
|||||||
Reference in New Issue
Block a user