DADA::MailingList::Subscribers

- NAME
- SYNOPSIS
- DESCRIPTION

- Subscription List Model

- A subscriber is mostly identified by their email address
- The Subscription List is made up of Sublists.
- A Subscription List can have Subscriber Fields
- Restrictions are enforced by Dada Mail to only allow correct information to be saved in the Subscription List
- The Subscription List has various backend options

- Public Methods

- Initializing
- new
- Add/Get/Edit/Move/Copy/Remove a Subscriber
- add_subscriber

- Diagnostics

- get_subscriber

- Diagnostics

- edit_subscriber

- Diagnostics

- move_subscriber

- Diagnostics

- copy_subscriber

- Diagnostics

- remove_subscriber

- Diagnostics

- Validating a Subscriber
- allowed_list_types
- check_for_double_email
- subscription_check
- subscription_check_xml
- unsubscription_check
- Add/Get/Edit/Remove a Subscription Field
- filter_subscribers
- filter_subscribers_w_meta
- add_subscriber_field

- Diagnostics

- subscriber_fields

- Diagnostics

- edit_subscriber_field

- Diagnostics

- remove_subscriber_field

- Diagnostics

- subscriber_field_exists

- Diagnostics

- validate_subscriber_field_name

- Subscriber Validation Requirements

- validate_remove_subscriber_field_name
- get_fallback_field_values
- _save_fallback_value

- Diagnostics

- _remove_fallback_value

- Diagnostics

- AUTHOR
- LICENCE AND COPYRIGHT

# NAME

DADA::MailingList::Subscribers API for the Dada Mailing Lists

# SYNOPSIS

     # Import
     use Dada::MailingList::Subscribers;

     # Create a new object
     my $lh = DADA::MailingList::Subscribers->new({-list => 'mylist'});

     # Check if this can be a valid subscription:

     my ($status, $errors) = $lh->subscription_check(
            {
                    -email => 'user@example.com',
            }
     );

     # How about to unsubscribe:

     my ($status, $errors) = $lh->unsubscription_check(
            {
                    -email => 'user@example.com',
            }
      );

     # Add
     $lh->add_subscriber(
            {
                    -email => 'user@example.com',
                    -type  => 'list',
            }
     );

     # Move
     $lh->move_subscriber(
            {
                    -email => 'user@example.com',
                    -from  => 'list',
                    -to    => 'black_list',
            }
      );

     # Copy
     $lh->copy_subscriber(
            {
                    -email => 'user@example.com',
                    -from  => 'black_list',
                    -to    => 'list',
            }
      );

     # Remove
     $lh->remove_subscriber(
            {
                    -email => 'user@example.com',
                    -type  => 'list',
            }
      );

# DESCRIPTION

This module represents the API for Dada Mail's subscriptions lists.

## Subscription List Model

Dada Mail's Subscription List system is currently fairly simple:

### A subscriber is mostly identified by their email address

Usually, when we talk of a, ``Subscriber'', we're talking about a email address that has been included in a Dada Mail Subscription List.

### The Subscription List is made up of Sublists.

A sublist is a list of subscribers. Each sublist is completely separated from each other sublist.

Each sublist is known because of its type.

The types of sublists are as follows:

- list

  This is your main subscription list and is the most important type of sublist. It holds a Mailing List's subscribers. When a mailing list message is sent out, this is the list whose addresses are used.

- black_list

  This is the sublist of addresses that are not allowed to join the sublist, list

  The addresses in this sublist do not have to be fully qualified email addresses, but can be simple strings, which are then used to match on other addresses, for verification.

- white_list

  This is the sublist of addresses that are allowed to join the sublist, list

  The addresses in this sublist do not have to be fully qualified email addresses, but can be simple strings, which are then used to match on other addresses, for verification.

- authorized_senders

  This is the sublist of addresses that can be allowed to post to a mailing list, from an email client, via the Dada Bridge plugin, if this feature has been enabled.

- sub_confirm_list

  This is the sublist that keeps subscription information on potential subscribers, when they've asked to join a list, but have not yet been verified via an email confirmation to subscribe.

- unsub_confirm_list

  This is the sublist that keeps unsubscription information on potential unsubscribers, when they've asked to leave a list, but have not yet been verified via an email confirmation to unsubscribe.

- invitelist

  This is a sublist of temporary subscribers, who've been invited to join a mailing list. It's only used internally and is removed shortly after sending out a list invitation has begun.

### A Subscription List can have Subscriber Fields

The Subscriber Fields are information that's separate than the email address of a subscriber. Their values are arbitrary and can be set to most anything you'd like.

Internally, the subscriber fields are mapped almost exactly to SQL columns - adding a subscriber field will add a column in an SQL table. Removing a field will remove a column.

### Restrictions are enforced by Dada Mail to only allow correct information to be saved in the Subscription List

The most obvious enforcement is that the subscriber has to have a valid email address.

Another enforcement is that a subscriber cannot be subscribed to a sublist twice.

A subscriber can be on more than one sublist at the same time.

Some sublists are used to enforce subscription on other sublists. For example, a subscriber in the black_list sublist will not be allowed to joing the, list sublist.

These enforcements are currently lazy - You can easily break these rules, but you don't want to, and checking the validation of a subscriber is easy. The easiest way to break these rules is to work with the backend that the subscribers are saved in directly.

### The Subscription List has various backend options

The Subscription List can either be saved as a series of PlainText files (one file for each type of sublist), or as an SQL table.

Each type of backend has different features that are available. The most notable feature is that the SQL backend supports arbitrary Subscriber Fields and the PlainText backend does not.

Currently, the following SQL flavors are supported:

- MySQL
- PostgreSQL
- SQLite

Except for being able to change the name of a Subscriber Field in SQLite, every SQL flavor has the same feature set.

# Public Methods

Below are the list of Public methods that we recommend using when manipulating a Dada Mail Subscription List:

Every method has its paramaters, if required (and when it's stated that they're required, they are), passed as a hashref.

## Initializing

## new

     my $lh = DADA::MailingList::Subscribers->new({-list => 'mylist'});

`new` requires you to pass a listshortname in, `-list`. If you don't, your script will die.

A `DADA::MailingList::Subscribers` object will be returned.

## Add/Get/Edit/Move/Copy/Remove a Subscriber

## add_subscriber

     $lh->add_subscriber(
            {
                    -email  => 'user@example.com',
                    -type   => 'list',
                    -fields => {
                                            # ...
                                       },
            }
    );

`add_subscriber` adds a subscriber to a sublist.

`-email` is required and should hold a valid email address in form of: `user@example.com`

`-type` holds the sublist you want to subscribe the address to, if no sublist is passed, list is used as a default.

`-fields` holds the subscription fields you'd like associated with the subscription, passed as a hashref.

For example, if you have two fields, first_name and, last_name, you would pass the subscriber fields like this:

     $lh->add_subscriber(
            {
                    -email  => 'user@example.com',
                    -type   => 'list',
                    -fields => {
                                            first_name => "John",
                                            last_name  => "Doe",
                                       },
            }
     );

Passing field values is optional.

Fields that are not actual fields that are being passed will be ignored.

### Diagnostics

- You must pass an email in the -email paramater!

  You forgot to pass an email in the, -email paramater, ie:

       # DON'T do this:
       $lh->add_subscriber();

- cannot do statement (at add_subscriber)!

  Something went wrong in the SQL side of things.

## get_subscriber

     my $sub_info = $lh->get_subscriber(
                    {
                            -email => 'user@example.com',
                            -type  => 'list',
                    }
            );

Returns the subscriber fields information in the form of a hashref.

`-email` is required and should hold a valid email address in form of: `user@example.com`. The address should also be subscribed and no check is done if the address you passed isn't.

`-type` holds the sublist you want to work with. If no sublist is passed, list is used as a default.

### Diagnostics

- You must pass an email in the -email paramater!

  You forgot to pass an email in the, -email paramater, ie:

       # DON'T do this:
       $lh->get_subscriber();

- cannot do statement (at get_subscriber)!

  Something went wrong in the SQL side of things.

## edit_subscriber

     $lh->edit_subscriber(
            {
                    -email  => 'user@example.com',
                    -type   => 'list',
                    -fields =>
                            {
                                    # ...
                            },
                    -method => 'writeover',
            }
     );

returns `1` on success.

Internally, this method removes a subscriber and adds the same subscriber again to the same list.

`-email` is required and should hold a valid email address in form of: `user@example.com`

`-type` holds the sublist you want to subscribe the address to, if no sublist is passed, list is used as a default.

`-fields` holds the subscription fields you'd like associated with the subscription, passed as a hashref.

For example, if you have two fields, first_name and, last_name, you would pass the subscriber fields like this:

     $lh->edit_subscriber(
            {
                    -email  => 'user@example.com',
                    -type   => 'list',
                    -fields => {
                                            first_name => "Jon",
                                            last_name  => "Doh",
                                       },
            }
     );

Passing field values is optional, although you probably would want to, as this is the point of the entire method.

Fields that are not actual fields that are being passed will be ignored.

`-method` holds the type of editing you want to do. Currently, this can be either, `update`, or, `writeover`.

`update` will only save the fields you pass - any other fields saved for this subscriber will not be erased.

`writeover` will save only the fields you pass - any other fields will be removed from the subscriber.

If no `-method` is passed, update is used as a default.

### Diagnostics

Internally, the subscriber is first removed, than added, using the `add_subscriber` and, `remove_subscriber` methods. Those diagnostics may pop up, if you use this method incorrectly

- The -mode paramater must be set to, 'update', 'writeover' or left undefined!

  You didn't set the -mode paramater correctly.

## move_subscriber

     $lh->move_subscriber(
            {
                    -email => 'user@example.com',
                    -from  => 'list',
                    -to    => 'black_list',
            }
     );

`-email` holds the email address of the subscriber you want to move.

`-from` holds the sublist you're moving from.

`-to` holds the sublist you're moving to.

All paramaters are required. No other paramaters will be honored.

This method will `die` if the subscriber isn't actually subscribed to the sublist set in, `-from` or, is already subscribed in the sublist set in, `-to`.

### Diagnostics

- email passed in, -email is not subscribed to list passed in, '-from'

  The subscriber isn't actually subscribed to the sublist set in, `-from`

- email passed in, -email ( ) is already subscribed to list passed in, '-to'

  The Subscriber is already subscribed in the sublist set in, `-to`.

- list_type passed in, -to is not valid
- list_type passed in, -from is not valid
- email passed in, -email is not valid
- cannot do statement (at move_subscriber)!

  Something went wrong in the SQL side of things.

## copy_subscriber

     $lh->copy_subscriber(
            {
                    -email => 'user@example.com',
                    -from  => 'list',
                    -to    => 'black_list',
            }
     );

`-email` holds the email address of the subscriber you want to copy.

`-from` holds the sublist you're copying from.

`-to` holds the sublist you're copying to.

All paramaters are required. No other paramaters will be honored.

This method will `die` if the subscriber isn't actually subscribed to the sublist set in, `-from` or, is already subscribed in the sublist set in, `-to`.

### Diagnostics

- email passed in, -email is not subscribed to list passed in, '-from'

  The subscriber isn't actually subscribed to the sublist set in, `-from`

- email passed in, -email ( ) is already subscribed to list passed in, '-to'

  The Subscriber is already subscribed in the sublist set in, `-to`.

- list_type passed in, -to is not valid
- list_type passed in, -from is not valid
- email passed in, -email is not valid
- cannot do statement (at move_subscriber)!

  Something went wrong in the SQL side of things.

## remove_subscriber

     $lh->remove_subscriber(
            {
                    -email => 'user@example.com',
                    -type  => 'list',
            }
     );

`remove_subscriber` removes a subscriber from a sublist.

`-email` is required and should hold a valid email address in form of: `user@example.com`

`-type` holds the sublist you want to subscribe the address to, if no sublist is passed, list is used as a default.

No other paramaters are honored.

### Diagnostics

- You must pass an email in the -email paramater!

  You forgot to pass an email in the, -email paramater, ie:

       # DON'T do this:
       $lh->remove_subscriber();

## Validating a Subscriber

## allowed_list_types

     my $list_types = $lh->allowed_list_types

Returns a hashref of the allowed sublist types. The keys are the actual sublist types, the value is simply set to, `1`, for easy lookup tabling.

Takes no paramaters.

The current list of allowed sublist types are:

- list
- black_list
- authorized_senders
- testers
- white_list
- sub_confirm_list
- unsub_confirm_list
- invitelist

## check_for_double_email

Note! The naming, coding and paramater style is somewhat old and crufty and this method is on the chopping block for a re-write

     my $is_subscribed = $lh->check_for_double_email(
            -Email          => 'user@example.com,
            -Type           => 'list',
            -Match_Type     => 'sublist_centric',
            );

Returns 1 if the email address passed in, `-Email` is subscribed to the sublist passed in, `-Type`.

`-Email` should hold a string that usually is an email address, although can be only a part of an email address.

`-Type` should hold a valid sublist name.

`-Type` will default to, `list` if no `-Type` is passed.

`-Status`

`-Match_Type` controls the behavior of how a email address is looked for and is usualy something you want to override for the, `black_list` and `white_list` sublists.

The sublists have different matching behaviors. For example, if, `bad` is subscribed to the `black_list` sublist, this will return `1`

     my $is_subscribed = $lh->check_for_double_email(
            -Email          => 'bad@example.com,
            -Type           => 'list',
            -Match_Type     => 'sublist_centric',
            );

Since the black list is not simply a list of addresses that are black listed, it's a list of patterns that are black listed.

`-Match_Type` can also be set to, `exact`, in which case, this would return, `0`

     my $is_subscribed = $lh->check_for_double_email(
            -Email          => 'bad@example.com,
            -Type           => 'list',
            -Match_Type     => 'exact',
            );

`-Match_Type` will default to, `sublist_centric` id no `-Math_Type` is passed.

## subscription_check

            my ($status, $errors) =  $lh->subscription_check(
                    {
                            -email => 'user@example.com',
                            -type  => 'list'
                            -skip  => []
                    }
            );

`-email` holds the address you'd like to validate. It is required.

`-type` holds the sublist you want to work on. If not passed, `list` will be used as the default.

`-skip` holds an arrary ref of checks you'd like not to have done. The checks are named the same as the errors.

For example:

     my ($status, $errors) = $lh->subscription_check(
                                                                    {
                                    -email => 'user@example.com',
                                                    -skip => [qw(black_listed closed_list)],
                                    }
                                                            );

This method returns an array with two elements.

The first element is the status of the validation. 1 will be set if the validation was successful, 0 if there was an error.

The second element is a list of the errors that were found when validating, in the form of a hashref, with its name as the name of the error and the value set to, 1 if that error was found.

The errors, which are fairly self-explainitory are as follows:

- invalid_email
- subscribed
- closed_list
- mx_lookup_failed
- black_listed
- not_white_listed
- over_subscription_quota
- already_sent_sub_confirmation
- settings_possibly_corrupted
- no_list

Unless you have a special case, always use this method to validate an email subscription.

## subscription_check_xml

            my ($xml, $status, $errors) =  $lh->subscription_check_xml({-email => $email});

Same as subscription_check but also returns an simplified XML-esque document describing the same thing.This was initially used to talk to Adobe Flash Apps. It hasn't been updated in a while.

The XML-esque doc is as so:

     <subscription>
      <email>some@where.com</email>
      <status>1</status>
      <errors>
       <error>no_list</error>
      </errors>
     </subscription>

## unsubscription_check

     my ($status, $errors) =  $lh->unsubscription_check(
                                                                    {
                                                                            -email => 'user@example.com',
                                                                            -type  => 'list',
                                                                            -skip  => [],

                                                                    }
                                                       );

Like the subscription_check method, this method returns a $status and a hashref of $%errors when checking the validity of an unsubscription. The following errors may be returned:

- no_list
- invalid_email
- not_subscribed
- settings_possibly_corrupted
- already_sent_unsub_confirmation

Again, any of these tests can be skipped using the -skp argument.

## Add/Get/Edit/Remove a Subscription Field

As noted, Subscriber Fields are only available in the SQL backends.

It should be also noted that future revisions of Dada Mail may see these types of methods in their own object, ie:

`DADA::MailingList::Subscribers::Fields`

or, whatever.

## filter_subscribers

     my (
            $subscribed,
            $not_subscribed,
            $black_listed,
            $not_white_listed,
            $invalid
            ) = $lh->filter_subscribers(
                    {
                            -emails => [],
                            -type   => 'list',
                    }
            );

This is a very powerful and complex method. There's dragons in the code, but the API is pretty simple.

Used to validated a large amount of addresses at one time. Similar to `subscripton_check` but is meant for more than one address. It's also meant to be bit faster than looping a list of addresses through `subscripton_check`.

Accepts two paramaters.

`-email` is an array ref of email addresses .

`-type` is the sublist we want to validate undef.

Depending on the type of sublist we're working on, validation works slightly different.

Returns a 5 element array, each element contains an array ref of email addresses.

This method also sets the precendence of black listed and white listed addresses, since an address can be a member of both sublists.

The precendence is the same as what's returned:

- black_list
- white_list
- invalid

In other words, if someone is both black listed and white listed, during validation, it'll be returned that they're black listed.

## filter_subscribers_w_meta

my (
| $subscribed,
| $not_subscribed,
| $black_listed,
| $not_white_listed,
| $invalid
| ) = $lh->filter_subscribers(
| {
| -emails => [],
| -type => 'list',
| }
| );

Similar to `filter_subscribers`, but allows you to pass the subscriber field information with the email address.

The, `-email` paramater should hold an arrayref of hashrefs, instead of just an array ref. The hashref itself should have the form of:

     {
            -email => 'user@example.com',
            -fields => {
                    -field1 => 'blah',
                    -field2 => 'blahblah',
            }
     }

No validation is done on the subscriber fields - they're simply passed through and returned.

Returns a 5 element array of hashrefs, in the same format as what's passed.

## add_subscriber_field

     $lh->add_subscriber_field(
            -field          => 'myfield',
            -fallback_value => 'My Fallback Value',
     );

`add_subscriber_field` adds a new subscriber field.

`-field` Should hold the name of the subscriber field you'd like to add. It is required.

`-fallback_value` holds what's known as the, fallback value, which is a value used in some instances of Dada Mail, if no value is saved in this field for a particular subscriber. It is optional.

### Diagnostics

- You must pass a value in the -field paramater!

  You forget to name your new field.

- Something's wrong with the field name you're trying to pass (yourfieldname). Validate the field name before attempting to add the field with, 'validate_subscriber_field_name' You forgot to validate the field name you passed in, `-field`.

  This will only be a warning and won't be fatal.

  This error should actually be followed by more warnings, looking like this:

  `Field Error:`

  Which will tell you exactly which test you failed.

- cannot do statement (at add_subscriber_field)!

  Something went wrong in the SQL side of things.

## subscriber_fields

     my $fields = $lh->subscriber_fields;

     # or:

     foreach(@{$lh->subscriber_fields}){
      # ...
     }

Returns the subscriber fields in the Subscription List, in the form of an array ref.

Takes no arguments... usually.

Internally (and privately), it does accept the, `-dotted` paramater. This will prepend, 'subscriber.' to every field name.

### Diagnostics

None that I can think of.

## edit_subscriber_field

     $lh->edit_subscriber_field(
            {
                    -old_name => 'old',
                    -new_name => 'new',

            }
     );

Changes the name of a Subscriber Field.

Returns 1 on success.

`-old_name` holds the name of the field you want to rename.

`-new_name` holds what you'd like to rename the field in `-old_name` to.

Both paramaters are required.

### Diagnostics

- You MUST supply the old field name in the -old_name paramater!

  You forgot to pass the old field name.

- You MUST supply the new field name in the -new_name paramater!

  You forgot to pass the new field name.

## remove_subscriber_field

     $lh->remove_subscriber_field(
            {
                    -field => 'myfield',
            },
     );

Removes the field specified in, `-field`. `-field` is required.

Returns `1` upon success.

### Diagnostics

- You MUST pass a field name in, -field!

  You forgot to set, `-field`

- cannot do statement! (at: remove_subscriber_field)

  Something went wrong on the SQL side of things.

## subscriber_field_exists

     my $exists = $lh->subscriber_field_exists(
            {
                    -field => 'myfield',
            }
     );

Checks the existance of a subscriber field name.

### Diagnostics

- You MUST pass a field name in, -field!

  You forgot to set, `-field`

- cannot do statement! (at: remove_subscriber_field)

  Something went wrong on the SQL side of things.

## validate_subscriber_field_name

     my ($status, $errors) = $lh->validate_subscriber_field_name(
                                                            {
                                                                    -field => $field,
                                                                    -skip  => [],
                                                            }
                                                    );

Used to validate a subscriber field name and meant to be used before a subscriber field is added.

Returns a two element array,

The first element is either `1` or `0` and is the status of the validation. A status of, 1 means the validation was successful; 0 means the validation had problems.

The second element is a list of the errors that were found when validating, in the form of a hashref, with the name of the error set as the key and the value set to, 1 if this error was found.

`-field` is required and should be the name of the field you're attempting to validate.

`-skip` is an optional paramater and is used to list the errors you're not so interested in. It should be set to an array ref.

### Subscriber Validation Requirements

Subscriber fields are validated mostly to make sure they're also valid SQL column names for all the SQL backends that are supported and also that the fields are not already used for internal SQL fields used by the program for other purposes. Validation is also done sparingly for reserved words.

The entire list of erros that can be reported back are as follows:

- field_blank
- field_name_too_long

  length of 64

- slashes_in_field_name

  `/` or, `\`

- spaces
- weird_characters

  Basically anything that's not alpha/numeric

- quotes

  `'` and, `"`

- field_exists
- field_is_special_field

  The field name is one of the following:

  - email_id
  - email
  - list
  - list_type
  - list_status
  - email_name
  - email_domain

## validate_remove_subscriber_field_name

     my ($status, $errors) = $lh->validate_remove_subscriber_field_name(
                                                            {
                                                                    -field      => $field,
                                                                    -skip       => [],
                                                                    -die_for_me => 0,
                                                            }
                                                    );

Similar to, `validate_subscriber_field_name` is used to validate a subscriber field name and is meant to be used before a subscriber field is removed.

Returns a two element array,

The first element is either `1` or `0` and is the status of the validation. A status of, 1 means the validation was successful; 0 means the validation had problems.

The second element is a list of the errors that were found when validating, in the form of a hashref, with the name of the error set as the key and the value set to, 1 if this error was found.

`-field` is required and should be the name of the field you're attempting to validate.

`-skip` is an optional paramater and is used to list the errors you're not so interested in. It should be set to an array ref.

`-die_for_me` is another optional paramater. If set to, `1`, an error found in validation will prove fatal.

The entire list of errors that can be reported back are as follows:

- field_is_special_field

  The field name is one of the following:

  - email_id
  - email
  - list
  - list_type
  - list_status
  - email_name
  - email_domain
- field_exists
- number_of_fields_limit_reached

## get_fallback_field_values

     my $field_values = $lh->get_fallback_field_values;

Returns the name of every subscriber field and its fallback value in the form of a hashref.

The fallback values are actually saved in the List Settings.

Take no arguments.

## _save_fallback_value

     $lh->_save_fallback_value(
                    {
                            -field          => $field,
                            -fallback_value => $fallback_field_value,
                    }
     );

Currently marked as a private method.

Used to save a new fallback field value for the field set in, `-field`. usually shouldn't be used alone, but there is actually no way to edit a fallback field value, without using this method.

If used on an existing field, make sure to remove the fallback field value first, using, `_remove_fallback_value`, ala:

     $lh->_remove_fallback_value({-field => 'myfield'});
     $lh->_save_fallback_value({-field => 'myfield'}, -fallback_value => 'new_value');

    Is called internally, when creating a new field via, C<add_subscriber_field>, so make sure not to call it twice.

### Diagnostics

- You MUST pass a value in the -field paramater!

## _remove_fallback_value

     $lh->_remove_fallback_value(
                    {
                            -field => 'myfield',
                    }
     );

Currently marked as a private method.

Used to remove a fallback field value. Used internally.

### Diagnostics

- You MUST pass a value in the -field paramater!

# AUTHOR

Justin Simoni http://mojo.skazat.com

# LICENCE AND COPYRIGHT

Copyright (c) 1999-2008 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.