1- import EmailReplyParser from ' email-reply-parser' ;
2- import Imap from ' imap' ;
3- import { simpleParser } from ' mailparser' ;
4- import { prisma } from ' ../../prisma' ;
5- import { EmailConfig , EmailQueue } from ' ../types/email' ;
6- import { AuthService } from ' ./auth.service' ;
1+ import EmailReplyParser from " email-reply-parser" ;
2+ import Imap from " imap" ;
3+ import { simpleParser } from " mailparser" ;
4+ import { prisma } from " ../../prisma" ;
5+ import { EmailConfig , EmailQueue } from " ../types/email" ;
6+ import { AuthService } from " ./auth.service" ;
77
88function getReplyText ( email : any ) : string {
9- const parsed = new EmailReplyParser ( ) . read ( email . text ) ;
10- let replyText = ''
9+ const parsed = new EmailReplyParser ( ) . read ( email . text ) ;
10+ const fragments = parsed . getFragments ( ) ;
1111
12- parsed . fragments . forEach ( fragment => {
13- if ( fragment . isHidden ( ) && ! fragment . isSignature ( ) && ! fragment . isQuoted ( ) ) return ;
14- replyText += fragment . content ;
15- } ) ;
12+ let replyText = "" ;
1613
17- return replyText ;
18-
14+ fragments . forEach ( ( fragment : any ) => {
15+ console . log ( "FRAGMENT" , fragment . _content , fragment . content ) ;
16+ if ( ! fragment . _isHidden && ! fragment . _isSignature && ! fragment . _isQuoted ) {
17+ replyText += fragment . _content ;
18+ }
19+ } ) ;
20+
21+ return replyText ;
1922}
2023
2124export class ImapService {
2225 private static async getImapConfig ( queue : EmailQueue ) : Promise < EmailConfig > {
2326 switch ( queue . serviceType ) {
24- case 'gmail' : {
25- const validatedAccessToken = await AuthService . getValidAccessToken ( queue ) ;
27+ case "gmail" : {
28+ const validatedAccessToken = await AuthService . getValidAccessToken (
29+ queue
30+ ) ;
31+
2632 return {
2733 user : queue . username ,
2834 host : queue . hostname ,
2935 port : 993 ,
3036 tls : true ,
31- xoauth2 : AuthService . generateXOAuth2Token ( queue . username , validatedAccessToken ) ,
32- tlsOptions : { rejectUnauthorized : false , servername : queue . hostname }
37+ xoauth2 : AuthService . generateXOAuth2Token (
38+ queue . username ,
39+ validatedAccessToken
40+ ) ,
41+ tlsOptions : { rejectUnauthorized : false , servername : queue . hostname } ,
3342 } ;
3443 }
35- case ' other' :
44+ case " other" :
3645 return {
3746 user : queue . username ,
3847 password : queue . password ,
3948 host : queue . hostname ,
4049 port : queue . tls ? 993 : 143 ,
4150 tls : queue . tls || false ,
42- tlsOptions : { rejectUnauthorized : false , servername : queue . hostname }
51+ tlsOptions : { rejectUnauthorized : false , servername : queue . hostname } ,
4352 } ;
4453 default :
45- throw new Error ( ' Unsupported service type' ) ;
54+ throw new Error ( " Unsupported service type" ) ;
4655 }
4756 }
4857
49- private static async processEmail ( parsed : any , isReply : boolean ) : Promise < void > {
58+ private static async processEmail (
59+ parsed : any ,
60+ isReply : boolean
61+ ) : Promise < void > {
5062 const { from, subject, text, html, textAsHtml } = parsed ;
5163
5264 if ( isReply ) {
@@ -57,111 +69,114 @@ export class ImapService {
5769
5870 const ticketId = ticketIdMatch [ 1 ] ;
5971 const ticket = await prisma . ticket . findFirst ( {
60- where : { Number : Number ( ticketId ) }
72+ where : { Number : Number ( ticketId ) } ,
6173 } ) ;
6274
6375 if ( ! ticket ) {
6476 throw new Error ( `Ticket not found: ${ ticketId } ` ) ;
6577 }
6678
6779 const replyText = getReplyText ( parsed ) ;
80+
6881 await prisma . comment . create ( {
6982 data : {
70- text : text ? replyText : ' No Body' ,
83+ text : text ? replyText : " No Body" ,
7184 userId : null ,
7285 ticketId : ticket . id ,
7386 reply : true ,
7487 replyEmail : from . value [ 0 ] . address ,
75- public : true
76- }
88+ public : true ,
89+ } ,
7790 } ) ;
7891 } else {
7992 const imapEmail = await prisma . imap_Email . create ( {
8093 data : {
8194 from : from . value [ 0 ] . address ,
82- subject : subject || ' No Subject' ,
83- body : text || ' No Body' ,
84- html : html || '' ,
85- text : textAsHtml
86- }
95+ subject : subject || " No Subject" ,
96+ body : text || " No Body" ,
97+ html : html || "" ,
98+ text : textAsHtml ,
99+ } ,
87100 } ) ;
88101
89102 await prisma . ticket . create ( {
90103 data : {
91104 email : from . value [ 0 ] . address ,
92105 name : from . value [ 0 ] . name ,
93- title : imapEmail . subject || '-' ,
106+ title : imapEmail . subject || "-" ,
94107 isComplete : false ,
95- priority : ' Low' ,
108+ priority : " Low" ,
96109 fromImap : true ,
97- detail : html || textAsHtml
98- }
110+ detail : html || textAsHtml ,
111+ } ,
99112 } ) ;
100113 }
101114 }
102115
103116 static async fetchEmails ( ) : Promise < void > {
104- const queues = ( await prisma . emailQueue . findMany ( ) ) as unknown as EmailQueue [ ] ;
117+ const queues =
118+ ( await prisma . emailQueue . findMany ( ) ) as unknown as EmailQueue [ ] ;
105119 const today = new Date ( ) ;
106120
107121 for ( const queue of queues ) {
108122 try {
109123 const imapConfig = await this . getImapConfig ( queue ) ;
110- if ( ! imapConfig . password ) {
111- console . error ( 'IMAP configuration is missing a password' ) ;
112- throw new Error ( 'IMAP configuration is missing a password' ) ;
124+
125+ if ( queue . serviceType === "other" && ! imapConfig . password ) {
126+ console . error ( "IMAP configuration is missing a password" ) ;
127+ throw new Error ( "IMAP configuration is missing a password" ) ;
113128 }
114129
115130 // @ts -ignore
116131 const imap = new Imap ( imapConfig ) ;
117132
118133 await new Promise ( ( resolve , reject ) => {
119- imap . once ( ' ready' , ( ) => {
120- imap . openBox ( ' INBOX' , false , ( err ) => {
134+ imap . once ( " ready" , ( ) => {
135+ imap . openBox ( " INBOX" , false , ( err ) => {
121136 if ( err ) {
122137 reject ( err ) ;
123138 return ;
124139 }
125- imap . search ( [ ' UNSEEN' , [ 'ON' , today ] ] , ( err , results ) => {
140+ imap . search ( [ " UNSEEN" , [ "ON" , today ] ] , ( err , results ) => {
126141 if ( err ) reject ( err ) ;
127142 if ( ! results ?. length ) {
128- console . log ( ' No new messages' ) ;
143+ console . log ( " No new messages" ) ;
129144 imap . end ( ) ;
130145 resolve ( null ) ;
131146 return ;
132147 }
133148
134- const fetch = imap . fetch ( results , { bodies : '' } ) ;
135-
136- fetch . on ( ' message' , ( msg ) => {
137- msg . on ( ' body' , ( stream ) => {
149+ const fetch = imap . fetch ( results , { bodies : "" } ) ;
150+
151+ fetch . on ( " message" , ( msg ) => {
152+ msg . on ( " body" , ( stream ) => {
138153 simpleParser ( stream , async ( err , parsed ) => {
139154 if ( err ) throw err ;
140- const isReply = parsed . subject ?. includes ( ' Re:' ) ;
155+ const isReply = parsed . subject ?. includes ( " Re:" ) ;
141156 await this . processEmail ( parsed , isReply || false ) ;
142157 } ) ;
143158 } ) ;
144159
145- msg . once ( ' attributes' , ( attrs ) => {
146- imap . addFlags ( attrs . uid , [ ' \\Seen' ] , ( ) => {
147- console . log ( ' Marked as read!' ) ;
160+ msg . once ( " attributes" , ( attrs ) => {
161+ imap . addFlags ( attrs . uid , [ " \\Seen" ] , ( ) => {
162+ console . log ( " Marked as read!" ) ;
148163 } ) ;
149164 } ) ;
150165 } ) ;
151166
152- fetch . once ( ' error' , reject ) ;
153- fetch . once ( ' end' , ( ) => {
154- console . log ( ' Done fetching messages' ) ;
167+ fetch . once ( " error" , reject ) ;
168+ fetch . once ( " end" , ( ) => {
169+ console . log ( " Done fetching messages" ) ;
155170 imap . end ( ) ;
156171 resolve ( null ) ;
157172 } ) ;
158173 } ) ;
159174 } ) ;
160175 } ) ;
161176
162- imap . once ( ' error' , reject ) ;
163- imap . once ( ' end' , ( ) => {
164- console . log ( ' Connection ended' ) ;
177+ imap . once ( " error" , reject ) ;
178+ imap . once ( " end" , ( ) => {
179+ console . log ( " Connection ended" ) ;
165180 resolve ( null ) ;
166181 } ) ;
167182
@@ -172,4 +187,4 @@ export class ImapService {
172187 }
173188 }
174189 }
175- }
190+ }
0 commit comments