providers.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package email
  2. /*
  3. providers.go
  4. Known mail providers. A preset fills in server settings, tells the UI
  5. which sign-in methods apply and explains how to obtain an app password,
  6. which is what Gmail, Yahoo, iCloud and AOL require for third-party clients.
  7. */
  8. import (
  9. "strings"
  10. )
  11. // Preset describes a mail provider the account wizard knows.
  12. type Preset struct {
  13. ID string `json:"id"`
  14. Name string `json:"name"`
  15. Icon string `json:"icon"` //Semantic UI icon name
  16. Color string `json:"color"`
  17. Domains []string `json:"domains"`
  18. IMAP ServerConfig `json:"imap"`
  19. SMTP ServerConfig `json:"smtp"`
  20. OAuth string `json:"oauth,omitempty"` //google | microsoft when XOAUTH2 is supported
  21. PasswordLabel string `json:"passwordLabel"`
  22. PasswordHelp string `json:"passwordHelp"`
  23. PasswordURL string `json:"passwordUrl,omitempty"`
  24. UsernameStyle string `json:"usernameStyle"` //email | localpart
  25. SaveSent bool `json:"saveSent"` //The client must append sent mail to the Sent folder itself
  26. Hidden bool `json:"hidden"` //Matched by domain / MX only, not shown as a tile
  27. mxSuffixes []string //MX host suffixes that identify custom domains hosted here
  28. domainPrefixes []string //Prefixes such as "hotmail." covering regional domains
  29. }
  30. var presets = []Preset{
  31. {
  32. ID: "gmail",
  33. Name: "Gmail",
  34. Icon: "google",
  35. Color: "#ea4335",
  36. Domains: []string{
  37. "gmail.com", "googlemail.com",
  38. },
  39. IMAP: ServerConfig{Host: "imap.gmail.com", Port: 993, Security: SecuritySSL},
  40. SMTP: ServerConfig{Host: "smtp.gmail.com", Port: 465, Security: SecuritySSL},
  41. OAuth: "google",
  42. PasswordLabel: "App password",
  43. PasswordHelp: "Google does not accept your normal password here. Turn on 2-Step Verification for your Google account, then create a 16 character app password and paste it below.",
  44. PasswordURL: "https://myaccount.google.com/apppasswords",
  45. UsernameStyle: "email",
  46. SaveSent: false,
  47. mxSuffixes: []string{"google.com", "googlemail.com"},
  48. },
  49. {
  50. ID: "outlook",
  51. Name: "Outlook.com / Hotmail",
  52. Icon: "microsoft",
  53. Color: "#0078d4",
  54. Domains: []string{
  55. "outlook.com", "hotmail.com", "live.com", "msn.com", "passport.com",
  56. },
  57. IMAP: ServerConfig{Host: "outlook.office365.com", Port: 993, Security: SecuritySSL},
  58. SMTP: ServerConfig{Host: "smtp-mail.outlook.com", Port: 587, Security: SecuritySTARTTLS},
  59. OAuth: "microsoft",
  60. PasswordLabel: "App password",
  61. PasswordHelp: "Microsoft requires modern sign-in for Outlook.com, Hotmail and Live accounts, so use \"Sign in with Microsoft\" when it is available. A password only works if your account still allows app passwords.",
  62. PasswordURL: "https://account.live.com/proofs/AppPassword",
  63. UsernameStyle: "email",
  64. SaveSent: false,
  65. domainPrefixes: []string{
  66. "outlook.", "hotmail.", "live.",
  67. },
  68. },
  69. {
  70. ID: "office365",
  71. Name: "Microsoft 365 (work or school)",
  72. Icon: "windows",
  73. Color: "#d83b01",
  74. Domains: []string{},
  75. IMAP: ServerConfig{Host: "outlook.office365.com", Port: 993, Security: SecuritySSL},
  76. SMTP: ServerConfig{Host: "smtp.office365.com", Port: 587, Security: SecuritySTARTTLS},
  77. OAuth: "microsoft",
  78. PasswordLabel: "Password",
  79. PasswordHelp: "Microsoft 365 organisations normally require \"Sign in with Microsoft\". Your IT administrator must also allow IMAP and SMTP for your mailbox.",
  80. UsernameStyle: "email",
  81. SaveSent: false,
  82. mxSuffixes: []string{"mail.protection.outlook.com", "outlook.com"},
  83. },
  84. {
  85. ID: "yahoo",
  86. Name: "Yahoo Mail",
  87. Icon: "yahoo",
  88. Color: "#6001d2",
  89. Domains: []string{
  90. "yahoo.com", "ymail.com", "rocketmail.com",
  91. },
  92. IMAP: ServerConfig{Host: "imap.mail.yahoo.com", Port: 993, Security: SecuritySSL},
  93. SMTP: ServerConfig{Host: "smtp.mail.yahoo.com", Port: 465, Security: SecuritySSL},
  94. PasswordLabel: "App password",
  95. PasswordHelp: "Yahoo requires an app password for mail apps. Open Account Security, choose \"Generate app password\" and paste the result below.",
  96. PasswordURL: "https://login.yahoo.com/account/security",
  97. UsernameStyle: "email",
  98. SaveSent: true,
  99. mxSuffixes: []string{"yahoodns.net"},
  100. domainPrefixes: []string{"yahoo."},
  101. },
  102. {
  103. ID: "icloud",
  104. Name: "iCloud Mail",
  105. Icon: "apple",
  106. Color: "#3693f3",
  107. Domains: []string{
  108. "icloud.com", "me.com", "mac.com",
  109. },
  110. IMAP: ServerConfig{Host: "imap.mail.me.com", Port: 993, Security: SecuritySSL},
  111. SMTP: ServerConfig{Host: "smtp.mail.me.com", Port: 587, Security: SecuritySTARTTLS},
  112. PasswordLabel: "App-specific password",
  113. PasswordHelp: "Apple requires an app-specific password. Sign in to your Apple Account, open Sign-In and Security, choose App-Specific Passwords and generate one for ArozOS Mail.",
  114. PasswordURL: "https://account.apple.com/account/manage",
  115. UsernameStyle: "email",
  116. SaveSent: true,
  117. mxSuffixes: []string{"mail.icloud.com"},
  118. },
  119. {
  120. ID: "aol",
  121. Name: "AOL Mail",
  122. Icon: "envelope",
  123. Color: "#31459b",
  124. Domains: []string{"aol.com", "aim.com"},
  125. IMAP: ServerConfig{Host: "imap.aol.com", Port: 993, Security: SecuritySSL},
  126. SMTP: ServerConfig{Host: "smtp.aol.com", Port: 465, Security: SecuritySSL},
  127. PasswordLabel: "App password",
  128. PasswordHelp: "AOL requires an app password. Open Account Security and generate an app password for this device.",
  129. PasswordURL: "https://login.aol.com/account/security",
  130. UsernameStyle: "email",
  131. SaveSent: true,
  132. },
  133. {
  134. ID: "zoho",
  135. Name: "Zoho Mail",
  136. Icon: "envelope",
  137. Color: "#e42527",
  138. Domains: []string{"zoho.com", "zohomail.com"},
  139. IMAP: ServerConfig{Host: "imap.zoho.com", Port: 993, Security: SecuritySSL},
  140. SMTP: ServerConfig{Host: "smtp.zoho.com", Port: 465, Security: SecuritySSL},
  141. PasswordLabel: "Password",
  142. PasswordHelp: "Enable IMAP access in Zoho Mail settings first. Accounts with two-factor authentication need an application-specific password.",
  143. UsernameStyle: "email",
  144. SaveSent: true,
  145. mxSuffixes: []string{"zoho.com"},
  146. Hidden: true,
  147. },
  148. {
  149. ID: "fastmail",
  150. Name: "Fastmail",
  151. Icon: "envelope",
  152. Color: "#0067b9",
  153. Domains: []string{"fastmail.com", "fastmail.fm"},
  154. IMAP: ServerConfig{Host: "imap.fastmail.com", Port: 993, Security: SecuritySSL},
  155. SMTP: ServerConfig{Host: "smtp.fastmail.com", Port: 465, Security: SecuritySSL},
  156. PasswordLabel: "App password",
  157. PasswordHelp: "Fastmail requires an app password. Create one under Settings, Privacy & Security, Integrations.",
  158. PasswordURL: "https://app.fastmail.com/settings/security/integrations",
  159. UsernameStyle: "email",
  160. SaveSent: true,
  161. mxSuffixes: []string{"messagingengine.com"},
  162. Hidden: true,
  163. },
  164. {
  165. ID: "qq",
  166. Name: "QQ Mail",
  167. Icon: "envelope",
  168. Color: "#1aad19",
  169. Domains: []string{"qq.com", "foxmail.com", "vip.qq.com"},
  170. IMAP: ServerConfig{Host: "imap.qq.com", Port: 993, Security: SecuritySSL},
  171. SMTP: ServerConfig{Host: "smtp.qq.com", Port: 465, Security: SecuritySSL},
  172. PasswordLabel: "Authorization code",
  173. PasswordHelp: "Enable IMAP/SMTP in QQ Mail settings and use the generated authorization code instead of your QQ password.",
  174. UsernameStyle: "email",
  175. SaveSent: true,
  176. mxSuffixes: []string{"qq.com"},
  177. Hidden: true,
  178. },
  179. {
  180. ID: "netease",
  181. Name: "NetEase Mail",
  182. Icon: "envelope",
  183. Color: "#d0021b",
  184. Domains: []string{"163.com", "126.com", "yeah.net"},
  185. IMAP: ServerConfig{Host: "imap.163.com", Port: 993, Security: SecuritySSL},
  186. SMTP: ServerConfig{Host: "smtp.163.com", Port: 465, Security: SecuritySSL},
  187. PasswordLabel: "Authorization code",
  188. PasswordHelp: "Enable IMAP/SMTP in your mailbox settings and use the client authorization code instead of your login password.",
  189. UsernameStyle: "email",
  190. SaveSent: true,
  191. Hidden: true,
  192. },
  193. {
  194. ID: "yandex",
  195. Name: "Yandex Mail",
  196. Icon: "envelope",
  197. Color: "#fc3f1d",
  198. Domains: []string{"yandex.com", "yandex.ru", "ya.ru"},
  199. IMAP: ServerConfig{Host: "imap.yandex.com", Port: 993, Security: SecuritySSL},
  200. SMTP: ServerConfig{Host: "smtp.yandex.com", Port: 465, Security: SecuritySSL},
  201. PasswordLabel: "App password",
  202. PasswordHelp: "Yandex requires an app password for mail clients. Create one in your Yandex ID security settings.",
  203. PasswordURL: "https://id.yandex.com/security/app-passwords",
  204. UsernameStyle: "email",
  205. SaveSent: true,
  206. mxSuffixes: []string{"yandex.net", "yandex.ru"},
  207. Hidden: true,
  208. },
  209. }
  210. // customPreset is used for any server the wizard does not know.
  211. var customPreset = Preset{
  212. ID: "custom",
  213. Name: "Other mail account",
  214. Icon: "server",
  215. Color: "#5b6474",
  216. Domains: []string{},
  217. PasswordLabel: "Password",
  218. PasswordHelp: "Use the password of your mailbox. If your provider uses two-factor authentication you may need an app password.",
  219. UsernameStyle: "email",
  220. SaveSent: true,
  221. }
  222. // Presets returns every known provider, the generic one last.
  223. func Presets() []Preset {
  224. results := make([]Preset, 0, len(presets)+1)
  225. results = append(results, presets...)
  226. results = append(results, customPreset)
  227. return results
  228. }
  229. // PresetByID finds a preset by its identifier.
  230. func PresetByID(id string) (Preset, bool) {
  231. for _, preset := range presets {
  232. if preset.ID == id {
  233. return preset, true
  234. }
  235. }
  236. if id == customPreset.ID {
  237. return customPreset, true
  238. }
  239. return Preset{}, false
  240. }
  241. // presetForDomain matches the domain of an address against the known
  242. // consumer domains (gmail.com, hotmail.co.uk, yahoo.co.jp, …).
  243. func presetForDomain(domain string) (Preset, bool) {
  244. domain = strings.ToLower(strings.TrimSpace(domain))
  245. if domain == "" {
  246. return Preset{}, false
  247. }
  248. for _, preset := range presets {
  249. for _, known := range preset.Domains {
  250. if domain == known {
  251. return preset, true
  252. }
  253. }
  254. for _, prefix := range preset.domainPrefixes {
  255. if strings.HasPrefix(domain, prefix) {
  256. return preset, true
  257. }
  258. }
  259. }
  260. return Preset{}, false
  261. }
  262. // presetForMX identifies a hosted custom domain from one of its MX hosts.
  263. func presetForMX(mxHost string) (Preset, bool) {
  264. mxHost = strings.ToLower(strings.TrimSuffix(strings.TrimSpace(mxHost), "."))
  265. if mxHost == "" {
  266. return Preset{}, false
  267. }
  268. for _, preset := range presets {
  269. for _, suffix := range preset.mxSuffixes {
  270. if mxHost == suffix || strings.HasSuffix(mxHost, "."+suffix) {
  271. return preset, true
  272. }
  273. }
  274. }
  275. return Preset{}, false
  276. }
  277. // presetSavesSent reports whether a client must append sent mail to the Sent
  278. // folder itself for this provider (Gmail and Outlook file it server-side).
  279. func presetSavesSent(providerID string) bool {
  280. if preset, ok := PresetByID(providerID); ok {
  281. return preset.SaveSent
  282. }
  283. return true
  284. }
  285. // usernameFor applies the preset username style to an address.
  286. func usernameFor(style string, address string) string {
  287. if style == "localpart" {
  288. if at := strings.LastIndex(address, "@"); at > 0 {
  289. return address[:at]
  290. }
  291. }
  292. return address
  293. }
  294. // domainOf returns the lower-cased domain of an address.
  295. func domainOf(address string) string {
  296. address = strings.TrimSpace(address)
  297. at := strings.LastIndex(address, "@")
  298. if at < 0 || at == len(address)-1 {
  299. return ""
  300. }
  301. return strings.ToLower(address[at+1:])
  302. }
  303. // authHintFor returns the advice shown when a login with a password fails.
  304. func authHintFor(providerID string) string {
  305. preset, ok := PresetByID(providerID)
  306. if !ok {
  307. return ""
  308. }
  309. switch preset.ID {
  310. case "gmail":
  311. return "Gmail only accepts an app password (or Sign in with Google). Create one at myaccount.google.com/apppasswords after enabling 2-Step Verification."
  312. case "outlook", "office365":
  313. return "Microsoft accounts need \"Sign in with Microsoft\". Basic passwords are rejected for most Outlook, Hotmail and Microsoft 365 mailboxes."
  314. case "yahoo", "aol":
  315. return "Use an app password generated in your account security settings, not your normal password."
  316. case "icloud":
  317. return "iCloud needs an app-specific password generated in your Apple Account settings."
  318. case "qq", "netease":
  319. return "Use the authorization code from your mailbox settings and make sure IMAP/SMTP is enabled."
  320. }
  321. return preset.PasswordHelp
  322. }