Skip to content

Commit 4df7001

Browse files
committed
Auto merge of #1909 - nkanderson:1360_email_invitation, r=carols10cents
Send email on crate owner invitation If the recipient of a crate ownership invitation has a verified email address, they will be sent an email indicating that a specified user has invited them to become an owner of a named crate. Only sends the email on the first instance of an invitation. Completes the first part of #1360.
2 parents 1c98d07 + cef0429 commit 4df7001

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

src/email.rs

+17
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,23 @@ https://crates.io/confirm/{}",
8686
send_email(email, subject, &body)
8787
}
8888

89+
/// Attempts to send a crate owner invitation email. Swallows all errors.
90+
///
91+
/// Whether or not the email is sent, the invitation entry will be created in
92+
/// the database and the user will see the invitation when they visit
93+
/// https://crates.io/me/pending-invites/.
94+
pub fn send_owner_invite_email(email: &str, user_name: &str, crate_name: &str) {
95+
let subject = "Crate ownership invitation";
96+
let body = format!(
97+
"{} has invited you to become an owner of the crate {}!\n
98+
Please visit https://crates.io/me/pending-invites to accept or reject
99+
this invitation.",
100+
user_name, crate_name
101+
);
102+
103+
let _ = send_email(email, subject, &body);
104+
}
105+
89106
fn send_email(recipient: &str, subject: &str, body: &str) -> CargoResult<()> {
90107
let mailgun_config = init_config_vars();
91108
let email = build_email(recipient, subject, body, &mailgun_config)?;

src/models/krate.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ use indexmap::IndexMap;
77
use url::Url;
88

99
use crate::app::App;
10+
use crate::email;
1011
use crate::util::{human, CargoResult};
1112

1213
use crate::models::{
13-
Badge, Category, CrateOwner, Keyword, NewCrateOwnerInvitation, Owner, OwnerKind,
14-
ReverseDependency, User, Version,
14+
Badge, Category, CrateOwner, CrateOwnerInvitation, Keyword, NewCrateOwnerInvitation, Owner,
15+
OwnerKind, ReverseDependency, User, Version,
1516
};
1617
use crate::views::{EncodableCrate, EncodableCrateLinks};
1718

@@ -426,19 +427,30 @@ impl Crate {
426427

427428
match owner {
428429
// Users are invited and must accept before being added
429-
owner @ Owner::User(_) => {
430-
insert_into(crate_owner_invitations::table)
430+
Owner::User(user) => {
431+
let maybe_inserted = insert_into(crate_owner_invitations::table)
431432
.values(&NewCrateOwnerInvitation {
432-
invited_user_id: owner.id(),
433+
invited_user_id: user.id,
433434
invited_by_user_id: req_user.id,
434435
crate_id: self.id,
435436
})
436437
.on_conflict_do_nothing()
437-
.execute(conn)?;
438+
.get_result::<CrateOwnerInvitation>(conn)
439+
.optional()?;
440+
441+
if maybe_inserted.is_some() {
442+
if let Ok(Some(email)) = user.verified_email(&conn) {
443+
email::send_owner_invite_email(
444+
&email.as_str(),
445+
&req_user.gh_login.as_str(),
446+
&self.name.as_str(),
447+
);
448+
}
449+
}
450+
438451
Ok(format!(
439452
"user {} has been invited to be an owner of crate {}",
440-
owner.login(),
441-
self.name
453+
user.gh_login, self.name
442454
))
443455
}
444456
// Teams are added as owners immediately

0 commit comments

Comments
 (0)