import htmlToText from 'html-to-text' ; import { ParsedMail } from 'mailparser' ; import { Connection } from 'mysql' ; import { SMTPServerDataStream , SMTPServerSession } from 'smtp-server' ; import Account from './Account' ; class Mail { mailObject : ParsedMail ; stream : SMTPServerDataStream ; session : SMTPServerSession ; callback : ( err : Error ) => void ; sqlConnection : Connection ; dateLoaded : Date ; constructor ( { mail , stream , session , callback , sqlConnection , } ) { this . mailObject = mail ; this . stream = stream ; this . session = session ; this . callback = callback ; this . sqlConnection = sqlConnection ; this . dateLoaded = new Date ( ) ; } /**
     * Check if the email requires conversion from HTML to Plain Text.
     */ contentRequiresConversion ( ) { if ( this . mailObject . text ) return false ; if ( this . mailObject . html ) return true ; return false ; } contentRequiresTruncation ( ) { if ( this . getContents ( ) === null ) return false ; return this . getContents ( ) . length > 2000 ; } emailContainsAttachments ( ) { return this . mailObject . attachments . length > 0 ; } getRecipient ( ) { return new Promise ( ( resolve , reject ) => { const emails = [ ] ; if ( this . mailObject . to ) { if ( Array . isArray ( this . mailObject . to ) ) { this . mailObject . to . map ( email => email . value ) . forEach ( i => i . forEach ( email => email . address && emails . push ( email . address ) ) ) ; } else { this . mailObject . to . value . map ( email => email . address ) . forEach ( address => address && emails . push ( address ) ) ; } } let addr = this . mailObject . headers . get ( 'x-forwarded-to' ) ; if ( addr ) emails . push ( addr . toString ( ) ) ; if ( this . session . envelope . rcptTo . length > 0 ) emails . push ( ... this . session . envelope . rcptTo . map ( email => email . address ) ) ; const promises = emails . map ( email => Account . getAccountFromEmail ( this . sqlConnection , email ) ) ; Promise . all ( promises ) . then ( ( results ) => { const accounts = results . filter ( acc => ! ! acc ) ; resolve ( accounts [ 0 ] || null ) ; } ) ; } ) ; } /**
     * Get the title of the email
     */ getTitle ( ) { return this . mailObject . subject || '_Untitled E-Mail_' ; } getAuthor ( ) { if ( ! this . mailObject . from ) return '_No Author Identified_' ; if ( this . mailObject . from . text . length > 256 ) return this . mailObject . from . text . substring ( 0 , 250 ) + '...' ; return this . mailObject . from . text ; } /**
     * Get the plaintext contents of the file
     */ getContents ( ) { if ( this . contentRequiresConversion ( ) ) { if ( this . mailObject . html === false ) return '' ; return htmlToText . fromString ( this . mailObject . html ) ; } else { if ( this . mailObject ?. text ?. trim ( ) . length === 0 ) return '' ; return this . mailObject . text || '' ; } } getTruncatedContents ( ) { if ( this . contentRequiresTruncation ( ) ) return this . getContents ( ) . substring ( 0 , 1995 ) + '...' ; return this . getContents ( ) ; } /**
     * Get the date of when the email was sent (or arrived)
     */ getDate ( ) { return this . mailObject . date || this . dateLoaded ; } getEmbed ( ) { const fields = [ ] ; if ( this . contentRequiresConversion ( ) ) { fields . push ( { name : 'Note' , value : 'This email has been converted from _HTML_ to _Plain Text_.' } ) ; } if ( this . contentRequiresTruncation ( ) ) { fields . push ( { name : 'Note' , value : 'This email has been truncated to fit under 2000 characters.' } ) ; } if ( this . emailContainsAttachments ( ) ) { fields . push ( { name : 'Attachments' , value : 'This email contains attachments.' } ) ; } return { title : this . getTitle ( ) , description : this . getTruncatedContents ( ) , timestamp : this . getDate ( ) , author : { name : this . getAuthor ( ) } , fields , footer : { text : 'dmail by https://leondrolio.com/' } } ; } } export default Mail ;