diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 9985f6e37..afe2869c5 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -3,8 +3,7 @@ - fixed #10450: A different errormessage is given if the username does exist and does not exist. (Arjan Widlak / United Knowledge) - fixed: Reverted bugfix for 10409 and changed the hover help to reflect the correct way to build list-type form controls in the MetaData. - - Fixed a problem with graphing created by the newer versions of Image - Magick. + - Fixed a problem with graphing created by the newer versions of Image Magick. - fixed: Template parser cannot be set - fixed #10361: Shortcuts duplicate extra header tags - fixed #10356: SQL report is cached too long @@ -19,12 +18,10 @@ - fixed #10365: Head tags do not work "Use Packed Head Tags". - fixed #9927: Survey - verbatim - fixed #10352: Deleting a user does not clean up any address books - - Fixed the problem with Basic Auth that UK fixed, but in a different way - that still allows non-realm based Basic authentication. - - fixed #10228: Calendar: Weekly re-occurence function not working properly - ( Martin Kamerbeek / Oqapi ) - - fixed #9851: New Users have blank profile field privacy settings (United - Knowledge) + - Fixed the problem with Basic Auth that UK fixed, but in a different way that still allows non-realm based Basic authentication. + - fixed #10228: Calendar: Weekly re-occurence function not working properly ( Martin Kamerbeek / Oqapi ) + - fixed #9851: New Users have blank profile field privacy settings (United Knowledge) + - fixed #10208: Account/Inbox.pm site invititations 7.7.8 - fixed: Basic Auth doesn't work if password contains colon (Arjan Widlak, diff --git a/lib/WebGUI/Account/Inbox.pm b/lib/WebGUI/Account/Inbox.pm index c70516aca..ccce0410c 100644 --- a/lib/WebGUI/Account/Inbox.pm +++ b/lib/WebGUI/Account/Inbox.pm @@ -839,10 +839,6 @@ sub www_inviteUserSave { my $user = $session->user; my $i18n = WebGUI::International->new($session,"Account_Inbox"); - #Must have a person to send email to - my $to = $form->get('to'); - return $self->www_inviteUser($i18n->get('missing email')) unless $to; - #Must have a subject my $defaultSubject = $setting->get("inboxInviteUserSubject"); WebGUI::Macro::process($session,\$defaultSubject); @@ -861,51 +857,84 @@ sub www_inviteUserSave { ; return $self->www_inviteUser($i18n->get('missing message')) unless $message; - - #User existance check. - my $existingUser = WebGUI::User->newByEmail($session,$to); - if (defined $existingUser) { - my $existingProfile = $existingUser->getProfileUrl; - my $existingUser = $existingUser->username; - my $errorMsg = sprintf($i18n->get('already a member'),$existingProfile,$existingUser); - return $self->www_inviteUser($errorMsg); - } - #Profile Email address check my $email = $session->user->profileField('email'); unless ($email) { return $self->www_inviteUser($i18n->get('no email')); } + #Must have a person to send email to + my $to = $form->get('to'); + $to =~ s/\s+//g; + return $self->www_inviteUser($i18n->get('missing email')) unless $to; + + # Test all email addresses before sending any + my $db = $session->db; + my @toList = split /[;,]/, $to; + for my $inviteeEmail (@toList) { + unless ( $inviteeEmail =~ WebGUI::Utility::emailRegex ) { + return $self->www_inviteUser( $i18n->get('invalid email') ); + } + + # User existance check. + my $existingUser = WebGUI::User->newByEmail( $session, $inviteeEmail ); + if ( defined $existingUser ) { + my $existingProfile = $existingUser->getProfileUrl; + my $existingUser = $existingUser->username; + my $errorMsg = sprintf( $i18n->get('already a member'), $existingProfile, $existingUser ); + return $self->www_inviteUser($errorMsg); + } + + # Outstanding Invitation check + my $sth = $db->read( "SELECT email FROM userInvitations WHERE email=?", [$inviteeEmail] ); + my ($emailStored) = $sth->array; + if ($emailStored) { + my $errorMsg = sprintf( $i18n->get('currently invited'), $inviteeEmail ); + return $self->www_inviteUser($errorMsg); + } + } ## end for my $inviteeEmail (@toList) + + # We think the email addresses are good now. + # Create a separate record for each invitee + # + for my $inviteeEmail (@toList) { + my $var = {}; + + ##Create the invitation url for each individual invitation + my $inviteId = $session->id->generate(); + $var->{'url'} + = $session->url->append( $session->url->getSiteURL, 'op=auth;method=createAccount;code=' . $inviteId ); + + ##Create the invitation record. + my $now = WebGUI::DateTime->new( $session, DateTime->now->set_time_zone('UTC')->epoch )->toMysqlDate; + my $hash = { + userId => $user->userId, + dateSent => $now, + email => $inviteeEmail, + dateCreated => $now, + }; + $session->db->setRow( 'userInvitations', 'inviteId', $hash, $inviteId ); + + my $invitation = WebGUI::Mail::Send->create( + $session, { + to => $to, + from => $email, + subject => $subject, + } + ); + + ## No sneaky attack paths... + $var->{'message'} = WebGUI::HTML::html2text( WebGUI::HTML::filter($message) ); + + my $emailBody = $self->processTemplate( $var, $self->getInviteUserMessageTemplateId ); + + $invitation->addText($emailBody); + + $invitation->send; + + } ## end for my $inviteeEmail (@toList) + my $var = {}; - ##No sneaky attack paths... - $var->{'message'} = WebGUI::HTML::html2text(WebGUI::HTML::filter($message)); - - ##Create the invitation url. - my $inviteId = $session->id->generate(); - $var->{'url'} = $session->url->append( - $session->url->getSiteURL,'op=auth;method=createAccount;code='.$inviteId - ); - - my $emailBody = $self->processTemplate($var,$self->getInviteUserMessageTemplateId); - - ##Create the invitation record. - my $hash = { - userId => $user->userId, - dateSent => WebGUI::DateTime->new($session, time)->toMysqlDate, - email => $to, - }; - $session->db->setRow('userInvitations','inviteId',$hash,$inviteId); - - my $invitation = WebGUI::Mail::Send->create($session, { - to => $to, - from => $email, - subject => $subject, - }); - $invitation->addText($emailBody); - $invitation->send; - - $var = {}; $self->appendCommonVars($var); return $self->processTemplate($var,$self->getInviteUserConfirmTemplateId); } diff --git a/lib/WebGUI/Form/Email.pm b/lib/WebGUI/Form/Email.pm index c9831ef93..a16ab6925 100644 --- a/lib/WebGUI/Form/Email.pm +++ b/lib/WebGUI/Form/Email.pm @@ -17,6 +17,7 @@ package WebGUI::Form::Email; use strict; use base 'WebGUI::Form::Text'; use WebGUI::International; +use WebGUI::Utility; =head1 NAME @@ -65,7 +66,7 @@ An optional value to process instead of POST input. sub getValue { my $self = shift; my $value = @_ ? shift : $self->session->form->param($self->get("name")); - if ($value =~ /^[0-9a-z._%+-]+@(?:[0-9a-z-]+\.)+[a-z]{2,9}$/i) { + if ($value =~ WebGUI::Utility::emailRegex) { return $value; } return undef; diff --git a/lib/WebGUI/Utility.pm b/lib/WebGUI/Utility.pm index 822290bf0..b393ce415 100644 --- a/lib/WebGUI/Utility.pm +++ b/lib/WebGUI/Utility.pm @@ -79,6 +79,19 @@ sub commify { } +#------------------------------------------------------------------- + +=head2 emailRegex ( ) + +Returns a regex object that can be used to validate email addresses. + +=cut + +sub emailRegex { + return qr/^([0-9a-zA-Z]+[-._+&])*\w+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,7}$/; +} + + #------------------------------------------------------------------- =head2 formatBytes ( integer ) diff --git a/lib/WebGUI/i18n/English/Account_Inbox.pm b/lib/WebGUI/i18n/English/Account_Inbox.pm index 9e0f07324..dbcb38856 100644 --- a/lib/WebGUI/i18n/English/Account_Inbox.pm +++ b/lib/WebGUI/i18n/English/Account_Inbox.pm @@ -470,8 +470,13 @@ our $I18N = { lastUpdated => 1181409056, }, + 'too many emails' => { + message => q|The invitation cannot be sent because you did not enter an email address.|, + lastUpdated => 1181409056, + }, + 'missing message' => { - message => q|Your invitiation must have a message.|, + message => q|Your invitation must have a message.|, lastUpdated => 1181409432, }, diff --git a/t/Utility.t b/t/Utility.t index d229b660a..95a764a26 100644 --- a/t/Utility.t +++ b/t/Utility.t @@ -17,7 +17,7 @@ use Tie::IxHash; use WebGUI::Test; use WebGUI::Session; -use Test::More tests => 44; # increment this value for each test you create +use Test::More tests => 46; # increment this value for each test you create use Test::Deep; my $session = WebGUI::Test->session; @@ -140,6 +140,19 @@ is(WebGUI::Utility::isInSubnet('192.168.0.1', ['192.257.0.1/32']), undef, 'isInS is(WebGUI::Utility::isInSubnet('192.168.0.1', ['192.168.258.1/32']), undef, 'isInSubnet: ip has an out of range quad'); is(WebGUI::Utility::isInSubnet('192.168.0.1', ['192.168.0.259/32']), undef, 'isInSubnet: ip has an out of range quad'); +##################################################################### +# +# emailRegex +# +##################################################################### + +isa_ok(WebGUI::Utility::emailRegex, 'Regexp'); + +TODO: { + local $TODO = 'Things to do'; + ok(0, 'Move email validation tests out of Form/Email into here'); +} + # Local variables: # mode: cperl # End: