@@ -96,20 +96,17 @@ func createEmail() -> String {
9696 " idToken " : idToken,
9797 ] )
9898
99- let ( _ , sendResp) = try await URLSession . shared. data ( for: sendReq)
99+ let ( sendData , sendResp) = try await URLSession . shared. data ( for: sendReq)
100100 guard let http = sendResp as? HTTPURLResponse , http. statusCode == 200 else {
101+ let errorBody = String ( data: sendData, encoding: . utf8) ?? " Unknown error "
101102 throw NSError ( domain: " EmulatorError " , code: 1 ,
102- userInfo: [ NSLocalizedDescriptionKey: " Failed to send verification email " ] )
103+ userInfo: [ NSLocalizedDescriptionKey: " Failed to send verification email: \( errorBody ) " ] )
103104 }
104105
105- // Step 2: Fetch OOB codes from emulator
106- let oobURL = URL ( string: " \( base) /emulator/v1/projects/ \( projectID) /oobCodes " ) !
107- let ( oobData, oobResp) = try await URLSession . shared. data ( from: oobURL)
108- guard ( oobResp as? HTTPURLResponse ) ? . statusCode == 200 else {
109- throw NSError ( domain: " EmulatorError " , code: 2 ,
110- userInfo: [ NSLocalizedDescriptionKey: " Failed to fetch OOB codes " ] )
111- }
106+ // Add a small delay to ensure the OOB code is registered in the emulator
107+ try await Task . sleep ( nanoseconds: 500_000_000 ) // 0.5 seconds
112108
109+ // Define structs for OOB response parsing
113110 struct OobEnvelope : Decodable { let oobCodes : [ OobItem ] }
114111 struct OobItem : Decodable {
115112 let oobCode : String
@@ -118,20 +115,50 @@ func createEmail() -> String {
118115 let creationTime : String ?
119116 }
120117
121- let envelope = try JSONDecoder ( ) . decode ( OobEnvelope . self, from: oobData)
122-
123- // Step 3: Find most recent VERIFY_EMAIL code for this email
124- let iso = ISO8601DateFormatter ( )
125- let codeItem = envelope. oobCodes
126- . filter {
127- $0. email. caseInsensitiveCompare ( email) == . orderedSame && $0. requestType == " VERIFY_EMAIL "
118+ // Step 2: Fetch OOB codes from emulator with retry logic
119+ let oobURL = URL ( string: " \( base) /emulator/v1/projects/ \( projectID) /oobCodes " ) !
120+
121+ var codeItem : OobItem ?
122+ var attempts = 0
123+ let maxAttempts = 5
124+
125+ while codeItem == nil && attempts < maxAttempts {
126+ let ( oobData, oobResp) = try await URLSession . shared. data ( from: oobURL)
127+ guard ( oobResp as? HTTPURLResponse ) ? . statusCode == 200 else {
128+ throw NSError ( domain: " EmulatorError " , code: 2 ,
129+ userInfo: [ NSLocalizedDescriptionKey: " Failed to fetch OOB codes " ] )
128130 }
129- . sorted {
130- let d0 = $0. creationTime. flatMap { iso. date ( from: $0) } ?? . distantPast
131- let d1 = $1. creationTime. flatMap { iso. date ( from: $0) } ?? . distantPast
132- return d0 > d1
131+
132+ let envelope = try JSONDecoder ( ) . decode ( OobEnvelope . self, from: oobData)
133+
134+ // Step 3: Find most recent VERIFY_EMAIL code for this email
135+ let iso = ISO8601DateFormatter ( )
136+ codeItem = envelope. oobCodes
137+ . filter {
138+ $0. email. caseInsensitiveCompare ( email) == . orderedSame && $0. requestType == " VERIFY_EMAIL "
139+ }
140+ . sorted {
141+ let d0 = $0. creationTime. flatMap { iso. date ( from: $0) } ?? . distantPast
142+ let d1 = $1. creationTime. flatMap { iso. date ( from: $0) } ?? . distantPast
143+ return d0 > d1
144+ }
145+ . first
146+
147+ if codeItem == nil {
148+ attempts += 1
149+ if attempts < maxAttempts {
150+ // Wait before retrying
151+ try await Task . sleep ( nanoseconds: 500_000_000 ) // 0.5 seconds
152+ } else {
153+ // Log available codes for debugging
154+ let availableCodes = envelope. oobCodes. map { " Email: \( $0. email) , Type: \( $0. requestType) " } . joined ( separator: " ; " )
155+ throw NSError ( domain: " EmulatorError " , code: 3 ,
156+ userInfo: [
157+ NSLocalizedDescriptionKey: " No VERIFY_EMAIL OOB code found for \( email) after \( maxAttempts) attempts. Available codes: \( availableCodes) " ,
158+ ] )
159+ }
133160 }
134- . first
161+ }
135162
136163 guard let oobCode = codeItem? . oobCode else {
137164 throw NSError ( domain: " EmulatorError " , code: 3 ,
0 commit comments