mirror of
				https://github.com/dani-garcia/vaultwarden.git
				synced 2025-10-31 13:51:14 +00:00 
			
		
		
		
	Upgrade dependencies and swap lettre to async transport
This commit is contained in:
		
					parent
					
						
							
								0c4e79cff6
							
						
					
				
			
			
				commit
				
					
						b64cf27038
					
				
			
		
					 10 changed files with 141 additions and 125 deletions
				
			
		
							
								
								
									
										80
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										80
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -273,9 +273,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" | |||
| 
 | ||||
| [[package]] | ||||
| name = "cached" | ||||
| version = "0.34.1" | ||||
| version = "0.36.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "12f5cd208ba696f870238022d81ca1d80ed9d696fd62341c747f2d8f6ecdd9fe" | ||||
| checksum = "76d9447b2a367383a918fbbe62f6892da68000170c7331003d132b4805b63214" | ||||
| dependencies = [ | ||||
|  "async-trait", | ||||
|  "async_once", | ||||
|  | @ -283,6 +283,7 @@ dependencies = [ | |||
|  "cached_proc_macro_types", | ||||
|  "futures", | ||||
|  "hashbrown 0.12.1", | ||||
|  "instant", | ||||
|  "lazy_static", | ||||
|  "once_cell", | ||||
|  "thiserror", | ||||
|  | @ -291,9 +292,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "cached_proc_macro" | ||||
| version = "0.12.0" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bce0f37f9b77c6b93cdf3f060c89adca303d2ab052cacb3c3d1ab543e8cecd2f" | ||||
| checksum = "4797df465f7409b55bab9ccd1edbf1d279ffdf763772c2804b96740ee72f3b82" | ||||
| dependencies = [ | ||||
|  "cached_proc_macro_types", | ||||
|  "darling", | ||||
|  | @ -455,9 +456,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "crypto-common" | ||||
| version = "0.1.3" | ||||
| version = "0.1.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" | ||||
| checksum = "5999502d32b9c48d492abe66392408144895020ec4709e549e840799f3bb74c0" | ||||
| dependencies = [ | ||||
|  "generic-array 0.14.5", | ||||
|  "typenum", | ||||
|  | @ -666,15 +667,15 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "either" | ||||
| version = "1.6.1" | ||||
| version = "1.7.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" | ||||
| checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "email-encoding" | ||||
| version = "0.1.2" | ||||
| version = "0.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "827e1fb86d24d558ab0454ca3fa084f8a6144ade1e3e6982f697c586bf96b41b" | ||||
| checksum = "34dd14c63662e0206599796cd5e1ad0268ab2b9d19b868d6050d688eba2bbf98" | ||||
| dependencies = [ | ||||
|  "base64", | ||||
|  "memchr", | ||||
|  | @ -1275,14 +1276,17 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
| 
 | ||||
| [[package]] | ||||
| name = "lettre" | ||||
| version = "0.10.0-rc.7" | ||||
| version = "0.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0f7e87d9d44162eea7abd87b1a7540fcb10d5e58e8bb4f173178f3dc6e453944" | ||||
| checksum = "5677c78c7c7ede1dd68e8a7078012bc625449fb304e7b509b917eaaedfe6e849" | ||||
| dependencies = [ | ||||
|  "async-trait", | ||||
|  "base64", | ||||
|  "email-encoding", | ||||
|  "email_address", | ||||
|  "fastrand", | ||||
|  "futures-io", | ||||
|  "futures-util", | ||||
|  "hostname", | ||||
|  "httpdate", | ||||
|  "idna 0.2.3", | ||||
|  | @ -1293,6 +1297,8 @@ dependencies = [ | |||
|  "quoted_printable", | ||||
|  "serde", | ||||
|  "socket2", | ||||
|  "tokio", | ||||
|  "tokio-native-tls", | ||||
|  "tracing", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1324,9 +1330,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "linked-hash-map" | ||||
| version = "0.5.4" | ||||
| version = "0.5.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" | ||||
| checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lock_api" | ||||
|  | @ -1628,9 +1634,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "once_cell" | ||||
| version = "1.12.0" | ||||
| version = "1.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" | ||||
| checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "opaque-debug" | ||||
|  | @ -2089,9 +2095,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.5.6" | ||||
| version = "1.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" | ||||
| checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  | @ -2109,9 +2115,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.6.26" | ||||
| version = "0.6.27" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" | ||||
| checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "remove_dir_all" | ||||
|  | @ -2411,9 +2417,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.137" | ||||
| version = "1.0.138" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" | ||||
| checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" | ||||
| dependencies = [ | ||||
|  "serde_derive", | ||||
| ] | ||||
|  | @ -2430,9 +2436,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.137" | ||||
| version = "1.0.138" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" | ||||
| checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  | @ -2441,9 +2447,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "serde_json" | ||||
| version = "1.0.81" | ||||
| version = "1.0.82" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" | ||||
| checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  | @ -2551,9 +2557,9 @@ checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" | |||
| 
 | ||||
| [[package]] | ||||
| name = "smallvec" | ||||
| version = "1.8.1" | ||||
| version = "1.9.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" | ||||
| checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "socket2" | ||||
|  | @ -2883,9 +2889,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-attributes" | ||||
| version = "0.1.21" | ||||
| version = "0.1.22" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" | ||||
| checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  | @ -2915,13 +2921,13 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "tracing-subscriber" | ||||
| version = "0.3.11" | ||||
| version = "0.3.14" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" | ||||
| checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59" | ||||
| dependencies = [ | ||||
|  "ansi_term", | ||||
|  "lazy_static", | ||||
|  "matchers", | ||||
|  "once_cell", | ||||
|  "regex", | ||||
|  "sharded-slab", | ||||
|  "smallvec", | ||||
|  | @ -3018,9 +3024,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "ucd-trie" | ||||
| version = "0.1.3" | ||||
| version = "0.1.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" | ||||
| checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "uncased" | ||||
|  | @ -3046,9 +3052,9 @@ checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" | |||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-normalization" | ||||
| version = "0.1.20" | ||||
| version = "0.1.21" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd" | ||||
| checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" | ||||
| dependencies = [ | ||||
|  "tinyvec", | ||||
| ] | ||||
|  |  | |||
							
								
								
									
										12
									
								
								Cargo.toml
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								Cargo.toml
									
										
									
									
									
								
							|  | @ -45,7 +45,7 @@ backtrace = "0.3.65" # Logging panics to logfile instead stderr only | |||
| dotenvy = { version = "0.15.1", default-features = false } | ||||
| 
 | ||||
| # Lazy initialization | ||||
| once_cell = "1.12.0" | ||||
| once_cell = "1.13.0" | ||||
| 
 | ||||
| # Numerical libraries | ||||
| num-traits = "0.2.15" | ||||
|  | @ -64,8 +64,8 @@ futures = "0.3.21" | |||
| tokio = { version = "1.19.2", features = ["rt-multi-thread", "fs", "io-util", "parking_lot", "time"] } | ||||
| 
 | ||||
| # A generic serialization/deserialization framework | ||||
| serde = { version = "1.0.137", features = ["derive"] } | ||||
| serde_json = "1.0.81" | ||||
| serde = { version = "1.0.138", features = ["derive"] } | ||||
| serde_json = "1.0.82" | ||||
| 
 | ||||
| # A safe, extensible ORM and Query builder | ||||
| diesel = { version = "1.4.8", features = ["chrono", "r2d2"] } | ||||
|  | @ -108,7 +108,7 @@ webauthn-rs = "0.3.2" | |||
| url = "2.2.2" | ||||
| 
 | ||||
| # Email librariese-Base, Update crates and small change. | ||||
| lettre = { version = "0.10.0-rc.7", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false } | ||||
| lettre = { version = "0.10.0", features = ["smtp-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } | ||||
| percent-encoding = "2.1.0" # URL encoding library used for URL's in the emails | ||||
| 
 | ||||
| # Template library | ||||
|  | @ -119,10 +119,10 @@ reqwest = { version = "0.11.11", features = ["stream", "json", "gzip", "brotli", | |||
| 
 | ||||
| # For favicon extraction from main website | ||||
| html5gum = "0.5.2" | ||||
| regex = { version = "1.5.6", features = ["std", "perf", "unicode-perl"], default-features = false } | ||||
| regex = { version = "1.6.0", features = ["std", "perf", "unicode-perl"], default-features = false } | ||||
| data-url = "0.1.1" | ||||
| bytes = "1.1.0" | ||||
| cached = "0.34.1" | ||||
| cached = "0.36.0" | ||||
| 
 | ||||
| # Used for custom short lived cookie jar during favicon extraction | ||||
| cookie = "0.16.0" | ||||
|  |  | |||
|  | @ -276,7 +276,7 @@ async fn invite_user(data: Json<InviteData>, _token: AdminToken, conn: DbConn) - | |||
| 
 | ||||
|     async fn _generate_invite(user: &User, conn: &DbConn) -> EmptyResult { | ||||
|         if CONFIG.mail_enabled() { | ||||
|             mail::send_invite(&user.email, &user.uuid, None, None, &CONFIG.invitation_org_name(), None) | ||||
|             mail::send_invite(&user.email, &user.uuid, None, None, &CONFIG.invitation_org_name(), None).await | ||||
|         } else { | ||||
|             let invitation = Invitation::new(user.email.clone()); | ||||
|             invitation.save(conn).await | ||||
|  | @ -290,11 +290,11 @@ async fn invite_user(data: Json<InviteData>, _token: AdminToken, conn: DbConn) - | |||
| } | ||||
| 
 | ||||
| #[post("/test/smtp", data = "<data>")] | ||||
| fn test_smtp(data: Json<InviteData>, _token: AdminToken) -> EmptyResult { | ||||
| async fn test_smtp(data: Json<InviteData>, _token: AdminToken) -> EmptyResult { | ||||
|     let data: InviteData = data.into_inner(); | ||||
| 
 | ||||
|     if CONFIG.mail_enabled() { | ||||
|         mail::send_test(&data.email) | ||||
|         mail::send_test(&data.email).await | ||||
|     } else { | ||||
|         err!("Mail is not enabled") | ||||
|     } | ||||
|  |  | |||
|  | @ -168,12 +168,12 @@ async fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult { | |||
| 
 | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if CONFIG.signups_verify() { | ||||
|             if let Err(e) = mail::send_welcome_must_verify(&user.email, &user.uuid) { | ||||
|             if let Err(e) = mail::send_welcome_must_verify(&user.email, &user.uuid).await { | ||||
|                 error!("Error sending welcome email: {:#?}", e); | ||||
|             } | ||||
| 
 | ||||
|             user.last_verifying_at = Some(user.created_at); | ||||
|         } else if let Err(e) = mail::send_welcome(&user.email) { | ||||
|         } else if let Err(e) = mail::send_welcome(&user.email).await { | ||||
|             error!("Error sending welcome email: {:#?}", e); | ||||
|         } | ||||
|     } | ||||
|  | @ -416,7 +416,7 @@ async fn post_email_token(data: JsonUpcase<EmailTokenData>, headers: Headers, co | |||
|     let token = crypto::generate_email_token(6); | ||||
| 
 | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if let Err(e) = mail::send_change_email(&data.NewEmail, &token) { | ||||
|         if let Err(e) = mail::send_change_email(&data.NewEmail, &token).await { | ||||
|             error!("Error sending change-email email: {:#?}", e); | ||||
|         } | ||||
|     } | ||||
|  | @ -485,14 +485,14 @@ async fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: D | |||
| } | ||||
| 
 | ||||
| #[post("/accounts/verify-email")] | ||||
| fn post_verify_email(headers: Headers) -> EmptyResult { | ||||
| async fn post_verify_email(headers: Headers) -> EmptyResult { | ||||
|     let user = headers.user; | ||||
| 
 | ||||
|     if !CONFIG.mail_enabled() { | ||||
|         err!("Cannot verify email address"); | ||||
|     } | ||||
| 
 | ||||
|     if let Err(e) = mail::send_verify_email(&user.email, &user.uuid) { | ||||
|     if let Err(e) = mail::send_verify_email(&user.email, &user.uuid).await { | ||||
|         error!("Error sending verify_email email: {:#?}", e); | ||||
|     } | ||||
| 
 | ||||
|  | @ -544,7 +544,7 @@ async fn post_delete_recover(data: JsonUpcase<DeleteRecoverData>, conn: DbConn) | |||
| 
 | ||||
|     if CONFIG.mail_enabled() { | ||||
|         if let Some(user) = User::find_by_mail(&data.Email, &conn).await { | ||||
|             if let Err(e) = mail::send_delete_account(&user.email, &user.uuid) { | ||||
|             if let Err(e) = mail::send_delete_account(&user.email, &user.uuid).await { | ||||
|                 error!("Error sending delete account email: {:#?}", e); | ||||
|             } | ||||
|         } | ||||
|  | @ -644,7 +644,7 @@ async fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> Empt | |||
|         Some(user) => { | ||||
|             let hint: Option<String> = user.password_hint; | ||||
|             if CONFIG.mail_enabled() { | ||||
|                 mail::send_password_hint(email, hint)?; | ||||
|                 mail::send_password_hint(email, hint).await?; | ||||
|                 Ok(()) | ||||
|             } else if let Some(hint) = hint { | ||||
|                 err!(format!("Your password hint is: {}", hint)); | ||||
|  |  | |||
|  | @ -251,7 +251,8 @@ async fn send_invite(data: JsonUpcase<EmergencyAccessInviteData>, headers: Heade | |||
|             Some(new_emergency_access.uuid), | ||||
|             Some(grantor_user.name.clone()), | ||||
|             Some(grantor_user.email), | ||||
|         )?; | ||||
|         ) | ||||
|         .await?; | ||||
|     } else { | ||||
|         // Automatically mark user as accepted if no email invites
 | ||||
|         match User::find_by_mail(&email, &conn).await { | ||||
|  | @ -304,7 +305,8 @@ async fn resend_invite(emer_id: String, headers: Headers, conn: DbConn) -> Empty | |||
|             Some(emergency_access.uuid), | ||||
|             Some(grantor_user.name.clone()), | ||||
|             Some(grantor_user.email), | ||||
|         )?; | ||||
|         ) | ||||
|         .await?; | ||||
|     } else { | ||||
|         if Invitation::find_by_mail(&email, &conn).await.is_none() { | ||||
|             let invitation = Invitation::new(email); | ||||
|  | @ -366,7 +368,7 @@ async fn accept_invite(emer_id: String, data: JsonUpcase<AcceptData>, conn: DbCo | |||
|         } | ||||
| 
 | ||||
|         if CONFIG.mail_enabled() { | ||||
|             mail::send_emergency_access_invite_accepted(&grantor_user.email, &grantee_user.email)?; | ||||
|             mail::send_emergency_access_invite_accepted(&grantor_user.email, &grantee_user.email).await?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
|  | @ -449,7 +451,7 @@ async fn confirm_emergency_access( | |||
|         emergency_access.save(&conn).await?; | ||||
| 
 | ||||
|         if CONFIG.mail_enabled() { | ||||
|             mail::send_emergency_access_invite_confirmed(&grantee_user.email, &grantor_user.name)?; | ||||
|             mail::send_emergency_access_invite_confirmed(&grantee_user.email, &grantor_user.name).await?; | ||||
|         } | ||||
|         Ok(Json(emergency_access.to_json())) | ||||
|     } else { | ||||
|  | @ -495,7 +497,8 @@ async fn initiate_emergency_access(emer_id: String, headers: Headers, conn: DbCo | |||
|             &initiating_user.name, | ||||
|             emergency_access.get_type_as_str(), | ||||
|             &emergency_access.wait_time_days.clone().to_string(), | ||||
|         )?; | ||||
|         ) | ||||
|         .await?; | ||||
|     } | ||||
|     Ok(Json(emergency_access.to_json())) | ||||
| } | ||||
|  | @ -531,7 +534,7 @@ async fn approve_emergency_access(emer_id: String, headers: Headers, conn: DbCon | |||
|         emergency_access.save(&conn).await?; | ||||
| 
 | ||||
|         if CONFIG.mail_enabled() { | ||||
|             mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name)?; | ||||
|             mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name).await?; | ||||
|         } | ||||
|         Ok(Json(emergency_access.to_json())) | ||||
|     } else { | ||||
|  | @ -571,7 +574,7 @@ async fn reject_emergency_access(emer_id: String, headers: Headers, conn: DbConn | |||
|         emergency_access.save(&conn).await?; | ||||
| 
 | ||||
|         if CONFIG.mail_enabled() { | ||||
|             mail::send_emergency_access_recovery_rejected(&grantee_user.email, &grantor_user.name)?; | ||||
|             mail::send_emergency_access_recovery_rejected(&grantee_user.email, &grantor_user.name).await?; | ||||
|         } | ||||
|         Ok(Json(emergency_access.to_json())) | ||||
|     } else { | ||||
|  | @ -779,9 +782,11 @@ pub async fn emergency_request_timeout_job(pool: DbPool) { | |||
|                         &grantee_user.name.clone(), | ||||
|                         emer.get_type_as_str(), | ||||
|                     ) | ||||
|                     .await | ||||
|                     .expect("Error on sending email"); | ||||
| 
 | ||||
|                     mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name.clone()) | ||||
|                         .await | ||||
|                         .expect("Error on sending email"); | ||||
|                 } | ||||
|             } | ||||
|  | @ -831,6 +836,7 @@ pub async fn emergency_notification_reminder_job(pool: DbPool) { | |||
|                         emer.get_type_as_str(), | ||||
|                         &emer.wait_time_days.to_string(), // TODO(jjlin): This should be the number of days left.
 | ||||
|                     ) | ||||
|                     .await | ||||
|                     .expect("Error on sending email"); | ||||
|                 } | ||||
|             } | ||||
|  |  | |||
|  | @ -652,7 +652,8 @@ async fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: Admi | |||
|                 Some(new_user.uuid), | ||||
|                 &org_name, | ||||
|                 Some(headers.user.email.clone()), | ||||
|             )?; | ||||
|             ) | ||||
|             .await?; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -732,7 +733,8 @@ async fn _reinvite_user(org_id: &str, user_org: &str, invited_by_email: &str, co | |||
|             Some(user_org.uuid), | ||||
|             &org_name, | ||||
|             Some(invited_by_email.to_string()), | ||||
|         )?; | ||||
|         ) | ||||
|         .await?; | ||||
|     } else { | ||||
|         let invitation = Invitation::new(user.email); | ||||
|         invitation.save(conn).await?; | ||||
|  | @ -830,10 +832,10 @@ async fn accept_invite( | |||
|         }; | ||||
|         if let Some(invited_by_email) = &claims.invited_by_email { | ||||
|             // User was invited to an organization, so they must be confirmed manually after acceptance
 | ||||
|             mail::send_invite_accepted(&claims.email, invited_by_email, &org_name)?; | ||||
|             mail::send_invite_accepted(&claims.email, invited_by_email, &org_name).await?; | ||||
|         } else { | ||||
|             // User was invited from /admin, so they are automatically confirmed
 | ||||
|             mail::send_invite_confirmed(&claims.email, &org_name)?; | ||||
|             mail::send_invite_confirmed(&claims.email, &org_name).await?; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -928,7 +930,7 @@ async fn _confirm_invite( | |||
|             Some(user) => user.email, | ||||
|             None => err!("Error looking up user."), | ||||
|         }; | ||||
|         mail::send_invite_confirmed(&address, &org_name)?; | ||||
|         mail::send_invite_confirmed(&address, &org_name).await?; | ||||
|     } | ||||
| 
 | ||||
|     user_to_confirm.save(conn).await | ||||
|  | @ -1298,7 +1300,7 @@ async fn put_policy( | |||
|                     let org = Organization::find_by_uuid(&member.org_uuid, &conn).await.unwrap(); | ||||
|                     let user = User::find_by_uuid(&member.user_uuid, &conn).await.unwrap(); | ||||
| 
 | ||||
|                     mail::send_2fa_removed_from_org(&user.email, &org.name)?; | ||||
|                     mail::send_2fa_removed_from_org(&user.email, &org.name).await?; | ||||
|                 } | ||||
|                 member.delete(&conn).await?; | ||||
|             } | ||||
|  | @ -1323,7 +1325,7 @@ async fn put_policy( | |||
|                         let org = Organization::find_by_uuid(&member.org_uuid, &conn).await.unwrap(); | ||||
|                         let user = User::find_by_uuid(&member.user_uuid, &conn).await.unwrap(); | ||||
| 
 | ||||
|                         mail::send_single_org_removed_from_org(&user.email, &org.name)?; | ||||
|                         mail::send_single_org_removed_from_org(&user.email, &org.name).await?; | ||||
|                     } | ||||
|                     member.delete(&conn).await?; | ||||
|                 } | ||||
|  | @ -1462,7 +1464,8 @@ async fn import(org_id: String, data: JsonUpcase<OrgImportData>, headers: Header | |||
|                         Some(new_org_user.uuid), | ||||
|                         &org_name, | ||||
|                         Some(headers.user.email.clone()), | ||||
|                     )?; | ||||
|                     ) | ||||
|                     .await?; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ pub async fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult { | |||
|     twofactor.data = twofactor_data.to_json(); | ||||
|     twofactor.save(conn).await?; | ||||
| 
 | ||||
|     mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?; | ||||
|     mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?).await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  | @ -132,7 +132,7 @@ async fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbC | |||
|     let twofactor = TwoFactor::new(user.uuid, TwoFactorType::EmailVerificationChallenge, twofactor_data.to_json()); | ||||
|     twofactor.save(&conn).await?; | ||||
| 
 | ||||
|     mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?; | ||||
|     mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?).await?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
|  |  | |||
|  | @ -138,7 +138,7 @@ async fn disable_twofactor(data: JsonUpcase<DisableTwoFactorData>, headers: Head | |||
|             if user_org.atype < UserOrgType::Admin { | ||||
|                 if CONFIG.mail_enabled() { | ||||
|                     let org = Organization::find_by_uuid(&user_org.org_uuid, &conn).await.unwrap(); | ||||
|                     mail::send_2fa_removed_from_org(&user.email, &org.name)?; | ||||
|                     mail::send_2fa_removed_from_org(&user.email, &org.name).await?; | ||||
|                 } | ||||
|                 user_org.delete(&conn).await?; | ||||
|             } | ||||
|  | @ -183,6 +183,7 @@ pub async fn send_incomplete_2fa_notifications(pool: DbPool) { | |||
|             user.email, login.ip_address | ||||
|         ); | ||||
|         mail::send_incomplete_2fa_login(&user.email, &login.ip_address, &login.login_time, &login.device_name) | ||||
|             .await | ||||
|             .expect("Error sending incomplete 2FA email"); | ||||
|         login.delete(&conn).await.expect("Error deleting incomplete 2FA record"); | ||||
|     } | ||||
|  |  | |||
|  | @ -135,7 +135,7 @@ async fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> Json | |||
|                     error!("Error updating user: {:#?}", e); | ||||
|                 } | ||||
| 
 | ||||
|                 if let Err(e) = mail::send_verify_email(&user.email, &user.uuid) { | ||||
|                 if let Err(e) = mail::send_verify_email(&user.email, &user.uuid).await { | ||||
|                     error!("Error auto-sending email verification email: {:#?}", e); | ||||
|                 } | ||||
|             } | ||||
|  | @ -150,7 +150,7 @@ async fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> Json | |||
|     let twofactor_token = twofactor_auth(&user.uuid, &data, &mut device, ip, &conn).await?; | ||||
| 
 | ||||
|     if CONFIG.mail_enabled() && new_device { | ||||
|         if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name) { | ||||
|         if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name).await { | ||||
|             error!("Error sending new device email: {:#?}", e); | ||||
| 
 | ||||
|             if CONFIG.require_device_email() { | ||||
|  | @ -225,7 +225,7 @@ async fn _api_key_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonR | |||
| 
 | ||||
|     if CONFIG.mail_enabled() && new_device { | ||||
|         let now = Utc::now().naive_utc(); | ||||
|         if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name) { | ||||
|         if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name).await { | ||||
|             error!("Error sending new device email: {:#?}", e); | ||||
| 
 | ||||
|             if CONFIG.require_device_email() { | ||||
|  |  | |||
							
								
								
									
										102
									
								
								src/mail.rs
									
										
									
									
									
								
							
							
						
						
									
										102
									
								
								src/mail.rs
									
										
									
									
									
								
							|  | @ -8,7 +8,7 @@ use lettre::{ | |||
|     transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism}, | ||||
|     transport::smtp::client::{Tls, TlsParameters}, | ||||
|     transport::smtp::extension::ClientId, | ||||
|     Address, SmtpTransport, Transport, | ||||
|     Address, AsyncSmtpTransport, AsyncTransport, Tokio1Executor, | ||||
| }; | ||||
| 
 | ||||
| use crate::{ | ||||
|  | @ -21,11 +21,11 @@ use crate::{ | |||
|     CONFIG, | ||||
| }; | ||||
| 
 | ||||
| fn mailer() -> SmtpTransport { | ||||
| fn mailer() -> AsyncSmtpTransport<Tokio1Executor> { | ||||
|     use std::time::Duration; | ||||
|     let host = CONFIG.smtp_host().unwrap(); | ||||
| 
 | ||||
|     let smtp_client = SmtpTransport::builder_dangerous(host.as_str()) | ||||
|     let smtp_client = AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host.as_str()) | ||||
|         .port(CONFIG.smtp_port()) | ||||
|         .timeout(Some(Duration::from_secs(CONFIG.smtp_timeout()))); | ||||
| 
 | ||||
|  | @ -110,7 +110,7 @@ fn get_template(template_name: &str, data: &serde_json::Value) -> Result<(String | |||
|     Ok((subject, body)) | ||||
| } | ||||
| 
 | ||||
| pub fn send_password_hint(address: &str, hint: Option<String>) -> EmptyResult { | ||||
| pub async fn send_password_hint(address: &str, hint: Option<String>) -> EmptyResult { | ||||
|     let template_name = if hint.is_some() { | ||||
|         "email/pw_hint_some" | ||||
|     } else { | ||||
|  | @ -119,10 +119,10 @@ pub fn send_password_hint(address: &str, hint: Option<String>) -> EmptyResult { | |||
| 
 | ||||
|     let (subject, body_html, body_text) = get_text(template_name, json!({ "hint": hint, "url": CONFIG.domain() }))?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_delete_account(address: &str, uuid: &str) -> EmptyResult { | ||||
| pub async fn send_delete_account(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_delete_claims(uuid.to_string()); | ||||
|     let delete_token = encode_jwt(&claims); | ||||
| 
 | ||||
|  | @ -136,10 +136,10 @@ pub fn send_delete_account(address: &str, uuid: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_verify_email(address: &str, uuid: &str) -> EmptyResult { | ||||
| pub async fn send_verify_email(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_verify_email_claims(uuid.to_string()); | ||||
|     let verify_email_token = encode_jwt(&claims); | ||||
| 
 | ||||
|  | @ -153,10 +153,10 @@ pub fn send_verify_email(address: &str, uuid: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_welcome(address: &str) -> EmptyResult { | ||||
| pub async fn send_welcome(address: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/welcome", | ||||
|         json!({ | ||||
|  | @ -164,10 +164,10 @@ pub fn send_welcome(address: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_welcome_must_verify(address: &str, uuid: &str) -> EmptyResult { | ||||
| pub async fn send_welcome_must_verify(address: &str, uuid: &str) -> EmptyResult { | ||||
|     let claims = generate_verify_email_claims(uuid.to_string()); | ||||
|     let verify_email_token = encode_jwt(&claims); | ||||
| 
 | ||||
|  | @ -180,10 +180,10 @@ pub fn send_welcome_must_verify(address: &str, uuid: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_2fa_removed_from_org(address: &str, org_name: &str) -> EmptyResult { | ||||
| pub async fn send_2fa_removed_from_org(address: &str, org_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/send_2fa_removed_from_org", | ||||
|         json!({ | ||||
|  | @ -192,10 +192,10 @@ pub fn send_2fa_removed_from_org(address: &str, org_name: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_single_org_removed_from_org(address: &str, org_name: &str) -> EmptyResult { | ||||
| pub async fn send_single_org_removed_from_org(address: &str, org_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/send_single_org_removed_from_org", | ||||
|         json!({ | ||||
|  | @ -204,10 +204,10 @@ pub fn send_single_org_removed_from_org(address: &str, org_name: &str) -> EmptyR | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_invite( | ||||
| pub async fn send_invite( | ||||
|     address: &str, | ||||
|     uuid: &str, | ||||
|     org_id: Option<String>, | ||||
|  | @ -236,10 +236,10 @@ pub fn send_invite( | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_invite( | ||||
| pub async fn send_emergency_access_invite( | ||||
|     address: &str, | ||||
|     uuid: &str, | ||||
|     emer_id: Option<String>, | ||||
|  | @ -267,10 +267,10 @@ pub fn send_emergency_access_invite( | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_invite_accepted(address: &str, grantee_email: &str) -> EmptyResult { | ||||
| pub async fn send_emergency_access_invite_accepted(address: &str, grantee_email: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/emergency_access_invite_accepted", | ||||
|         json!({ | ||||
|  | @ -279,10 +279,10 @@ pub fn send_emergency_access_invite_accepted(address: &str, grantee_email: &str) | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_invite_confirmed(address: &str, grantor_name: &str) -> EmptyResult { | ||||
| pub async fn send_emergency_access_invite_confirmed(address: &str, grantor_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/emergency_access_invite_confirmed", | ||||
|         json!({ | ||||
|  | @ -291,10 +291,10 @@ pub fn send_emergency_access_invite_confirmed(address: &str, grantor_name: &str) | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_recovery_approved(address: &str, grantor_name: &str) -> EmptyResult { | ||||
| pub async fn send_emergency_access_recovery_approved(address: &str, grantor_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/emergency_access_recovery_approved", | ||||
|         json!({ | ||||
|  | @ -303,10 +303,10 @@ pub fn send_emergency_access_recovery_approved(address: &str, grantor_name: &str | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_recovery_initiated( | ||||
| pub async fn send_emergency_access_recovery_initiated( | ||||
|     address: &str, | ||||
|     grantee_name: &str, | ||||
|     atype: &str, | ||||
|  | @ -322,10 +322,10 @@ pub fn send_emergency_access_recovery_initiated( | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_recovery_reminder( | ||||
| pub async fn send_emergency_access_recovery_reminder( | ||||
|     address: &str, | ||||
|     grantee_name: &str, | ||||
|     atype: &str, | ||||
|  | @ -341,10 +341,10 @@ pub fn send_emergency_access_recovery_reminder( | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_recovery_rejected(address: &str, grantor_name: &str) -> EmptyResult { | ||||
| pub async fn send_emergency_access_recovery_rejected(address: &str, grantor_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/emergency_access_recovery_rejected", | ||||
|         json!({ | ||||
|  | @ -353,10 +353,10 @@ pub fn send_emergency_access_recovery_rejected(address: &str, grantor_name: &str | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_emergency_access_recovery_timed_out(address: &str, grantee_name: &str, atype: &str) -> EmptyResult { | ||||
| pub async fn send_emergency_access_recovery_timed_out(address: &str, grantee_name: &str, atype: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/emergency_access_recovery_timed_out", | ||||
|         json!({ | ||||
|  | @ -366,10 +366,10 @@ pub fn send_emergency_access_recovery_timed_out(address: &str, grantee_name: &st | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str) -> EmptyResult { | ||||
| pub async fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/invite_accepted", | ||||
|         json!({ | ||||
|  | @ -379,10 +379,10 @@ pub fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str) | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult { | ||||
| pub async fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/invite_confirmed", | ||||
|         json!({ | ||||
|  | @ -391,10 +391,10 @@ pub fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTime, device: &str) -> EmptyResult { | ||||
| pub async fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTime, device: &str) -> EmptyResult { | ||||
|     use crate::util::upcase_first; | ||||
|     let device = upcase_first(device); | ||||
| 
 | ||||
|  | @ -409,10 +409,10 @@ pub fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTime, de | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_incomplete_2fa_login(address: &str, ip: &str, dt: &NaiveDateTime, device: &str) -> EmptyResult { | ||||
| pub async fn send_incomplete_2fa_login(address: &str, ip: &str, dt: &NaiveDateTime, device: &str) -> EmptyResult { | ||||
|     use crate::util::upcase_first; | ||||
|     let device = upcase_first(device); | ||||
| 
 | ||||
|  | @ -428,10 +428,10 @@ pub fn send_incomplete_2fa_login(address: &str, ip: &str, dt: &NaiveDateTime, de | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_token(address: &str, token: &str) -> EmptyResult { | ||||
| pub async fn send_token(address: &str, token: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/twofactor_email", | ||||
|         json!({ | ||||
|  | @ -440,10 +440,10 @@ pub fn send_token(address: &str, token: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_change_email(address: &str, token: &str) -> EmptyResult { | ||||
| pub async fn send_change_email(address: &str, token: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/change_email", | ||||
|         json!({ | ||||
|  | @ -452,10 +452,10 @@ pub fn send_change_email(address: &str, token: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| pub fn send_test(address: &str) -> EmptyResult { | ||||
| pub async fn send_test(address: &str) -> EmptyResult { | ||||
|     let (subject, body_html, body_text) = get_text( | ||||
|         "email/smtp_test", | ||||
|         json!({ | ||||
|  | @ -463,10 +463,10 @@ pub fn send_test(address: &str) -> EmptyResult { | |||
|         }), | ||||
|     )?; | ||||
| 
 | ||||
|     send_email(address, &subject, body_html, body_text) | ||||
|     send_email(address, &subject, body_html, body_text).await | ||||
| } | ||||
| 
 | ||||
| fn send_email(address: &str, subject: &str, body_html: String, body_text: String) -> EmptyResult { | ||||
| async fn send_email(address: &str, subject: &str, body_html: String, body_text: String) -> EmptyResult { | ||||
|     let smtp_from = &CONFIG.smtp_from(); | ||||
|     let email = Message::builder() | ||||
|         .message_id(Some(format!("<{}@{}>", crate::util::get_uuid(), smtp_from.split('@').collect::<Vec<&str>>()[1]))) | ||||
|  | @ -475,7 +475,7 @@ fn send_email(address: &str, subject: &str, body_html: String, body_text: String | |||
|         .subject(subject) | ||||
|         .multipart(MultiPart::alternative_plain_html(body_text, body_html))?; | ||||
| 
 | ||||
|     match mailer().send(&email) { | ||||
|     match mailer().send(email).await { | ||||
|         Ok(_) => Ok(()), | ||||
|         // Match some common errors and make them more user friendly
 | ||||
|         Err(e) => { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue