DADA::Mail::MailOut
- NAME
- VERSION
- SYNOPSIS
- DESCRIPTION
- METHODS
- new
- create
- associate
- batch_lock
- unlock_batch_lock
- is_batch_locked
- create_directory
- mailout_directory_name
- create_subscriber_list
- create_total_sending_out_num
- create_counter
- create_first_accessed_file
- create_last_accessed_file
- create_batch_lock
- countsubscriber
- create_raw_message
- _integrity_check
- status
- should_be_restarted
- process_has_stalled
- process_stalled_after
- mail_fields_from_raw_message
- _poll
- reload
- counter_at
- message_for_mail_send
- clean_up
- _list_name_check
- _list_exists
- pause
- resume
- EXPORTED SUBROUTINES
- DIAGNOSTICS
- BUGS AND LIMITATIONS
- AUTHOR
- LICENSE AND COPYRIGHT
NAME
DADA::Mail::MailOut - Helps Monitor a Mass Mailings
VERSION
Refer to the version of Dada Mail that this module comes in.
SYNOPSIS
# A few subroutines, exported by default:
my @mailouts = DADA::Mail::MailOut::current_mailouts({-list => $list });
my $exists = DADA::Mail::MailOut::mailout_exists($list, $id, $type);
my $report = DADA::Mail::MailOut::monitor_mailout({--verbose => 0, --list => $list});
print $report;
# Create a new DADA::Mail::MailOut object:
my $mailout = DADA::Mail::MailOut->new({-list => $list});
# Make a new Mass Mailing:
$mailout->create(
-fields => {%fields},
-list_type => 'list',
-mh_obj => $mh_obj,
);
# how's that mailout doin'?
my $status = $mailout->status;
# Let's pause the mailing!
$mailout->pause;
# Ok, let's start it back up again, where it left off:
$mailout->resume;
# do I need to reload the mailout?
my $yes_restart = $mailout->should_be_restarted;
# if so, let's do that:
if($yes_restart){
$mailout->reload();
}
DESCRIPTION
This module does a few things, all of which happen to deal with setting up a mass mailing and then monitoring its status.
Mass Mailings do take a while and the CGI environment that Dada Mail is (usually) run in, isn't the best thing to be in during a long-running process, like mail sending to a few thousand of your closest friends.
Because of that, this module attempts to keep close track of how the mailing is doing and give an option to reload a mailing at the time it stopped. Mailings usually stop because the mailing process itself can be killed by the server itself.
The create() method does most of the magic in getting a mailing setup. When called correctly, it will make a temporary directory (usually in $TMP that holds within it the following files:
The Temporary Subscriber List
To keep the main subscriber list free for adding/editing/removing/viewing (especially with the Plaintext Backend), a temporary subscriber list is created for each mailing.
This subscriber list does not just hold the email address of a subscriber, but other meta information, like the pin associated with the subscriber, amongst other things.
See the DADA::MailingList::Subscribers::[..]::create_mass_sending_file()
https://dadamailproject.com/support/documentation-11_22_0/MailingList_Subscribers_PlainText.pm.html
method for exactly how this is made.
The Total Amount of Recipients Amount
This file simply holds the total amount of recipients of a given mailing. This will be different than the amount of subscribers on a list, as the list owner also will receive a copy of a mailout. There are also some other fringe reasons for discrepencies, which I won't go into right here.
The Amount Sent Counter
This file will be +1'd everytime an address has been sent to. Note! That this counter will be added to, regardless of whether the individual email sent was successful.
The, "First Accessed", File
This file just basically holds the time() that a mailout started.
The, "Last Accessed", File
This file will be updated with what's returned by the time() perl builtin, every time countsubscriber() is called.
This file is basically used to make sure that a mailing process is still going on. If the time saved in this file becomes too long, a mailing may become ripe for a reload().
A Copy of the Message Being Sent Out
A copy of the actual email message source is saved. The message headers can later be accessed for reporting purposes and the entire message source can be used if the message has to be reload()ed.
The, "pause button"
This is basically a file that, if present, means that the mailing should be, "paused" - mailing should be stopped until it is, "resumed". The file itself will hold the time that the mailing was put on pause.
and a few others, I haven't documented yet.
Safeguarding Duplicate Mailings
This all gets quite complicated, fast, but I'm going to highlight just one part of DADA::Mail::MailOut's job, and that is to stop a mailing self-duplicating itself, and sending out two (or more!) copies of the message, to the subscriber, which is bad news. There are a few safety measures:
The Batch Lock File
The Batch Lock File is somewhat of a semaphore file, except that it doesn't work by having Dada Mail
flock
the file, it merely works be being presentIf the Batch Lock File is present, it tells Dada Mail something is happening.
The Last Accessed File
The problem with this approach is that, the lock can get stale, so there's another file called the, "Last Access File", which gets update with the last time something happened (usually, done by DADA::Mail::Send while sending out a mass mailing)
If the Batch Lock file is present, but the Last Access File says that the last time something happened is a while ago, the Batch Lock File gets removed, thus, "unlocking" the mailing, for the mailing to be restarted.
The PID File
It's a simple system, but it's hard to break - you'd have to manually remove the Batch Lock (which, I can see someone attempting to do) and manually rewind the, "Last Accessed File", to some time in the past.
If this happens, say because of some bizarre bug in Dada Mail, a mailing will be reloaded and ther eis a chance that duplicate messages would be sent,
if not for the PID File.
The PID file holds the process that, "In Control" of the mass mailing. In Dada ::Mail::Send, when we enter the loop that goes through all the subscribers to mail out a mass, the, "Controlling PID" is set and checked, every time a subscriber is mailed to. If the Controlling PID doesn't match the process that's sending out, the process stops, as another process has taken over.
That above scenario should NEVER HAPPEN, but, if it does, there are safeguards against it.
METHODS
new
Takes one argument - the list shortname, ala:
my $mailout = DADA::Mail::MailOut->new({-list => 'listshortname'});
All there is to it.
Note! that a MailOut object is pretty useless, until you call the, create() method.
create
Used to setup, or, "create" a mailout. Makes all the temporary files and directories need. Needs a few things passed - do pay attention, since what it needs is slightly odd:
$mailout->create(
-fields => {%fields},
-list_type => 'list',
-mh_obj => $mh_obj,
);
-fields
-fields is your actual mailing list message - the fields themselves are the headers of your message. The Body of the message itself is saved in the, Body key/value.
This is a fairly odd format to have everything in, but it's sort of native to DADA::Mail::Send and that's the module most likely to be calling create().
-list_type
List Type holds which subscription sublist you're sending to. Most likely, this is going to be, list. There are times where it may be, black_list, or, invite_list, etc.
-mh_obj
-mh_obj should actually be a DADA::Mail::Send object - again, very strange thing to pass to this module, but again, create is usually called within DADA::Mail::Send, so that module basically gives a copy of itself to use.
You'll most likely never call create() yourself, but that's the jist of it.
associate
$mailout->associate($id, $type);
associate
associates an already existing mailing with the object you have on hand - similar to create, but doesn't create anything - it just allows you to work with something you already have.
It takes two arguments - both of which are required. Not passing them will cause your program to croak
.
Returns 1 on success.
batch_lock
$mailout->batch_lock;
Locks a mailout. The presence of a lock prohibits a different process from reloading a mailout that looks as if it is stopped.
You shouldn't really ever remove a batch lock (although I know this is tempting), as doing so won't explicitly make a mailing restart right away - there are a few things that come in play when it is decided a mailout should be restarted.
The batch lock itself is just a plain text file. Its contents are the unix time
of when the batch was locked.
Returns, 1 on success.
unlock_batch_lock
$mailout->unlock_batch_lock;
unlinks
(removes) a batch lock. Will return 1 on success and 0 upon failure.
There's a few reasons why this may fail:
The batch lock was never there
Unlinking the batch lock wasn't successful
is_batch_locked
$mailout->is_batch_locked
Looks and see if the batch lock is present. Returns 1 if it is, 0 if it isn't. This method does not see if the batch is stale.
create_directory
mailout_directory_name
create_subscriber_list
create_total_sending_out_num
create_counter
create_first_accessed_file
create_last_accessed_file
create_batch_lock
countsubscriber
create_raw_message
_integrity_check
status
Although you may never call create, calling status may be much more commonplace.
my $status = $mailout->status;
or even:
for(keys %{$mailout->status}){ print $_; # or... something... }
status returns a hashref of various information about your mailout. Best not to call this too many times at once, as it does query all those temporary files we've created. I'll go over what you're most likely going to use:
id
The internal id of your mailout. This will also be, "similar" to the Message-ID of your mailing, the id of your archived message, etc.
total_sending_out_num
How many messages you're supposed to be sending out.
total_sent_out
How many messages you've proported to have sent out.
last_access
The last time basically, "total_sent_out" was last accessed.
first_access
Basically the time() when we create()d the mailout.
email_fields
Itself holds a hashref of the actual message you're sending out. Good for making reports.
type
The type of message you're sending (list, black_list, invite_list, etc)
is_batch_locked
Will tell you if basically, the mailout is active and you shouldn't clobber the mail sending by calling reload(). If you do call reload() when this is set to, "1", the module will croak. So... don't.
percent_done
Just takes a percentage based on how many message you've sent out, with how many message are still left to send out, rounded to the nearest whole number. Again, good for reports, but don't use to know exactly where you are in your mailing.
process_has_stalled
Let's you know if it's been a while since something has happened - but DO NOT USE to figure out if you should call reload, use should_be_restarted instead.
should_be_restarted
Will let you know if a mailout should be reloaded. Basically you can do one of these:
my $status = $mailout->status; if($status->{should_be_restarted} == 1){ $mailout->reload(); }
should_be_restarted
process_has_stalled
process_stalled_after
mail_fields_from_raw_message
_poll
reload
counter_at
message_for_mail_send
clean_up
_list_name_check
_list_exists
pause
$mailout->pause;
Pauses a mailing. Most likely, a mailing will be paused after the current mailing batch is completed, or if the mailing has been dropped, the very next time it's attempted to be reloaded.
When called, a, "pause button" file will be created.
Returns the time() when it was called for success,
Returns undef if there was some sort of problem pausing a mailing - usually this problem will be because the mailing is already paused.
resume
$mailout->resume;
The opposite of pause. Removes the, "pause button" file, which will allow the mailout, next time it's checked, to resume mailing.
Take no arguments.
Returns 1 on success.
Return undef if there is some sort of error.
EXPORTED SUBROUTINES
A few subroutines are exported by default:
current_mailouts
my @mailouts = DADA::Mail::MailOut::current_mailouts({-list => $list});
Returns an array of hashrefs that reflect the current mailouts. It can take one parameter, a listshortname. If passed, it will only return mailouts pertaining to that particular list.
mailout_exists
my $exists = DADA::Mail::MailOut::mailout_exists($list, $id, $type);
Returns 1 if a mailout exists, 0 if it doesn't. The three parameters are required.
monitor_mailout
When called, monitor_mailout() will check up on all your mailouts and, if needed, will restart any mailouts that need to be reloaded.
Returns a string that contains a report of the activity of all the mailouts.
This subroutine can take a few options, like so:
my $report = monitor_mailout({ -list => $list, -verbose => 0});
If you pass a listshortname in the, -list parameter, only that specific list's mailouts will be checked.
If you set the, -verbose parameter to a true value, the subroutine will print the report, as well as pass the report as its return value.
DIAGNOSTICS
BUGS AND LIMITATIONS
Please report problems to the author of this module
AUTHOR
Justin Simoni
See: https://dadamailproject.com/contact
LICENSE AND COPYRIGHT
Copyright (c) 2006 - 2021 Justin Simoni All rights reserved.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.