# Citeste emailurile din mbox-urile Thunderbird Portable (fara conectorul Gmail).
#   citeste_email.ps1 [-Cauta <text>] [-Cont <nume>] [-Ultimele <n>]   -> lista mesaje
#   citeste_email.ps1 -Nr <linie> [-Linii <n>]                         -> corpul unui mesaj
param(
    [string]$Cauta = '',
    [string]$Cont = '',
    [int]$Ultimele = 20,
    [int]$Nr = 0,
    [int]$Linii = 200,
    [string]$Radacina = 'D:\UTIL\portable\PortableApps\ThunderbirdPortable\Data\profile\ImapMail'
)

$ErrorActionPreference = 'Stop'

function Get-Mboxuri {
    param([string]$Cont)
    $c = if ($Cont) { $Cont } else { '*' }
    Get-ChildItem $Radacina -Directory -Filter $c |
        ForEach-Object { Join-Path $_.FullName 'INBOX' } |
        Where-Object { Test-Path $_ } |
        Where-Object { (Get-Item $_).LastWriteTime -gt (Get-Date).AddYears(-2) }
}

function Deschide-Fisier {
    param([string]$Cale)
    # Thunderbird tine fisierul deschis -> FileShare ReadWrite obligatoriu
    $fs = New-Object IO.FileStream($Cale, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)
    New-Object IO.StreamReader($fs, [Text.Encoding]::GetEncoding(28591))
}

function Decodeaza-Subiect {
    param([string]$S)
    $rx = [regex]'=\?([^?]+)\?([BbQq])\?([^?]*)\?='
    $rx.Replace($S, {
        param($m)
        $enc = [Text.Encoding]::GetEncoding($m.Groups[1].Value)
        $txt = $m.Groups[3].Value
        if ($m.Groups[2].Value -match '[Bb]') {
            $enc.GetString([Convert]::FromBase64String($txt))
        } else {
            $b = New-Object Collections.Generic.List[byte]
            for ($i = 0; $i -lt $txt.Length; $i++) {
                if ($txt[$i] -eq '=') { $b.Add([Convert]::ToByte($txt.Substring($i + 1, 2), 16)); $i += 2 }
                elseif ($txt[$i] -eq '_') { $b.Add(32) }
                else { $b.Add([byte][char]$txt[$i]) }
            }
            $enc.GetString($b.ToArray())
        }
    })
}

# ---- corpul unui mesaj: de la linia data pana la urmatorul separator mbox ----
if ($Nr -gt 0) {
    foreach ($f in Get-Mboxuri -Cont $Cont) {
        $r = Deschide-Fisier $f
        try {
            $i = 0; $scris = 0; $pornit = $false
            while ($null -ne ($l = $r.ReadLine())) {
                $i++
                if ($i -lt $Nr) { continue }
                # linia ceruta trebuie sa fie inceput de mesaj, altfel e alt cont
                if ($i -eq $Nr -and $l -notmatch '^From - \w\w\w \w\w\w ') { break }
                if ($pornit -and $l -match '^From - \w\w\w \w\w\w ') { break }
                $pornit = $true
                $l
                if (++$scris -ge $Linii) { "... (taiat la $Linii linii, mareste cu -Linii)"; break }
            }
            if ($pornit) { return }
        } finally { $r.Dispose() }
    }
    Write-Warning "Linia $Nr nu exista in mbox-urile cautate."
    return
}

# ---- lista de mesaje ----
$mesaje = @()
foreach ($f in Get-Mboxuri -Cont $Cont) {
    $cont = Split-Path (Split-Path $f -Parent) -Leaf
    $r = Deschide-Fisier $f
    try {
        $i = 0; $inAntet = $false; $m = $null
        while ($null -ne ($l = $r.ReadLine())) {
            $i++
            if ($l -match '^From - \w\w\w \w\w\w ') {
                if ($m) { $mesaje += $m }
                $m = [pscustomobject]@{ Cont = $cont; Linie = $i; Data = ''; De_la = ''; Subiect = '' }
                $inAntet = $true
                continue
            }
            if (-not $inAntet -or -not $m) { continue }
            if ($l -eq '') { $inAntet = $false; continue }
            if ($l -like 'Date: *' -and -not $m.Data) { $m.Data = $l.Substring(6).Trim() }
            elseif ($l -like 'From: *' -and -not $m.De_la) { $m.De_la = $l.Substring(6).Trim() }
            elseif ($l -like 'Subject: *' -and -not $m.Subiect) { $m.Subiect = Decodeaza-Subiect $l.Substring(9).Trim() }
        }
        if ($m) { $mesaje += $m }
    } finally { $r.Dispose() }
}

if ($Cauta) {
    $mesaje = $mesaje | Where-Object { $_.Subiect -like "*$Cauta*" -or $_.De_la -like "*$Cauta*" }
}
$mesaje | Select-Object -Last $Ultimele | Format-Table -AutoSize -Wrap
