bash: email subject dekódolás?

Kaptam egy egyszerűnek tűnő feladatot. Ck. 200 email -ből (dovecot IMAP) kellene táblázatot csinálni. Az első oszlop a dátum a második a subject (tárgy). Mi sem egyszerűbb gondoltam én, de nem tudok rájönni mi ez a kódolás és hogy tudom dekódolni:

Subject: =?ISO-8859-1?Q?Sz=E9kesfeh=E9rv=E1r?= 2. (Krumpli)

Tárgy valójában: Székesfehérvár 2. (Krumpli)

Próbáltam iconv -al és munpack -sl, base64 -el de semmi nem tudtam kinyerni a "Székesfehérvár 2. (Krumpli)" szöveget.
Próbáltam csak egy részével "Sz=E9kesfeh=E9rv=E1r?= 2. (Krumpli)".

Mit nézek be? Mit lehet ehhez használni?

MEGKERÜLTEM

A roundcube listát kinyomtattam pdf -be, copy egy szöveges fájlba, majd néml harccal beemeltem libreoffice calc -ba. Nem lett tökéletes a karakter készltek miatt (utf8) de elfogadták :)

Hozzászólások

Pedig a munpack elvben jo lenne erre, reszlet a man-jabol:

To decode a MIME message, first save it to a text file.  If possible,  save  it  with  all
       headers  included.   Munpack  can  decode  some MIME files when the headers are missing or
       incomplete, other files it cannot decode without having the information  in  the  headers.
       In  general, messages which have a statement at the beginning that they are in MIME format
       can be decoded without the headers.  Messages which have been split  into  multiple  parts
       generally require all headers in order to be reassembled and decoded.”

Nem értek hozzá, de érdekelnek a problémamegoldások.

Ezzel esetleg nem vagy előrébb: https://cs.stanford.edu/people/miles/iso8859.html ?

Lower Case Latin-1 Letters
Character
Reference
Hex Character Entity Name Description
à E0 à à small a grave  
á E1 á á small a acute  
â E2 â â small a circumflex  
ã E3 ã ã small a tilde  
ä E4 ä ä small a dieresis or umlaut  
å E5 å å small a ring  
æ E6 æ æ small ae ligature  
ç E7 ç ç small c cedilla  
è E8 è è small e grave  
é E9 é é small e acute
echo -n "Sz=E9kesfeh=E9rv=E1r" | recode "qp..data,ISO-8859-1..$(locale charmap)"
Székesfehérvár

Hűha! Majdnem tökéletes. Köszönöm!

echo "Sz=E9kesfeh=E9rv=E1r?= 2. (Krumpli)" | recode "qp..data.ISO-885-1..$(locale charset)"

Székesfehérvár?recode: Invalid input in step `Quoted-Printable..data'

Ha kiveszem belőle a "?" akor már lekezeli :)

A leírás nekem eléggézavaros (a "manual" semmi olyat nem látok amit te készítettél.
Gyomláljam (valahogy) ki a "?" jeleket, vagy tudsz még valami opciót?
(Én megpróbálok rájönni erre a furcsa parancs formátumra)

* Én egy indián vagyok. Minden indián hazudik.

Fentebb linkelték az RFC2047-et, abban részletesen le van írva, de a lényeg a következő:

 

An "encoded-word" is a sequence of printable ASCII characters that begins with "=?", ends with "?=", and has two "?"s in between. It specifies a character set and an encoding method, and also includes the original text encoded as graphic ASCII characters, according to the rules for that encoding method.

 

Nehezítésképpen egy mező (pl. Subject) több soros is lehet, és ahogy nálad is, váltakozhat benne a kódolt és kódolatlan szöveg. Valamikor nagyon régen írtam egy awk szkriptet, ami szépen lekezel minden lehetőséget, most megosztom veled:

 

BEGIN {
  RS="\r?\n"
  FS=":"
  AddLine=0
}

$0~"^$" || AddLine==1 && $0!~"^[ \t]+" {
  exit 0
}

AddLine==0 {
  if (tolower($1)==tolower(HeaderField)) {
    $0=substr($0,index($0,":")+1)
    sub("^ *","")
    AddLine=1
  }
}

AddLine==1 {
  sub("^[ \t]+","")
  sub("[ \t]+$","")
  LineBuffer=LineBuffer sep $0
  sep=" "
}

END {
  gsub("\?=[ \t]+=\?","?==?",LineBuffer)
  DecodedLine=""
  while (LineBuffer!="") {
    QWordStartOffset=index(LineBuffer,"=?")
    if (QWordStartOffset==0) {
      DecodedLine=DecodedLine LineBuffer
      break
    }
    else {
      DecodedLine=DecodedLine substr(LineBuffer,1,QWordStartOffset-1)
    LineBuffer=substr(LineBuffer,QWordStartOffset)
    TempLineBuffer=LineBuffer
    Offset=index(TempLineBuffer,"?")
    QWordLength=Offset
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer
      break
    }
    TempLineBuffer=substr(TempLineBuffer,Offset+1)
    Offset=index(TempLineBuffer,"?")
    QWordLength+=Offset
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer
      break
    }
    TempLineBuffer=substr(TempLineBuffer,Offset+1)
    Offset=index(TempLineBuffer,"?")
    QWordLength+=Offset
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer
      break
    }
    TempLineBuffer=substr(TempLineBuffer,Offset+1)
    Offset=index(TempLineBuffer,"?=")
    QWordLength+=Offset+1
    if (Offset!=0) {
      QWord=substr(LineBuffer,1,QWordLength)
      split(QWord,QWordElements,"\?")
      Charset=QWordElements[2]
      Encoding=toupper(QWordElements[3])
      QWordText=QWordElements[4]
      if (Encoding=="Q") {
        gsub("_","\x20",QWordText)
        cmd="echo \"" QWordText "\" | recode -fq \"" Charset "\"/quoted-printable..\"" OutputCharset "\""
        cmd | getline DecodedQWord
        close (cmd)
      }
      else if (Encoding=="B") {
        cmd="echo \"" QWordText "\" | recode -fq \"" Charset "\"/base64..\"" OutputCharset "\""
        cmd | getline DecodedQWord
        close (cmd) } else DecodedQWord=QWord
        DecodedLine=DecodedLine DecodedQWord
        LineBuffer=substr(LineBuffer,QWordLength+1)
      }
      else {
        DecodedLine=DecodedLine LineBuffer
        break
      }
    }
  }
  sub("^[ \t]+","",DecodedLine)
  sub("[ \t]+$","",DecodedLine)
  printf "%s\n",DecodedLine
}

 

Demo egy valódi levéllel:

Subject: =?iso-8859-2?Q?HPE_Webinar_megh=EDv=F3:_Automatiz=E1ci=F3_avagy_=FCzemelt?=
  =?iso-8859-2?Q?et=E9s_a_kanap=E9r=F5l_/_=E1prilis_09._cs=FCt=F6rt=F6k_09:?=
  =?iso-8859-2?Q?30?=
$ awk -v HeaderField="Subject" -v OutputCharset="$(locale charmap)" -f get-header-field.awk test.eml
HPE Webinar meghívó: Automatizáció avagy üzemeltetés a kanapéről / április 09. csütörtök 09:30

Nagyon köszönöm!
Átrágom magam rajta.
Tudom, hogy elküldték az RFC -t de az sem mai csirke, így még mindig úgy hiszem biztos van rá kész megoldás (pl. láttam php és perl scripteket). Valójában az ilyen scriptekben az a megbecsülendő, hogy ki van próbálva, működik. Ráadásul nem túl gyakori feladvány egy-egy embernél.

Mentem, lopom!

* Én egy indián vagyok. Minden indián hazudik.

formail -c -X "subject"  < mail_file| perl -e 'use open qw(:std :utf8); use Encode qw(decode); while (my $line = <STDIN>) { print decode("MIME-Header", $line); }'

Szerkesztve: 2020. 07. 28., k – 17:09

Esetleg Python3 ?

>>> from email.header import decode_header
>>> d = decode_header('=?iso-8859-1?q?p=E9lda?=')
>>> d[0][0].decode(d[0][1])
'példa'

>>> d = decode_header('Subject: =?ISO-8859-1?Q?Sz=E9kesfeh=E9rv=E1r?= 2. (Krumpli)')
>>> d
[(b'Subject: ', None), (b'Sz\xe9kesfeh\xe9rv\xe1r', 'iso-8859-1'), (b' 2. (Krumpli)', None)]

>>> print (d[0][0].decode(), d[1][0].decode(d[1][1]), d[2][0].decode())
Subject:  Székesfehérvár  2. (Krumpli)

Szerkesztve: 2020. 07. 28., k – 18:26

Perl játszik? :)

$ perl -C -MEncode -E 'say decode("MIME-Header", "Subject: =?ISO-8859-2?Q?Sz=E9kesfeh=E9rv=E1r?= 2. (Krumpli)")'
Subject: Székesfehérvár 2. (Krumpli)

 

 

 

 

 

követem Poleszt

perl -MEncode -pe '$_=decode("MIME-Header",$_)'