我发现了一个Powershell脚本,可以将Office 365用户同步到Mailchimp联系人。它运行良好,但唯一的问题是,我希望它要么"取消订阅";或";存档";Mailchimp IF中的联系人以前在Office 365中获得许可的用户不再具有任何活动许可。
现在,如果用户许可证在Office 365中更改,它将更新许可证,但如果所有许可证都已删除,则不会更新。我认为脚本中的以下一行是导致没有许可证的用户无法同步的原因,但我不知道补救的最佳方法…
$users = Get-MsolUser | Where-Object {$_.islicensed}
如果我将这一行更改为$users = Get-MsolUser -All
,那么它将检索用户,无论他们是否获得许可,但这仍然不能完全解决我的问题,因为我的目标仍然是只同步获得许可的用户,但要确保一旦O365用户未获得许可,他们将";取消订阅";或";存档的";在Mailchimp(两者都可以(。
我正在粘贴下面的整个脚本,并添加了一个<------在我上面提到的代码行旁边(大约是代码行的3/4(。任何关于我如何调整剧本以实现我的目标的想法都将不胜感激。
$user = "abc"
$apiKey = "544492bf22f6895d4ae-us15"
$pair = "${user}:${apiKey}"
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
$Headers = @{
Authorization = $basicAuthValue
}
$baseUri = "https://us15.api.mailchimp.com"
$listInfo = @{
listName = "Office 365 Customer Sync"
company = "abc"
address1 = "abc"
address2 = " "
city = "abc"
state = "NY"
zip = "11111"
country = "US"
phone = ""
permission_reminder = "You are receiving this email because you are a client of Abtech Technologies"
from_name = "John Doe"
from_email = "jdoe@email.com"
subject = ""
language = "en"
}
$Office365members = @()
Connect-MsolService
function Ensure-MailChimpList ($ListName) {
$lists = Invoke-RestMethod -URI $baseUri/3.0/lists?offset=0"&"count=100 -Method Get -Headers $Headers
if ($lists.lists.name -notcontains $ListName) {
$list = New-MailChimpList -ListInfo $listInfo
return $list
}
else {
$list = $lists.lists | Where-object {$_.name -contains $listName}
return $list
}
}
function New-MailChimpList ($ListInfo) {
$listBody = @{
name = $listInfo.listName
contact = @{
company = $listInfo.company
address1 = $listInfo.address1
address2 = $listInfo.address2
city = $listInfo.city
state = $listInfo.state
zip = $listInfo.zip
country = $listInfo.country
phone = $listInfo.phone
}
permission_reminder = $listInfo.permission_reminder
campaign_defaults = @{
from_name = $listInfo.from_name
from_email = $listInfo.from_email
subject = $listInfo.subject
language = $listInfo.language
}
email_type_option = $false
}
$listBody = $listBody | ConvertTo-Json
$newList = Invoke-RestMethod -URI $baseUri/3.0/lists -Method POST -Headers $Headers -Body $listBody
return $newList
}
function Get-MailChimpListSegments {
$segments = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/segments?offset=0"&"count=200 -Method Get -Headers $Headers
return $segments
}
function Get-MailChimpListMergeFields {
$mergeFields = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/merge-fields -Method Get -Headers $Headers
return $mergeFields
}
function New-MailChimpListMergeField ($Name, $Type, $Tag) {
$merge_field = @{
name = $Name
type = $Type
tag = $Tag
}
$merge_field = $merge_field | ConvertTo-Json
Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/merge-fields -Method POST -Headers $Headers -Body $merge_field
}
function New-MailChimpListBatch ($MemberBatch) {
$body = @{
members = $MemberBatch
update_existing = $true
}
$body = $body | ConvertTo-Json -Depth 10
$batchresult = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId -Method POST -Headers $Headers -Body $body
return $batchresult
}
function New-MailChimpListMember ($email, $FirstName, $LastName, $Company, $Licenses) {
$merge_fields = @{
FNAME = $FirstName
LNAME = $LastName
COMPANY = $Company
LICENSES = $Licenses
}
$member = @{
email_address = $email
status = "subscribed"
merge_fields = $merge_fields
}
return $member
}
function Update-MailChimpListMember ($ExistingMember, $Office365Member) {
$merge_fields = @{
FNAME = $Office365Member.FirstName
LNAME = $Office365Member.LastName
COMPANY = $Office365Member.Company
LICENSES = $Office365Member.Licenses
}
$member = @{
email_address = $Office365Member.Email
status = $existingMember.Status
merge_fields = $merge_fields
}
return $member
}
# function Unsubscribe-MailChimpListMember ($ExistingMember) {
# $member = @{
# email_address = $ExistingMember.Email
# status = "unsubscribed"
# }
# return $member
# Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/members/$($existingMember.SubscriberHash) -Method PATCH -Headers $Headers -Body $member
# }
function Get-ExistingMailChimpListMembers {
$existingMembers = $null
$existingmembers = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/members?offset=0"&"count=100 -Method Get -Headers $Headers
for ($i = 100; $i -le $existingMembers.total_items; $i += 100) {
$members = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/members?offset=$i"&"count=100 -Method Get -Headers $Headers
$existingMembers.members += $members.members
}
return $existingMembers
}
function New-LicenseSegment ($SkuPartNumber) {
$conditions = @()
$conditionproperty = @{
condition_type = "TextMerge"
field = "LICENSES"
op = "contains"
value = $SkuPartNumber.TrimStart("License: ")
}
$conditions += $conditionproperty
$segment = @{
name = $SkuPartNumber
options = @{
match = "any"
conditions = $conditions
}
}
$segment = $segment | ConvertTo-Json -Depth 10
$newSegment = Invoke-RestMethod -URI $baseUri/3.0/lists/$listId/segments -Method POST -Headers $Headers -Body $segment
return $newSegment
}
function Create-ExistingMemberCollection ($ExistingMembers) {
$existingMemberCollection = @()
foreach ($existingmember in $existingmembers) {
$memberObject = New-Object PSObject -Property @{
Licenses = $existingmember.merge_fields.LICENSES
FirstName = $existingmember.merge_fields.FNAME
LastName = $existingmember.merge_fields.LNAME
Company = $existingmember.merge_fields.COMPANY
Email = $existingmember.email_address
SubscriberHash = $existingmember.id
Status = $existingmember.status
}
$existingMemberCollection += $memberObject
}
return $existingMemberCollection
}
function Create-UploadBatch ($collection) {
# Upload the collection in batches of 100
$counter = [pscustomobject] @{ Value = 0 }
$batchsize = 100
$batches = $collection | Group-Object -Property { [math]::Floor($counter.Value++ / $batchSize) }
foreach ($batch in $batches) { New-MailChimpListBatch -MemberBatch $batch.Group}
}
# Check whether list exists and create it if it doesn't
$listID = (Ensure-MailChimpList -ListName $listInfo.listName).id
# Check for current merge fields in list
Write-Host "Retrieving Merge Fields"
$mergeFields = Get-MailChimpListMergeFields
$updateSegments = $false
$requiredMergeFields = "Company", "Licenses"
foreach ($requiredMergeField in $requiredMergeFields) {
if (!$mergeFields.merge_fields.Name.contains($requiredMergeField)) {
Write-Host "Creating Merge Field: $requiredMergeField" -ForegroundColor Yellow
$newMergeField = New-MailChimpListMergeField -Name $requiredMergeField -Type text -Tag $requiredMergeField.ToUpper()
}
}
# Retrieve existing segments, then filter by license related segments
$existingSegments = Get-MailChimpListSegments
$existingLicenseSegments = $existingSegments | Where-Object {$_.segments.name -match "License: "}
$requiredSegments = @()
# Create collection containing required info for all users in all tenants
Write-Host "Retrieving users and license info" -ForegroundColor Blue
$users = $null
$users = Get-MsolUser | Where-Object {$_.islicensed} <----------------------------------------------
$company = (Get-MsolCompanyInformation).DisplayName
foreach ($user in $users) {
[string[]]$userLicenses = $null
foreach ($license in $user.Licenses.AccountSku.SkuPartNumber) {
$userLicenses += "'$license'"
}
$userLicensesString = $userLicenses -join ','
# Check if these licenses already have segments created or queued
foreach ($license in $userlicenses) {
$expectedSegmentName = "License: $license"
if ($existingLicenseSegments.segments.Name -notcontains $expectedSegmentName -and $requiredSegments -notcontains $expectedSegmentName) {
$requiredSegments += $expectedSegmentName
Write-Host "Adding $expectedSegmentName to required segments list. Update pending." -ForegroundColor Yellow
$updateSegments = $true
}
}
$firstName = $user.FirstName
if (!$user.FirstName) {
$firstName = $user.DisplayName.Split(" ")[0]
}
$lastName = $user.LastName
if (!$user.lastName -and !$user.firstname) {
$lastName = $user.DisplayName.Split(" ") | Where-Object {$_ -notcontains $user.DisplayName.Split(" ")[0]}
$lastName = $lastName -join " "
}
elseif (!$user.lastName -and $user.firstname) {
$lastname = ""
}
elseif (!$user.LastName -and !($user.DisplayName.Split(" ") | Where-Object {$_ -notcontains $user.DisplayName.Split(" ")[0]})) {
$lastname = ""
}
$email = $user.UserPrincipalName
$memberObject = New-Object PSObject -Property @{
Licenses = $userLicensesString
FirstName = $firstName
LastName = $lastName
Company = $company
Email = $email
}
$Office365members += $memberObject
}
Write-Host "Retrieved $($office365Members.count) licensed users" -ForegroundColor Green
# If an update is required, add new segments
if ($updateSegments) {
Write-Host "New segments required: $requiredSegments" -ForegroundColor Green
# Create new license segments
if ($requiredSegments.count -gt 0) {
foreach ($requiredSegment in $requiredSegments) {
Write-Host "Creating new segment - $requiredSegment" -ForegroundColor Blue
$newSegment = New-LicenseSegment -SkuPartNumber $requiredSegment
}
}
}
# Check if members exist in list
# Build list of existing members
Write-Host "Getting existing members"
$existingMembers = (Get-ExistingMailChimpListMembers).members
$newMemberCollection = @()
# Check if Office 365 users already exist in mailchimp. If they don't, add them to a collection for upload
foreach ($member in $Office365members) {
if ($existingMembers.email_address -notcontains $member.Email) {
Write-Host "Adding $($member.firstName) $($member.lastName) to new subscriber collection" -ForegroundColor Green
$newMemberObject = New-MailChimpListMember -email $member.Email -FirstName $member.FirstName -LastName $member.LastName -Licenses $member.Licenses -Company $member.Company
$newMemberCollection += $newMemberObject
}
}
Create-UploadBatch -collection $newMemberCollection
# Retrieve updated list of existing members
$existingMembers = (Get-ExistingMailChimpListMembers).members
$existingMemberCollection = Create-ExistingMemberCollection -ExistingMembers $existingMembers
# Update users when details have changed.
$updatedMemberCollection = @()
foreach ($existingMember in $existingMemberCollection) {
$office365Member = $null
$office365Member = $Office365members | Where-Object {$_.Email -contains $existingMember.Email}
if ($office365member) {
if ($office365Member.FirstName -notmatch $existingMember.FirstName -or `
$office365Member.LastName -notmatch $existingMember.LastName -or `
$office365Member.Licenses -notmatch $existingMember.Licenses -or `
$office365Member.Company -notmatch $existingMember.Company){
Write-Host "Updating record for $($existingMember.Email)" -ForegroundColor Yellow
$updatedMemberObject = Update-MailChimpListMember -ExistingMember $existingMember -Office365Member $office365Member
$updatedMemberCollection += $updatedMemberObject
}
}
}
Create-UploadBatch ($updatedMemberCollection)
# Unsubscribe users who no longer exist in Office 365
# $unsubscribedMemberCollection = @()
# foreach ($existingMember in $existingMemberCollection) {
# if ($Office365members.License -notcontains $existingmember.License -and $existingmember.status -notcontains "unsubscribed") {
# Write-Host "$($existingmember.License) is no longer licensed in Office 365, unsubscribing." -ForegroundColor Red
# $unsubscribedMemberObject = Unsubscribe-MailChimpListMember -ExistingMember $existingMember
# $unsubscribedMemberCollection += $unsubscribedMemberObject
# }
# }
# Create-UploadBatch ($unsubscribedMemberCollection)
如果你看一下你提供的最后几行,代码的作者似乎已经试图解决这个问题,但可能无法使其正常工作,或者不再需要它,所以他们把它注释掉了。这是您的现有代码,没有修改:
# Unsubscribe users who no longer exist in Office 365
$unsubscribedMemberCollection = @()
foreach ($existingMember in $existingMemberCollection) {
if ($Office365members.License -notcontains $existingmember.License -and $existingmember.status -notcontains "unsubscribed") {
Write-Host "$($existingmember.License) is no longer licensed in Office 365, unsubscribing." -ForegroundColor Red
$unsubscribedMemberObject = Unsubscribe-MailChimpListMember -ExistingMember $existingMember
$unsubscribedMemberCollection += $unsubscribedMemberObject
}
}
Create-UploadBatch ($unsubscribedMemberCollection)
粗略检查一下,有一个关键变化很突出——$existingmember.License
在运行的代码中不再是单数,它现在是$existingmember.Licenses
的集合,因此这可能是之前设计的取消订阅方法无法按预期工作的原因之一我继续回答这个问题的前提是,取消订阅的行为运行良好,但您只是缺少正确识别没有当前许可证的用户的方法。
当前,此代码检索具有$Office365members.License
的许可证列表,然后检查它是否包含为$existingmember
存储的许可证。如果$existingmember
删除了一个许可证,但另一个许可仍然正确,则上述代码将取消订阅。因此,我们需要重构代码,只对当前没有任何许可证的用户采取行动:
# Unsubscribe users who no longer exist in Office 365
$unsubscribedMemberCollection = @()
foreach ($existingMember in $existingMemberCollection) {
# create a new object to hold a list of True/False values for each checked license
$licenseCheck = [System.Collections.ArrayList]::new()
forEach($license in $existingMember.Licenses){
if ($Office365members.License -notcontains $License -and $existingmember.status -notcontains "unsubscribed") {
# Add $false for a non-existent license
[void]$licenseCheck.Add($false)
Write-Host "$($License) not found." -ForegroundColor Red
}else{
# Add $true wherever the user still has a valid license
[void]$licenseCheck.Add($true)
#Write-Host "$($existingmember.License) found." -ForegroundColor Green
}
}
# Trigger the unsubscribe if the user does not have any valid licenses
if($licenseCheck -notcontains $true){
Write-Host "$($License) is no longer licensed in Office 365, unsubscribing." -ForegroundColor Red
$unsubscribedMemberObject = Unsubscribe-MailChimpListMember -ExistingMember $existingMember
$unsubscribedMemberCollection += $unsubscribedMemberObject
}
}
Create-UploadBatch ($unsubscribedMemberCollection)
我要补充的是,上面的代码是不完美的,因为它会取消订阅没有有效许可证的用户(我认为这是必要的行为(,但如果他们仍然持有至少一个有效许可证,则不会更新他们的许可证。但话说回来,你说你的其他功能已经做到了,所以我的操作假设是,这个代码只需要涵盖现有用户所有许可证都被删除的情况。