added mail send queue
This commit is contained in:
parent
b062e61508
commit
7c71d93c1e
6 changed files with 263 additions and 44 deletions
|
|
@ -29,6 +29,7 @@
|
|||
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
|
||||
- Added a mail queue system.
|
||||
options for developers.
|
||||
- The group mail screen now allows sending of HTML messages.
|
||||
- Added prequery statements to the SQLReport and configurable allowed statements
|
||||
|
|
|
|||
|
|
@ -134,6 +134,11 @@ sub addWorkflow {
|
|||
value text,
|
||||
primary key (activityId, name)
|
||||
)");
|
||||
$session->db->write("create table mailQueue (
|
||||
messageId varchar(22) binary not null primary key,
|
||||
message mediumtext,
|
||||
toGroup varchar(22) binary
|
||||
)");
|
||||
print "\t\tPurging old workflow info.\n";
|
||||
my $versionTag = WebGUI::VersionTag->getWorking($session);
|
||||
$versionTag->set({name=>"Upgrade to ".$toVersion});
|
||||
|
|
@ -164,6 +169,7 @@ sub addWorkflow {
|
|||
"WebGUI::Workflow::Activity::ExpireGroupings", "WebGUI::Workflow::Activity::PurgeOldAssetRevisions",
|
||||
"WebGUI::Workflow::Activity::ExpireSubscriptionCodes", "WebGUI::Workflow::Activity::PurgeOldTrash",
|
||||
"WebGUI::Workflow::Activity::GetSyndicatedContent", "WebGUI::Workflow::Activity::ProcessRecurringPayments",
|
||||
"WebGUI::Workflow::Activity::SendQueuedMailMessages",
|
||||
"WebGUI::Workflow::Activity::SyncProfilesToLdap", "WebGUI::Workflow::Activity::SummarizePassiveProfileLog"],
|
||||
"WebGUI::User"=>["WebGUI::Workflow::Activity::CreateCronJob", "WebGUI::Workflow::Activity::NotifyAboutUser"],
|
||||
"WebGUI::VersionTag"=>["WebGUI::Workflow::Activity::CommitVersionTag", "WebGUI::Workflow::Activity::RollbackVersionTag",
|
||||
|
|
@ -304,6 +310,23 @@ sub addWorkflow {
|
|||
$activity->set("subject", "Content Denied");
|
||||
$activity->set("message", "Your version tag was denied. Please take corrective actions and recommit your changes.");
|
||||
$activity->set("who", "committer");
|
||||
$workflow = WebGUI::Workflow->create($session, {
|
||||
title=>"Send Queued Email Messages",
|
||||
description => "Sends all the messages in the mail queue.",
|
||||
enabled=>1,
|
||||
isSerial=>1,
|
||||
type=>"None"
|
||||
}, "pbworkflow000000000006");
|
||||
$activity = $workflow->addActivity("WebGUI::Workflow::Activity::SendQueuedMailMessages", "pbwfactivity0000000021");
|
||||
$activity->set("title", "Send Queued Messages");
|
||||
WebGUI::Workflow::Cron->create($session, {
|
||||
title=>'Send Queued Email Messages Every 5 Minutes',
|
||||
enabled=>1,
|
||||
runOnce=>0,
|
||||
minuteOfHour=>"*/5",
|
||||
priority=>3,
|
||||
workflowId=>$workflow->getId
|
||||
}, "pbcron0000000000000004");
|
||||
print "\t\tUpdating settings.\n";
|
||||
$session->setting->remove("autoCommit");
|
||||
$session->setting->remove("alertOnNewUser");
|
||||
|
|
|
|||
|
|
@ -302,7 +302,8 @@
|
|||
"WebGUI::Workflow::Activity::ExpireGroupings", "WebGUI::Workflow::Activity::PurgeOldAssetRevisions",
|
||||
"WebGUI::Workflow::Activity::ExpireSubscriptionCodes", "WebGUI::Workflow::Activity::PurgeOldTrash",
|
||||
"WebGUI::Workflow::Activity::GetSyndicatedContent", "WebGUI::Workflow::Activity::ProcessRecurringPayments",
|
||||
"WebGUI::Workflow::Activity::SyncProfilesToLdap", "WebGUI::Workflow::Activity::SummarizePassiveProfileLog"],
|
||||
"WebGUI::Workflow::Activity::SyncProfilesToLdap", "WebGUI::Workflow::Activity::SummarizePassiveProfileLog",
|
||||
"WebGUI::Workflow::Activity::SendQueuedMailMessages"],
|
||||
"WebGUI::User" : ["WebGUI::Workflow::Activity::CreateCronJob", "WebGUI::Workflow::Activity::NotifyAboutUser"],
|
||||
"WebGUI::VersionTag" : ["WebGUI::Workflow::Activity::CommitVersionTag", "WebGUI::Workflow::Activity::RollbackVersionTag",
|
||||
"WebGUI::Workflow::Activity::TrashVersionTag", "WebGUI::Workflow::Activity::CreateCronJob",
|
||||
|
|
|
|||
|
|
@ -14,10 +14,13 @@ http://www.plainblack.com info@plainblack.com
|
|||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Net::SMTP;
|
||||
use MIME::Entity;
|
||||
use MIME::Parser;
|
||||
use LWP::MediaTypes qw(guess_media_type);
|
||||
use strict;
|
||||
use WebGUI::Group;
|
||||
use WebGUI::User;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -31,11 +34,15 @@ This package is used for sending emails via SMTP.
|
|||
|
||||
use WebGUI::Mail::Send;
|
||||
|
||||
my $mail = WebGUI::Mail::Send->new($session, { to=>$to, from=>$from, subject=>$subject});
|
||||
my $mail = WebGUI::Mail::Send->create($session, { to=>$to, from=>$from, subject=>$subject});
|
||||
my $mail = WebGUI::Mail::Send->retrieve($session, $messageId);
|
||||
|
||||
$mail->addText($text);
|
||||
$mail->addHtml($html);
|
||||
$mail->addAttachment($pathToFile);
|
||||
|
||||
$mail->send;
|
||||
$mail->queue;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
|
|
@ -46,7 +53,7 @@ These methods are available from this class:
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addAttachment ( pathToFile )
|
||||
=head2 addAttachment ( pathToFile [ , mimetype ] )
|
||||
|
||||
Adds an attachment to the message.
|
||||
|
||||
|
|
@ -54,15 +61,20 @@ Adds an attachment to the message.
|
|||
|
||||
The filesystem path to the file you wish to attach.
|
||||
|
||||
=head3 mimetype
|
||||
|
||||
Optionally specify a mime type for this attachment. If one is not specified it will be guessed based upon the file extension.
|
||||
|
||||
=cut
|
||||
|
||||
sub addAttachment {
|
||||
my $self = shift;
|
||||
my $path = shift;
|
||||
my $mimetype = shift || guess_media_type($path);
|
||||
$self->{_message}->attach(
|
||||
Path=>$path,
|
||||
Encoding=>'-SUGGEST',
|
||||
Type=>guess_media_type($path)
|
||||
Type=>$mimetype
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -114,9 +126,9 @@ sub addText {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 new ( session, headers )
|
||||
=head2 create ( session, headers )
|
||||
|
||||
Constructor.
|
||||
Creates a new message and returns a WebGUI::Mail::Send object. This is a class method.
|
||||
|
||||
=head3 session
|
||||
|
||||
|
|
@ -130,6 +142,10 @@ A hash reference containing addressing and other header level options.
|
|||
|
||||
A string containing a comma seperated list of email addresses to send to.
|
||||
|
||||
=head4 toGroup
|
||||
|
||||
A WebGUI groupId. The email address of the users in this group will be looked up and will each be sent a copy of this message.
|
||||
|
||||
=head4 subject
|
||||
|
||||
A short string of text to be placed in the subject line.
|
||||
|
|
@ -156,22 +172,13 @@ A mime type for the message. Defaults to "multipart/mixed".
|
|||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
sub create {
|
||||
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},
|
||||
Type=>$headers->{contentType} || "multipart/mixed",
|
||||
From=>$headers->{from} || $session->setting->get("companyEmail"),
|
||||
To=>$headers->{to},
|
||||
Cc=>$headers->{cc},
|
||||
Bcc=>$headers->{bcc},
|
||||
|
|
@ -180,12 +187,80 @@ sub new {
|
|||
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");
|
||||
if ($session->config->get("emailOverride")) {
|
||||
my $to = $headers->{to};
|
||||
$to = "WebGUI Group ".$headers->{toGroup} if ($headers->{toGroup});
|
||||
$message->head->replace("to", $session->config->get("emailOverride"));
|
||||
$message->head->replace("cc",undef);
|
||||
$message->head->replace("bcc",undef);
|
||||
delete $headers->{toGroup};
|
||||
$message->attach(Data=>"This message was intended for ".$to." but was overridden in the config file.\n\n");
|
||||
}
|
||||
bless {_message=>$message, _session=>$session, _headers=>$headers}, $class;
|
||||
bless {_message=>$message, _session=>$session, _toGroup=>$headers->{toGroup} }, $class;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getMessageIdsInQueue ( session )
|
||||
|
||||
Returns an array reference of the message IDs in the mail queue. Use with the retrieve() method. This is a class method.
|
||||
|
||||
=head3 session
|
||||
|
||||
A reference to the current session.
|
||||
|
||||
=cut
|
||||
|
||||
sub getMessageIdsInQueue {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
return $session->db->buildArrayRef("select messageId from mailQueue");
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 queue ( )
|
||||
|
||||
Puts this message in the mail queue so it can be sent out later by the workflow system. Returns a messageId so that the message can be retrieved later if necessary. Note that this is the preferred method of sending messages because it keeps WebGUI running faster.
|
||||
|
||||
=cut
|
||||
|
||||
sub queue {
|
||||
my $self = shift;
|
||||
return $self->session->db->setRow("mailQueue", "messageId", { messageId=>"new", message=>$self->{_message}->stringify, toGroup=>$self->{_toGroup} });
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 retrieve ( session, messageId )
|
||||
|
||||
Retrieves a message from the mail queue, which thusly deletes it from the queue. This is a class method.
|
||||
|
||||
=head3 session
|
||||
|
||||
A reference to the current session.
|
||||
|
||||
=head3 messageId
|
||||
|
||||
The unique id for a message in the queue.
|
||||
|
||||
=cut
|
||||
|
||||
sub retrieve {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $messageId = shift;
|
||||
return undef unless $messageId;
|
||||
my $data = $session->db->getRow("mailQueue","messageId", $messageId);
|
||||
return undef unless $data->{messageId};
|
||||
$session->db->deleteRow("mailQueue","messageId", $messageId);
|
||||
my $parser = MIME::Parser->new;
|
||||
bless {_session=>$session, _message=>$parser->parse_data($data->{messageId}), _toGroup=>$data->{toGroup}}, $class;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 send ( )
|
||||
|
|
@ -196,31 +271,50 @@ Sends the message via SMTP. Returns 1 if successful.
|
|||
|
||||
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"));
|
||||
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 {
|
||||
$self->session->errorHandler->error("Couldn't connect to mail server: ".$self->session->setting->get("smtpServer"));
|
||||
return 0;
|
||||
}
|
||||
} 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"));
|
||||
return 0;
|
||||
my $smtp = Net::SMTP->new($self->session->setting->get("smtpServer")); # connect to an SMTP server
|
||||
if (defined $smtp) {
|
||||
$smtp->mail($self->{_message}->head->get("from")); # use the sender's address here
|
||||
$smtp->to(split(",",$self->{_message}->head->get("to"))); # recipient's address
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
my $group = $self->{_toGroup};
|
||||
delete $self->{_toGroup};
|
||||
if ($group) {
|
||||
my $group = WebGUI::Group->new($self->session, $self->{_toGroup});
|
||||
$self->{_message}->head->replace("bcc", undef);
|
||||
$self->{_message}->head->replace("cc", undef);
|
||||
foreach my $userId (@{$group->getUsers(1,1)}) {
|
||||
my $user = WebGUI::User->new($self->session, $userId);
|
||||
if ($user->profileField("email")) {
|
||||
$self->{_message}->head->replace("To",$user->profileField("email"));
|
||||
unless ($self->send) {
|
||||
$status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
88
lib/WebGUI/Workflow/Activity/SendQueuedMailMessages.pm
Normal file
88
lib/WebGUI/Workflow/Activity/SendQueuedMailMessages.pm
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package WebGUI::Workflow::Activity::SendQueuedMailMessages;
|
||||
|
||||
|
||||
=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 strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::Mail::Send;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::SendQueuedMailMessages
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Sends all the messages in the mail queue.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Workflow_Activity_SendQueuedMailMessages");
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get("topicName"),
|
||||
properties=> { }
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
foreach my $id (@{WebGUI::Mail::Send->getMessageIdsInQueue($self->session)}) {
|
||||
my $message = WebGUI::Mail::Send->retrieve($self->session, $id);
|
||||
if (defined $message) {
|
||||
unless ($message->send) {
|
||||
# if the message fails to send, requeue it
|
||||
$message->queue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package WebGUI::i18n::English::Workflow_Activity_SendQueuedMailMessages;
|
||||
|
||||
our $I18N = {
|
||||
'topicName' => {
|
||||
message => q|Send Queued Mail Messages|,
|
||||
context => q|The name of this workflow activity.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
Loading…
Add table
Add a link
Reference in a new issue