Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support reply-to in 'email-send' admin action. #8516

Merged
merged 1 commit into from
Feb 5, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/lib/admin/actions/email_send.dart
Original file line number Diff line number Diff line change
@@ -38,6 +38,8 @@ The list of resolved emails will be deduplicated.
'from': 'The email address to impersonate (`support@pub.dev` by default).',
'subject': 'The subject of the email message.',
'body': 'The text content of the email body.',
'reply-to':
'(optional) A comma separated list of email addresses to be used in the Reply-To header.',
'in-reply-to':
'(optional) The local message id of the email that this is a reply to '
'(e.g. moderation case id). The email sender will the `In-Reply-To` and `References` '
@@ -65,6 +67,7 @@ The list of resolved emails will be deduplicated.
);
final cc = options['cc'];
final inReplyTo = options['in-reply-to'];
final replyTo = options['reply-to'];

final emailList = await _resolveEmails(to!);
final ccEmailList = cc == null ? null : await _resolveEmails(cc);
@@ -79,6 +82,7 @@ The list of resolved emails will be deduplicated.
ccRecipients:
ccEmailList?.map((v) => EmailAddress(v)).toList() ?? const [],
inReplyToLocalMessageId: inReplyTo,
replyTos: replyTo?.split(',') ?? const <String>[],
));
return {
'emails': emailList,
1 change: 1 addition & 0 deletions app/lib/service/email/email_sender.dart
Original file line number Diff line number Diff line change
@@ -176,6 +176,7 @@ Message _toMessage(EmailMessage input) {
'Message-ID': '<${input.localMessageId}@pub.dev>',
if (inReplyToMessageId != null) 'In-Reply-To': inReplyToMessageId,
if (inReplyToMessageId != null) 'References': inReplyToMessageId,
if (input.replyTos.isNotEmpty) 'Reply-To': input.replyTos.join(','),
};
return Message()
..headers = headers
3 changes: 3 additions & 0 deletions app/lib/service/email/email_templates.dart
Original file line number Diff line number Diff line change
@@ -120,6 +120,7 @@ class EmailMessage {
final List<EmailAddress> ccRecipients;
final String subject;
final String bodyText;
final List<String> replyTos;

EmailMessage(
this.from,
@@ -129,6 +130,7 @@ class EmailMessage {
this.inReplyToLocalMessageId,
this.localMessageId,
this.ccRecipients = const <EmailAddress>[],
this.replyTos = const <String>[],
}) : bodyText = reflowBodyText(bodyText);

/// Throws [ArgumentError] if the [localMessageId] or the
@@ -157,6 +159,7 @@ class EmailMessage {
'ccRecipients': ccRecipients.map((e) => e.email).toList(),
'subject': subject,
'bodyText': bodyText,
if (replyTos.isNotEmpty) 'replyTos': replyTos,
};
}

4 changes: 3 additions & 1 deletion app/test/admin/email_send_test.dart
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ void main() {
'to': 'package:oxygen',
'subject': 'Test email',
'body': 'Test body',
'reply-to': 'other1@pub.dev,other2@pub.dev',
}),
);
expect(rs1.output, {
@@ -57,7 +58,8 @@ void main() {
'recipients': ['admin@pub.dev'],
'ccRecipients': [],
'subject': 'Test email',
'bodyText': 'Test body'
'bodyText': 'Test body',
'replyTos': ['other1@pub.dev', 'other2@pub.dev'],
});
});
});