api: make sendEmailNotification recipient explicit
Having sendEmailNotification take a full message as argument is very powerful, but restricting it to only send mail to the currently logged-in user will in fact not get us very far. Examples of mails that should be sent (potentially encrypted) that are not triggered by a logged-in user include the password reset email, billing emails triggered by metasrht-daily, and possibly more in other services. This commit extends the API to include the username of the desired recipient. This will not add much overhead to the callers and more importantly, still make sure to keep any PGP-related code in meta.sr.ht.
This commit is contained in:
parent
b63e211398
commit
7dd83975ae
|
@ -115,7 +115,8 @@ to this email.
|
|||
}
|
||||
}
|
||||
|
||||
func sendEmailNotification(ctx context.Context, message string) error {
|
||||
func sendEmailNotification(ctx context.Context,
|
||||
username, userEmail, message string, pgpKey *string) error {
|
||||
r := strings.NewReader(message)
|
||||
mr, err := mail.CreateReader(r)
|
||||
if err != nil {
|
||||
|
@ -151,12 +152,11 @@ func sendEmailNotification(ctx context.Context, message string) error {
|
|||
return fmt.Errorf("missing or malformed subject")
|
||||
}
|
||||
|
||||
user := auth.ForContext(ctx)
|
||||
header.SetAddressList("To", []*mail.Address{
|
||||
&mail.Address{user.Username, user.Email},
|
||||
&mail.Address{username, userEmail},
|
||||
})
|
||||
|
||||
return email.EnqueueStd(ctx, header, p.Body, user.PGPKey)
|
||||
return email.EnqueueStd(ctx, header, p.Body, pgpKey)
|
||||
}
|
||||
|
||||
// Sends a security-related notice to the authorized user.
|
||||
|
|
|
@ -519,13 +519,13 @@ type Mutation {
|
|||
clientSecret: String!, redirectUri: String): OAuthGrantRegistration @internal
|
||||
|
||||
"""
|
||||
Sends a notification email to the currently logged-in user.
|
||||
Sends a notification email to the given user.
|
||||
|
||||
The 'message' parameter must be a RFC 5322 compliant Internet message with
|
||||
the special requirement that it must not contain any recipients (i.e. no
|
||||
'To', 'Cc', or 'Bcc' header).
|
||||
"""
|
||||
sendEmailNotification(message: String!): Boolean! @internal
|
||||
sendEmailNotification(username: String!, message: String!): Boolean! @anoninternal
|
||||
|
||||
"""
|
||||
Deletes the authenticated user's account.
|
||||
|
|
|
@ -1214,8 +1214,34 @@ func (r *mutationResolver) IssueOAuthGrant(ctx context.Context, authorization st
|
|||
}
|
||||
|
||||
// SendEmailNotification is the resolver for the sendEmailNotification field.
|
||||
func (r *mutationResolver) SendEmailNotification(ctx context.Context, message string) (bool, error) {
|
||||
err := sendEmailNotification(ctx, message)
|
||||
func (r *mutationResolver) SendEmailNotification(ctx context.Context, username string, message string) (bool, error) {
|
||||
user, err := loaders.ForContext(ctx).UsersByName.Load(username)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if user == nil {
|
||||
return false, fmt.Errorf("Email notification request to unknown user: %s", user)
|
||||
}
|
||||
var key *string
|
||||
|
||||
if user.PGPKeyID != nil {
|
||||
if err := database.WithTx(ctx, &sql.TxOptions{
|
||||
Isolation: 0,
|
||||
ReadOnly: true,
|
||||
}, func(tx *sql.Tx) error {
|
||||
row := tx.QueryRowContext(ctx, `
|
||||
SELECT key
|
||||
FROM "pgpkey" WHERE id = $1;
|
||||
`, *user.PGPKeyID)
|
||||
if err := row.Scan(&key); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
err = sendEmailNotification(ctx, user.Username, user.Email, message, key)
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue