Skip to content

Commit a182c6e

Browse files
Copy-DbaDbMail: App parameter ExcludePassword (#10117)
1 parent 0581591 commit a182c6e

2 files changed

Lines changed: 42 additions & 19 deletions

File tree

public/Copy-DbaDbMail.ps1

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ function Copy-DbaDbMail {
3636
Limits migration to specific Database Mail component types instead of copying everything. Choose 'ConfigurationValues' for global settings like retry attempts and file size limits, 'Profiles' for mail profile definitions, 'Accounts' for SMTP account configurations, or 'MailServers' for SMTP server details.
3737
Use this when you only need to sync specific components or when troubleshooting individual Database Mail layers.
3838
39+
.PARAMETER ExcludePassword
40+
Copies credential definitions without the actual password values.
41+
Use this in security-conscious environments where password decryption is restricted or when passwords should be manually reset after migration.
42+
3943
.PARAMETER WhatIf
4044
If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.
4145
@@ -110,6 +114,7 @@ function Copy-DbaDbMail {
110114
[string[]]$Type,
111115
[PSCredential]$SourceSqlCredential,
112116
[PSCredential]$DestinationSqlCredential,
117+
[switch]$ExcludePassword,
113118
[switch]$Force,
114119
[switch]$EnableException
115120
)
@@ -121,7 +126,7 @@ function Copy-DbaDbMail {
121126

122127
Write-Message -Message "Migrating mail server configuration values." -Level Verbose
123128
$copyMailConfigStatus = [PSCustomObject]@{
124-
SourceServer = $sourceServer.Name
129+
SourceServer = $sourceServerName
125130
DestinationServer = $destServer.Name
126131
Name = "Server Configuration"
127132
Type = "Mail Configuration"
@@ -158,7 +163,7 @@ function Copy-DbaDbMail {
158163
$newAccountName = $accountName -replace [Regex]::Escape($source), $destinstance
159164
Write-Message -Message "Updating account name from '$accountName' to '$newAccountName'." -Level Verbose
160165
$copyMailAccountStatus = [PSCustomObject]@{
161-
SourceServer = $sourceServer.Name
166+
SourceServer = $sourceServerName
162167
DestinationServer = $destServer.Name
163168
Name = $accountName
164169
Type = "Mail Account"
@@ -227,7 +232,7 @@ function Copy-DbaDbMail {
227232
$newProfileName = $profileName -replace [Regex]::Escape($source), $destinstance
228233
Write-Message -Message "Updating profile name from '$profileName' to '$newProfileName'." -Level Verbose
229234
$copyMailProfileStatus = [PSCustomObject]@{
230-
SourceServer = $sourceServer.Name
235+
SourceServer = $sourceServerName
231236
DestinationServer = $destServer.Name
232237
Name = $profileName
233238
Type = "Mail Profile"
@@ -291,18 +296,20 @@ function Copy-DbaDbMail {
291296
$sourceMailServers = $sourceServer.Mail.Accounts.MailServers
292297
$destMailServers = $destServer.Mail.Accounts.MailServers
293298

294-
Write-Message -Message "Getting mail server credentials." -Level Verbose
295-
$sql = "SELECT credentials.name AS credential_name, sysmail_server.account_id FROM sys.credentials JOIN msdb.dbo.sysmail_server ON credentials.credential_id = sysmail_server.credential_id"
296-
$credentialAccounts = @($sourceServer.Query($sql))
297-
if ($credentialAccounts.Count -gt 0) {
298-
$decryptedCredentials = Get-DecryptedObject -SqlInstance $sourceServer -Type Credential | Where-Object { $_.Name -in $credentialAccounts.credential_name }
299+
if (-not $ExcludePassword) {
300+
Write-Message -Message "Getting mail server credentials." -Level Verbose
301+
$sql = "SELECT credentials.name AS credential_name, sysmail_server.account_id FROM sys.credentials JOIN msdb.dbo.sysmail_server ON credentials.credential_id = sysmail_server.credential_id"
302+
$credentialAccounts = @($sourceServer.Query($sql))
303+
if ($credentialAccounts.Count -gt 0) {
304+
$decryptedCredentials = Get-DecryptedObject -SqlInstance $sourceServer -Type Credential | Where-Object { $_.Name -in $credentialAccounts.credential_name }
305+
}
299306
}
300307

301308
Write-Message -Message "Migrating mail servers." -Level Verbose
302309
foreach ($mailServer in $sourceMailServers) {
303310
$mailServerName = [string]$mailServer.name
304311
$copyMailServerStatus = [PSCustomObject]@{
305-
SourceServer = $sourceServer.Name
312+
SourceServer = $sourceServerName
306313
DestinationServer = $destServer.Name
307314
Name = $mailServerName
308315
Type = "Mail Server"
@@ -344,14 +351,16 @@ function Copy-DbaDbMail {
344351
Write-Message -Message "Copying mail server $mailServerName." -Level Verbose
345352
$sql = $mailServer.Script() | Out-String
346353
$sql = $sql -replace "(?<=@account_name=N'[\d\w\s']*)$sourceRegEx(?=[\d\w\s']*',)", $destinstance
347-
$credentialName = ($credentialAccounts | Where-Object { $_.account_id -eq $mailServer.Parent.ID }).credential_name
348-
if ($credentialName) {
349-
$decryptedCred = $decryptedCredentials | Where-Object { $_.Name -eq $credentialName }
350-
if ($decryptedCred) {
351-
$password = $decryptedCred.Password.Replace("'", "''")
352-
$sql = $sql -replace "@password=N''", "@password=N'$($password)'"
353-
} else {
354-
Write-Message -Level Warning -Message "Failed to get mail server password, it will need to be entered manually on the destination."
354+
if (-not $ExcludePassword) {
355+
$credentialName = ($credentialAccounts | Where-Object { $_.account_id -eq $mailServer.Parent.ID }).credential_name
356+
if ($credentialName) {
357+
$decryptedCred = $decryptedCredentials | Where-Object { $_.Name -eq $credentialName }
358+
if ($decryptedCred) {
359+
$password = $decryptedCred.Password.Replace("'", "''")
360+
$sql = $sql -replace "@password=N''", "@password=N'$($password)'"
361+
} else {
362+
Write-Message -Level Warning -Message "Failed to get mail server password, it will need to be entered manually on the destination."
363+
}
355364
}
356365
}
357366
Write-Message -Message $sql -Level Debug
@@ -370,7 +379,15 @@ function Copy-DbaDbMail {
370379
}
371380

372381
try {
373-
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9
382+
if ($ExcludePassword) {
383+
Write-Message -Level Verbose -Message "Opening normal connection because we don't need the passwords."
384+
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9
385+
$sourceServerName = $sourceServer.Name
386+
} else {
387+
Write-Message -Level Verbose -Message "Opening dedicated admin connection for password retrieval."
388+
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 -DedicatedAdminConnection -WarningAction SilentlyContinue
389+
$sourceServerName = $sourceServer.Name -replace '^ADMIN:', ''
390+
}
374391
} catch {
375392
Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source
376393
return
@@ -451,7 +468,7 @@ function Copy-DbaDbMail {
451468
Write-Message -Message "Destination Database Mail XPs: $destDbMailEnabled" -Level Verbose
452469

453470
$enableDBMailStatus = [PSCustomObject]@{
454-
SourceServer = $sourceServer.Name
471+
SourceServer = $sourceServerName
455472
DestinationServer = $destServer.Name
456473
Name = "Database Mail XPs"
457474
Type = "Mail Configuration"
@@ -487,4 +504,9 @@ function Copy-DbaDbMail {
487504
}
488505
}
489506
}
507+
end {
508+
if (-not $ExcludePassword) {
509+
$null = $sourceServer | Disconnect-DbaInstance -WhatIf:$false
510+
}
511+
}
490512
}

tests/Copy-DbaDbMail.Tests.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Describe $CommandName -Tag UnitTests {
1717
"SourceSqlCredential",
1818
"DestinationSqlCredential",
1919
"Force",
20+
"ExcludePassword",
2021
"EnableException"
2122
)
2223
Compare-Object -ReferenceObject $expectedParameters -DifferenceObject $hasParameters | Should -BeNullOrEmpty

0 commit comments

Comments
 (0)