1+ use crate :: email:: EmailMessage ;
12use crate :: models:: ApiToken ;
23use crate :: schema:: api_tokens;
34use crate :: views:: EncodableApiTokenWithToken ;
@@ -20,6 +21,7 @@ use diesel::sql_types::Timestamptz;
2021use diesel_async:: RunQueryDsl ;
2122use http:: StatusCode ;
2223use http:: request:: Parts ;
24+ use minijinja:: context;
2325use secrecy:: ExposeSecret ;
2426
2527#[ derive( Deserialize ) ]
@@ -171,17 +173,12 @@ pub async fn create_api_token(
171173 . build ( ) ;
172174
173175 if let Some ( recipient) = recipient {
174- let email = NewTokenEmail {
175- token_name : & new. api_token . name ,
176- user_name : & user. gh_login ,
177- domain : & app. emails . domain ,
178- } ;
179-
180176 // At this point the token has been created so failing to send the
181177 // email should not cause an error response to be returned to the
182178 // caller.
183- let email_ret = app. emails . send ( & recipient, email) . await ;
184- if let Err ( e) = email_ret {
179+ if let Err ( e) =
180+ send_creation_email ( & app. emails , & recipient, & new. api_token . name , & user. gh_login ) . await
181+ {
185182 error ! ( "Failed to send token creation email: {e}" )
186183 }
187184 }
@@ -286,28 +283,17 @@ pub async fn revoke_current_api_token(app: AppState, req: Parts) -> AppResult<Re
286283 Ok ( StatusCode :: NO_CONTENT . into_response ( ) )
287284}
288285
289- struct NewTokenEmail < ' a > {
290- token_name : & ' a str ,
291- user_name : & ' a str ,
292- domain : & ' a str ,
293- }
294-
295- impl crate :: email:: Email for NewTokenEmail < ' _ > {
296- fn subject ( & self ) -> String {
297- format ! ( "crates.io: New API token \" {}\" created" , self . token_name)
298- }
299-
300- fn body ( & self ) -> String {
301- format ! (
302- "\
303- Hello {user_name}!
304-
305- A new API token with the name \" {token_name}\" was recently added to your {domain} account.
306-
307- If this wasn't you, you should revoke the token immediately: https://{domain}/settings/tokens" ,
308- token_name = self . token_name,
309- user_name = self . user_name,
310- domain = self . domain,
311- )
312- }
286+ async fn send_creation_email (
287+ emails : & crate :: Emails ,
288+ recipient : & str ,
289+ token_name : & str ,
290+ user_name : & str ,
291+ ) -> anyhow:: Result < ( ) > {
292+ let context = context ! {
293+ token_name,
294+ user_name,
295+ domain => emails. domain,
296+ } ;
297+ let email = EmailMessage :: from_template ( "new_token" , context) ?;
298+ Ok ( emails. send ( recipient, email) . await ?)
313299}
0 commit comments