Bash szkriptből levél letöltése és feldolgozása

Erre a feladatra kérnék egy kis segítséget! (Ötlet, kulcsszavak, linkek, hasonló probléma megoldására, stb.)

Egy konkrét külső szolgáltatónál lévő mailboxból a leveleket kell letölteni és az esetleges mellékleteket kimenteni egy könyvtárba. Mindezt Linuxon bash shell szkriptből, amit cronból futtatnék.
Hab lenne a tortán, ha a feladó e-mailcime szerint (esetleg a levél tárgya szerint) külön alkönyvtárba mentené a mellékleteket. De ez tényleg csak extra, meg tudok lenni nélküle. Annyi előnye lenne, hogy ha több felhasználó is küldene azonos fájlnévvel mellékletet, akkor azok ne írják egymást felül.
A levél törzs tartalma egyelőre nem érdekes! :)

A mailbox hozzáférési adatai felhasználói név és jelszó természetesen ismert. Viszont a pop3-on megkövetelt az SSL/TLS használata. A levelet a letöltés után a mailboxból el kell(ene) távolítani, tehát ne maradjon meg az örökkévalóságnak a szerveren.

Hozzászólások

Hello,

Bashból POP3-at simán telnettel lehet tolni, de neked SSL is kell hozzá, szóval openssl (openssl s_client -connect mail.example.com:995). Itt persze van még mit állítani, de a lényeg, hogy ugyanúgy szöveget fogsz visszkapni.
A levél letöltése a RETR parancs, törlésére meg a DELE kell, hogy működjön.
Innentől kb annyi a dolgod, hogy megnyitod az ssl kapcsolatot, lekérdezed a leveleket, aztán utána oda pakolgatod, ahova akarod, annyi alkönyvtárba amennyibe csak szeretnéd (mondjuk a csatolt fájlokat még vissza kell alakítanod, ahhoz ha jól emlékszem az uudecode lesz jó).

FathoM

Ui.: keress ezekre: Bash POP3 SSL client

A bash miért kitétel?

Bármelyik scriptnyelvben (perl, python, pick your favourite) van natív támogatás, hogy elérj protokollokat (pl. imap, pop3), és mime részekre felparseold és szétkapd a levelet.
Ugyanezt bash-ra lefejleszteni... Nem lehetetlen, csak értelmetlen energiapazarlásnak érzem.

+1 a scriptnyelvekre

php-val is elég egyszerű:

https://davidwalsh.name/gmail-php-imap

A példakódból neked elég a php-s rész is, a benne levő függvényekkel fel is lehet bontani részekre a leveleket, de ki is rakhatod fájlba ha nagyon akarod.

(Bash-el is megoldható a feladat, az biztos, és procmail,fetchmail vonalon is lehet menni, de erre a feladatra szerintem feleslegesek, végül én is ezért maradtam a php-nél.)

szerk.: bocs, végén elsiklottam afelett, hogy pop3 kell, nem használtam azzal, de a fenti funkciók elvileg pop3-al is mennek, php manual-ban egyben emlitik.

fetchmail procmail

(ahogy azt mar felettem irtak)

Ez egy olyan feladatnak tűnik, ahol a gombhoz varrjuk a kabát...
Amúgy a munkpack pont azt csinálja, hogy egy nyers levélből kihányja a csatolmányokat.

Nekem egy problémám van vele, hogy a mai "modern" utf kódolású neveket nem szereti. Szóval egy árvíztűrő.doc helyett valami dzsuva lesz a neve annak amit kitol. Ezzel sokat nem küzdöttem, mert csak néha van szükségem arra hogy 1-1 karanténból kikotort email csatolmányát kiszedjem és így még mindig egyszerűbb mint kézzel.

Van még az mu (maildir-utils) nevű cucc is (link), ennek a mu extract nevű funkciója is hasonlót tud, de erről csak olvastam. CentOS-re nem tudom van-e.

Nem az UTF-8-at, hanem a quoted-printable kodolast nem (sem? :-)) szereti. En is munpack-kal csomagolom ki a csatolmanyokat, es valamikor regen irtam is egy awk szkriptet, ami a munpack altal eloallitott fileneveket (lenyegeben a quoted-printable kodolasban a kerdojelet X-szel helyettesiti) helyreallitja.

Itt talalhato, garancia termeszetesen nincs :-)

A standard inputon varja a munpack-fele filenevet, a standard outputra irja ki, hogy szerinte mi lehetett az eredeti filenev... ;-)

munpack-rename:

#! /bin/sh

awk -v Recode="/usr/bin/recode" -v OutputCharset="UTF-8" '
{
  LineBuffer=LineBuffer sep $0;
  sep=" "
}

END {
  gsub("X=[ \t]+=X","X==X",LineBuffer);
  DecodedLine="";
  while (LineBuffer!="") {
    Offset=index(LineBuffer,"=X");
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer;
      break
    }
    DecodedLine=DecodedLine substr(LineBuffer,1,Offset-1);
    LineBuffer=substr(LineBuffer,Offset);
    CharsetOffset=3;
    Offset=index(substr(LineBuffer,CharsetOffset),"X");
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer;
      break
    }
    EncodingOffset=CharsetOffset+Offset;
    Offset=index(substr(LineBuffer,EncodingOffset),"X");
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer;
      break
    }
    QWordTextOffset=EncodingOffset+Offset;
    Offset=index(substr(LineBuffer,QWordTextOffset),"X=");
    if (Offset==0) {
      DecodedLine=DecodedLine LineBuffer;
      break
    }
    QWordEndMarkOffset=QWordTextOffset+Offset;
    Charset=substr(LineBuffer,CharsetOffset,EncodingOffset-CharsetOffset-1);
    Encoding=toupper(substr(LineBuffer,EncodingOffset,QWordTextOffset-EncodingOffset-1));
    QWordText=substr(LineBuffer,QWordTextOffset,QWordEndMarkOffset-QWordTextOffset-1);
    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,QWordEndMarkOffset+1)
  }
  sub("^[ \t]+","",DecodedLine);
  sub("[ \t]+$","",DecodedLine);
  printf "%s\n",DecodedLine
}
'

Teszt:

$ echo -n "=XISO-8859-2XQX=E1rv=EDzt=FBr=F5_t=FCk=F6rf=FAr=F3g=E9pX=" | ./munpack-rename
árvíztűrő tükörfúrógép