summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorAnike Arni <anikarni@gmail.com>2017-04-19 10:25:04 -0300
committerGitHub <noreply@github.com>2017-04-19 10:25:04 -0300
commit3d394a960f43a87e38c2b8ffcbfc521ec5c759ff (patch)
tree9c5854907d0d5b198fbb83e4250c6e8eaa231fc0 /service
parent317e614b8d7314b8ec1a8ff3b2dfe7e189ad732e (diff)
parent6061af542abbb293660eedc5fe583234112bfdaa (diff)
Merge pull request #1054 from pixelated/recovery-code-email-template
[#927] Add recovery code mail template
Diffstat (limited to 'service')
-rw-r--r--service/pixelated/account_recovery.py18
-rw-r--r--service/pixelated/assets/recovery.mail.en-US20
-rw-r--r--service/test/functional/features/steps/mail_list.py6
-rw-r--r--service/test/functional/features/steps/mail_view.py6
-rw-r--r--service/test/unit/test_account_recovery.py14
5 files changed, 53 insertions, 11 deletions
diff --git a/service/pixelated/account_recovery.py b/service/pixelated/account_recovery.py
index 2208faf5..723d4048 100644
--- a/service/pixelated/account_recovery.py
+++ b/service/pixelated/account_recovery.py
@@ -14,12 +14,15 @@
# You should have received a copy of the GNU Affero General Public License
# along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
+import pkg_resources
+
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.logger import Logger
from twisted.mail import smtp
from email.mime.text import MIMEText
+from pixelated.resources.account_recovery_resource import AccountRecoveryResource
log = Logger()
@@ -53,7 +56,7 @@ class AccountRecovery(object):
log.info('Sending mail containing the user\'s recovery code')
sender = 'team@{}'.format(self._domain)
- msg = MIMEText('Your code %s' % code)
+ msg = MIMEText(self._get_recovery_mail(code))
msg['Subject'] = 'Recovery Code'
msg['From'] = sender
msg['To'] = backup_email
@@ -68,3 +71,16 @@ class AccountRecovery(object):
except Exception as e:
log.error('Failed trying to send the email with the recovery code')
raise e
+
+ def _get_recovery_mail(self, code, language='en-US'):
+ recovery_mail = pkg_resources.resource_filename(
+ 'pixelated.assets',
+ 'recovery.mail.%s' % (language))
+
+ account_recovery_url = '{}/{}'.format(self._domain, AccountRecoveryResource.BASE_URL)
+
+ with open(recovery_mail) as mail_template_file:
+ return mail_template_file.read().format(
+ domain=self._domain,
+ recovery_code=code,
+ account_recovery_url=account_recovery_url)
diff --git a/service/pixelated/assets/recovery.mail.en-US b/service/pixelated/assets/recovery.mail.en-US
new file mode 100644
index 00000000..d17f8a28
--- /dev/null
+++ b/service/pixelated/assets/recovery.mail.en-US
@@ -0,0 +1,20 @@
+Hello,
+
+You are receiving this email because you registered at a Pixelated provider, on {domain}.
+In case you ever forget your password, you can access this link {account_recovery_url} and put the following recovery code:
+
+{recovery_code}
+
+This code is the only way to recover access to your account in case you lose your password.
+Be careful and keep it safe!!!
+
+Why is this so important?
+
+Pixelated is an email client that respects your privacy and uses PGP Encryption to do so.
+Your password also gives you access to your keys, so if you forget it you will lose access to your account and the ability to decrypt your messages.
+We understand that forgetting passwords is a common thing, so we developed a more secure way to recover access to your account, therefore, a little bit more annoying ;)
+This code is half of a big code to recover your account, the other half is with the account administrator. In case you forget your password, use this code and your administrator code to recover access to your account. It's like those locks with two keys :)
+You will only succeed if you have both codes, so, never hurts to ask again: SAVE THIS CODE!
+
+
+PS: If you didn't create an account at {domain}, please ignore this email.
diff --git a/service/test/functional/features/steps/mail_list.py b/service/test/functional/features/steps/mail_list.py
index 2953c1af..21694153 100644
--- a/service/test/functional/features/steps/mail_list.py
+++ b/service/test/functional/features/steps/mail_list.py
@@ -138,9 +138,3 @@ def impl(context):
@then('I should not see any email')
def impl(context):
_wait_for_mail_list_to_be_empty(context)
-
-
-@then(u'I see the mail has the recovery code')
-def step_impl(context):
- expected_body = 'Your code'
- context.execute_steps(u"Then I see that the body has '%s'" % expected_body)
diff --git a/service/test/functional/features/steps/mail_view.py b/service/test/functional/features/steps/mail_view.py
index d10f86e7..9b49e6e5 100644
--- a/service/test/functional/features/steps/mail_view.py
+++ b/service/test/functional/features/steps/mail_view.py
@@ -109,3 +109,9 @@ def impl(context):
assert cc is not None
assert bcc is not None
+
+
+@then(u'I see the mail has the recovery code')
+def step_impl(context):
+ expected_body = 'This code is they only way to recover access to your account in case you lose your password.'
+ context.execute_steps(u"Then I see that the body has '%s'" % expected_body)
diff --git a/service/test/unit/test_account_recovery.py b/service/test/unit/test_account_recovery.py
index 08298419..b0edc466 100644
--- a/service/test/unit/test_account_recovery.py
+++ b/service/test/unit/test_account_recovery.py
@@ -19,7 +19,7 @@ from twisted.internet import defer
from twisted.trial import unittest
from twisted.mail import smtp
-from mock import patch, Mock
+from mock import patch, Mock, mock_open
from mockito import when, any as ANY
from pixelated.account_recovery import AccountRecovery
@@ -50,15 +50,21 @@ class AccountRecoveryTest(unittest.TestCase):
yield self.account_recovery.update_recovery_code()
self.mock_bonafide_session.update_recovery_code.assert_called_once_with(self.generated_code)
+ @patch('pixelated.account_recovery.smtp.sendmail')
+ @patch('pixelated.account_recovery.pkg_resources.resource_filename')
@defer.inlineCallbacks
- def test_send_recovery_code_by_email(self):
+ def test_send_recovery_code_by_email(self, mock_resource, mock_sendmail):
+ mock_sendmail.return_value = defer.succeed(None)
+
sender = 'team@{}'.format(self.domain)
- msg = MIMEText('Your code %s' % self.generated_code)
+ mock_file_content = '{domain}, {recovery_code}, {account_recovery_url}'
+ recovery_code_email = 'test.com, 4645a2f8997e5d0d, test.com/account-recovery'
+ msg = MIMEText(recovery_code_email)
msg['Subject'] = 'Recovery Code'
msg['From'] = sender
msg['To'] = self.backup_email
- with patch.object(smtp, 'sendmail', return_value=defer.succeed(None)) as mock_sendmail:
+ with patch('pixelated.account_recovery.open', mock_open(read_data=mock_file_content), create=True):
yield self.account_recovery._send_mail(self.generated_code, self.backup_email)
mock_sendmail.assert_called_with(