PageRenderTime 49ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/email/js/ext/pop3/probe.js

https://gitlab.com/Guy1394/gaia
JavaScript | 181 lines | 103 code | 16 blank | 62 comment | 29 complexity | d4e0321553f6992dbf08585aae762316 MD5 | raw file
  1. define([
  2. './pop3',
  3. '../syncbase',
  4. 'logic',
  5. '../errorutils',
  6. 'exports'
  7. ], function(pop3, syncbase, logic, errorutils, exports) {
  8. var scope = logic.scope('Pop3Prober');
  9. /**
  10. * Validate connection information for an account and verify that the
  11. * server on the other end is something we are capable of sustaining
  12. * an account with.
  13. *
  14. * If we succeed at logging in, hand off the established connection to
  15. * our caller so they can reuse the connection.
  16. */
  17. exports.probeAccount = function(credentials, connInfo) {
  18. var opts = {
  19. host: connInfo.hostname,
  20. port: connInfo.port,
  21. crypto: connInfo.crypto,
  22. username: credentials.username,
  23. password: credentials.password,
  24. connTimeout: syncbase.CONNECT_TIMEOUT_MS
  25. };
  26. logic(scope, 'connecting', { connInfo: connInfo });
  27. var resolve, reject;
  28. var promise = new Promise(function(_resolve, _reject) {
  29. resolve = _resolve;
  30. reject = _reject;
  31. });
  32. // We need the server to support UIDL and TOP. To test that it does,
  33. // first we assume that there's a message in the mailbox. If so, we
  34. // can just run `UIDL 1` and `TOP 1` to see if it works. If there
  35. // aren't any messages, we'll just run `UIDL` by itself to see if
  36. // that works. If so, great. If it errors out in any other path, the
  37. // server doesn't have the support we need and we must give up.
  38. var conn = new pop3.Pop3Client(opts, function(err) {
  39. if (err) { reject(err); return; }
  40. conn.protocol.sendRequest('UIDL', ['1'], false, function(err, rsp) {
  41. if (rsp) {
  42. conn.protocol.sendRequest('TOP', ['1', '0'], true, function(err, rsp) {
  43. if (rsp) {
  44. // both UIDL and TOP work. Awesome!
  45. resolve(conn);
  46. } else if (err.err) {
  47. // Uh, this server must not support TOP. That sucks.
  48. logic(scope, 'server-not-great', { why: 'no TOP' });
  49. reject('pop-server-not-great');
  50. } else {
  51. // if the error was socket-level or something, let it pass
  52. // through untouched
  53. reject(rsp.err);
  54. }
  55. });
  56. } else {
  57. // Either their inbox is empty or they don't support UIDL.
  58. conn.protocol.sendRequest('UIDL', [], true, function(err, rsp) {
  59. if (rsp) {
  60. // It looks like they support UIDL, so let's go for it.
  61. resolve(conn);
  62. } else if (err.err) {
  63. // They must not support UIDL. Not good enough.
  64. logic(scope, 'server-not-great', { why: 'no UIDL' });
  65. reject('pop-server-not-great');
  66. } else {
  67. // if the error was socket-level or something, let it pass
  68. // through untouched
  69. reject(rsp.err);
  70. }
  71. });
  72. }
  73. });
  74. });
  75. return promise
  76. .then(function(conn) {
  77. logic(scope, 'success');
  78. return {
  79. conn: conn,
  80. timezoneOffset: null
  81. };
  82. })
  83. .catch(function(err) {
  84. err = normalizePop3Error(err);
  85. logic(scope, 'error', { error: err });
  86. if (conn) {
  87. conn.close();
  88. }
  89. return Promise.reject(err);
  90. });
  91. }
  92. // These strings were taken verbatim from failed Gmail POP connection logs:
  93. var GMAIL_POP_DISABLED_RE = /\[SYS\/PERM\] Your account is not enabled for POP/;
  94. var GMAIL_DOMAIN_DISABLED_RE =
  95. /\[SYS\/PERM\] POP access is disabled for your domain\./;
  96. function analyzePop3LibraryError(err) {
  97. if (!err || !err.name) {
  98. return null;
  99. }
  100. // All POP3 library callback errors are normalized to the following form:
  101. //
  102. // var err = {
  103. // scope: 'connection|authentication|mailbox|message',
  104. // name: '...',
  105. // message: '...',
  106. // request: Pop3Client.Request (if applicable),
  107. // exception: (A socket error, if available),
  108. // };
  109. if (err.name === 'bad-user-or-pass' &&
  110. err.message && GMAIL_POP_DISABLED_RE.test(err.message)) {
  111. return 'pop3-disabled';
  112. }
  113. else if (err.name === 'bad-user-or-pass' &&
  114. err.message && GMAIL_DOMAIN_DISABLED_RE.test(err.message)) {
  115. return 'pop3-disabled';
  116. }
  117. // If there was a socket exception and the exception looks like
  118. // a security exception, note that it was a security-related
  119. // problem rather than just a bad server connection.
  120. else if (err.name === 'unresponsive-server' && err.exception &&
  121. err.exception.name && /security/i.test(err.exception.name)) {
  122. return 'bad-security';
  123. }
  124. // In two cases (bad auth, and unresponsive server), we might get
  125. // a more detailed status message from the server that saysa that
  126. // our account (or the entire server) is temporarily unavailble.
  127. // Per RFC 3206, these statuses indicate that the server is
  128. // unavailable right now but will be later.
  129. else if ((err.name === 'unresponsive-server' ||
  130. err.name === 'bad-user-or-pass') &&
  131. err.message && /\[(LOGIN-DELAY|SYS|IN-USE)/i.test(err.message)) {
  132. return 'server-maintenance';
  133. } else {
  134. return err.name;
  135. }
  136. }
  137. var normalizePop3Error = exports.normalizePop3Error = function(err) {
  138. var reportAs = (analyzePop3LibraryError(err) ||
  139. errorutils.analyzeException(err) ||
  140. 'unknown');
  141. logic(scope, 'normalized-error', { error: err, reportAs: reportAs });
  142. return reportAs;
  143. };
  144. /**
  145. * Notes on transient failures:
  146. *
  147. * LOGIN-DELAY: RFC2449 defines the LOGIN-DELAY capability to tell the
  148. * client how often it should check and introduces it as a response
  149. * code if the client checks too frequently. See
  150. * http://tools.ietf.org/html/rfc2449#section-8.1.1
  151. *
  152. * SYS: RFC3206 provides disambiguation between system failures and
  153. * auth failures. SYS/TEMP is something that should go away on its
  154. * own. SYS/PERM is for errors that probably require a human involved.
  155. * We aren't planning on actually telling the user what the SYS/PERM
  156. * problem was so they can contact tech support, so we lump them in
  157. * the same bucket. See http://tools.ietf.org/html/rfc3206#section-4
  158. *
  159. * IN-USE: Someone else is already in the maildrop, probably another
  160. * POP3 client. If optimizing for multiple POP3-using devices was
  161. * something we wanted to optimize for we would indicate a desire to
  162. * retry here with a more extensive back-off strategy. See
  163. * http://tools.ietf.org/html/rfc2449#section-8.1.2
  164. */
  165. }); // end define