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

MBS-13815: Enable sending contact emails through new service #3390

Merged
merged 4 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions lib/DBDefs.pm.sample
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ sub WEB_SERVER { 'www.musicbrainz.example.com' }

# sub SMTP_SERVER { 'localhost' }

# An instance of https://github.com/metabrainz/mb-mail-service.
# sub MAIL_SERVICE_BASE_URL { 'http://localhost:3000' }

# This value should be set to some secret value for your server. Any old
# string of stuff should do; something suitably long and random, like for
# passwords. However you MUST change it from the default
Expand Down
3 changes: 3 additions & 0 deletions lib/DBDefs/Default.pm
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ sub STATIC_RESOURCES_LOCATION { '//' . shift->WEB_SERVER . '/static/build' }

sub SMTP_SERVER { 'localhost' }

# An instance of https://github.com/metabrainz/mb-mail-service.
sub MAIL_SERVICE_BASE_URL { 'http://localhost:3000' }

# This value should be set to some secret value for your server. Any old
# string of stuff should do; something suitably long and random, like for
# passwords. However you MUST change it from the default
Expand Down
13 changes: 7 additions & 6 deletions lib/MusicBrainz/Server/Controller/User.pm
Original file line number Diff line number Diff line change
Expand Up @@ -373,25 +373,26 @@ sub contact : Chained('load') RequireAuth HiddenOnMirrors SecureForm
my $form = $c->form( form => 'User::Contact' );

if ($c->form_posted_and_valid($form)) {

my $result;
my $sent;
try {
$result = $c->model('Email')->send_message_to_editor(
$c->model('Email')->send_message_to_editor(
from => $c->user,
to => $editor,
subject => $form->value->{subject},
message => $form->value->{body},
reveal_address => $form->value->{reveal_address},
send_to_self => $form->value->{send_to_self},
);
$sent = 1;
}
catch {
log_debug { "Couldn't send email: $_" } $_;
$c->flash->{message} = l('Your message could not be sent');
};

$c->res->redirect($c->uri_for_action('/user/contact', [ $editor->name ], { sent => $result }));
$c->detach;
if ($sent) {
$c->res->redirect($c->uri_for_action('/user/contact', [ $editor->name ], { sent => 1 }));
$c->detach;
}
}

$c->stash(
Expand Down
139 changes: 63 additions & 76 deletions lib/MusicBrainz/Server/Email.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package MusicBrainz::Server::Email;
use utf8;
use Moose;
use Readonly;
use Data::Dumper;
use Encode qw( encode );
use Email::Address::XS;
use Email::Sender::Simple qw( sendmail );
use Email::MIME;
use Email::MIME::Creator;
use Email::Sender::Transport::SMTP;
use HTTP::Request::Common qw( POST );
use JSON::XS qw( encode_json );
use URI::Escape qw( uri_escape_utf8 );
use DBDefs;
use Try::Tiny;
Expand Down Expand Up @@ -38,6 +41,7 @@ has 'c' => (
);

Readonly our $url_prefix => 'https://' . DBDefs->WEB_SERVER_USED_IN_EMAIL;
Readonly our $mail_service_base_url => DBDefs->MAIL_SERVICE_BASE_URL;

sub _encode_header {
my $header = shift;
Expand Down Expand Up @@ -83,66 +87,6 @@ sub _create_email
});
}

sub _create_message_to_editor_email
{
my ($self, %opts) = @_;

my $from = $opts{from} or die q(Missing 'from' argument);
my $to = $opts{to} or die q(Missing 'to' argument);
my $subject = $opts{subject} or die q(Missing 'subject' argument);
my $message = $opts{message} or die q(Missing 'message' argument);

my $time = $opts{time} || time();

my @correspondents = sort_by { $_->name } ($from, $to);
my @headers = (
'To' => _user_address($to),
'Sender' => $EMAIL_NOREPLY_ADDRESS,
'Subject' => _encode_header($subject),
'Message-Id' => _message_id('correspondence-%s-%s-%d', $correspondents[0]->id, $correspondents[1]->id, $time),
'References' => _message_id('correspondence-%s-%s', $correspondents[0]->id, $correspondents[1]->id),
'In-Reply-To' => _message_id('correspondence-%s-%s', $correspondents[0]->id, $correspondents[1]->id),
);

push @headers, 'From', _user_address($from, 1);
if ($opts{reveal_address}) {
push @headers, 'Reply-To', _user_address($from);
}
else {
push @headers, 'Reply-To', $EMAIL_NOREPLY_ADDRESS;
}

my $from_name = $from->name;
my $contact_url = $url_prefix .
sprintf '/user/%s/contact', uri_escape_utf8($from->name);

my $body = <<"EOS";
MusicBrainz user '$from_name' has sent you the following message:
------------------------------------------------------------------------
$message
------------------------------------------------------------------------
EOS

if ($opts{reveal_address}) {
$body .= <<"EOS";
If you would like to respond, please reply to this message or visit
$contact_url to send '$from_name' an email.

-- The MusicBrainz Team
EOS
}
else {
$body .= <<"EOS";
If you would like to respond, please visit
$contact_url to send '$from_name' an email.

-- The MusicBrainz Team
EOS
}

return $self->_create_email(\@headers, $body);
}

sub _create_email_verification_email
{
my ($self, %opts) = @_;
Expand Down Expand Up @@ -445,27 +389,54 @@ sub send_message_to_editor
{
my ($self, %opts) = @_;

$opts{time} = time();
{
my $email = $self->_create_message_to_editor_email(%opts);
$self->_send_email($email);
my $from = $opts{from} or die q(Missing 'from' argument);
my $to = $opts{to} or die q(Missing 'to' argument);
my $subject = $opts{subject} or die q(Missing 'subject' argument);
my $message = $opts{message} or die q(Missing 'message' argument);

my @correspondents = sort_by { $_->name } ($from, $to);
my $contact_url = $url_prefix .
sprintf '/user/%s/contact', uri_escape_utf8($from->name);
my $body = {
template_id => 'editor-message',
to => _user_address($to),
from => $EMAIL_NOREPLY_ADDRESS,
# TODO: send the user's language preference here. (This preference is not yet stored on the server)
# Which language should we use, as this email is going to a different user?
# 'lang'
JadedBlueEyes marked this conversation as resolved.
Show resolved Hide resolved
message_id => _message_id('correspondence-%s-%s-%d', $correspondents[0]->id, $correspondents[1]->id, time()),
references => [_message_id('correspondence-%s-%s', $correspondents[0]->id, $correspondents[1]->id)],
in_reply_to => [_message_id('correspondence-%s-%s', $correspondents[0]->id, $correspondents[1]->id)],
params => {
to_name => $to->name,
from_name => $from->name,
subject => $subject,
message => $message,
contact_url => $contact_url,
revealed_address => $opts{reveal_address} ? \1 : \0,
},
};

if ($opts{reveal_address}) {
$body->{reply_to} = _user_address($from);
} else {
$body->{reply_to} = $EMAIL_NOREPLY_ADDRESS;
}

$self->_mb_mail_service_send_single($body);

if ($opts{send_to_self}) {
my $copy = $self->_create_message_to_editor_email(%opts);
my $toname = $opts{to}->name;
my $message = $opts{message};
$body->{to} = _user_address($from);
$body->{params}{is_self_copy} = \1;
# TODO: Should we set language here to the initiator's language?

$copy->header_str_set( To => _user_address($opts{from}) );
$copy->body_str_set(<<"EOF");
This is a copy of the message you sent to MusicBrainz editor '$toname':
------------------------------------------------------------------------
$message
------------------------------------------------------------------------
Please do not respond to this e-mail.
EOF
if ($opts{reveal_address}) {
$body->{reply_to} = _user_address($from);
} else {
$body->{reply_to} = $EMAIL_NOREPLY_ADDRESS;
}

$self->_send_email($copy);
$self->_mb_mail_service_send_single($body);
}
}

Expand Down Expand Up @@ -713,6 +684,22 @@ sub _send_email
return sendmail($email, $args);
}

sub _mb_mail_service_send_single {
my ($self, $body) = @_;

my $res = $self->c->lwp->request(
POST "$mail_service_base_url/send_single",
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Content' => encode_json($body),
);
unless ($res->is_success) {
my $status = $res->code;
die "Failed to send mail ($status):\n" . Dumper($res->content);
}
return;
}

__PACKAGE__->meta->make_immutable;
no Moose;
1;
Expand Down
Loading