diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 68b7ef231..12364bce2 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -6,6 +6,7 @@ - fixed #10775: i18n AuthLDAP::6 description - fixed #10774: i18n Asset::Storyarchive tag asset url - fixed #10657: Story Topic: delete story displays failsafe + - fixed SMS/Email notification handling (Patrick Donelan, SDH Consulting) 7.7.17 - fixed #10697: Story: Image crowds text diff --git a/docs/upgrades/packages-7.7.18/root_import_inbox-sms-notification.wgpkg b/docs/upgrades/packages-7.7.18/root_import_inbox-sms-notification.wgpkg new file mode 100644 index 000000000..02a8e2c53 Binary files /dev/null and b/docs/upgrades/packages-7.7.18/root_import_inbox-sms-notification.wgpkg differ diff --git a/docs/upgrades/upgrade_7.7.17-7.7.18.pl b/docs/upgrades/upgrade_7.7.17-7.7.18.pl index 290608cb8..0140eb301 100644 --- a/docs/upgrades/upgrade_7.7.17-7.7.18.pl +++ b/docs/upgrades/upgrade_7.7.17-7.7.18.pl @@ -31,7 +31,8 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here - +addSmsGatewaySubjectSetting($session); +addInboxNotificationsSubjectSetting($session); finish($session); # this line required @@ -44,6 +45,19 @@ finish($session); # this line required # print "DONE!\n" unless $quiet; #} +sub addSmsGatewaySubjectSetting { + my $session = shift; + print "\tAdding smsGatewaySubject setting... " unless $quiet; + $session->setting->add('smsGatewaySubject', ''); + print "DONE!\n" unless $quiet; +} + +sub addInboxNotificationsSubjectSetting { + my $session = shift; + print "\tAdding inboxNotificationsSubject setting... " unless $quiet; + $session->setting->add('inboxNotificationsSubject', ''); + print "DONE!\n" unless $quiet; +} # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- diff --git a/lib/WebGUI/Account/Inbox.pm b/lib/WebGUI/Account/Inbox.pm index 0e1f56004..b49af1910 100644 --- a/lib/WebGUI/Account/Inbox.pm +++ b/lib/WebGUI/Account/Inbox.pm @@ -237,6 +237,12 @@ sub editSettingsForm { hoverHelp => $i18n->get('send inbox notifications only help'), defaultValue => $setting->get('sendInboxNotificationsOnly'), ); + $f->text( + name => 'inboxNotificationsSubject', + label => $i18n->get('inbox notifications subject'), + hoverHelp => $i18n->get('inbox notifications subject help'), + defaultValue => $setting->get('inboxNotificationsSubject'), + ); $f->template( name => 'inboxNotificationTemplateId', label => $i18n->get('inbox notification template'), @@ -244,6 +250,13 @@ sub editSettingsForm { defaultValue => $self->getInboxNotificationTemplateId, namespace => 'Account/Inbox/Notification', ); + $f->template( + name => 'inboxSmsNotificationTemplateId', + label => $i18n->get('inbox sms notification template'), + hoverHelp => $i18n->get('inbox sms notification template help'), + defaultValue => $self->getInboxSmsNotificationTemplateId, + namespace => 'Account/Inbox/Notification', + ); return $f->printRowsOnly; } @@ -284,12 +297,14 @@ sub editSettingsFormSave { $setting->set("inboxInviteUserTemplateId", $form->process("inboxInviteUserTemplateId", "template")); $setting->set("inboxInviteUserConfirmTemplateId", $form->process("inboxInviteUserConfirmTemplateId", "template")); #General Inbox Settings - $setting->set("inboxRichEditId", $form->process("inboxRichEditId", "selectRichEditor") ); + $setting->set("inboxRichEditId", $form->process("inboxRichEditId", "selectRichEditor") ); $setting->set("inboxCopySender", $form->process("inboxCopySender", "yesNo")); #Inbox Notification Settings $setting->set("sendInboxNotificationsOnly", $form->process("sendInboxNotificationsOnly", "yesNo")); + $setting->set("inboxNotificationsSubject", $form->process("inboxNotificationsSubject", "text")); $setting->set("inboxNotificationTemplateId", $form->process("inboxNotificationTemplateId","template")); + $setting->set("inboxSmsNotificationTemplateId", $form->process("inboxSmsNotificationTemplateId","template")); } @@ -321,6 +336,19 @@ sub getInboxNotificationTemplateId { #------------------------------------------------------------------- +=head2 getInboxSMSNotificationTemplateId ( ) + +This method returns the template ID for inbox SMS notifications. + +=cut + +sub getInboxSmsNotificationTemplateId { + my $self = shift; + return $self->session->setting->get("inboxSmsNotificationTemplateId") || "i9-G00ALhJOr0gMh-vHbKA"; +} + +#------------------------------------------------------------------- + =head2 getInvitationCount ( ) This method returns the total number of invitations in the invitation box. @@ -1302,39 +1330,84 @@ sub www_sendMessageSave { #Let sendMessage deal with displaying errors return $self->www_sendMessage($errorMsg) if $hasError; - my $messageProperties = { - message => $message, - subject => $subject, - status => 'unread', - sentBy => $fromUser->userId - }; - - if ($session->setting->get('sendInboxNotificationsOnly')) { - my $template = WebGUI::Asset::Template->new($session, $self->getInboxNotificationTemplateId); - if ($template) { - ##Create template variables - my $var = { - fromUsername => $fromUser->username, - subject => $messageProperties->{subject}, - message => $messageProperties->{message}, - inboxLink => $session->url->append($session->url->getSiteURL, 'op=account;module=inbox'), - }; - ##Fill in template - my $output = $template->process($var); - ##Evaluate macros by hand - WebGUI::Macro::process($session, \$output); - ##Assign template output to $messageProperties->{emailMessage} - $messageProperties->{emailMessage} = $output; - } - else { - $session->log->warn(sprintf "Unable to instanciate notification template: ". $self->getInboxNotificationTemplateId); - } - - } - foreach my $uid (@toUsers) { + my $messageProperties = { + message => $message, + subject => $subject, + status => 'unread', + sentBy => $fromUser->userId + }; + my $messageOptions = {}; + + # Handle Email/SMS Notifications + my $user = WebGUI::User->new($session, $uid); + + # Sender only gets CCd on inbox message (not real email) + my $isSender = $uid == $session->user->userId; + $messageOptions->{no_email} = 1 if $isSender; + + # Optionally set SMS notification details (excluding sender) + my $smsAddress = $user->getInboxSmsNotificationAddress; + if ( $smsAddress && !$isSender ) { + my $smsNotificationTemplate + = WebGUI::Asset::Template->new($session, $self->getInboxSmsNotificationTemplateId); + if ($smsNotificationTemplate) { + ##Create template variables + my $var = { + fromUsername => $fromUser->username, + subject => $messageProperties->{subject}, + message => $messageProperties->{message}, + inboxLink => $session->url->append($session->url->getSiteURL, 'op=account;module=inbox'), + }; + ##Fill in template + my $output = $smsNotificationTemplate->process($var); + ##Evaluate macros by hand + WebGUI::Macro::process($session, \$output); + ##Assign template output to $messageProperties->{emailMessage} + $messageProperties->{smsMessage} = $output; + $messageProperties->{smsAddress} = $smsAddress; + $messageProperties->{smsSubject} = $self->session->setting->get('smsGatewaySubject'); + } + else { + $session->log->warn(sprintf "Unable to instanciate notification template: ". $self->getInboxSmsNotificationTemplateId); + } + } + + # Optionally set email notification details (excluding sender) + if ($session->setting->get('sendInboxNotificationsOnly') && !$isSender) { + my $notificationAddresses = $user->getInboxNotificationAddresses; + + # If user has turned off email notifications and admin has turned on sendInboxNotificationsOnly, + # user gets no email at all - because email and email notification are mutually exclusive. + # Note that they can still possibly get SMS notification above + if (!$notificationAddresses) { + $messageOptions->{no_email} = 1; + } else { + my $template = WebGUI::Asset::Template->new($session, $self->getInboxNotificationTemplateId); + if ($template) { + ##Create template variables + my $var = { + fromUsername => $fromUser->username, + subject => $messageProperties->{subject}, + message => $messageProperties->{message}, + inboxLink => $session->url->append($session->url->getSiteURL, 'op=account;module=inbox'), + }; + ##Fill in template + my $output = $template->process($var); + ##Evaluate macros by hand + WebGUI::Macro::process($session, \$output); + ##Assign template output to $messageProperties->{emailMessage} + $messageProperties->{emailMessage} = $output; + $messageProperties->{emailSubject} = $session->setting->get('inboxNotificationsSubject'); + } + else { + $session->log->warn(sprintf "Unable to instanciate notification template: ". $self->getInboxNotificationTemplateId); + } + } + } + $messageProperties->{userId} = $uid; - my $thisMessage = $inbox->addMessage($messageProperties); + my $thisMessage = $inbox->addMessage($messageProperties, $messageOptions); if ($uid eq $session->user->userId) { $thisMessage->setRead; } diff --git a/lib/WebGUI/Inbox/Message.pm b/lib/WebGUI/Inbox/Message.pm index 594bf93fc..642aed264 100644 --- a/lib/WebGUI/Inbox/Message.pm +++ b/lib/WebGUI/Inbox/Message.pm @@ -97,6 +97,18 @@ Email message to use rather than inbox message contents. Email subject to use rather than inbox message subject. +=head4 smsMessage + +SMS notification message to send to C + +=head4 smsSubject + +SMS notification subject (typically used for SMS Gateway authentication) + +=head4 smsAddress + +Email address that SMS notification is sent to (typically the user's C C<@> C) + =head3 options A hash reference containing options for handling the message. @@ -106,6 +118,17 @@ A hash reference containing options for handling the message. If no_email is true, then no email will be made or sent. Only the inbox message will be made. +=head4 no_sms + +If no_sms is true, then no attempt to sms notifications will be sent. + +=head4 overridePerUserDelivery + +If true, then the C flag will not be passed to L, and thus the +per-user settings for email delivery will not be used. Useful if you want to force this message to +be sent as an Email rather than allowing the user's C setting to +take effect. + =cut sub create { @@ -127,6 +150,9 @@ sub create { $self->{_properties}{userId} = $session->user->userId; } my $status = $self->{_properties}{status}; + my $smsMessage = $properties->{smsMessage}; + my $smsSubject = $properties->{smsSubject}; + my $smsAddress = $properties->{smsAddress}; if ($status eq "completed") { $self->{_properties}{completedBy} = $session->user->userId; @@ -158,13 +184,15 @@ sub create { ); } } - if ( $options->{ to_email } ) { - my $subject = (defined $properties->{emailSubject}) ? $properties->{emailSubject} : $self->{_properties}{subject}; + unless ( $options->{ no_email } ) { + my $subject = (defined $properties->{emailSubject}) ? $properties->{emailSubject} : $self->{_properties}{subject}; my $mail = WebGUI::Mail::Send->create($session, { toUser=>$self->{_properties}{userId}, toGroup=>$self->{_properties}{groupId}, subject=>$subject, - }); + }, + $options->{overridePerUserDelivery} ? undef : 'isInbox', + ); my $preface = ""; my $fromUser = WebGUI::User->new($session, $properties->{sentBy}); #Don't append prefaces to the visitor users or messages that don't specify a user (default case) @@ -177,6 +205,23 @@ sub create { $mail->addFooter; $mail->queue; } + + unless ( $options->{ no_sms } ) { + # If smsAddress provided, send smsMessage too + if ( $smsAddress && $smsMessage) { + my $sms = WebGUI::Mail::Send->create( + $session, + { to => $smsAddress, + subject => $smsSubject, + } + ); + if ($sms) { + $sms->addText($smsMessage); + $sms->queue; + } + } + } + $self->{_session} = $session; bless $self, $class; } diff --git a/lib/WebGUI/Mail/Send.pm b/lib/WebGUI/Mail/Send.pm index c3401724b..b9f69e424 100644 --- a/lib/WebGUI/Mail/Send.pm +++ b/lib/WebGUI/Mail/Send.pm @@ -284,7 +284,7 @@ sub create { if (defined $user) { my $email; if ($isInbox) { - $email = $user->getInboxAddresses; + $email = $user->getInboxNotificationAddresses; } else { $email = $user->profileField("email"); @@ -511,7 +511,7 @@ sub send { next USER unless $user->status eq 'Active'; ##Don't send this to invalid user accounts my $emailAddress; if ($self->{_isInbox}) { - $emailAddress = $user->getInboxAddresses; + $emailAddress = $user->getInboxNotificationAddresses; } else { $emailAddress = $user->profileField('email'); diff --git a/lib/WebGUI/Operation/Settings.pm b/lib/WebGUI/Operation/Settings.pm index 811cbdf8b..dbbb2e9ff 100644 --- a/lib/WebGUI/Operation/Settings.pm +++ b/lib/WebGUI/Operation/Settings.pm @@ -305,11 +305,19 @@ sub definition { }); push(@fields, { tab => 'messaging', - fieldType => 'email', + fieldType => 'text', name => 'smsGateway', label => $i18n->get('sms gateway'), hoverHelp => $i18n->get('sms gateway help'), defaultValue => $setting->get('smsGateway'), + }); + push(@fields, { + tab => 'messaging', + fieldType => 'text', + name => 'smsGatewaySubject', + label => $i18n->get('sms gateway subject'), + hoverHelp => $i18n->get('sms gateway subject help'), + defaultValue => $setting->get('smsGatewaySubject'), }); # misc push(@fields, { diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index 7ea7a453a..2e42a9d66 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -704,30 +704,55 @@ sub getId { #------------------------------------------------------------------- -=head2 getInboxAddresses ( ) +=head2 getInboxNotificationAddresses ( ) Return a string with addresses that the user wants to receive Inbox notifications. If the user does not want Inbox notifications, then the string will be empty. +This is called by L, and has the effect that if +the site C setting is on and the user +has turned off C, no email at all is +sent. + =cut -sub getInboxAddresses { +sub getInboxNotificationAddresses { my $self = shift; my $emails = ''; if ( $self->profileField('receiveInboxEmailNotifications') && $self->profileField('email')) { $emails = $self->profileField('email'); } - if ( $self->profileField('receiveInboxSmsNotifications') - && $self->profileField('cellPhone') - && $self->session->setting->get('smsGateway')) { - $emails .= ',' if $emails; - my $phoneNumber = $self->profileField('cellPhone'); - $phoneNumber =~ tr/0-9//dc; ##remove nonnumbers - $emails = join '', $emails, $phoneNumber, '@', $self->session->setting->get('smsGateway'); - } return $emails; +} + +#------------------------------------------------------------------- + +=head2 getInboxSmsNotificationAddress ( ) + +Return the email address that SMS notifications will be sent to for +this user, constructed as: + + cellPhone@smsGateway + +=cut + +sub getInboxSmsNotificationAddress { + my $self = shift; + + return unless $self->profileField('receiveInboxSmsNotifications'); + + my $smsGateway = $self->session->setting->get('smsGateway'); + return unless $smsGateway; + + my $cellPhone = $self->profileField('cellPhone'); + return unless $cellPhone; + + # Remove non-numbers from cellPhone + $cellPhone =~ tr/0-9//dc; + + return join q{}, $cellPhone, '@', $smsGateway; } #------------------------------------------------------------------- diff --git a/lib/WebGUI/i18n/English/Account_Inbox.pm b/lib/WebGUI/i18n/English/Account_Inbox.pm index 002f26b65..1bf5849bf 100644 --- a/lib/WebGUI/i18n/English/Account_Inbox.pm +++ b/lib/WebGUI/i18n/English/Account_Inbox.pm @@ -774,6 +774,17 @@ our $I18N = { message => q|Should WebGUI just send notifications about Inbox messages, instead of the message itself?|, lastUpdated => 1235696295, }, + + 'inbox notifications subject' => { + message => q|Inbox Notification Email Subject|, + context => q|Site setting. A notification is a short message that a message is in the Inbox.|, + lastUpdated => 0, + }, + + 'inbox notifications subject help' => { + message => q|The email subject to use for inbox notifications|, + lastUpdated => 0, + }, 'inbox notification' => { message => q|You have a new message in your Inbox.|, @@ -790,6 +801,22 @@ our $I18N = { message => q|Choose a template that will be used to display Inbox Notifications.|, lastUpdated => 1242274703, }, + + 'inbox sms notification' => { + message => q|You have a new message in your Inbox.|, + lastUpdated => 1235708853, + }, + + 'inbox sms notification template' => { + message => q|Inbox SMS Notification Template|, + context => q|Site setting. A notification is a short SMS message that a message is in the Inbox.|, + lastUpdated => 1242274705, + }, + + 'inbox sms notification template help' => { + message => q|Choose a template that will be used to display Inbox SMS Notifications.|, + lastUpdated => 1242274703, + }, }; diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index b0d6553c8..2028ddca8 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -4555,7 +4555,7 @@ Users may override this setting in their profile. }, 'sms gateway' => { - message => q|SMS gateway|, + message => q|SMS Gateway|, context => q|email to SMS/text email address for this site.|, lastUpdated => 1235685248, }, @@ -4564,6 +4564,17 @@ Users may override this setting in their profile. message => q|The email address that this site would use to send an SMS message.|, lastUpdated => 1235695517, }, + + 'sms gateway subject' => { + message => q|SMS Gateway Subject|, + context => q|Subject to use for the SMS Gateway for this site.|, + lastUpdated => 0, + }, + + 'sms gateway subject help' => { + message => q|The email subject to pass to the SMS Gateway (typically used for SMS Gateway authorization).|, + lastUpdated => 0, + }, 'Select One' => { message => q|Select One|, diff --git a/t/Mail/Send.t b/t/Mail/Send.t index 5d3fb5418..992fa173e 100644 --- a/t/Mail/Send.t +++ b/t/Mail/Send.t @@ -42,7 +42,7 @@ if ( $@ ) { diag( "Can't prepare mail server: $@" ) } #---------------------------------------------------------------------------- # Tests -plan tests => 18; # Increment this number for each test you create +plan tests => 16; # Increment this number for each test you create #---------------------------------------------------------------------------- # Test create @@ -274,7 +274,6 @@ $emailUser->profileField('email', 'heywood@shawshank.gov'); my $lonelyUser = WebGUI::User->create($session); WebGUI::Test->usersToDelete($lonelyUser); $lonelyUser->profileField('receiveInboxEmailNotifications', 0); -$lonelyUser->profileField('receiveInboxSmsNotifications', 0); $lonelyUser->profileField('email', 'jake@shawshank.gov'); my $inboxGroup = WebGUI::Group->new($session, 'new'); @@ -300,45 +299,6 @@ SKIP: { # Test the mail is($received->{to}->[0], '', 'send, toUser with email address'); - - $inboxUser->profileField('receiveInboxEmailNotifications', 0); - $inboxUser->profileField('receiveInboxSmsNotifications', 1); - - # Send the mail - $mail = WebGUI::Mail::Send->create( $session, { - toUser => $inboxUser->userId, - }, - 'fromInbox', - ); - $mail->addText( 'sent via SMS' ); - - $mail->send; - my $received = WebGUI::Test->getMail; - - # Test the mail - is($received->{to}->[0], '<55555@textme.com>', 'send, toUser with SMS address'); - - $inboxUser->profileField('receiveInboxEmailNotifications', 1); - $inboxUser->profileField('receiveInboxSmsNotifications', 1); - - # Send the mail - $mail = WebGUI::Mail::Send->create( $session, { - toUser => $inboxUser->userId, - }, - 'fromInbox', - ); - $mail->addText( 'sent via SMS' ); - - $mail->send; - my $received = WebGUI::Test->getMail; - - # Test the mail - cmp_bag( - $received->{to}, - ['<55555@textme.com>', '',], - 'send, toUser with SMS and email addresses' - ); - } #---------------------------------------------------------------------------- @@ -377,7 +337,7 @@ cmp_bag( \@emailAddresses, [ 'heywood@shawshank.gov'."\n", - 'ellis_boyd_redding@shawshank.gov,55555@textme.com'."\n", + 'ellis_boyd_redding@shawshank.gov'."\n", ], 'send: when the original is sent, new messages are created for each user in the group, following their user profile settings' ); diff --git a/t/User.t b/t/User.t index d05e94a3b..cd4ad3713 100644 --- a/t/User.t +++ b/t/User.t @@ -22,7 +22,7 @@ use WebGUI::User; use WebGUI::ProfileField; use WebGUI::Shop::AddressBook; -use Test::More tests => 224; # increment this value for each test you create +use Test::More tests => 221; # increment this value for each test you create use Test::Deep; use Data::Dumper; @@ -970,7 +970,7 @@ $friend->deleteFromGroups([$neighbor->friends->getId]); ################################################################ # -# getInboxAddresses +# getInboxNotificationAddresses # ################################################################ @@ -982,32 +982,23 @@ $inmate->profileField('email', ''); $inmate->profileField('cellPhone', ''); $inmate->profileField('receiveInboxEmailNotifications', 0); $inmate->profileField('receiveInboxSmsNotifications', 0); -is ($inmate->getInboxAddresses, '', 'getInboxAddresses: with no profile info, returns blank'); +is ($inmate->getInboxNotificationAddresses, '', 'getInboxNotificationAddresses: with no profile info, returns blank'); $inmate->profileField('receiveInboxEmailNotifications', 1); -is ($inmate->getInboxAddresses, '', 'getInboxAddresses: with receiveInboxEmailNotifications=1, but not email address, returns blank'); +is ($inmate->getInboxNotificationAddresses, '', 'getInboxNotificationAddresses: with receiveInboxEmailNotifications=1, but not email address, returns blank'); $inmate->profileField('email', 'andy@shawshank.com'); -is ($inmate->getInboxAddresses, 'andy@shawshank.com', 'getInboxAddresses: email address only'); +is ($inmate->getInboxNotificationAddresses, 'andy@shawshank.com', 'getInboxNotificationAddresses: email address only'); $inmate->profileField('receiveInboxSmsNotifications', 1); -is ($inmate->getInboxAddresses, 'andy@shawshank.com', 'getInboxAddresses: receive only email address, with receiveInboSMSNotifications=1 but no other profile info'); +is ($inmate->getInboxNotificationAddresses, 'andy@shawshank.com', 'getInboxNotificationAddresses: receive only email address, with receiveInboSMSNotifications=1 but no other profile info'); $inmate->profileField('cellPhone', '37927'); -is ($inmate->getInboxAddresses, 'andy@shawshank.com', 'getInboxAddresses: receive only email address, with receiveInboSMSNotifications=1 and cell phone but no gateway'); +is ($inmate->getInboxNotificationAddresses, 'andy@shawshank.com', 'getInboxNotificationAddresses: receive only email address, with receiveInboSMSNotifications=1 and cell phone but no gateway'); $inmate->profileField('cellPhone', ''); $session->setting->set('smsGateway', 'textme.com'); -is ($inmate->getInboxAddresses, 'andy@shawshank.com', 'getInboxAddresses: receive only email address, with receiveInboSMSNotifications=1 and gateway but no cell phone'); - -$inmate->profileField('cellPhone', '37927'); -is ($inmate->getInboxAddresses, 'andy@shawshank.com,37927@textme.com', 'getInboxAddresses: receive only email address, with receiveInboSMSNotifications=1 and gateway but no cell phone'); - -$inmate->profileField('receiveInboxEmailNotifications', 0); -is ($inmate->getInboxAddresses, '37927@textme.com', 'getInboxAddresses: can get SMS and no email, even with email info present'); - -$inmate->profileField('receiveInboxSmsNotifications', 0); -is ($inmate->getInboxAddresses, '', 'getInboxAddresses: can get no SMS and no email, even with profile info present'); +is ($inmate->getInboxNotificationAddresses, 'andy@shawshank.com', 'getInboxNotificationAddresses: receive only email address, with receiveInboSMSNotifications=1 and gateway but no cell phone'); ################################################################ #