Skip to content

Commit 73f2cae

Browse files
authored
Merge pull request #2451 from dlglin/SMTP-Auth
Add username and password option for SMTP authentication
2 parents bf11f98 + ea523cc commit 73f2cae

File tree

10 files changed

+96
-77
lines changed

10 files changed

+96
-77
lines changed

conf/defaults.config

+10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ include("VERSION"); # get WW version
4242
# Mail Settings
4343
################################################################################
4444

45+
# $generic_sender_name will be used as the "From:" name on all feedback emails
46+
# sent without a defined user.
47+
$generic_sender_name = '';
48+
49+
# The following variables will override the "From:" address in messages sent by
50+
# the named feature.
51+
$feedback_sender_email = ''; # For student feedback
52+
$instructor_sender_email = ''; # For instructors emailing students
53+
$jitar_sender_email = ''; # For notifications of incomplete JiTaR sets
54+
4555
# By default, feedback is sent to all users who have permission to
4656
# receive_feedback in a course. If this list is non-empty, feedback is also sent
4757
# to the addresses specified here.

conf/localOverrides.conf.dist

+18
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,24 @@
3838
# Additional mail settings in defaults.config can be overridden here
3939
################################################################################
4040

41+
# $generic_sender_name will be used as the "From:" name on all feedback emails
42+
# sent without a defined user.
43+
44+
$generic_sender_name = '';
45+
46+
# The following variables will override the "From:" address in messages sent by
47+
# the named feature.
48+
# When one of these is set, all messages sent by that feature will use the
49+
# supplied email address as the "From:" address, and the address of the relevant
50+
# user will be set as the "Reply-to:" address for the message.
51+
# These may be required if you have provided an SMTP username and password in
52+
# site.conf. They can also be used to improve email verification and avoid
53+
# messages getting filtered as spam.
54+
55+
$feedback_sender_email = ''; # For student feedback
56+
$instructor_sender_email = ''; # For instructors emailing students
57+
$jitar_sender_email = ''; # For notifications of incomplete JiTaR sets
58+
4159
# By default, feedback is sent to all users who have permission to
4260
# receive_feedback in a course. If this list is non-empty, feedback is also sent
4361
# to the addresses specified here.

conf/site.conf.dist

+28-23
Original file line numberDiff line numberDiff line change
@@ -242,26 +242,16 @@ $webwork_courses_dir = "/opt/webwork/courses"; # a typical place to put course d
242242
# The following directives need to be configured in order for your webwork
243243
# server to be able to send mail.
244244

245-
# Mail sent by the PG system and the mail merge and feedback modules will be
246-
# sent via this SMTP server. localhost may work if your server is capable
247-
# of sending email, otherwise type the name of your School's outgoing email
248-
# server.
245+
# Mail sent by the mail merge and feedback modules will be sent via this SMTP
246+
# server. localhost may work if your server is capable of sending email,
247+
# otherwise type the name of your School's outgoing email server.
249248
$mail{smtpServer} = ''; # e.g. 'mail.yourschool.edu' or 'localhost'
250249

251-
# When connecting to the above server, WeBWorK will send this address in the
252-
# MAIL FROM command. This has nothing to do with the "From" address on the mail
253-
# message. It can really be anything, but some mail servers require it contain
254-
# a valid mail domain, or at least be well-formed.
255-
$mail{smtpSender} = ''; # e.g. '[email protected]'
256-
# Be sure to use single quotes for the address or the @ sign will be interpreted as an array.
257-
258250
$mail{set_return_path} = ''; #sets the return_path to the From: field (sender's email address)
259251
# The return path is used to send error messages about bounced emails
260252
# "noreply\@$mail{smtpServer}" discards error messages,
261-
# using $mail{smtpSender} would deliver error messages to that address.
262253
# The default setting should be adjusted for local domain
263254
# Leaving the return path blank triggers the default which results in Return-Path being set to the email of the sender.
264-
#
265255

266256
# Seconds to wait before timing out when connecting to the SMTP server.
267257
# the default is 120 seconds.
@@ -270,32 +260,47 @@ $mail{set_return_path} = ''; #sets the return_path to the From: field (sender's
270260

271261
$mail{smtpTimeout} = 30;
272262

273-
274263
# TLS is a method for providing secure connections to the smtp server.
275264
# https://en.wikipedia.org/wiki/Transport_Layer_Security
276-
# At some sites coordinating the certificates properly is tricky
277-
# Set this value to 0 to avoid checking certificates.
278-
# Set it to 0 to trouble shoot an inability to verify certificates with the smtp server
265+
# Allowed values: 'starttls', 'ssl', 'maybestarttls', 0
266+
# Values of 'maybestarttls' and 0 are insecure and are not recommended for
267+
# production environments, except where the smtp server is localhost.
279268

280269
$mail{tls_allowed} = 0;
281270

282-
#$tls_allowed=0; #old method -- this variable no longer works.
271+
# Extra settings for SSL/TLS
272+
# You may need to use this setting if your SMTP server uses a self-signed certificate.
273+
# SSL_verify_mode => 0 is not recommended for production environments for security
274+
# reasons. See https://metacpan.org/pod/IO::Socket::SSL#Common-Usage-Errors
283275

276+
#$mail{smtpSSLOptions} = {SSL_verify_mode => 0};
284277

285278
# errors of the form
286-
# unable to establish SMTP connection to smtp-gw.rochester.edu port 465
287-
# indicate that there is a mismatch between the port number and the use of ssl
288-
# use port 25 when ssl is off and use port 465 when ssl is on (tls_allowed=1)
279+
# "unable to establish SMTP connection to smtp-gw.rochester.edu port 465"
280+
# indicate that there may be a mismatch between the port number and the use of ssl.
281+
# Many mail servers use port 25 when ssl is off, use port 465 when ssl is on (tls_allowed='ssl'),
282+
# and use port 587 when starttls is used (tls_allowed='starttls').
289283

290284

291-
# Set the SMTP port manually. Typically this does not need to be done it will use
292-
# port 25 if no SSL is on and 465 if ssl is on
285+
# Set the SMTP port manually. Typically this does not need to be done. It will use
286+
# port 25 if insecure, and 465 if ssl is on
293287

294288
#$mail{smtpPort} = 25;
295289

296290
# Debugging tutorial for sending email using ssl/tls
297291
# https://maulwuff.de/research/ssl-debugging.html
298292

293+
# SMTP Authentication
294+
# If your SMTP server requires authentication you can provide the username and password
295+
# for the account on the mail server.
296+
# If you set these credentials, you may need to define the variables $feedback_sender_email,
297+
# $instructor_sender_email and $jitar_sender_email in localOverrides.conf, as some SMTP
298+
# servers require the "From:" address of outgoing emails to match this username. Setting
299+
# those sender variables will then put the user's email address in the "Reply-to:" field.
300+
301+
#$mail{smtpUsername} = '';
302+
#$mail{smtpPassword} = '';
303+
299304
# Set maxAttachmentSize to the maximum number of megabytes to allow for the size of
300305
# files attached to feedback emails. Note that this should be set to match the
301306
# limitations of the email server chosen above, and should be set to a value greater

courses.dist/modelCourse/templates/email/welcome.msg

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## template for a Welcome message to be emailed to class (delete this line)
2+
## Note that the From: address will be replaced by the email address of the account
3+
## from which the message is sent.
24
From: [email protected] (Jan Teacher)
3-
45
Subject: online homework for Math 123
56
Message:
67
Hi $FN,

lib/Mojolicious/WeBWorK/Tasks/SendInstructorEmail.pm

+8-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,14 @@ sub mail_message_to_recipients ($job, $ce, $db, $mail_data) {
7979
$mail_data->{merge_data}
8080
);
8181

82-
my $email =
83-
Email::Stuffer->to($user_record->email_address)->from($mail_data->{from})->subject($mail_data->{subject})
84-
->text_body($msg)->header('X-Remote-Host' => $mail_data->{remote_host});
82+
my $email = Email::Stuffer->to($user_record->email_address)->subject($mail_data->{subject})->text_body($msg)
83+
->header('X-Remote-Host' => $mail_data->{remote_host});
84+
if ($ce->{instructor_sender_email}) {
85+
$email->from($mail_data->{from_name} . ' <' . $ce->{instructor_sender_email} . '>')
86+
->reply_to($mail_data->{from});
87+
} else {
88+
$email->from($mail_data->{from});
89+
}
8590

8691
eval {
8792
$email->send_or_die({

lib/WeBWorK/ContentGenerator/Feedback.pm

+7-3
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,14 @@ $emailableURL
185185
$msg .= "***** Data about the environment: *****\n\n" . Dumper($ce) . "\n\n";
186186
}
187187

188-
my $email =
189-
Email::Stuffer->to(join(',', @recipients))->from($sender)->subject($subject)->text_body($msg)
188+
my $from_name = $user ? $user->full_name : $ce->{generic_sender_name};
189+
my $email = Email::Stuffer->to(join(',', @recipients))->subject($subject)->text_body($msg)
190190
->header('X-Remote-Host' => $remote_host);
191-
191+
if ($ce->{feedback_sender_email}) {
192+
$email->from("$from_name <$ce->{feedback_sender_email}>")->reply_to($sender);
193+
} else {
194+
$email->from($sender);
195+
}
192196
# Extra headers
193197
$email->header('X-WeBWorK-Route', $route) if defined $route;
194198
$email->header('X-WeBWorK-Course', $courseID) if defined $courseID;

lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

+12-36
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ sub initialize ($c) {
8787

8888
# Store data
8989
$c->{defaultPreviewUser} = $ur;
90-
$c->{defaultFrom} = $ur->rfc822_mailbox;
91-
$c->{defaultReply} = $ur->rfc822_mailbox;
90+
$c->{from} = $ur->rfc822_mailbox;
91+
$c->{from_name} = $ur->full_name;
9292
$c->{defaultSubject} = $c->stash('courseID') . ' notice';
9393
$c->{merge_file} = $mergefile // '';
9494

@@ -196,13 +196,11 @@ sub initialize ($c) {
196196
}
197197

198198
# Get inputs
199-
my ($from, $replyTo, $r_text, $subject);
199+
my ($r_text, $subject);
200200
if ($input_source eq 'file') {
201201
if ($input_file) {
202-
($from, $replyTo, $subject, $r_text) = $c->read_input_file("$emailDirectory/$input_file");
202+
($subject, $r_text) = $c->read_input_file("$emailDirectory/$input_file");
203203
} else {
204-
$from = $c->{defaultFrom};
205-
$replyTo = $c->{defaultReply};
206204
$subject = $c->{defaultSubject};
207205

208206
# If action is openMessage and no file was found, then 'None' was selected.
@@ -212,16 +210,12 @@ sub initialize ($c) {
212210
$c->param('savefilename', 'default.msg') if $c->param('savefilename');
213211
}
214212
}
215-
$c->param('from', $from) if $from;
216-
$c->param('replyTo', $replyTo) if $replyTo;
217213
$c->param('subject', $subject) if $subject;
218214
$c->param('body', $$r_text) if $r_text;
219215
} elsif ($input_source eq 'form') {
220216
# read info from the form
221217
# bail if there is no message body
222218

223-
$from = $c->param('from');
224-
$replyTo = $c->param('replyTo');
225219
$subject = $c->param('subject');
226220
my $body = $c->param('body');
227221
# Sanity check: body must contain non-white space when previewing message.
@@ -233,8 +227,6 @@ sub initialize ($c) {
233227
my $remote_host = $c->tx->remote_address || "UNKNOWN";
234228

235229
# Store data
236-
$c->{from} = $from;
237-
$c->{replyTo} = $replyTo;
238230
$c->{subject} = $subject;
239231
$c->{remote_host} = $remote_host;
240232
$c->{r_text} = $r_text;
@@ -280,8 +272,7 @@ sub initialize ($c) {
280272
$temp_body =~ s/\r\n/\n/g;
281273
$temp_body = join(
282274
"\n",
283-
"From: $from",
284-
"Reply-To: $replyTo",
275+
"From: $c->{from}",
285276
"Subject: $subject",
286277
"Content-Type: text/plain; charset=UTF-8",
287278
"Message:",
@@ -315,15 +306,6 @@ sub initialize ($c) {
315306
return;
316307
}
317308

318-
# verify format of Reply-to address (zero or more valid rfc2822/ref5322 addresses)
319-
if (defined $c->{replyTo} and $c->{replyTo} ne "") {
320-
my @parsed_replyto_addrs = Email::Address::XS->parse($c->{replyTo});
321-
unless (@parsed_replyto_addrs > 0) {
322-
$c->addbadmessage($c->maketext("Invalid Reply-to address."));
323-
return;
324-
}
325-
}
326-
327309
# Check that recipients have been selected.
328310
unless (@{ $c->{ra_send_to} }) {
329311
$c->addbadmessage(
@@ -353,7 +335,7 @@ sub initialize ($c) {
353335
text => ${ $c->{r_text} // \'' },
354336
merge_data => $c->{rh_merge_data},
355337
from => $c->{from},
356-
defaultFrom => $c->{defaultFrom},
338+
from_name => $c->{from_name},
357339
remote_host => $c->{remote_host},
358340
} ],
359341
{ notes => { courseID => $c->stash('courseID') } }
@@ -393,10 +375,9 @@ sub print_preview ($c) {
393375
# Note that this escaping is done in the Mojolicious template automatically.
394376
$msg = join(
395377
"",
396-
"To: ", $c->{preview_user}->email_address, "\n",
397-
"From: ", $c->{from}, "\n",
398-
"Reply-To: ", $c->{replyTo}, "\n",
399-
"Subject: ", $c->{subject}, "\n",
378+
"To: ", $c->{preview_user}->email_address, "\n",
379+
"From: ", $c->{from}, "\n",
380+
"Subject: ", $c->{subject}, "\n",
400381
# In a real mails we would UTF-8 encode the message and give the Content-Type header. For the preview which is
401382
# displayed as html, just add the header, but do NOT use Encode::encode("UTF-8",$msg).
402383
"Content-Type: text/plain; charset=UTF-8\n\n",
@@ -435,7 +416,7 @@ sub saveMessageFile ($c, $body, $msgFileName) {
435416
sub read_input_file ($c, $filePath) {
436417
my ($text, @text);
437418
my $header = '';
438-
my ($subject, $from, $replyTo);
419+
my $subject;
439420

440421
open my $FILE, "<:encoding(UTF-8)", $filePath
441422
or do { $c->addbadmessage($c->maketext(q{Can't open [_1]}, $filePath)); return };
@@ -445,17 +426,12 @@ sub read_input_file ($c, $filePath) {
445426
$text = join('', <$FILE>);
446427
close $FILE;
447428

448-
$text =~ s/^\s*//; # remove initial white space if any.
449-
$header =~ /^From:\s(.*)$/m;
450-
$from = $1 || $c->{defaultFrom};
451-
452-
$header =~ /^Reply-To:\s(.*)$/m;
453-
$replyTo = $1 || $c->{defaultReply};
429+
$text =~ s/^\s*//; # remove initial white space if any.
454430

455431
$header =~ /^Subject:\s(.*)$/m;
456432
$subject = $1 || $c->{defaultSubject};
457433

458-
return ($from, $replyTo, $subject, \$text);
434+
return ($subject, \$text);
459435
}
460436

461437
sub get_message_file_names ($c) {

lib/WeBWorK/Utils.pm

+4-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,10 @@ sub createEmailSenderTransportSMTP ($ce) {
331331
return Email::Sender::Transport::SMTP->new({
332332
host => $ce->{mail}{smtpServer},
333333
ssl => $ce->{mail}{tls_allowed} // 0,
334-
defined $ce->{mail}->{smtpPort} ? (port => $ce->{mail}{smtpPort}) : (),
334+
defined $ce->{mail}->{smtpPort} ? (port => $ce->{mail}{smtpPort}) : (),
335+
defined $ce->{mail}->{smtpUsername} ? (sasl_username => $ce->{mail}{smtpUsername}) : (),
336+
defined $ce->{mail}->{smtpPassword} ? (sasl_password => $ce->{mail}{smtpPassword}) : (),
337+
defined $ce->{mail}->{smtpSSLOptions} ? (ssl_options => $ce->{mail}{smtpSSLOptions}) : (),
335338
timeout => $ce->{mail}{smtpTimeout},
336339
});
337340
}

lib/WeBWorK/Utils/ProblemProcessing.pm

+6-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,12 @@ Recitation: $recitation
477477
Comment: $comment
478478
/;
479479

480-
my $email = Email::Stuffer->to(join(',', @recipients))->from($sender)->subject($subject)->text_body($msg);
480+
my $email = Email::Stuffer->to(join(',', @recipients))->subject($subject)->text_body($msg);
481+
if ($ce->{jitar_sender_email}) {
482+
$email->from("$full_name <$ce->{jitar_sender_email}>")->reply_to($sender);
483+
} else {
484+
$email->from($sender);
485+
}
481486

482487
# Extra headers
483488
$email->header('X-WeBWorK-Course: ', $courseID) if defined $courseID;

templates/ContentGenerator/Instructor/SendMail/main_form.html.ep

+1-9
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,7 @@
3434
<%= label_for from => maketext('From:'),
3535
class => 'col-sm-3 col-form-label col-form-label-sm' =%>
3636
<div class="col-sm-9">
37-
<%= text_field from => $c->{from}, id => 'from',
38-
class => 'form-control form-control-sm' =%>
39-
</div>
40-
</div>
41-
<div class="row mb-1">
42-
<%= label_for replyTo => maketext('Reply-To:'),
43-
class => 'col-sm-3 col-form-label col-form-label-sm' =%>
44-
<div class="col-sm-9">
45-
<%= text_field replyTo => $c->{replyTo}, id => 'replyTo',
37+
<%= text_field from => $c->{from}, id => 'from', readonly => undef, disabled => undef,
4638
class => 'form-control form-control-sm' =%>
4739
</div>
4840
</div>

0 commit comments

Comments
 (0)