@@ -25,6 +25,14 @@ class NewEmailHandler {
2525 self . queue = queue
2626 }
2727
28+ enum ResultType {
29+ case Success
30+ case Failure
31+ case UnableToDecrypt
32+ case UnableToDecryptExternal
33+ case TooManyRequests
34+ }
35+
2836 struct Result {
2937 let email : Email ?
3038 let success : Bool
@@ -40,15 +48,30 @@ class NewEmailHandler {
4048 }
4149 }
4250
43- func command( params: [ String : Any ] , completion: @escaping ( _ result: Result ) -> Void ) {
51+ struct EmailProcessResult {
52+ let email : Email ?
53+ let type : ResultType
54+
55+ init ( type: ResultType ) {
56+ self . type = type
57+ self . email = nil
58+ }
59+
60+ init ( email: Email ) {
61+ self . email = email
62+ self . type = . Success
63+ }
64+ }
65+
66+ func command( params: [ String : Any ] , eventId: Any , completion: @escaping ( _ result: Result ) -> Void ) {
4467 guard let myAccount = database. getAccountById ( accountId) else {
4568 completion ( Result ( success: false ) )
4669 return
4770 }
4871
4972 guard let event = try ? NewEmail . init ( params: params) ,
5073 let recipientId = event. recipientId else {
51- completion ( Result ( success: false ) )
74+ completion ( Result ( success: false ) )
5275 return
5376 }
5477
@@ -60,23 +83,67 @@ class NewEmailHandler {
6083 }
6184 let defaults = CriptextDefaults ( )
6285 defaults. deleteEmailStrike ( id: email. compoundKey)
63- completion ( Result ( success: true ) )
86+ completion ( Result ( success: false ) )
6487 return
6588 }
89+ self . getEmailBody ( event: event, recipientId: recipientId, eventId: eventId, myAccount: myAccount) { ( result) in
90+ switch ( result. type) {
91+ case . UnableToDecryptExternal:
92+ guard let account = self . database. getAccountById ( self . accountId) else {
93+ completion ( Result ( success: false ) )
94+ return
95+ }
96+ self . reEncryptEmail ( event: event, eventId: eventId, jwt: account. jwt) { ( result) in
97+ switch ( result. type) {
98+ case . TooManyRequests:
99+ let content = String . localize ( " CONTENT_UNENCRYPTED " )
100+ guard let unencryptedEmail = self . constructEmail ( content: content, event: event, myAccount: account) else {
101+ completion ( Result ( success: false ) )
102+ return
103+ }
104+ completion ( Result ( email: unencryptedEmail) )
105+ default :
106+ completion ( Result ( success: result. type == . Success) )
107+ }
108+ }
109+ default :
110+ guard let email = result. email else {
111+ completion ( Result ( success: false ) )
112+ return
113+ }
114+ completion ( Result ( email: email) )
115+ }
116+ }
66117
118+ }
119+
120+ private func reEncryptEmail( event: NewEmail , eventId: Any , jwt: String , completion: @escaping ( _ result: EmailProcessResult ) -> Void ) {
121+ self . api. reEncryptEmail ( metadataKey: event. metadataKey, eventId: eventId, token: jwt) { ( responseData) in
122+ switch ( responseData) {
123+ case . TooManyRequests:
124+ completion ( EmailProcessResult ( type: . TooManyRequests) )
125+ case . Success:
126+ completion ( EmailProcessResult ( type: . Success) )
127+ default :
128+ completion ( EmailProcessResult ( type: . Failure) )
129+ }
130+ }
131+ }
132+
133+ private func getEmailBody( event: NewEmail , recipientId: String , eventId: Any , myAccount: Account , completion: @escaping ( _ result: EmailProcessResult ) -> Void ) {
67134 api. getEmailBody ( metadataKey: event. metadataKey, token: myAccount. jwt, queue: self . queue) { ( responseData) in
68135 var unsent = false
69136 var content = " "
70137 var contentHeader : String ? = nil
71138 guard let myAccount = self . database. getAccountById ( self . accountId) else {
72- completion ( Result ( success : false ) )
139+ completion ( EmailProcessResult ( type : . Failure ) )
73140 return
74141 }
75142 if case . Missing = responseData {
76143 unsent = true
77144 } else if case let . SuccessDictionary( data) = responseData {
78145 guard let bodyString = data [ " body " ] as? String else {
79- completion ( Result ( success : false ) )
146+ completion ( EmailProcessResult ( type : . Failure ) )
80147 return
81148 }
82149 let decryptedContentResult = self . handleContentByMessageType (
@@ -95,9 +162,12 @@ class NewEmailHandler {
95162 defaults. deleteEmailStrike ( id: emailId)
96163 } else {
97164 defaults. addEmailStrike ( id: emailId)
98- completion ( Result ( success : false ) )
165+ completion ( EmailProcessResult ( type : . Failure ) )
99166 return
100167 }
168+ case . UnableToDecryptExternal:
169+ completion ( EmailProcessResult ( type: . UnableToDecryptExternal) )
170+ return
101171 default :
102172 content = String . localize ( " CONTENT_UNENCRYPTED " )
103173 }
@@ -108,109 +178,121 @@ class NewEmailHandler {
108178 contentHeader = headersResult
109179 }
110180 } else {
111- completion ( Result ( success : false ) )
181+ completion ( EmailProcessResult ( type : . Failure ) )
112182 return
113183 }
114184
115- guard !FileUtils. existBodyFile ( email: myAccount. email, metadataKey: " \( event. metadataKey) " ) else {
116- if let email = self . database. getMail ( key: event. metadataKey, account: myAccount) {
117- completion ( Result ( email: email) )
118- return
119- }
120- completion ( Result ( success: true ) )
185+ let finalEmail = self . constructEmail ( content: content, event: event, myAccount: myAccount, unsent: unsent, contentHeader: contentHeader)
186+ guard finalEmail != nil else {
187+ completion ( EmailProcessResult ( type: . Success) )
121188 return
122189 }
123190
124- var replyThreadId = event. threadId
125- if let inReplyTo = event. inReplyTo,
126- let replyEmail = SharedDB . getEmail ( messageId: inReplyTo, account: myAccount) {
127- replyThreadId = replyEmail. threadId
191+ completion ( EmailProcessResult ( email: finalEmail!) )
192+ }
193+ }
194+
195+ func constructEmail( content: String , event: NewEmail , myAccount: Account , unsent: Bool = false , contentHeader: String ? = nil ) -> Email ? {
196+ guard !FileUtils. existBodyFile ( email: myAccount. email, metadataKey: " \( event. metadataKey) " ) else {
197+ if let email = self . database. getMail ( key: event. metadataKey, account: myAccount) {
198+ return email
128199 }
129-
130- let contentPreview = self . getContentPreview ( content: content)
131- let email = Email ( )
132- email. account = myAccount
133- email. threadId = replyThreadId
134- email. subject = event. subject
135- email. key = event. metadataKey
136- email. messageId = event. messageId
137- email. boundary = event. boundary ?? " "
138- email. date = event. date
139- email. unread = true
140- email. secure = event. guestEncryption == 1 || event. guestEncryption == 3 ? true : false
141- email. preview = contentPreview. 0
142- email. replyTo = event. replyTo ?? " "
143- email. buildCompoundKey ( )
144-
145- if ( unsent) {
146- email. unsentDate = email. date
147- email. delivered = Email . Status. unsent. rawValue
148- } else {
149- FileUtils . saveEmailToFile ( email: myAccount. email, metadataKey: " \( event. metadataKey) " , body: contentPreview. 1 , headers: contentHeader)
200+ return nil
201+ }
202+
203+ var replyThreadId = event. threadId
204+ if let inReplyTo = event. inReplyTo,
205+ let replyEmail = SharedDB . getEmail ( messageId: inReplyTo, account: myAccount) {
206+ replyThreadId = replyEmail. threadId
207+ }
208+
209+ let contentPreview = self . getContentPreview ( content: content)
210+ let email = Email ( )
211+ email. account = myAccount
212+ email. threadId = replyThreadId
213+ email. subject = event. subject
214+ email. key = event. metadataKey
215+ email. messageId = event. messageId
216+ email. boundary = event. boundary ?? " "
217+ email. date = event. date
218+ email. unread = true
219+ email. secure = event. guestEncryption == 1 || event. guestEncryption == 3 ? true : false
220+ email. preview = contentPreview. 0
221+ email. replyTo = event. replyTo ?? " "
222+ email. buildCompoundKey ( )
223+
224+ if ( unsent) {
225+ email. unsentDate = email. date
226+ email. delivered = Email . Status. unsent. rawValue
227+ } else {
228+ FileUtils . saveEmailToFile ( email: myAccount. email, metadataKey: " \( event. metadataKey) " , body: contentPreview. 1 , headers: contentHeader)
229+ }
230+
231+ guard let recipientId = event. recipientId else {
232+ return nil
233+ }
234+
235+ self . handleAttachments ( recipientId: recipientId, event: event, email: email, myAccount: myAccount, body: contentPreview. 1 )
236+
237+ email. fromAddress = event. from
238+ var fromMe = false
239+ if self . isFromMe ( email: email, account: myAccount, event: event) ,
240+ let sentLabel = SharedDB . getLabel ( SystemLabel . sent. id) {
241+ fromMe = true
242+ if !unsent {
243+ email. delivered = Email . Status. sent. rawValue
150244 }
151-
152- self . handleAttachments ( recipientId: recipientId, event: event, email: email, myAccount: myAccount, body: contentPreview. 1 )
153-
154- email. fromAddress = event. from
155- var fromMe = false
156- if self . isFromMe ( email: email, account: myAccount, event: event) ,
157- let sentLabel = SharedDB . getLabel ( SystemLabel . sent. id) {
158- fromMe = true
159- if !unsent {
160- email. delivered = Email . Status. sent. rawValue
161- }
162- email. unread = false
163- email. labels. append ( sentLabel)
164- if self . isMeARecipient ( email: email, account: myAccount, event: event) ,
165- let inboxLabel = SharedDB . getLabel ( SystemLabel . inbox. id) {
166- email. unread = true
167- email. labels. append ( inboxLabel)
168- }
169- } else if let inboxLabel = SharedDB . getLabel ( SystemLabel . inbox. id) {
245+ email. unread = false
246+ email. labels. append ( sentLabel)
247+ if self . isMeARecipient ( email: email, account: myAccount, event: event) ,
248+ let inboxLabel = SharedDB . getLabel ( SystemLabel . inbox. id) {
249+ email. unread = true
170250 email. labels. append ( inboxLabel)
171- let fromContact = self . database. getContact ( ContactUtils . parseContact ( event. from, account: myAccount) . email)
172- if ( fromContact != nil ) {
173- if ( fromContact? . spamScore ?? 0 >= 2 ) {
174- let spamLabel = SharedDB . getLabel ( SystemLabel . spam. id)
175- email. labels. append ( spamLabel!)
176- }
177- }
178- }
179-
180- if ( !event. labels. isEmpty) {
181- let labels = event. labels. reduce ( [ Label] ( ) , { ( labelsArray, labelText) -> [ Label ] in
182- guard let label = SharedDB . getLabel ( text: labelText) ,
183- ( !fromMe || label. id != SystemLabel . spam. id) else {
184- return labelsArray
185- }
186- return labelsArray. appending ( label)
187- } )
188- email. labels. append ( objectsIn: labels)
189- }
190-
191- guard self . database. store ( email) else {
192- completion ( Result ( success: true ) )
193- return
194251 }
195-
196- ContactUtils . parseEmailContacts ( [ event. from] , email: email, type: . from, account: myAccount)
197- ContactUtils . parseEmailContacts ( event. to, email: email, type: . to, account: myAccount)
198- ContactUtils . parseEmailContacts ( event. cc, email: email, type: . cc, account: myAccount)
199- ContactUtils . parseEmailContacts ( event. bcc, email: email, type: . bcc, account: myAccount)
200-
201- if let myContact = SharedDB . getContact ( myAccount. email) ,
202- myContact. displayName != myAccount. name {
203- SharedDB . update ( contact: myContact, name: myAccount. name)
252+ } else if let inboxLabel = SharedDB . getLabel ( SystemLabel . inbox. id) {
253+ email. labels. append ( inboxLabel)
254+ let fromContact = self . database. getContact ( ContactUtils . parseContact ( event. from, account: myAccount) . email)
255+ if ( fromContact != nil ) {
256+ if ( fromContact? . spamScore ?? 0 >= 2 ) {
257+ let spamLabel = SharedDB . getLabel ( SystemLabel . spam. id)
258+ email. labels. append ( spamLabel!)
259+ }
204260 }
205-
206- completion ( Result ( email: email) )
207261 }
262+
263+ if ( !event. labels. isEmpty) {
264+ let labels = event. labels. reduce ( [ Label] ( ) , { ( labelsArray, labelText) -> [ Label ] in
265+ guard let label = SharedDB . getLabel ( text: labelText) ,
266+ ( !fromMe || label. id != SystemLabel . spam. id) else {
267+ return labelsArray
268+ }
269+ return labelsArray. appending ( label)
270+ } )
271+ email. labels. append ( objectsIn: labels)
272+ }
273+
274+ guard self . database. store ( email) else {
275+ return nil
276+ }
277+
278+ ContactUtils . parseEmailContacts ( [ event. from] , email: email, type: . from, account: myAccount)
279+ ContactUtils . parseEmailContacts ( event. to, email: email, type: . to, account: myAccount)
280+ ContactUtils . parseEmailContacts ( event. cc, email: email, type: . cc, account: myAccount)
281+ ContactUtils . parseEmailContacts ( event. bcc, email: email, type: . bcc, account: myAccount)
282+
283+ if let myContact = SharedDB . getContact ( myAccount. email) ,
284+ myContact. displayName != myAccount. name {
285+ SharedDB . update ( contact: myContact, name: myAccount. name)
286+ }
287+ return email
208288 }
209289
210290 enum DecryptResult {
211291 case Content( String )
212292 case Duplicated
213293 case NoSession
294+ case UnableToDecrypt
295+ case UnableToDecryptExternal
214296 case Uknown
215297 }
216298
@@ -240,6 +322,8 @@ class NewEmailHandler {
240322 return . Duplicated
241323 } else if ( error. name. rawValue == " AxolotlNoSessionException " ) {
242324 return . NoSession
325+ } else if ( isExternal) {
326+ return . UnableToDecryptExternal
243327 } else {
244328 return . Uknown
245329 }
0 commit comments