選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

68 行
2.5KB

  1. param(
  2. [string]$ConfigPath = (Join-Path (Split-Path -Parent $PSScriptRoot) 'config.ini')
  3. )
  4. $ErrorActionPreference = 'Stop'
  5. $settings = @{}
  6. foreach ($line in Get-Content -LiteralPath $ConfigPath -Encoding UTF8) {
  7. if ($line -match '^\s*([A-Z_]+)\s*=\s*(.*?)\s*$') {
  8. $settings[$matches[1]] = $matches[2]
  9. }
  10. }
  11. $smtpHost = $settings['SMTP_HOST']
  12. $smtpPort = 0
  13. if ([string]::IsNullOrWhiteSpace($smtpHost) -or
  14. -not [int]::TryParse($settings['SMTP_PORT'], [ref]$smtpPort) -or
  15. $smtpPort -lt 1 -or $smtpPort -gt 65535) {
  16. throw 'Valid SMTP_HOST and SMTP_PORT are required in the config file'
  17. }
  18. function Read-Reply($reader) {
  19. $lines = New-Object 'System.Collections.Generic.List[string]'
  20. do {
  21. $line = $reader.ReadLine()
  22. if ($null -eq $line -or $line -notmatch '^\d{3}[- ]') {
  23. throw "Invalid or incomplete SMTP reply: $line"
  24. }
  25. $lines.Add($line)
  26. } while ($line.Substring(3, 1) -eq '-')
  27. return ,$lines.ToArray()
  28. }
  29. $client = New-Object System.Net.Sockets.TcpClient
  30. try {
  31. $connect = $client.BeginConnect($smtpHost, $smtpPort, $null, $null)
  32. if (-not $connect.AsyncWaitHandle.WaitOne(10000)) { throw 'SMTP connection timed out' }
  33. $client.EndConnect($connect)
  34. $client.ReceiveTimeout = 10000
  35. $client.SendTimeout = 10000
  36. $stream = $client.GetStream()
  37. $reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::ASCII)
  38. $writer = New-Object System.IO.StreamWriter($stream, [System.Text.Encoding]::ASCII)
  39. $writer.NewLine = "`r`n"
  40. $writer.AutoFlush = $true
  41. $greeting = Read-Reply $reader
  42. if (-not $greeting[-1].StartsWith('220')) { throw "SMTP greeting rejected: $($greeting[-1])" }
  43. $writer.WriteLine('EHLO localhost')
  44. $ehlo = Read-Reply $reader
  45. if (-not $ehlo[-1].StartsWith('250')) { throw "EHLO rejected: $($ehlo[-1])" }
  46. if (-not ($ehlo | Where-Object { $_ -match '^250[- ]STARTTLS(?:\s|$)' })) {
  47. throw 'Server did not advertise STARTTLS'
  48. }
  49. $writer.WriteLine('STARTTLS')
  50. $startTls = Read-Reply $reader
  51. if (-not $startTls[-1].StartsWith('220')) { throw "STARTTLS rejected: $($startTls[-1])" }
  52. $secureStream = New-Object System.Net.Security.SslStream($stream, $false)
  53. $secureStream.AuthenticateAsClient($smtpHost)
  54. if (-not $secureStream.IsAuthenticated -or -not $secureStream.IsEncrypted) {
  55. throw 'TLS negotiation did not establish an encrypted session'
  56. }
  57. Write-Output "SMTP STARTTLS OK: $smtpHost`:$smtpPort ($($secureStream.SslProtocol))"
  58. $secureStream.Close()
  59. }
  60. finally {
  61. $client.Close()
  62. }

Powered by TurnKey Linux.