fix: Mails sent from WebGUI now wrap at 78 characters to prevent a problem with SMTP servers that do not accept lines longer than 998 characters. This is per the SMTP RFCs. Added testing for this fix, still much to test for WebGUI::Mail::Send. Added API method to facilitate testing.

This commit is contained in:
Doug Bell 2008-01-12 07:46:32 +00:00
parent 1127d9dff2
commit 338c494d47
4 changed files with 222 additions and 67 deletions

View file

@ -15,10 +15,11 @@ http://www.plainblack.com info@plainblack.com
=cut
use strict;
use Net::SMTP;
use LWP::MediaTypes qw(guess_media_type);
use MIME::Entity;
use MIME::Parser;
use LWP::MediaTypes qw(guess_media_type);
use Net::SMTP;
use Text::Wrap;
use WebGUI::Group;
use WebGUI::Macro;
use WebGUI::User;
@ -72,7 +73,7 @@ sub addAttachment {
my $self = shift;
my $path = shift;
my $mimetype = shift || guess_media_type($path);
$self->{_message}->attach(
$self->getMimeEntity->attach(
Path=>$path,
Encoding=>'-SUGGEST',
Type=>$mimetype
@ -114,7 +115,7 @@ sub addHeaderField {
my $self = shift;
my $name = shift;
my $value = shift;
$self->{_message}->head->add($name, $value);
$self->getMimeEntity->head->add($name, $value);
}
@ -163,13 +164,21 @@ A string of HTML.
=cut
sub addHtmlRaw {
my $self = shift;
my $text = shift;
$self->{_message}->attach(
Charset=>"UTF-8",
Data=>$text,
Type=>"text/html"
);
my $self = shift;
my $text = shift;
# Wrap text after 78 characters
local $Text::Wrap::columns = 78;
# Do not break up words
local $Text::Wrap::huge = "overflow";
$self->getMimeEntity->attach(
Charset => "UTF-8",
Data => wrap( '', '', $text ),
Type => "text/html",
);
return;
}
@ -186,12 +195,20 @@ A string of text.
=cut
sub addText {
my $self = shift;
my $text = shift;
$self->{_message}->attach(
Charset=>"UTF-8",
Data=>$text
);
my $self = shift;
my $text = shift;
# Wrap text after 78 characters
local $Text::Wrap::columns = 78;
# Do not break up words
local $Text::Wrap::huge = "overflow";
$self->getMimeEntity->attach(
Charset => "UTF-8",
Data => wrap( '', '', $text ),
);
return;
}
@ -335,6 +352,18 @@ sub getMessageIdsInQueue {
return $session->db->buildArrayRef("select messageId from mailQueue");
}
#----------------------------------------------------------------------------
=head2 getMimeEntity ( )
Returns the MIME::Entity object associated with this mail message.
=cut
sub getMimeEntity {
my $self = shift;
return $self->{_message};
}
#-------------------------------------------------------------------
@ -346,7 +375,7 @@ Puts this message in the mail queue so it can be sent out later by the workflow
sub queue {
my $self = shift;
return $self->session->db->setRow("mailQueue", "messageId", { messageId=>"new", message=>$self->{_message}->stringify, toGroup=>$self->{_toGroup} });
return $self->session->db->setRow("mailQueue", "messageId", { messageId=>"new", message=>$self->getMimeEntity->stringify, toGroup=>$self->{_toGroup} });
}
@ -370,7 +399,7 @@ sub replaceHeaderField {
my $self = shift;
my $name = shift;
my $value = shift;
$self->{_message}->head->replace($name, $value);
$self->getMimeEntity->head->replace($name, $value);
}
@ -413,54 +442,61 @@ Sends the message via SMTP. Returns 1 if successful.
=cut
sub send {
my $self = shift;
my $status = 1;
if ($self->{_message}->head->get("To")) {
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"));
$status = 0;
}
} else {
my $smtp = Net::SMTP->new($self->session->setting->get("smtpServer")); # connect to an SMTP server
if (defined $smtp) {
$smtp->mail($self->{_message}->head->get("X-Return-Path"));
$smtp->to(split(",",$self->{_message}->head->get("to")));
$smtp->cc(split(",",$self->{_message}->head->get("cc")));
$smtp->bcc(split(",",$self->{_message}->head->get("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"));
$status = 0;
}
}
}
# due to the large number of emails that may be generated by sending emails to a group,
# emails to members of a group are queued rather than sent directly
my $group = $self->{_toGroup};
delete $self->{_toGroup};
if ($group) {
my $group = WebGUI::Group->new($self->session, $group);
my $self = shift;
my $mail = $self->getMimeEntity;
my $status = 1;
if ($mail->head->get("To")) {
if ($self->session->setting->get("smtpServer") =~ /\/sendmail/) {
if (open(MAIL,"| ".$self->session->setting->get("smtpServer")." -t -oi -oem")) {
$mail->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"));
$status = 0;
}
}
else {
my $smtp = Net::SMTP->new($self->session->setting->get("smtpServer")); # connect to an SMTP server
if (defined $smtp) {
$smtp->mail($mail->head->get("X-Return-Path"));
$smtp->to(split(",",$mail->head->get("to")));
$smtp->cc(split(",",$mail->head->get("cc")));
$smtp->bcc(split(",",$mail->head->get("bcc")));
$smtp->data(); # Start the mail
$smtp->datasend($mail->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"));
$status = 0;
}
}
}
# due to the large number of emails that may be generated by sending emails to a group,
# emails to members of a group are queued rather than sent directly
my $group = $self->{_toGroup};
delete $self->{_toGroup};
if ($group) {
my $group = WebGUI::Group->new($self->session, $group);
return $status
if !defined $group;
$self->{_message}->head->replace("bcc", undef);
$self->{_message}->head->replace("cc", undef);
foreach my $userId (@{$group->getAllUsers(1)}) {
my $user = WebGUI::User->new($self->session, $userId);
if !defined $group;
$mail->head->replace("bcc", undef);
$mail->head->replace("cc", undef);
foreach my $userId (@{$group->getAllUsers(1)}) {
my $user = WebGUI::User->new($self->session, $userId);
next unless $user->status eq 'Active'; ##Don't send this to invalid user accounts
if ($user->profileField("email")) {
$self->{_message}->head->replace("To",$user->profileField("email"));
$self->queue;
}
}
}
return $status;
if ($user->profileField("email")) {
$mail->head->replace("To",$user->profileField("email"));
$self->queue;
}
}
}
return $status;
}
#-------------------------------------------------------------------