Advertisement
Guest User

Untitled

a guest
Mar 30th, 2017
659
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.89 KB | None | 0 0
  1. //: Playground - noun: a place where people can play
  2.  
  3. import UIKit
  4.  
  5. struct EmailInfo {
  6.  
  7. struct Guessed {
  8. var firstname: String? = nil {
  9. didSet {
  10. if firstname != nil && firstname!.characters.count < 2 {
  11. firstname = nil
  12. }
  13. }
  14. }
  15. var lastname: String? = nil {
  16. didSet {
  17. if lastname != nil && lastname!.characters.count < 2 {
  18. lastname = nil
  19. }
  20. }
  21. }
  22. // TODO:
  23. // var companyName: String? = nil // better results if your target is professional, work with school too
  24. // TODO: what can we guess from the extension (top level domain) ? country or lang ?
  25. }
  26.  
  27. let email: String
  28.  
  29. // splitted email
  30. let local: String
  31. let hostname: String
  32. let ext: String
  33.  
  34. var guessed = Guessed()
  35.  
  36. private init(email: String) {
  37.  
  38. self.email = email
  39.  
  40. var emailComponents = email.components(separatedBy: "@")
  41. let domain = emailComponents.popLast()!
  42. local = emailComponents.joined(separator: "@") // email local part can have arobase in it
  43.  
  44. var domainComponents = domain.components(separatedBy: ".")
  45. hostname = domainComponents.removeFirst()
  46. ext = domainComponents.joined(separator: ".") // extension can contains multiple points
  47. }
  48.  
  49. mutating func guessFirstNameAndLastName(filterOnlyFirstnameOnCommonProviders: Bool = true) {
  50. // we remove non alphabetics char and use them to split into potential names
  51. let alpha = "qwertyuiopasdfghjklzxcvbnm"
  52. let charToIgnore = NSCharacterSet(charactersIn: alpha + alpha.uppercased()).inverted
  53. let components = local.components(separatedBy: charToIgnore)
  54. let firstComponentIsSingleLetter: Bool = components.first!.characters.count == 1
  55.  
  56. // we remove initials because we can do nothing from them
  57. var filteredComponents = components.filter({ (component) -> Bool in
  58. return component.characters.count > 1
  59. })
  60.  
  61. guard filteredComponents.count > 0 else {
  62. return
  63. }
  64.  
  65. guessed.firstname = filteredComponents.removeFirst()
  66. if filteredComponents.count == 0 && firstComponentIsSingleLetter { // handle case j.smith@icloud.com
  67. guessed.lastname = guessed.firstname
  68. guessed.firstname = nil
  69. } else {
  70. guessed.lastname = filteredComponents.joined(separator: " ")
  71. }
  72.  
  73. if filterOnlyFirstnameOnCommonProviders &&
  74. guessed.firstname != nil &&
  75. guessed.lastname == nil &&
  76. (hostname.contains("mail") || EmailInfo.commonMailProviders.contains(hostname)) {
  77. // we only have firstname and hostname is common -> we probably are wrong so we delete it
  78. guessed.firstname = nil
  79. }
  80. }
  81.  
  82. mutating func updateFirstnameKnowing(lastname lastName: String)
  83. {
  84. guard guessed.lastname != lastName else {
  85. return
  86. }
  87.  
  88. if guessed.firstname == nil && guessed.lastname == nil {
  89. guessFirstNameAndLastName(filterOnlyFirstnameOnCommonProviders: false)
  90. }
  91.  
  92. if guessed.firstname == lastName { // order was wrong -> we invert both exemple : smith.john@gmail.com
  93. guessed.firstname = guessed.lastname
  94. } else if guessed.firstname?.contains(lastName) ?? false { // both are in one string without separator exemple : johnsmith@gmail.com
  95. guessed.firstname = guessed.firstname?.replacingOccurrences(of: lastName, with: "")
  96. }
  97.  
  98. guessed.lastname = lastName
  99. }
  100.  
  101. mutating func updateLastnameKnowing(firstname firstName: String)
  102. {
  103. guard guessed.firstname != firstName else {
  104. return
  105. }
  106.  
  107. if guessed.firstname == nil && guessed.lastname == nil {
  108. guessFirstNameAndLastName(filterOnlyFirstnameOnCommonProviders: false)
  109. }
  110.  
  111. if guessed.lastname == firstName { // order was wrong -> we invert both exemple : smith.john@gmail.com
  112. guessed.lastname = guessed.firstname
  113. } else if guessed.firstname?.contains(firstName) ?? false && guessed.firstname != firstName { // both are in one string without separator (mean the only component we found is in first name) exemple : johnsmith@gmail.com
  114. guessed.lastname = guessed.firstname?.replacingOccurrences(of: firstName, with: "")
  115. } else if guessed.lastname == nil && guessed.firstname?.characters.first == firstName.characters.first {
  116. guessed.lastname = guessed.firstname
  117. guessed.lastname?.characters.removeFirst()
  118. }
  119.  
  120. guessed.firstname = firstName
  121. }
  122.  
  123. static let commonMailProviders = ["yahoo", "outlook", "live", "icloud"] // + anything containing "mail" in it (gmail, hotmail, yopmail, caramail, ...)
  124.  
  125. static func guessInfo(from email: String, knownInfo: Guessed? = nil) -> EmailInfo {
  126. var emailInfo = EmailInfo(email: email)
  127. if (knownInfo?.lastname == nil || knownInfo?.firstname == nil) {
  128. emailInfo.guessFirstNameAndLastName()
  129. if let lastname = knownInfo?.lastname {
  130. emailInfo.updateFirstnameKnowing(lastname: lastname)
  131. } else if let firstname = knownInfo?.firstname {
  132. emailInfo.updateLastnameKnowing(firstname: firstname)
  133. }
  134. } else {
  135. emailInfo.guessed.firstname = knownInfo?.firstname
  136. emailInfo.guessed.lastname = knownInfo?.lastname
  137. }
  138. return emailInfo
  139. }
  140. }
  141.  
  142.  
  143. var emails = [ // common mail formats to test
  144. "j-s@hotmail.fr", // nothing we can do
  145. "john@company.fr", // OK
  146. "john.k.smith@gmail.com", // OK
  147. "john@smith.fr", // uncommon ? john@company.fr is more common so we don't try to handle this case
  148. "john.smith@gmail.com", // OK
  149. "john.smith42@gmail.com", // OK
  150. "john.smith.42@gmail.com", // OK
  151. "johnsmith@gmail.com", // good after update, guess nothing when provider is common
  152. "smithjohn@gmail.com", // good after update, guess nothing when provider is common
  153. "smith.john@gmail.com", // good after update, best we can do
  154. "j.smith@yahoo.com", // best we can do
  155. "jsmith@icloud.com" // good after update, guess nothing when provider is common
  156. ]
  157.  
  158. for email in emails {
  159. print("email : " + email)
  160. var info = EmailInfo.guessInfo(from: email)
  161. print("firsname : " + (info.guessed.firstname ?? ""))
  162. print("lastname : " + (info.guessed.lastname ?? ""))
  163. print("-- update with firstname known as John")
  164. info.updateLastnameKnowing(firstname: "john")
  165. print("firsname : " + (info.guessed.firstname ?? ""))
  166. print("lastname : " + (info.guessed.lastname ?? ""))
  167. print("-- update with lastname known as Smith")
  168. info = EmailInfo.guessInfo(from: email)
  169. info.updateFirstnameKnowing(lastname: "smith")
  170. print("firsname : " + (info.guessed.firstname ?? ""))
  171. print("lastname : " + (info.guessed.lastname ?? ""))
  172. print("-----------")
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement