diff --git a/CHANGELOG b/CHANGELOG
index e20b86c85e8743f7624ec9d638d7a198ff45a034..a081cc5077f32cea96152034960618eaec1f13ed 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+0.3.7 Dec 6:
+  o Fix error return values on openpgp backend.
+  o Remove address check when sending email and rely in the email
+    client to verify that is correct. Closes #4491.
+  o Support sending encrypted mails to addresses using the '+' sign.
+  o Improve exception names and handling.
+
 0.3.6 Nov 15:
   o Default encoding to 'utf-8' in case of system encodings not
     set. Closes #4427.
diff --git a/changes/VERSION_COMPAT b/changes/VERSION_COMPAT
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/leap/keymanager/__init__.py b/src/leap/keymanager/__init__.py
index dbc5489180d83bacb63cc6a70156e2e4c0bb5498..6cfbf7102573a12093ae4e2b643de0f3cb75ba6c 100644
--- a/src/leap/keymanager/__init__.py
+++ b/src/leap/keymanager/__init__.py
@@ -425,6 +425,9 @@ class KeyManager(object):
         :type data: str
         :param privkey: The key used to decrypt.
         :type privkey: OpenPGPKey
+        :param passphrase: The passphrase for the secret key used for
+                           decryption.
+        :type passphrase: str
         :param verify: The key used to verify a signature.
         :type verify: OpenPGPKey
 
diff --git a/src/leap/keymanager/errors.py b/src/leap/keymanager/errors.py
index 27180dbd9710dc0a7a75087d4dfe271c7490f128..ebe4fd5e4af24966a6fbcbb9c95cda05303c8b29 100644
--- a/src/leap/keymanager/errors.py
+++ b/src/leap/keymanager/errors.py
@@ -58,21 +58,21 @@ class InvalidSignature(Exception):
     pass
 
 
-class EncryptionFailed(Exception):
+class EncryptError(Exception):
     """
     Raised upon failures of encryption.
     """
     pass
 
 
-class DecryptionFailed(Exception):
+class DecryptError(Exception):
     """
     Raised upon failures of decryption.
     """
     pass
 
 
-class EncryptionDecryptionFailed(Exception):
+class GPGError(Exception):
     """
     Raised upon failures of encryption/decryption.
     """
diff --git a/src/leap/keymanager/openpgp.py b/src/leap/keymanager/openpgp.py
index f6223d576b52beb167835fca30e3c99c3458fd0f..856b21e449d63491a03cc6a6f2a8b16a3bc41f6c 100644
--- a/src/leap/keymanager/openpgp.py
+++ b/src/leap/keymanager/openpgp.py
@@ -297,7 +297,11 @@ class OpenPGPScheme(EncryptionScheme):
         :rtype: OpenPGPKey
         @raise KeyNotFound: If the key was not found on local storage.
         """
-        leap_assert(is_address(address), 'Not an user address: %s' % address)
+        # Remove the identity suffix after the '+' until the '@'
+        # e.g.: test_user+something@provider.com becomes test_user@probider.com
+        # since the key belongs to the identity without the '+' suffix.
+        address = re.sub(r'\+.*\@', '@', address)
+
         doc = self._get_key_doc(address, private)
         if doc is None:
             raise errors.KeyNotFound(address)
@@ -337,6 +341,7 @@ class OpenPGPScheme(EncryptionScheme):
             leap_assert(match is not None, 'No user address in key data.')
             address = match.group(1)
 
+            openpgp_privkey = None
             if privkey is not None:
                 match = re.match(mail_regex, privkey['uids'].pop())
                 leap_assert(match is not None, 'No user address in key data.')
@@ -370,6 +375,7 @@ class OpenPGPScheme(EncryptionScheme):
         """
         leap_assert_type(key_data, (str, unicode))
 
+        openpgp_privkey = None
         try:
             openpgp_pubkey, openpgp_privkey = self.parse_ascii_key(key_data)
         except (errors.KeyAddressMismatch, errors.KeyFingerprintMismatch) as e:
@@ -465,14 +471,18 @@ class OpenPGPScheme(EncryptionScheme):
     def _assert_gpg_result_ok(result):
         """
         Check if GPG result is 'ok' and log stderr outputs.
-        :param result: The GPG results
-        :type result:
+
+        :param result: GPG results, which have a field calld 'ok' that states
+                       whether the gpg operation was successful or not.
+        :type result: object
+
+        :raise GPGError: Raised when the gpg operation was not successful.
         """
         stderr = getattr(result, 'stderr', None)
         if stderr:
             logger.debug("%s" % (stderr,))
         if getattr(result, 'ok', None) is not True:
-            raise errors.EncryptionDecryptionFailed(
+            raise errors.GPGError(
                 'Failed to encrypt/decrypt: %s' % stderr)
 
     def encrypt(self, data, pubkey, passphrase=None, sign=None,
@@ -491,6 +501,8 @@ class OpenPGPScheme(EncryptionScheme):
 
         :return: The encrypted data.
         :rtype: str
+
+        :raise EncryptError: Raised if failed encrypting for some reason.
         """
         leap_assert_type(pubkey, OpenPGPKey)
         leap_assert(pubkey.private is False, 'Key is not public.')
@@ -509,8 +521,12 @@ class OpenPGPScheme(EncryptionScheme):
             # in the ciphertext.
             # result.ok    - (bool) indicates if the operation succeeded
             # result.data  - (bool) contains the result of the operation
-            self._assert_gpg_result_ok(result)
-            return result.data
+            try:
+                self._assert_gpg_result_ok(result)
+                return result.data
+            except errors.GPGError as e:
+                logger.error('Failed to decrypt: %s.' % str(e))
+                raise error.EncryptError()
 
     def decrypt(self, data, privkey, passphrase=None, verify=None):
         """
@@ -520,14 +536,18 @@ class OpenPGPScheme(EncryptionScheme):
         :type data: str
         :param privkey: The key used to decrypt.
         :type privkey: OpenPGPKey
+        :param passphrase: The passphrase for the secret key used for
+                           decryption.
+        :type passphrase: str
         :param verify: The key used to verify a signature.
         :type verify: OpenPGPKey
 
         :return: The decrypted data.
         :rtype: unicode
 
-        @raise InvalidSignature: Raised if unable to verify the signature with
-            C{verify} key.
+        :raise DecryptError: Raised if failed decrypting for some reason.
+        :raise InvalidSignature: Raised if unable to verify the signature with
+                                 C{verify} key.
         """
         leap_assert(privkey.private is True, 'Key is not private.')
         keys = [privkey]
@@ -536,26 +556,31 @@ class OpenPGPScheme(EncryptionScheme):
             leap_assert(verify.private is False)
             keys.append(verify)
         with self._temporary_gpgwrapper(keys) as gpg:
-            result = gpg.decrypt(
-                data, passphrase=passphrase, always_trust=True)
-            self._assert_gpg_result_ok(result)
-            # verify signature
-            if (verify is not None):
-                if result.valid is False or \
-                        verify.fingerprint != result.pubkey_fingerprint:
-                    raise errors.InvalidSignature(
-                        'Failed to verify signature with key %s: %s' %
-                        (verify.key_id, stderr))
-
-            # XXX: this is the encoding used by gpg module
-            # https://github.com/isislovecruft/python-gnupg/\
-            #   blob/master/gnupg/_meta.py#L121
-            encoding = locale.getpreferredencoding()
-            if encoding is None:
-                encoding = sys.stdin.encoding
-            if encoding is None:
-                encoding = 'utf-8'
-            return result.data.decode(encoding, 'replace')
+            try:
+                result = gpg.decrypt(
+                    data, passphrase=passphrase, always_trust=True)
+                self._assert_gpg_result_ok(result)
+                # verify signature
+                if (verify is not None):
+                    if result.valid is False or \
+                            verify.fingerprint != result.pubkey_fingerprint:
+                        raise errors.InvalidSignature(
+                            'Failed to verify signature with key %s: %s' %
+                            (verify.key_id, result.stderr))
+
+                # XXX: this is the encoding used by gpg module
+                # https://github.com/isislovecruft/python-gnupg/\
+                #   blob/master/gnupg/_meta.py#L121
+                encoding = locale.getpreferredencoding()
+                if encoding is None:
+                    encoding = sys.stdin.encoding
+                if encoding is None:
+                    encoding = 'utf-8'
+                return result.data.decode(encoding, 'replace')
+            except errors.GPGError as e:
+                logger.error('Failed to decrypt: %s.' % str(e))
+                raise errors.DecryptError(str(e))
+
 
     def is_encrypted(self, data):
         """
@@ -608,7 +633,7 @@ class OpenPGPScheme(EncryptionScheme):
             if result.fingerprint is None:
                 raise errors.SignFailed(
                     'Failed to sign with key %s: %s' %
-                    (privkey['keyid'], stderr))
+                    (privkey['keyid'], result.stderr))
             leap_assert(
                 result.fingerprint == kfprint,
                 'Signature and private key fingerprints mismatch: '