package Ġde . ide asin logic . tools . im app df ĊĊ Ċ import Ġjak arta . mail . Flags Ċ import Ġjak arta . mail . Message Ċ import Ġjak arta . mail . Messaging Exception Ċ import Ġjak arta . mail . Session Ċ import Ġjak arta . mail . internet . Internet Address Ċ import Ġjak arta . mail . internet . Mime Body Part Ċ import Ġjak arta . mail . internet . Mime Message Ċ import Ġjak arta . mail . internet . Mime Multipart Ċ import Ġmu . Kotlin Logging Ċ import Ġorg . slf 4 j . M DC Ċ import Ġjava . io . File Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . io . InputStream Ċ import Ġjava . util .* Ċ import Ġjava . util . function . Consumer ĊĊ Ċ /** Ċ Ġ* ĠRead Ġa Ġsingle Ġmail Ġwith Ġattachments , Ġconvert Ġthe Ġfirst ĠPDF Ġvia Ġocr my pdf Ġand Ġsend Ġto Ġnew Ġmail Ġaddress . Ċ Ġ* ĠConfiguration Ġvia Ġ` docker / home / java / conf / config . properties `. Ċ Ġ*/ Ċ class ĠI MAP Message Reader Ġinternal Ġconstructor ( session : ĠSession , Ġprivate Ġval Ġprop : ĠProperties ) Ġ{ Ċ ĉ private Ġval Ġocr Ġ= ĠO CR Wrapper () Ċ ĉ private Ġval Ġsmtp Sender : ĠSMTP Sender Ċ ĉ private Ġval Ġdelete After Processing : ĠBoolean ĊĊ ĉ /** Ċĉ Ġ* ĠCheck , Ġif Ġthe Ġmessage Ġcan Ġbe Ġprocessed . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġmessage Ġan ĠI MAP Message Ċĉ Ġ* Ġ@ return Ġtrue , Ġif Ġall Ġpre conditions Ġare Ġful filled Ċĉ Ġ* Ġ@ throws ĠMessaging Exception Ġon Ġmessage Ġerrors Ċĉ Ġ*/ Ċ ĉ @ Throws ( Messaging Exception :: class ) Ċ ĉ private Ġfun Ġshould Handle Message ( message : ĠMime Message ): ĠBoolean Ġ{ Ċĉ ĉ // Ġignore Ġdeleted Ġmessages Ċĉ ĉ if Ġ( message . flags . contains ( Flags . Flag . DELETED )) Ġ{ Ċĉĉ ĉ log . trace (" ignore Ġdeleted Ġmessage ") Ċĉĉ ĉ return Ġfalse Ċĉ ĉ } Ċĉ ĉ if Ġ( message . flags . contains ( Flags . Flag . SE EN )) Ġ{ Ċĉĉ ĉ // Ġlog . trace (" ignore Ġseen Ġmessage "); Ċĉĉ ĉ return Ġfalse Ċĉ ĉ } Ċĉ ĉ if Ġ( message . from Ġ== Ġnull Ġ|| Ġmessage . from . size Ġ== Ġ 0 ) Ġ{ Ċĉĉ ĉ log . trace (" ignore Ġmessage Ġwithout Ġsender ") Ċĉĉ ĉ return Ġfalse Ċĉ ĉ } ĊĊĉ ĉ // Ġmessages Ġshould Ġhave Ġat Ġleast Ġone Ġrecipient Ċĉ ĉ val Ġrecipients Ġ= Ġmessage . get Recipients ( Message . Recipient Type . TO ) Ċĉ ĉ if Ġ( recipients . size Ġ== Ġ 0 ) Ġ{ Ċĉĉ ĉ log . debug (" ignore Ġmessage Ġ" Ġ+ Ġmessage . message Number Ġ+ Ġ" Ġwithout Ġrc pt ") Ċĉĉ ĉ return Ġfalse Ċĉ ĉ } Ċĉ ĉ log . info (" loaded Ġmessage Ġ" Ġ+ Ġmessage . message Number Ġ+ Ġ" Ġrc pt =" Ġ+ Ġrecipients [ 0 ]. toString ()) Ċĉ ĉ message . set Flag ( Flags . Flag . SE EN , Ġtrue ) Ċĉ ĉ return Ġtrue Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠHandle Ġa Ġsingle ĠI MAP Ġmessage . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġmessage Ġa Ġmessage Ġto Ġprocess . Ċĉ Ġ* Ġ@ throws ĠMessaging Exception ĠĠ Ġif Ġmessage Ġcould Ġnot Ġbe Ġread Ġor Ġsent . Ċĉ Ġ* Ġ@ throws ĠIOException ĠĠĠĠĠĠĠĠĠ Ġif Ġdata Ġcould Ġnot Ġbe Ġread Ċĉ Ġ*/ Ċ ĉ @ Throws ( Messaging Exception :: class , ĠIOException :: class ) Ċ ĉ fun Ġhandle Message ( message : ĠMime Message ) Ġ{ Ċĉ ĉ try Ġ{ Ċĉĉ ĉ M DC . put ( MESSAGE _ ID , Ġmessage . message ID ) ĊĊĉĉ ĉ // Ġsender , Ġrecipient Ġgiven ? Ċĉĉ ĉ if Ġ(! should Handle Message ( message )) Ġ{ Ċĉĉĉ ĉ message . set Flag ( Flags . Flag . DELETED , Ġdelete After Processing ) Ċĉĉĉ ĉ return Ċĉĉ ĉ } Ċĉĉ ĉ val Ġsubject Ġ= Ġmessage . subject ĊĊĉĉ ĉ // Ġtry Ġto Ġtraverse Ġall ĠPDF s Ċĉĉ ĉ val Ġinput Files Ġ= Ġtraverse ( message . content ) Ċĉĉ ĉ if Ġ( input Files . isEmpty ()) Ġ{ Ċĉĉĉ ĉ log . info (" no Ġinput Files Ġpresent , Ġabort ing ") Ċĉĉĉ ĉ message . set Flag ( Flags . Flag . DELETED , Ġdelete After Processing ) Ċĉĉĉ ĉ return Ċĉĉ ĉ } Ċĉĉ ĉ val Ġlang Ġ= Ġprop . getProperty (" ocr . lang ", Ġ" de u + eng ") ĊĊĉĉ ĉ // ĠPDF Ġis Ġpresent , Ġstart ĠO CR Ċĉĉ ĉ val Ġout Files Ġ= Ġinput Files Ċĉĉĉ ĉ . map Ġ{ Ġit . key Ġto Ġocr . run OCR ( it . value , Ġlang ) Ġ} Ċĉĉĉ ĉ . filter Ġ{ Ġit . second Ġ!= Ġnull Ġ} Ċĉĉĉ ĉ . map Ġ{ Ġit . first Ġto Ġit . second !! Ġ} Ċĉĉĉ ĉ . toMap () ĊĊĉĉ ĉ // Ġsend Ġto Ġtarget Ċĉĉ ĉ val Ġfwd Ġ= Ġget Target Recipient ( message ) Ċĉĉ ĉ if Ġ( out Files . isEmpty ()) Ġ{ Ċĉĉĉ ĉ log . info (" Empty Ġinput File ? ĠUsing Ġoriginal Ġinstead ") Ċĉĉĉ ĉ smtp Sender . send Mail ( fwd , Ġinput Files , Ġsubject ) Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ smtp Sender . send Mail ( fwd , Ġout Files , Ġsubject ) Ċĉĉĉ ĉ out Files . values . forEach ( Consumer Ġ{ Ġobj : ĠFile Ġ-> Ġobj . delete () Ġ}) Ċĉĉ ĉ } Ċĉĉ ĉ input Files . values . forEach ( Consumer Ġ{ Ġobj : ĠFile Ġ-> Ġobj . delete () Ġ}) Ċĉĉ ĉ message . set Flag ( Flags . Flag . DELETED , Ġdelete After Processing ) Ċĉ ĉ } Ġfinally Ġ{ Ċĉĉ ĉ M DC . remove ( MESSAGE _ ID ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠFind Ġthe Ġrecipient Ġfor Ġthis Ġmessage : ĠEither Ġthe Ġsender Ġor ĠâĢĵ Ġif Ġconfigured ĠâĢĵ Ġa Ġreplacement Ġfrom Ġthe Ġconfig Ġfile . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġmessage Ġan ĠI MAP Message Ċĉ Ġ* Ġ@ return Ġthe Ġcalculated Ġrecipients Ġof Ġthe Ġmessage . Ċĉ Ġ* Ġ@ throws ĠMessaging Exception Ġif ĠI MAP Ġconnection Ġis Ġbroken . Ċĉ Ġ*/ Ċ ĉ @ Throws ( Messaging Exception :: class ) Ċ ĉ private Ġfun Ġget Target Recipient ( message : ĠMime Message ): ĠInternet Address Ġ{ Ċĉ ĉ val Ġfrom Ġ= Ġmessage . from [ 0 ] Ġas ĠInternet Address Ċĉ ĉ val Ġrecipients Ġ= Ġmessage . get Recipients ( Message . Recipient Type . TO ) Ċĉ ĉ // Ġif Ġsender Ġis Ġgiven Ġ-> Ġuse Ġit Ċĉ ĉ var Ġfwd Ġ= Ġfrom Ċĉ ĉ // Ġif Ġtarget Ġrecipient Ġis Ġin Ġconfig Ġfile Ċĉ ĉ val Ġaddress Ġ= Ġ( recipients [ 0 ] Ġas ĠInternet Address ). address Ċĉ ĉ if Ġ( prop . containsKey (" fwd .$ address ")) Ġ{ Ċĉĉ ĉ fwd Ġ= ĠInternet Address ( prop . getProperty (" fwd .$ address ")) Ċĉ ĉ } Ċĉ ĉ log . trace (" forward Ġpdf Ġfrom Ġ$ address Ġto Ġ$ fwd ") Ċĉ ĉ return Ġfwd Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠTra verse Ġthe Ġmail Ġobject . Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġcontent Ġa Ġmime Ġbody . Ċĉ Ġ* Ġ@ return Ġa ĠFile , Ġif ĠPDF Ġfound . Ċĉ Ġ* Ġ@ throws ĠMessaging Exception Ġif Ġmessage Ġcould Ġnot Ġbe Ġopened . Ċĉ Ġ* Ġ@ throws ĠIOException ĠĠĠĠĠĠĠ Ġif Ġmessage Ġcould Ġnot Ġbe Ġread . Ċĉ Ġ*/ Ċ ĉ @ Throws ( Messaging Exception :: class , ĠIOException :: class ) Ċ ĉ private Ġfun Ġtraverse ( content : ĠAny ): ĠMap < String , ĠFile > Ġ{ Ċĉ ĉ log . trace Ġ{ Ġ" got Ġcontent =" Ġ+ Ġcontent . java Class Ġ} Ċĉ ĉ // Ġoriginal Ġmail Ġmust Ġbe Ġmultipart Ċĉ ĉ if Ġ( content Ġ! is ĠMime Multipart ) Ġ{ Ċĉĉ ĉ return Ġempty Map () Ċĉ ĉ } Ċĉ ĉ val Ġfile Map : ĠMutable Map < String , ĠFile > Ġ= ĠHashMap () Ċĉ ĉ // Ġcheck Ġevery Ġpart . Ċĉ ĉ val Ġpart Ġ= Ġcontent Ċĉ ĉ for Ġ( i Ġin Ġ 0 Ġuntil Ġpart . count ) Ġ{ Ċĉĉ ĉ val Ġbody Ġ= Ġpart . getBody Part ( i ) Ċĉĉ ĉ log . trace Ġ{ Ġ" got Ġbody Ġpart Ġ" Ġ+ Ġbody . java Class Ġ+ Ġ" Ġwith Ġcontent =" Ġ+ Ġbody . contentType Ġ+ Ġ" Ġreader =" Ġ+ Ġbody . content . java Class Ġ} Ċĉĉ ĉ // Ġparts Ġshould Ġbe ĠI MAP Body Part Ċĉĉ ĉ if Ġ( body Ġ! is ĠMime Body Part ) Ġ{ Ċĉĉĉ ĉ continue Ċĉĉ ĉ } Ċĉĉ ĉ val Ġattachment Ġ= Ġbody Ċĉĉ ĉ val Ġpart Content Ġ= Ġattachment . content ĊĊĉĉ ĉ if Ġ( part Content Ġis ĠMime Multipart ) Ġ{ Ċĉĉĉ ĉ file Map . put All ( traverse ( part Content )) Ċĉĉĉ ĉ continue Ċĉĉ ĉ } ĊĊĉĉ ĉ // Ġattachment Ġshould Ġbe ĠPDF Ċĉĉ ĉ if Ġ( attachment . fileName Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ continue Ċĉĉ ĉ } Ċĉĉ ĉ val Ġextension Ġ= Ġattachment . fileName . lowercase (). replace ("^ .* \\. ([ a - z ]* ? )$ ". to Regex (), Ġ"$ 1 ") Ċĉĉ ĉ if Ġ( extension Ġ!= Ġ" pdf " Ġ&& Ċĉĉĉ ĉ extension Ġ!= Ġ" png " Ġ&& Ċĉĉĉ ĉ extension Ġ!= Ġ" jpg " Ġ&& Ċĉĉĉ ĉ extension Ġ!= Ġ" jpeg " Ċĉĉ ĉ ) Ġ{ Ċĉĉĉ ĉ log . debug Ġ{ Ġ" unknown Ġextension : Ġ$ extension " Ġ} Ċĉĉĉ ĉ continue Ċĉĉ ĉ } Ċĉĉ ĉ log . trace Ġ{ Ġ" got Ġpdf =" Ġ+ Ġattachment . fileName Ġ+ Ġ" Ġcontent =" Ġ+ Ġpart Content . java Class Ġ} Ċĉĉ ĉ when Ġ( part Content ) Ġ{ Ċĉĉĉ ĉ is ĠInputStream Ġ-> Ġpart Content . use Ġ{ ĠinputStream Ġ-> Ċĉĉĉĉ ĉ val Ġfile Ġ= ĠFile . create TempFile (" scan -", Ġ". pdf ") Ċĉĉĉĉ ĉ File OutputStream ( file ). use Ġ{ Ġf os Ġ-> Ċĉĉĉĉĉ ĉ inputStream . copy To ( fos ) Ċĉĉĉĉĉ ĉ log . trace Ġ{ Ġ" w rote Ġpdf =" Ġ+ Ġattachment . fileName Ġ+ Ġ" Ġto Ġfile Ġ" Ġ+ Ġfile Ġ} Ċĉĉĉĉĉ ĉ file Map . put ( attachment . fileName , Ġfile ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉĉ ĉ else Ġ-> Ġcontinue Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ return Ġfile Map Ċ ĉ } ĊĊ ĉ comp anion Ġobject Ġ{ Ċĉ ĉ private Ġconst Ġval ĠMESSAGE _ ID Ġ= Ġ" message ID " Ċĉ ĉ private Ġval Ġlog Ġ= ĠKotlin Logging . logger Ġ{ Ġ} Ċ ĉ } ĊĊ ĉ init Ġ{ Ċĉ ĉ smtp Sender Ġ= ĠSMTP Sender ( session , Ġprop ) Ċĉ ĉ delete After Processing Ġ= Ġjava . lang . Boolean . valueOf ( prop . getProperty (" delete After Processing ", Ġ" false ")) Ċ ĉ } Ċ }