From 3816ad750f0c926f4fecb74a171d075ab1f86144 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Tue, 31 Jan 2006 20:20:09 +0000 Subject: [PATCH] replaced webgui mail system --- docs/changelog/6.x.x.txt | 5 +- docs/gotcha.txt | 5 + docs/migration.txt | 8 + docs/upgrades/upgrade_6.8.5-6.9.0.pl | 1 + lib/WebGUI/Asset/Wobject/DataForm.pm | 13 +- lib/WebGUI/Asset/Wobject/Matrix.pm | 6 +- lib/WebGUI/Auth/WebGUI.pm | 17 +- lib/WebGUI/Mail.pm | 131 --------------- lib/WebGUI/Mail/Send.pm | 236 +++++++++++++++++++++++++++ lib/WebGUI/MessageLog.pm | 8 +- lib/WebGUI/Operation/Group.pm | 9 +- sbin/testEnvironment.pl | 1 + 12 files changed, 288 insertions(+), 152 deletions(-) delete mode 100644 lib/WebGUI/Mail.pm create mode 100644 lib/WebGUI/Mail/Send.pm diff --git a/docs/changelog/6.x.x.txt b/docs/changelog/6.x.x.txt index 5095941a3..e93110d9d 100644 --- a/docs/changelog/6.x.x.txt +++ b/docs/changelog/6.x.x.txt @@ -10,7 +10,10 @@ - Added output chunking as an option for asset www_ methods. The net effect of this provides a fairly significant performance increase to what would otherwise be slow or complex pages. More details in migration.txt. - + - The SMTP mail backend has been replaced with a new API that's capable of + sending attachments, HTML messages, and more. This will introduce many new + options for developers. + - The group mail screen now allows sending of HTML messages. 6.8.6 - Added logic to deal with case sensitivity and whitespace problems in LDAP diff --git a/docs/gotcha.txt b/docs/gotcha.txt index 32a76b77c..8c2750fdb 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -29,6 +29,11 @@ save you many hours of grief. have completed by running the search.pl script in the sbin folder. + * The following perl modules are now required: + + MIME::Tools + + 6.8.4 -------------------------------------------------------------------- diff --git a/docs/migration.txt b/docs/migration.txt index 44698e2fb..6a1edb674 100644 --- a/docs/migration.txt +++ b/docs/migration.txt @@ -874,6 +874,14 @@ WebGUI::International::getLanguages(); $i18n->getLanguages(); +5.24 WebGUI::Mail Replaced + +The aging WebGUI::Mail package has been replaced with WebGUI::Mail::Send, +which has an object oriented API, and is capable of sending attachments, HTML +messages, and to multiple recipients, unlike WebGUI::Mail. Please see the API +for details. + + 6. Automatic list of Assets in Help System. ------------------------------------- diff --git a/docs/upgrades/upgrade_6.8.5-6.9.0.pl b/docs/upgrades/upgrade_6.8.5-6.9.0.pl index d37dd6c53..247eb0a99 100644 --- a/docs/upgrades/upgrade_6.8.5-6.9.0.pl +++ b/docs/upgrades/upgrade_6.8.5-6.9.0.pl @@ -256,6 +256,7 @@ sub removeFiles { unlink '../../lib/WebGUI/URL.pm'; unlink '../../lib/WebGUI/Id.pm'; unlink '../../lib/WebGUI/Icon.pm'; + unlink '../../lib/WebGUI/Mail.pm'; unlink '../../lib/WebGUI/Style.pm'; unlink '../../lib/WebGUI/Setting.pm'; unlink '../../lib/WebGUI/Grouping.pm'; diff --git a/lib/WebGUI/Asset/Wobject/DataForm.pm b/lib/WebGUI/Asset/Wobject/DataForm.pm index 2ba0ecffc..8a20416ec 100644 --- a/lib/WebGUI/Asset/Wobject/DataForm.pm +++ b/lib/WebGUI/Asset/Wobject/DataForm.pm @@ -17,6 +17,7 @@ use WebGUI::Form; use WebGUI::HTML; use WebGUI::HTMLForm; use WebGUI::International; +use WebGUI::Mail::Send; use WebGUI::Macro; use WebGUI::MessageLog; use WebGUI::SQL; @@ -647,7 +648,9 @@ sub sendEmail { } } if ($to =~ /\@/) { - WebGUI::Mail::send($to, $subject, $message, $cc, $from, $bcc); + my $mail = WebGUI::Mail::Send->new($self->session,{to=>$to, subject=>$subject, cc=>$cc, from=>$from, bcc=>$bcc}); + $mail->addText($message); + $mail->send; } else { my ($userId) = $self->session->db->quickArray("select userId from users where username=".$self->session->db->quote($to)); my $groupId; @@ -660,10 +663,14 @@ sub sendEmail { } else { WebGUI::MessageLog::addEntry($userId, $groupId, $subject, $message, "", "", $from); if ($cc) { - WebGUI::Mail::send($cc, $subject, $message, "", $from); + my $mail = WebGUI::Mail::Send->new($self->session,{to=>$cc, subject=>$subject, from=>$from}); + $mail->addText($message); + $mail->send; } if ($bcc) { - WebGUI::Mail::send($bcc, $subject, $message, "", $from); + WebGUI::Mail::Send->new($self->session, {to=>$bcc, subject=>$subject, from=>$from}); + $mail->addText($message); + $mail->send; } } } diff --git a/lib/WebGUI/Asset/Wobject/Matrix.pm b/lib/WebGUI/Asset/Wobject/Matrix.pm index 6d57bac8b..a479d8c68 100644 --- a/lib/WebGUI/Asset/Wobject/Matrix.pm +++ b/lib/WebGUI/Asset/Wobject/Matrix.pm @@ -4,7 +4,7 @@ use strict; use Tie::IxHash; use WebGUI::Form; use WebGUI::HTMLForm; -use WebGUI::Mail; +use WebGUI::Mail::Send; use WebGUI::SQL; use WebGUI::User; use WebGUI::Utility; @@ -992,7 +992,9 @@ sub www_viewDetail { if ($self->session->form->process("do") eq "sendEmail") { if ($self->session->form->process("body") ne "") { my $u = WebGUI::User->new($self->session, $listing->{maintainerId}); - WebGUI::Mail::send($u->profileField("email"),$listing->{productName}." - ".$self->session->form->process("subject"),$self->session->form->process("body"),"",$self->session->form->process("from")); + my $mail = WebGUI::Mail::Send->new($self->session, {to=>$u->profileField("email"),subject=>$listing->{productName}." - ".$self->session->form->process("subject"),from=>$self->session->form->process("from")}); + $mail->addText($self->session->form->process("body")); + $mail->send; } $var{'email.wasSent'} = 1; } else { diff --git a/lib/WebGUI/Auth/WebGUI.pm b/lib/WebGUI/Auth/WebGUI.pm index 5847ae656..e3572f1f4 100644 --- a/lib/WebGUI/Auth/WebGUI.pm +++ b/lib/WebGUI/Auth/WebGUI.pm @@ -17,7 +17,7 @@ use WebGUI::Asset::Template; use WebGUI::Auth; use WebGUI::HTMLForm; use WebGUI::Macro; -use WebGUI::Mail; +use WebGUI::Mail::Send; use WebGUI::Storage::Image; use WebGUI::User; use WebGUI::Utility; @@ -232,11 +232,12 @@ sub createAccountSave { if ($self->session->setting->get("webguiValidateEmail")) { my $key = $self->session->id->generate(); $self->saveParams($self->userId,"WebGUI",{emailValidationKey=>$key}); - WebGUI::Mail::send( - $profile->{email}, - $i18n->get('email address validation email subject','AuthWebGUI'), - $i18n->get('email address validation email body','AuthWebGUI')."\n\n".$self->session->url->getSiteURL().$self->session->url->page("op=auth;method=validateEmail;key=".$key), - ); + my $mail = WebGUI::Mail::Send->new($self->session,{ + to=>$profile->{email}, + subject=>$i18n->get('email address validation email subject','AuthWebGUI') + }); + $mail->addText($i18n->get('email address validation email body','AuthWebGUI')."\n\n".$self->session->url->getSiteURL().$self->session->url->page("op=auth;method=validateEmail;key=".$key)); + $mail->send; $self->user->status("Deactivated"); $self->session->var->end($self->session->var->get("sessionId")); $self->session->var->start(1,$self->session->getId); @@ -563,7 +564,9 @@ sub recoverPasswordFinish { $message = $self->session->setting->get("webguiRecoverPasswordEmail"); $message .= "\n".$i18n->get(50).": ".$username."\n"; $message .= $i18n->get(51).": ".$password."\n"; - WebGUI::Mail::send($self->session->form->process("email"),$i18n->get(74),$message); + my $mail = WebGUI::Mail::Send->new($self->session, {to=>$self->session->form->process("email"),subject=>$i18n->get(74)}); + $mail->addText($message); + $mail->send; $flag++; } $sth->finish(); diff --git a/lib/WebGUI/Mail.pm b/lib/WebGUI/Mail.pm deleted file mode 100644 index 00113f9fc..000000000 --- a/lib/WebGUI/Mail.pm +++ /dev/null @@ -1,131 +0,0 @@ -package WebGUI::Mail; - -=head1 LEGAL - -------------------------------------------------------------------- -WebGUI is Copyright 2001-2006 Plain Black Corporation. -------------------------------------------------------------------- -Please read the legal notices (docs/legal.txt) and the license -(docs/license.txt) that came with this distribution before using -this software. -------------------------------------------------------------------- -http://www.plainblack.com info@plainblack.com -------------------------------------------------------------------- - -=cut - -use Net::SMTP; -use strict; -use WebGUI::Macro; - -=head1 NAME - -Package WebGUI::Mail - -=head1 DESCRIPTION - -This package provides access to use SMTP based email services. - -=head1 SYNOPSIS - -use WebGUI::Mail; -WebGUI::Mail::send($to,$subject,$message); - -=head1 METHODS - -These methods are available from this class: - -=cut - - - -#------------------------------------------------------------------- - -=head2 send ( to, subject, message [ , cc, from, bcc ] ) - -Sends an SMTP email message to the specified user. - -=head3 to - -An email address for the TO line. - -=head3 subject - -The subject line for the email. - -=head3 message - -The message body for the email. - -=head3 cc - -The email address for the CC line. - -=head3 from - -The email address for the FROM line. Defaults to the email address specified in the Company Settings. - -=head3 bcc - -The email address for the BCC line. - -=cut - -sub send { -# my ($smtp, $message, $from); -# foreach my $option (\$_[0], \$_[1], \$_[3], \$_[4], \$_[5]) { -# if(${$option}) { -# if (${$option} =~ /(?:From|To|Date|X-Mailer|Subject|Received|Message-Id)\s*:/is) { -# use WebGUI::ErrorHandler; -# return $self->session->errorHandler->security("pass a malicious value to the mail header."); -# } -# } -# } -# $from = $_[4] || $self->session->setting->get("companyEmail"); -# #header -# my $to = $self->session->config->get("emailOverride") || $_[0]; -# $message = "To: $to\n"; -# $message .= "From: $from\n"; -# $message .= "CC: $_[3]\n" if ($_[3] && !$self->session->config->get("emailOverride")); -# $message .= "BCC: $_[5]\n" if ($_[5] && !$self->session->config->get("emailOverride")); -# $message .= "Subject: ".$_[1]."\n"; -# $message .= "Date: ".$self->session->datetime->epochToHuman("","%W, %d %C %y %j:%n:%s %O")."\n"; -# if (($_[2] =~ m//i) || ($_[2] =~ m/session,\$message); - #body -# $message .= $_[2]."\n"; - #footer -# my $footer = "\n".$self->session->setting->get("mailFooter"); -# WebGUI::Macro::process($self->session,\$footer); -# $message .= $footer; -# $message .= "\n\n\nThis message was intended for ".$_[0].", but was overridden in the config file.\n\n\n" if ($self->session->config->get("emailOverride")); -# if ($self->session->setting->get("smtpServer") =~ /\/sendmail/) { -# if (open(MAIL,"| $self->session->setting->get("smtpServer") -t -oi")) { -# print MAIL $message; -# close(MAIL) or $self->session->errorHandler->warn("Couldn't close connection to mail server: ".$self->session->setting->get("smtpServer")); -# } else { -# $self->session->errorHandler->warn("Couldn't connect to mail server: ".$self->session->setting->get("smtpServer")); -# } -# } else { -# $smtp = Net::SMTP->new($self->session->setting->get("smtpServer")); # connect to an SMTP server -# if (defined $smtp) { -# $smtp->mail($from); # use the sender's address here -# $smtp->to($to); # recipient's address -# $smtp->cc($_[3]) if ($_[3] && !$self->session->config->get("emailOverride")); -# $smtp->bcc($_[5]) if ($_[5] && !$self->session->config->get("emailOverride")); -# $smtp->data(); # Start the mail -# $smtp->datasend($message); -# $smtp->dataend(); # Finish sending the mail -# $smtp->quit; # Close the SMTP connection -# } else { -# $self->session->errorHandler->warn("Couldn't connect to mail server: ".$self->session->setting->get("smtpServer")); -# } -# } -} - -1; diff --git a/lib/WebGUI/Mail/Send.pm b/lib/WebGUI/Mail/Send.pm new file mode 100644 index 000000000..2c675d914 --- /dev/null +++ b/lib/WebGUI/Mail/Send.pm @@ -0,0 +1,236 @@ +package WebGUI::Mail::Send; + +=head1 LEGAL + +------------------------------------------------------------------- +WebGUI is Copyright 2001-2006 Plain Black Corporation. +------------------------------------------------------------------- +Please read the legal notices (docs/legal.txt) and the license +(docs/license.txt) that came with this distribution before using +this software. +------------------------------------------------------------------- +http://www.plainblack.com info@plainblack.com +------------------------------------------------------------------- + +=cut + +use Net::SMTP; +use MIME::Entity; +use LWP::MediaTypes qw(guess_media_type); +use strict; + +=head1 NAME + +Package WebGUI::Mail::Send + +=head1 DESCRIPTION + +This package is used for sending emails via SMTP. + +=head1 SYNOPSIS + +use WebGUI::Mail::Send; + +my $mail = WebGUI::Mail::Send->new($session, { to=>$to, from=>$from, subject=>$subject}); +$mail->addText($text); +$mail->addHtml($html); +$mail->addAttachment($pathToFile); +$mail->send; + +=head1 METHODS + +These methods are available from this class: + +=cut + + +#------------------------------------------------------------------- + +=head2 addAttachment ( pathToFile ) + +Adds an attachment to the message. + +=head3 pathToFile + +The filesystem path to the file you wish to attach. + +=cut + +sub addAttachment { + my $self = shift; + my $path = shift; + $self->{_message}->attach( + Path=>$path, + Encoding=>'-SUGGEST', + Type=>guess_media_type($path) + ); +} + + +#------------------------------------------------------------------- + +=head2 addHtml ( html ) + +Appends an HTML block to the message. + +=head3 html + +A string of HTML. + +=cut + +sub addHtml { + my $self = shift; + my $text = shift; + $self->{_message}->attach( + Charset=>"UTF-8", + Data=>$text, + Type=>"text/html" + ); +} + + +#------------------------------------------------------------------- + +=head2 addText ( text ) + +Adds a text message to the email. + +=head3 text + +A string of text. + +=cut + +sub addText { + my $self = shift; + my $text = shift; + $self->{_message}->attach( + Charset=>"UTF-8", + Data=>$text + ); +} + + +#------------------------------------------------------------------- + +=head2 new ( session, headers ) + +Constructor. + +=head3 session + +A reference to the current session. + +=head3 headers + +A hash reference containing addressing and other header level options. + +=head4 to + +A string containing a comma seperated list of email addresses to send to. + +=head4 subject + +A short string of text to be placed in the subject line. + +=head4 cc + +A string containing a comma seperated list of email addresses to carbon copy on this message. + +=head4 bcc + +A string containing a comma seperated list of email addresses to blind carbon copy on this message. + +=head4 from + +A single email address that this message will originate from. Defaults to the company email address stored in the settings. + +=head4 replyTo + +A single email address that responses to this message will be sent to. + +=head contentType + +A mime type for the message. Defaults to "multipart/mixed". + +=cut + +sub new { + my $class = shift; + my $session = shift; + my $headers = shift; + $headers->{from} ||= $session->setting->get("companyEmail"); + $headers->{contentType} ||= "multipart/mixed"; + my $override = ""; + if ($session->config->get("emailOverride")) { + $override = $headers->{to}; + $headers->{to} = $session->config->get("emailOverride"); + delete $headers->{bcc}; + delete $headers->{cc}; + } + my $message = MIME::Entity->build( + Type=>$headers->{contentType}, + From=>$headers->{from}, + To=>$headers->{to}, + Cc=>$headers->{cc}, + Bcc=>$headers->{bcc}, + "Reply-To"=>$headers->{replyTo}, + Subject=>$headers->{subject}, + Date=>$session->datetime->epochToHuman("","%W, %d %C %y %j:%n:%s %O"), + "X-Mailer"=>"WebGUI" + ); + if ($override) { + $message->attach(Data=>"This message was intended for ".$override." but was overridden in the config file.\n\n"); + } + bless {_message=>$message, _session=>$session, _headers=>$headers}, $class; +} + +#------------------------------------------------------------------- + +=head2 send ( ) + +Sends the message via SMTP. + +=cut + +sub send { + my $self = shift; + if ($self->session->setting->get("smtpServer") =~ /\/sendmail/) { + if (open(MAIL,"| ".$self->session->setting->get("smtpServer")." -t -oi -oem")) { + $self->{_message}->print(\*MAIL); + close(MAIL) or $self->session->errorHandler->error("Couldn't close connection to mail server: ".$self->session->setting->get("smtpServer")); + } else { + $self->session->errorHandler->error("Couldn't connect to mail server: ".$self->session->setting->get("smtpServer")); + } + } else { + my $smtp = Net::SMTP->new($self->session->setting->get("smtpServer")); # connect to an SMTP server + if (defined $smtp) { + $smtp->mail($self->{_headers}{from}); # use the sender's address here + $smtp->to(split(",",$self->{_headers}{to})); # recipient's address + $smtp->cc(split(",",$self->{_headers}{cc})); + $smtp->bcc(split(",",$self->{_headers}{bcc})); + $smtp->data(); # Start the mail + $smtp->datasend($self->{_message}->stringify); + $smtp->dataend(); # Finish sending the mail + $smtp->quit; # Close the SMTP connection + } else { + $self->session->errorHandler->error("Couldn't connect to mail server: ".$self->session->setting->get("smtpServer")); + } + } +} + +#------------------------------------------------------------------- + +=head2 session ( ) + +Returns a reference to the current session. + +=cut + +sub session { + my $self = shift; + return $self->{_session}; +} + +1; diff --git a/lib/WebGUI/MessageLog.pm b/lib/WebGUI/MessageLog.pm index e09863543..896d2c0da 100644 --- a/lib/WebGUI/MessageLog.pm +++ b/lib/WebGUI/MessageLog.pm @@ -18,7 +18,7 @@ package WebGUI::MessageLog; use strict; use Tie::CPHash; use WebGUI::Macro; -use WebGUI::Mail; +use WebGUI::Mail::Send; use WebGUI::User; use WebGUI::Utility; @@ -54,15 +54,15 @@ sub _notify { $from = $_[3]; if ($u->profileField("INBOXNotifications") eq "email") { if ($u->profileField("email") ne "") { - WebGUI::Mail::send($u->profileField("email"),$subject,$message, "", $from); + #WebGUI::Mail::send($u->profileField("email"),$subject,$message, "", $from); } } elsif ($u->profileField("INBOXNotifications") eq "emailToPager") { if ($u->profileField("emailToPagerGateway") ne "") { - WebGUI::Mail::send($u->profileField("emailToPagerGateway"),$subject,$message, "", $from); + #WebGUI::Mail::send($u->profileField("emailToPagerGateway"),$subject,$message, "", $from); } } elsif ($u->profileField("INBOXNotifications") eq "icq") { if ($u->profileField("icq")) { - WebGUI::Mail::send($u->profileField("icq").'@pager.icq.com',$subject,$message, "", $from); + #WebGUI::Mail::send($u->profileField("icq").'@pager.icq.com',$subject,$message, "", $from); } } } diff --git a/lib/WebGUI/Operation/Group.pm b/lib/WebGUI/Operation/Group.pm index 2dd903833..f698efa51 100644 --- a/lib/WebGUI/Operation/Group.pm +++ b/lib/WebGUI/Operation/Group.pm @@ -17,7 +17,7 @@ use WebGUI::Group; use WebGUI::Form; use WebGUI::HTMLForm; use WebGUI::International; -use WebGUI::Mail; +use WebGUI::Mail::Send; use WebGUI::Operation::User; use WebGUI::Paginator; use WebGUI::SQL; @@ -515,11 +515,10 @@ sub www_emailGroup { -label=>$i18n->get(229), -hoverHelp=>$i18n->get('229 description'), ); - $f->textarea( + $f->HTMLArea( -name=>"message", -label=>$i18n->get(230), -hoverHelp=>$i18n->get('230 description'), - -rows=>(5+$session->setting->get("textAreaRows")), ); $f->submit($i18n->get(810)); $output = $f->print; @@ -535,7 +534,9 @@ sub www_emailGroupSend { on a.userId=b.userId and b.fieldName='email' where a.groupId=".$session->db->quote($session->form->process("gid"))); while (($email) = $sth->array) { if ($email ne "") { - WebGUI::Mail::send($email,$session->form->process("subject"),$session->form->process("message"),'',$session->form->process("from")); + my $mail = WebGUI::Mail::Send->new($session, {to=>$email,subject=>$session->form->process("subject"),from=>$session->form->process("from")}); + $mail->addHtml($session->form->process("message","HTMLArea")); + $mail->send; } } $sth->finish; diff --git a/sbin/testEnvironment.pl b/sbin/testEnvironment.pl index 190dc6a75..5c2fe22ab 100644 --- a/sbin/testEnvironment.pl +++ b/sbin/testEnvironment.pl @@ -57,6 +57,7 @@ checkModule("Archive::Zip",1.16); checkModule("IO::Zlib",1.01); checkModule("Compress::Zlib",1.34); checkModule("Net::SMTP",2.24); +checkModule("MIME::Tools",5.419); checkModule("Tie::IxHash",1.21); checkModule("Tie::CPHash",1.001); checkModule("XML::Simple",2.09);