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:
Ross Scroggs
2018-11-19 08:56:41 -08:00
committed by Jay Lee
parent fe3c043d61
commit 610dbd4dcf
3 changed files with 110 additions and 10 deletions

View File

@ -212,6 +212,7 @@ If an item contains spaces, it should be surrounded by ".
<Section> ::= <String>
<SerialNumber> ::= <String>
<S/MIMEID> ::= <String>
<SMTPHostName> ::= <String>
<StudentItem> ::= <EmailAddress>|<UniqueID>|<String>
<TeamDriveID> ::= <String>
<Timezone> ::= <String>
@ -219,6 +220,7 @@ If an item contains spaces, it should be surrounded by ".
<URI> ::= <String>
<URL> ::= <String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
<UserName> ::= <<String>
<CourseFieldName> ::=
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]
[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 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> [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> delete sendas <EmailAddress>
gam <UserTypeEntity> show sendas [format]

View File

@ -5029,6 +5029,8 @@ def getPop(users):
else:
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):
if result[u'displayName']:
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))
if not result.get(u'isPrimary', 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 ')
signature = result.get(u'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))
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):
emailAddress = normalizeEmailAddressOrUID(sys.argv[i], noUid=True)
i += 1
@ -5109,6 +5120,7 @@ def addUpdateSendAs(users, i, addCmd):
command = u'update sendas'
body = {}
signature = None
smtpMsa = {}
tagReplacements = {}
html = False
while i < len(sys.argv):
@ -5123,10 +5135,39 @@ def addUpdateSendAs(users, i, addCmd):
elif myarg == u'html':
html = True
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:
i = getSendAsAttributes(i, myarg, body, tagReplacements, command)
if signature is not None:
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}
if not addCmd:
kwargs[u'sendAsEmail'] = emailAddress
@ -5313,9 +5354,17 @@ def printShowSendAs(users, csvFormat):
for sendas in result[u'sendAs']:
row = {u'User': user, u'isPrimary': False}
for item in sendas:
if item not in titles:
titles.append(item)
row[item] = sendas[item]
if item != u'smtpMsa':
if item not in titles:
titles.append(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)
if csvFormat:
writeCSVfile(csvRows, titles, u'SendAs', todrive)
@ -11629,18 +11678,18 @@ def doPrintCrosDevices():
sortCSVTitles([u'deviceId',], titles)
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')
products = []
licenses = []
licenseCounts = []
if not returnFields:
titles = [u'userId', u'productId', u'skuId']
csvRows = []
todrive = False
i = 3
while i < len(sys.argv):
myarg = sys.argv[i].lower()
if myarg == u'todrive':
if not returnCounts and myarg == u'todrive':
todrive = True
i += 1
elif myarg in [u'products', u'product']:
@ -11649,9 +11698,29 @@ def doPrintLicenses(returnFields=None, skus=None):
elif myarg in [u'sku', u'skus']:
skus = sys.argv[i+1].split(u',')
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:
systemErrorExit(2, '%s is not a valid argument for "gam print licenses"' % sys.argv[i])
fields = u'nextPageToken,items(productId,skuId,userId)'
if not countsOnly:
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:
fields = u'nextPageToken,items({0})'.format(returnFields)
if skus:
@ -11661,6 +11730,9 @@ def doPrintLicenses(returnFields=None, skus=None):
try:
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)
if countsOnly:
licenseCounts.append([u'Product', product, u'SKU', sku, u'Licenses', len(licenses)])
licenses = []
except (GAPI_invalid, GAPI_forbidden):
pass
else:
@ -11674,8 +11746,22 @@ def doPrintLicenses(returnFields=None, skus=None):
try:
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)
if countsOnly:
licenseCounts.append([u'Product', productId, u'Licenses', len(licenses)])
licenses = []
except (GAPI_invalid, GAPI_forbidden):
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 == u'userId':
userIds = []
@ -11700,6 +11786,14 @@ def doPrintLicenses(returnFields=None, skus=None):
u'skuId': _skuIdToDisplayName(skuId)})
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_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',]
@ -12868,6 +12962,8 @@ def ProcessGAMCommand(args):
doPrintShowUserSchemas(False)
elif argument in [u'guardian', u'guardians']:
doPrintShowGuardians(False)
elif argument in [u'license', u'licenses', u'licence', u'licences']:
doShowLicenses()
else:
systemErrorExit(2, '%s is not a valid argument for "gam show"' % argument)
sys.exit(0)

View File

@ -50,7 +50,7 @@ SKUS = {
u'1010050001': {
u'product': u'101005', u'aliases': [u'identitypremium', u'cloudidentitypremium'], u'displayName': 'Cloud Identity Premium'},
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'product': u'Google-Apps', u'aliases': [u'standard', u'free'], u'displayName': u'G Suite Free/Standard'},
u'Google-Apps-For-Business': {