[Console]::OutputEncoding = [Text.Encoding]::UTF8 $ErrorActionPreference = 'Stop' $configPath = Join-Path $PSScriptRoot 'thunderbird-config.json' if (-not (Test-Path $configPath)) { throw "Config not found: $configPath" } $cfg = Get-Content $configPath -Raw -Encoding UTF8 | ConvertFrom-Json $socketMap = @{ 'none' = 0; 'STARTTLS' = 2; 'SSL' = 3 } $authMap = @{ 'normal' = 3; 'encrypted' = 4; 'ntlm' = 8; 'gssapi' = 7; 'oauth2' = 10 } if (-not $socketMap.ContainsKey($cfg.Incoming.SocketType)) { throw "Incoming.SocketType must be one of: $($socketMap.Keys -join ', ')" } if (-not $socketMap.ContainsKey($cfg.Outgoing.SocketType)) { throw "Outgoing.SocketType must be one of: $($socketMap.Keys -join ', ')" } if (-not $authMap.ContainsKey($cfg.Incoming.AuthMethod)) { throw "Incoming.AuthMethod must be one of: $($authMap.Keys -join ', ')" } if (-not $authMap.ContainsKey($cfg.Outgoing.AuthMethod)) { throw "Outgoing.AuthMethod must be one of: $($authMap.Keys -join ', ')" } $winUser = $cfg.WindowsUser $appRoot = "C:\Users\$winUser\AppData\Roaming\Thunderbird" $profilesDir = Join-Path $appRoot 'Profiles' $profileName = $cfg.ProfileName $profilePath = Join-Path $profilesDir $profileName $iniPath = Join-Path $appRoot 'profiles.ini' if (-not (Test-Path "C:\Users\$winUser")) { throw "Windows user '$winUser' not found (no C:\Users\$winUser folder)" } # Stop any running Thunderbird so we don't fight it Get-Process thunderbird -ErrorAction SilentlyContinue | Stop-Process -Force New-Item -ItemType Directory -Force -Path $profilePath | Out-Null $incSocket = $socketMap[$cfg.Incoming.SocketType] $outSocket = $socketMap[$cfg.Outgoing.SocketType] $incAuth = $authMap[$cfg.Incoming.AuthMethod] $outAuth = $authMap[$cfg.Outgoing.AuthMethod] $prefs = @" // Generated by setup-thunderbird.ps1 user_pref("mail.shell.checkDefaultClient", false); user_pref("mailnews.start_page.enabled", false); user_pref("mail.accountmanager.accounts", "account1,account2"); user_pref("mail.accountmanager.defaultaccount", "account1"); user_pref("mail.accountmanager.localfoldersserver", "server2"); user_pref("mail.account.account1.identities", "id1"); user_pref("mail.account.account1.server", "server1"); user_pref("mail.account.account2.server", "server2"); user_pref("mail.server.server1.type", "$($cfg.Incoming.Type)"); user_pref("mail.server.server1.hostname", "$($cfg.Incoming.Hostname)"); user_pref("mail.server.server1.port", $($cfg.Incoming.Port)); user_pref("mail.server.server1.socketType", $incSocket); user_pref("mail.server.server1.userName", "$($cfg.Incoming.Username)"); user_pref("mail.server.server1.authMethod", $incAuth); user_pref("mail.server.server1.name", "$($cfg.Identity.Email)"); user_pref("mail.server.server1.login_at_startup", true); user_pref("mail.server.server1.check_new_mail", true); user_pref("mail.server.server2.type", "none"); user_pref("mail.server.server2.hostname", "Local Folders"); user_pref("mail.server.server2.name", "Local Folders"); user_pref("mail.server.server2.userName", "nobody"); user_pref("mail.identity.id1.fullName", "$($cfg.Identity.FullName)"); user_pref("mail.identity.id1.useremail", "$($cfg.Identity.Email)"); user_pref("mail.identity.id1.smtpServer", "smtp1"); user_pref("mail.identity.id1.valid", true); user_pref("mail.smtpservers", "smtp1"); user_pref("mail.smtp.defaultserver", "smtp1"); user_pref("mail.smtpserver.smtp1.hostname", "$($cfg.Outgoing.Hostname)"); user_pref("mail.smtpserver.smtp1.port", $($cfg.Outgoing.Port)); user_pref("mail.smtpserver.smtp1.try_ssl", $outSocket); user_pref("mail.smtpserver.smtp1.username", "$($cfg.Outgoing.Username)"); user_pref("mail.smtpserver.smtp1.authMethod", $outAuth); user_pref("mail.smtpserver.smtp1.description", "$($cfg.Outgoing.Hostname)"); "@ $prefsPath = Join-Path $profilePath 'prefs.js' Set-Content -Path $prefsPath -Value $prefs -Encoding UTF8 Write-Host "[*] Wrote prefs.js -> $prefsPath" # profiles.ini: Thunderbird 72+ selects profile via [Install] section, not Default=1 on Profile. # Merge: preserve existing Profile/Install entries, force our profile as default everywhere. $profileRelPath = "Profiles/$profileName" if (Test-Path $iniPath) { $iniRaw = Get-Content $iniPath -Raw # Redirect any existing Install block to our profile $iniRaw = [regex]::Replace($iniRaw, '(?m)^Default=Profiles/[^\r\n]+', "Default=$profileRelPath") # Clear Default=1 from other Profile sections so only ours is default $iniRaw = [regex]::Replace($iniRaw, '(?ms)(\[Profile\d+\][^\[]*?Name=(?!' + [regex]::Escape($profileName) + ')[^\r\n]+[^\[]*?)Default=1\s*', '$1') # If our Profile entry is missing, append it if ($iniRaw -notmatch "(?m)^Name=$([regex]::Escape($profileName))\s*$") { $nextIdx = 0 while ($iniRaw -match "(?m)^\[Profile$nextIdx\]") { $nextIdx++ } $append = @" [Profile$nextIdx] Name=$profileName IsRelative=1 Path=$profileRelPath Default=1 "@ $iniRaw = $iniRaw.TrimEnd() + "`r`n" + $append + "`r`n" } Set-Content -Path $iniPath -Value $iniRaw -Encoding ASCII Write-Host "[*] Merged profiles.ini -> $iniPath" } else { $ini = @" [General] StartWithLastProfile=1 Version=2 [Profile0] Name=$profileName IsRelative=1 Path=$profileRelPath Default=1 "@ Set-Content -Path $iniPath -Value $ini -Encoding ASCII Write-Host "[*] Wrote profiles.ini -> $iniPath" } # Also update installs.ini (Thunderbird 72+) if present $installsIni = Join-Path $appRoot 'installs.ini' if (Test-Path $installsIni) { $raw = Get-Content $installsIni -Raw $raw = [regex]::Replace($raw, '(?m)^Default=Profiles/[^\r\n]+', "Default=$profileRelPath") Set-Content -Path $installsIni -Value $raw -Encoding ASCII Write-Host "[*] Updated installs.ini -> $installsIni" } # If we're running as a different user than the profile target, fix ownership so they can read/write if ($winUser -ne $env:USERNAME) { Write-Host "[*] Adjusting ACL for '$winUser' on $appRoot" & icacls $appRoot /grant "${winUser}:(OI)(CI)F" /T /Q | Out-Null } Write-Host "" Write-Host "[OK] Thunderbird profile '$profileName' configured for Windows user '$winUser'" Write-Host " Identity: $($cfg.Identity.FullName) <$($cfg.Identity.Email)>" Write-Host " Incoming: $($cfg.Incoming.Type) $($cfg.Incoming.Hostname):$($cfg.Incoming.Port) ($($cfg.Incoming.SocketType))" Write-Host " Outgoing: smtp $($cfg.Outgoing.Hostname):$($cfg.Outgoing.Port) ($($cfg.Outgoing.SocketType))" Write-Host "" Write-Host "Next step: log in as '$winUser', start Thunderbird; it will prompt for the password on first connection."