diff --git a/src/api/admin.rs b/src/api/admin.rs
index b5e3ef8d5b41604021518bece26daabf033b4d4b..2d68d5652a829db623861561666178c4679c7eea 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -4,9 +4,9 @@ use serde_json::Value;
 use crate::api::{JsonResult, JsonUpcase};
 use crate::CONFIG;
 
-use crate::mail;
 use crate::db::models::*;
 use crate::db::DbConn;
+use crate::mail;
 
 use rocket::request::{self, FromRequest, Request};
 use rocket::{Outcome, Route};
@@ -41,14 +41,14 @@ fn invite_user(data: JsonUpcase<InviteData>, _token: AdminToken, conn: DbConn) -
         err!("Invitations are not allowed")
     }
 
-    let mut invitation = Invitation::new(data.Email);
-    invitation.save(&conn)?;
-
     if let Some(ref mail_config) = CONFIG.mail {
         let mut user = User::new(email);
         user.save(&conn)?;
         let org_name = "bitwarden_rs";
         mail::send_invite(&user.email, &user.uuid, None, None, &org_name, None, mail_config)?;
+    } else {
+        let mut invitation = Invitation::new(data.Email);
+        invitation.save(&conn)?;
     }
 
     Ok(Json(json!({})))
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
index 9db46a0b8856cc36e428ab8d3b562ff39b306392..ae76734f381880b1756f765a5b8460785ac76f8c 100644
--- a/src/api/core/accounts.rs
+++ b/src/api/core/accounts.rs
@@ -61,29 +61,24 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
 
     let mut user = match User::find_by_mail(&data.Email, &conn) {
         Some(user) => {
-            if Invitation::find_by_mail(&data.Email, &conn).is_some() {
-                if CONFIG.mail.is_none() {
-                    for mut user_org in UserOrganization::find_invited_by_user(&user.uuid, &conn).iter_mut() {
-                        user_org.status = UserOrgStatus::Accepted as i32;
-                        user_org.save(&conn)?;
-                    }
-                    if !Invitation::take(&data.Email, &conn) {
-                        err!("Error accepting invitation")
-                    }
+            if !user.password_hash.is_empty() {
+                err!("User already exists")
+            }
+
+            if let Some(token) = data.Token {
+                let claims: InviteJWTClaims = decode_invite_jwt(&token)?;
+                if claims.email == data.Email {
                     user
                 } else {
-                    let token = match &data.Token {
-                        Some(token) => token,
-                        None => err!("No valid invite token"),
-                    };
-
-                    let claims: InviteJWTClaims = decode_invite_jwt(&token)?;
-                    if claims.email == data.Email {
-                        user
-                    } else {
-                        err!("Registration email does not match invite email")
-                    }
+                    err!("Registration email does not match invite email")
+                }
+            } else if Invitation::take(&data.Email, &conn) {
+                for mut user_org in UserOrganization::find_invited_by_user(&user.uuid, &conn).iter_mut() {
+                    user_org.status = UserOrgStatus::Accepted as i32;
+                    user_org.save(&conn)?;
                 }
+
+                user
             } else if CONFIG.signups_allowed {
                 err!("Account with this email already exists")
             } else {
@@ -91,14 +86,17 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
             }
         }
         None => {
-            if CONFIG.signups_allowed || (CONFIG.mail.is_none() && Invitation::take(&data.Email, &conn)) {
-                User::new(data.Email)
+            if CONFIG.signups_allowed || Invitation::take(&data.Email, &conn) {
+                User::new(data.Email.clone())
             } else {
                 err!("Registration not allowed")
             }
         }
     };
 
+    // Make sure we don't leave a lingering invitation.
+    Invitation::take(&data.Email, &conn);
+
     if let Some(client_kdf_iter) = data.KdfIterations {
         user.client_kdf_iter = client_kdf_iter;
     }
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
index 38bb60213bec8e2115ca8f733afddf09b3d7962f..6e278907efd1b11f4d75a422bd9e3503505a3e93 100644
--- a/src/api/core/organizations.rs
+++ b/src/api/core/organizations.rs
@@ -460,17 +460,19 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade
         };
         let user = match User::find_by_mail(&email, &conn) {
             None => {
-                if CONFIG.invitations_allowed {
-                    // Invite user if that's enabled
+                if !CONFIG.invitations_allowed {
+                    err!(format!("User email does not exist: {}", email))
+                }
+
+                if CONFIG.mail.is_none() {
                     let mut invitation = Invitation::new(email.clone());
                     invitation.save(&conn)?;
-                    let mut user = User::new(email.clone());
-                    user.save(&conn)?;
-                    user_org_status = UserOrgStatus::Invited as i32;
-                    user
-                } else {
-                    err!(format!("User email does not exist: {}", email))
                 }
+
+                let mut user = User::new(email.clone());
+                user.save(&conn)?;
+                user_org_status = UserOrgStatus::Invited as i32;
+                user
             }
             Some(user) => {
                 if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &conn).is_some() {
@@ -506,16 +508,16 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade
                 Some(org) => org.name,
                 None => err!("Error looking up organization"),
             };
-            
+
             mail::send_invite(
-                &email, 
-                &user.uuid, 
-                Some(org_id.clone()), 
-                Some(new_user.uuid), 
-                &org_name, 
-                Some(headers.user.email.clone()), 
-                mail_config
-                )?;
+                &email,
+                &user.uuid,
+                Some(org_id.clone()),
+                Some(new_user.uuid),
+                &org_name,
+                Some(headers.user.email.clone()),
+                mail_config,
+            )?;
         }
     }
 
@@ -546,9 +548,6 @@ fn reinvite_user(org_id: String, user_org: String, headers: AdminHeaders, conn:
         None => err!("User not found."),
     };
 
-    let mut invitation = Invitation::new(user.email.clone());
-    invitation.save(&conn)?;
-
     let org_name = match Organization::find_by_uuid(&org_id, &conn) {
         Some(org) => org.name,
         None => err!("Error looking up organization."),
@@ -556,14 +555,17 @@ fn reinvite_user(org_id: String, user_org: String, headers: AdminHeaders, conn:
 
     if let Some(ref mail_config) = CONFIG.mail {
         mail::send_invite(
-        &user.email,
-        &user.uuid,
-        Some(org_id),
-        Some(user_org.uuid),
-        &org_name,
-        Some(headers.user.email),
-        mail_config,
+            &user.email,
+            &user.uuid,
+            Some(org_id),
+            Some(user_org.uuid),
+            &org_name,
+            Some(headers.user.email),
+            mail_config,
         )?;
+    } else {
+        let mut invitation = Invitation::new(user.email.clone());
+        invitation.save(&conn)?;
     }
 
     Ok(())
@@ -585,16 +587,19 @@ fn accept_invite(_org_id: String, _org_user_id: String, data: JsonUpcase<AcceptD
     match User::find_by_mail(&claims.email, &conn) {
         Some(_) => {
             Invitation::take(&claims.email, &conn);
-            if claims.user_org_id.is_some() && claims.org_id.is_some() {
-                let mut user_org =
-                    match UserOrganization::find_by_uuid_and_org(&claims.user_org_id.unwrap(), &claims.org_id.clone().unwrap(), &conn) {
-                        Some(user_org) => user_org,
-                        None => err!("Error accepting the invitation"),
-                    };
-                user_org.status = UserOrgStatus::Accepted as i32;
-                if user_org.save(&conn).is_err() {
-                    err!("Failed to accept user to organization")
+
+            if let (Some(user_org), Some(org)) = (&claims.user_org_id, &claims.org_id) {
+                let mut user_org = match UserOrganization::find_by_uuid_and_org(user_org, org, &conn) {
+                    Some(user_org) => user_org,
+                    None => err!("Error accepting the invitation"),
+                };
+
+                if user_org.status != UserOrgStatus::Invited as i32 {
+                    err!("User already accepted the invitation")
                 }
+
+                user_org.status = UserOrgStatus::Accepted as i32;
+                user_org.save(&conn)?;
             }
         }
         None => err!("Invited user not found"),
@@ -605,7 +610,7 @@ fn accept_invite(_org_id: String, _org_user_id: String, data: JsonUpcase<AcceptD
         if let Some(org_id) = &claims.org_id {
             org_name = match Organization::find_by_uuid(&org_id, &conn) {
                 Some(org) => org.name,
-                None => err!("Organization not found.")
+                None => err!("Organization not found."),
             };
         };
         if let Some(invited_by_email) = &claims.invited_by_email {