Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'bugfixes-5_0_4' into 5_1_0-alpha1

  • Loading branch information...
commit 280b2ac1e4c5e8e295af9969a7a221642b177055 2 parents 388671b + 69eb7b7
@justingit authored
View
138 dada/DADA/App/BounceHandler/MessageParser.pm
@@ -75,6 +75,14 @@ sub run_all_parses {
%{$diagnostics} = ( %{$diagnostics}, %{$ses_diagnostics} )
if $ses_diagnostics;
}
+ elsif($self->isa_rfc6522_bounce($entity)) {
+ my ( $rfc6522_list, $rfc6522_email, $rfc6522_diagnostics ) =
+ $self->parse_for_rfc6522($entity);
+ $list ||= $rfc6522_list;
+ $email ||= $rfc6522_email;
+ %{$diagnostics} = ( %{$diagnostics}, %{$rfc6522_diagnostics} )
+ if $rfc6522_diagnostics;
+ }
elsif($self->bounce_from_secureserver_dot_net($entity)){
my ( $ss_list, $ss_email, $ss_diagnostics ) =
$self->parse_for_secureserver_dot_net($entity);
@@ -186,6 +194,7 @@ sub run_all_parses {
# This is a special case - since this outside module adds pseudo diagonistic
# reports, we'll say, add them if they're NOT already there:
+
my ( $bp_list, $bp_email, $bp_diagnostics ) =
$self->parse_using_m_ds_bp($entity);
@@ -197,6 +206,8 @@ sub run_all_parses {
%{$diagnostics} = ( %{$diagnostics}, %{$bp_diagnostics} )
if $bp_diagnostics;
+
+
chomp($email) if $email;
#small hack, turns, %2 into, '-'
@@ -330,12 +341,28 @@ sub find_list_in_list_headers {
my $entity = shift;
my @parts = $entity->parts;
my $list;
+ my $orig_msg_copy = undef;
- if ( $entity->head->mime_type eq 'message/rfc822' ) {
- my $orig_msg_copy = $parts[0];
- $list = $self->list_in_list_headers($orig_msg_copy);
-
+ if ( $entity->head->mime_type eq 'message/rfc822') {
+ $orig_msg_copy = $parts[0];
+ $list = $self->list_in_list_headers($orig_msg_copy);
}
+ elsif($entity->head->mime_type eq 'text/rfc822-headers'){
+
+ require MIME::Parser;
+ my $parser = new MIME::Parser;
+ $parser = optimize_mime_parser($parser);
+
+ eval {
+ $orig_msg_copy = $parser->parse_data( $entity->bodyhandle->as_string );
+ };
+ if ($@) {
+ warn "Trouble parsing text/rfc822-headers message. $@";
+ }
+ else {
+ }
+ $list = $self->list_in_list_headers($orig_msg_copy);
+ }
else {
my $i;
for $i ( 0 .. $#parts ) {
@@ -350,11 +377,14 @@ sub find_list_in_list_headers {
sub list_in_list_headers {
my $self = shift;
my $entity = shift;
- my $list = undef;
-
- my $list_header = $entity->head->get( 'List', 0 );
- $list = $list_header if $list_header !~ /\:/;
-
+ my $list = undef;
+ my $list_header = $entity->head->get( 'List', 0 ) || undef;
+ if(defined($list_header)){
+ if($list_header !~ /\:/) {
+ $list = $list_header;
+ }
+ }
+
if ( !$list ) {
$list_header = $entity->head->get( 'X-List', 0 );
$list = $list_header if $list_header !~ /\:/;
@@ -382,12 +412,28 @@ sub find_message_id_in_headers {
my $entity = shift;
my @parts = $entity->parts;
my $mid;
- if ( $entity->head->mime_type eq 'message/rfc822' ) {
- my $orig_msg_copy = $parts[0];
-
+ if ( $entity->head->mime_type eq 'message/rfc822' || $entity->head->mime_type eq 'text/rfc822-headers') {
+ my $orig_msg_copy = '';
+
+ if($entity->head->mime_type eq 'text/rfc822-headers') {
+
+ require MIME::Parser;
+ my $parser = new MIME::Parser;
+ $parser = optimize_mime_parser($parser);
+
+ eval { $orig_msg_copy = $parser->parse_data($entity->bodyhandle->as_string) };
+ if ( $@ ) {
+ warn "Trouble parsing text/rfc822-headers message. $@";
+ }
+ else {
+ }
+ }
+ else {
+ $orig_msg_copy = $parts[0];
+ }
+
# Amazon SES finds this in the, "X-Message-ID" header:
# Amazon SES will also set its own Message-ID. Maddening!
-
if($orig_msg_copy->head->get( 'X-Message-ID', 0 )){
$mid = $orig_msg_copy->head->get( 'X-Message-ID', 0 );
}
@@ -476,10 +522,17 @@ sub generic_delivery_status_parse {
$diag->{Guessed_MTA} = 'Postfix';
}
- my ( $rfc, $remail ) = split( ';', $diag->{'Final-Recipient'} );
- if ( $remail eq '<>' ) { #example: Final-Recipient: LOCAL;<>
- ( $rfc, $remail ) = split( ';', $diag->{'Original-Recipient'} );
- }
+ my $rfc = undef;
+ my $remail = undef;
+ if(exists($diag->{'Original-Recipient'})){
+ ( $rfc, $remail ) = split( ';', $diag->{'Original-Recipient'} );
+ }
+ elsif(exists($diag->{'Final-Recipient'})){
+ ( $rfc, $remail ) = split( ';', $diag->{'Final-Recipient'} );
+ if ( $remail eq '<>' ) { #example: Final-Recipient: LOCAL;<>
+ $remail = undef;
+ }
+ }
$email = $remail;
for ( keys %$diag ) {
@@ -575,6 +628,23 @@ sub bounce_from_ses {
}
}
+sub isa_rfc6522_bounce {
+ my $self = shift;
+ my $entity = shift;
+# print '$entity->effective_type ' . $entity->effective_type . "\n";
+# print '$entity->head->mime_attr(\'content-type.report-type\'); ' . $entity->head->mime_attr('content-type.report-type') . "\n";
+
+ if ( $entity->effective_type eq 'multipart/report'
+ && $entity->head->mime_attr('content-type.report-type') eq 'delivery-status' )
+ {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
sub bounce_from_secureserver_dot_net {
my $self = shift;
my $entity = shift;
@@ -592,9 +662,16 @@ sub bounce_from_secureserver_dot_net {
+sub parse_for_amazon_ses {
+ my $self = shift;
+ my $entity = shift;
+ my ( $list, $email, $diag ) = $self->parse_for_rfc6522($entity);
+ $diag->{Guessed_MTA} = 'Amazon_SES';
+ return ( $list, $email, $diag );
+}
-sub parse_for_amazon_ses {
+sub parse_for_rfc6522 {
my $self = shift;
my $entity = shift;
@@ -604,6 +681,12 @@ sub parse_for_amazon_ses {
my $list;
my @parts = $entity->parts;
+
+ # Human readable
+ my $notification = '';
+ if($parts[0]){
+ $notification = $self->generic_human_readable_parse($parts[0]);
+ }
if($parts[1]){
my $mds_entity = $parts[1];
@@ -613,20 +696,27 @@ sub parse_for_amazon_ses {
}
if($parts[2]){
my $orig_msg_entity = $parts[2];
- if ( $orig_msg_entity->head->mime_type eq 'message/rfc822' ) {
+ if ( $orig_msg_entity->head->mime_type eq 'message/rfc822'
+ || $orig_msg_entity->head->mime_type eq 'text/rfc822-headers'
+ ) {
$list = $self->find_list_in_list_headers($orig_msg_entity);
$diag->{'Message-Id'} = $self->find_message_id_in_headers($orig_msg_entity);
}
}
-
-
- $diag->{Guessed_MTA} = 'Amazon_SES';
+ $diag->{'Notification'} = $notification;
return ( $list, $email, $diag );
-
-
+
}
+sub generic_human_readable_parse {
+ my $self = shift;
+ my $entity = shift;
+
+ return $entity->bodyhandle->as_string;
+
+}
+
sub parse_for_secureserver_dot_net {
View
45 dada/DADA/App/BounceHandler/Rules.pm
@@ -94,17 +94,20 @@ sub find_rule_to_use {
MESSAGEFIELD:
for my $pos_match ( @{ $message_fields->{$m_field} } ) {
if ( $is_regex == 1 ) {
- if ( $diagnostics->{$real_field} =~ m/$pos_match/ ) {
- $ThingsToMatch{$m_field} = 1;
- next MESSAGEFIELD;
- }
+ if(exists($diagnostics->{$real_field})){
+ if ( $diagnostics->{$real_field} =~ m/$pos_match/ ) {
+ $ThingsToMatch{$m_field} = 1;
+ next MESSAGEFIELD;
+ }
+ }
}
else {
-
- if ( $diagnostics->{$real_field} eq $pos_match ) {
- $ThingsToMatch{$m_field} = 1;
- next MESSAGEFIELD;
- }
+ if(exists($diagnostics->{$real_field})){
+ if ( $diagnostics->{$real_field} eq $pos_match ) {
+ $ThingsToMatch{$m_field} = 1;
+ next MESSAGEFIELD;
+ }
+ }
}
}
@@ -929,6 +932,30 @@ qr/SMTP\; 550|550 MAILBOX NOT FOUND|550 5\.1\.1 unknown or illegal alias|User un
}
},
+
+ {
+ bounce_4dot4dot1_error => {
+ Examine => {
+ Message_Fields => {
+ Status => [qw(4.4.1)],
+ Action => [qw(failed)],
+ 'Diagnostic-Code_regex' => [ (qr/(C|c)onnection refused/) ],
+ },
+ Data => {
+ Email => 'is_valid',
+ List => 'is_valid',
+ }
+ },
+ Action => {
+
+ #unsubscribe_bounced_email => 'from_list',
+ add_to_score => 'hardbounce_score',
+ },
+ }
+ },
+
+
+
{
permanent_move_failure => {
Examine => {
View
12 dada/DADA/App/FormatMessages.pm
@@ -597,9 +597,15 @@ sub _add_opener_image {
my $self = shift;
my $content = shift;
- my $img_opener_code = '<!--open_img--><img src="' . $DADA::Config::PROGRAM_URL . '/spacer_image/<!-- tmpl_var list_settings.list -->/<!-- tmpl_var message_id -->/spacer.png" width="1" height="1" /><!--/open_img-->';
- #</body>
- $content =~ s/(\<\/body(.*?)\>)/$img_opener_code\n$1/i;
+ my $img_opener_code = '<!--open_img--><img src="<!-- tmpl_var PROGRAM_URL -->/spacer_image/<!-- tmpl_var list_settings.list -->/<!-- tmpl_var message_id -->/spacer.png" width="1" height="1" /><!--/open_img-->';
+
+ if($content =~ m/\<\/body(.*?)\>/i){
+ #</body>
+ $content =~ s/(\<\/body(.*?)\>)/$img_opener_code\n$1/i;
+ }else {
+ # No end body tag?!
+ $content .= "\n" . $img_opener_code
+ }
return $content;
}
View
15 dada/DADA/App/Guts.pm
@@ -84,7 +84,7 @@ require Exporter;
uriescape
lc_email
make_safer
- convert_to_html_entities
+ encode_html_entities
webify_plain_text
check_list_setup
make_all_list_files
@@ -1438,14 +1438,15 @@ sub make_safer {
}
}
-sub convert_to_html_entities {
+sub encode_html_entities {
- my $s = shift;
+ my $s = shift;
+ my $unsafe_chars = shift || undef;
eval {require HTML::Entities};
if(!$@){
- $s = HTML::Entities::encode_entities($s, "\200-\377" ); #, "\200-\377"
+ $s = HTML::Entities::encode_entities($s, $unsafe_chars ); #, "\200-\377"
}else{
# require HTML::EntitiesPurePerl
@@ -1453,7 +1454,7 @@ sub convert_to_html_entities {
eval {require HTML::EntitiesPurePerl};
if(!$@){
- $s = HTML::EntitiesPurePerl::encode_entities($s, "\200-\377" ); #", \200-\377"
+ $s = HTML::EntitiesPurePerl::encode_entities($s, $unsafe_chars); #", \200-\377"
}
}
# These are done by the above (if there's no argument in, encode_entities - right?
@@ -1487,7 +1488,7 @@ sub webify_plain_text {
# so, I use the below for Text Versions of HTML messages
require HTML::FromText;
- $args->{-str} = convert_to_html_entities($args->{-str});
+ $args->{-str} = encode_html_entities($args->{-str}, "\200-\377");
$r = HTML::FromText::text2html($args->{-str},
metachars => 1,
urls => 1,
@@ -1507,7 +1508,7 @@ sub webify_plain_text {
$multi_line = 1;
}
- $args->{-str} = convert_to_html_entities($args->{-str});
+ $args->{-str} = encode_html_entities($args->{-str}, "\200-\377");
require HTML::TextToHTML;
my $conv = HTML::TextToHTML->new;
View
188 dada/DADA/MailingList/Archives.pm
@@ -479,7 +479,9 @@ at the bottom of each archive index
=cut
-# This should be template'd out
+# This looks like it creates navigation for lists of archives, rather than for individual archives...
+# One day, this should be replaced with Data::Pageset
+
sub create_index_nav {
my $self = shift;
@@ -524,16 +526,16 @@ sub create_index_nav {
# next holds previous, previous holds next;
if($back >= 0){
- $next_link = qq{<a href="$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$back">Next</a> &gt;&gt;};
+ $next_link = qq{$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$back};
}else{
- $next_link = "&nbsp;";
+ $next_link = undef;
}
if(($forward-1) < $#{$entries}){
- $prev_link = qq{&lt; &lt;<a href="$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$forward">Previous</a>};
+ $prev_link = qq{$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$forward};
}else{
- $prev_link = "&nbsp;";
+ $prev_link = undef;
}
@@ -542,56 +544,35 @@ sub create_index_nav {
if($back >= 0){
- $prev_link = qq{&lt;&lt; <a href="$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$back">Previous</a>};
+ $prev_link = qq{$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$back};
}else{
- $prev_link = "&nbsp;";
+ $prev_link = undef;
}
if($forward-1 < $#{$entries}){
- $next_link = qq{<a href="$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$forward">Next</a> &gt;&gt;};
+ $next_link = qq{$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{;start=$forward};
}else{
- $next_link = "&nbsp;";
+ $next_link = undef;
}
}
- my $index_link = qq{<a href="$DADA::Config::PROGRAM_URL?flavor=$af;list=} . uriescape($self->{list}) . qq{">Archive Index</a>};
-
- my $table = qq{
+ require DADA::Template::Widgets;
+ return DADA::Template::Widgets::screen(
+ {
+ -screen => 'archive_index_nav_table_widget.tmpl',
+ -list => $self->{name},
+ -vars => {
+ flavor_label => $af,
+ prev_link => $prev_link,
+ next_link => $next_link,
+ },
+ -list_settings_vars => $self->{ls}->params,
+ -list_settings_vars_param => { -dot_it => 1 },
- <table cellpadding="5" width="100%">
- <tr>
- <td valign="top" align="left" width="33%">
- <p>
- <strong>
- $prev_link
- </strong>
- </p>
- </td>
-
- <td valign="top" align="center" width="33%">
- <p>
- <strong>
- $index_link
- </strong>
- </p>
- </td>
-
-
- <td valign="top" align="right" width="33%">
- <p>
- <strong>
- $next_link
- </strong>
- </p>
- </td>
- </tr>
- </table>
-
- };
-
- return $table;
+ }
+ );
}
@@ -612,80 +593,57 @@ like this:
=cut
-sub make_nav_table {
+sub make_nav_table {
+ my $self = shift;
- # No - seriously, wtf is this method doing here?! (This is stupid)
- my $self = shift;
-
- my %args = (-List => undef,
- -Id => undef,
- -Function => 'visitor',
- @_);
-
- my $id = $args{-Id};
- # ?!?!?!
- my $list = $args{-List};
- my $function = $args{-Function};
- my $flavor_label;
-
- if($function eq "admin"){
- $flavor_label = "view_archive";
- }else{
- $flavor_label = "archive";
- }
-
- my ($prev, $next);
-
- ($prev, $next) = $self->get_neighbors($id);
-
- my $prev_subject = $self->get_archive_subject($prev);
- my $next_subject = $self->get_archive_subject($next);
-
+ my %args = (
+ -List => undef,
+ -Id => undef,
+ -Function => 'visitor',
+ @_
+ );
- my $prev_link;
- my $next_link;
-
- if (defined($prev)){
- $prev_link = qq{&lt;&lt; Previous: <a href="$DADA::Config::PROGRAM_URL?flavor=$flavor_label;list=} . uriescape($list) . qq{;id=$prev">$prev_subject</a>};
- }else{
- $prev_link = "&nbsp;";
- }
-
- if (defined($next)){
- $next_link = qq{Next: <a href="$DADA::Config::PROGRAM_URL?flavor=$flavor_label;list=} . uriescape($list) . qq{;id=$next">$next_subject</a> &gt;&gt;};
- }else{
- $next_link = "&nbsp;";
- }
-
- my $index_link = qq{<a href="$DADA::Config::PROGRAM_URL?flavor=$flavor_label;list=} . uriescape($list) . qq{">Archive Index</a> };
-
- my $table = qq{
-
- <table cellpadding="5">
- <tr>
- <td valign="top" align="left" width="33%">
- <p>
- <strong>
- $prev_link
- </strong>
- </p>
- </td>
- <td valign="top" align="center" width="33%">
- <p>| <strong>$index_link</strong> |</p>
- </td>
- <td valign="top" align="right" width="33%">
- <p><strong>$next_link</strong></p>
- </td>
- </tr>
- </table>
-
- };
-
-
- $table = $self->_parse_in_list_info(-data => $table);
- return $table;
+ my $id = $args{-Id};
+
+ # ?!?!?!
+ my $list = $args{-List};
+ my $function = $args{-Function};
+ my $flavor_label;
+ if ( $function eq "admin" ) {
+ $flavor_label = "view_archive";
+ }
+ else {
+ $flavor_label = "archive";
+ }
+
+ my ( $prev, $next );
+
+ ( $prev, $next ) = $self->get_neighbors($id);
+
+ my $prev_subject = $self->get_archive_subject($prev);
+ my $next_subject = $self->get_archive_subject($next);
+
+ require DADA::Template::Widgets;
+ return DADA::Template::Widgets::screen(
+ {
+ -screen => 'archive_nav_table_widget.tmpl',
+ -list => $list,
+ -vars => {
+ prev => $prev,
+ next => $next,
+ prev_subject =>
+ $self->_parse_in_list_info( -data => $prev_subject ),
+ next_subject =>
+ $self->_parse_in_list_info( -data => $next_subject ),
+ flavor_label => $flavor_label,
+ },
+ -list_settings_vars => $self->{ls}->params,
+ -list_settings_vars_param => { -dot_it => 1 },
+
+ }
+ );
}
@@ -1608,7 +1566,7 @@ sub message_blurb {
$msg =~ s/\n|\r/ /g;
- $msg = DADA::App::Guts::convert_to_html_entities($msg);
+ $msg = DADA::App::Guts::encode_html_entities($msg, "\200-\377");
my $l = length($msg);
my $size = $args{-size};
View
49 dada/DADA/Template/templates/archive_index_nav_table_widget.tmpl
@@ -0,0 +1,49 @@
+<!-- begin archive_index_nav_table_widget.tmpl -->
+
+
+<table cellpadding="5" width="100%">
+ <tr>
+ <td valign="top" align="left" width="33%">
+ <p>
+ <strong>
+ <!-- tmpl_if prev_link -->
+ &lt; &lt;
+ <a href="<!-- tmpl_var prev_link -->">
+ Previous
+ </a>
+ <!-- tmpl_else -->
+ &nbsp;
+ <!-- /tmpl_if -->
+
+ </strong>
+ </p>
+ </td>
+
+ <td valign="top" align="center" width="33%">
+ <p>
+ <strong>
+ <a href="<!-- tmpl_var PROGRAM_URL -->?flavor=<!-- tmpl_var flavor_label -->;<!-- tmpl_var list_settings.list -->">
+ Index
+ </a>
+ </strong>
+ </p>
+ </td>
+
+
+ <td valign="top" align="right" width="33%">
+ <p>
+ <strong>
+ <!-- tmpl_if next_link -->
+ <a href="<!-- tmpl_var next_link -->">
+ Next
+ </a> &gt;&gt;
+ <!-- tmpl_else -->
+ &nbsp;
+ <!-- /tmpl_if -->
+ </strong>
+ </p>
+ </td>
+ </tr>
+</table>
+
+<!-- end archive_index_nav_table_widget.tmpl -->
View
45 dada/DADA/Template/templates/archive_nav_table_widget.tmpl
@@ -0,0 +1,45 @@
+<!-- begin archive_nav_table_widget.tmpl -->
+
+<table cellpadding="5">
+ <tr>
+ <td valign="top" align="left" width="33%">
+ <p>
+ <strong>
+ <!-- tmpl_if prev_subject -->
+ &lt;&lt; Previous:
+ <a href="<!-- tmpl_var PROGRAM_URL -->?flavor=<!-- tmpl_var flavor_label -->;list=<!-- tmpl_var list_settings.list -->;id=<!-- tmpl_var prev -->">
+ <!-- tmpl_var prev_subject -->
+ </a>
+ <!-- tmpl_else -->
+ &nbsp;
+ <!-- /tmpl_if -->
+ </strong>
+ </p>
+ </td>
+ <td valign="top" align="center" width="33%">
+ <p>| <strong>
+ <a href="<!-- tmpl_var PROGRAM_URL -->?flavor=<!-- tmpl_var flavor_label -->;list=<!-- tmpl_var list_settings.list -->">
+ Archive Index
+ </a>
+
+ </strong> |</p>
+ </td>
+ <td valign="top" align="right" width="33%">
+ <p>
+ <strong>
+ <!-- tmpl_if next_subject -->
+ Next:
+ <a href="<!-- tmpl_var PROGRAM_URL -->?flavor=<!-- tmpl_var flavor_label -->;list=<!-- tmpl_var list_settings.list -->;id=<!-- tmpl_var next -->">
+ <!-- tmpl_var next_subject -->
+ </a>
+ &gt;&gt;
+ <!-- tmpl_else -->
+ &nbsp;
+ <!-- /tmpl_if -->
+ </strong>
+ </p>
+ </td>
+ </tr>
+</table>
+
+<!-- end archive_nav_table_widget.tmpl -->
View
33 dada/extras/developers/TODOlist.txt
@@ -10,25 +10,31 @@ Key:
[*] Naw...
[?] Someday
-[x] HTML Forms: Specify accept-charset in your <form> tag to tell the browser to submit user-entered data encoded in UTF-8:
+[ ] Markdown support -
+Write "PlainText" messages in TextTile, and have them formatted when shown in messages, etc - option to turn into HTML when sending?
+Power user option!
- <form action="foo" accept-charset="UTF-8">...</form>
+[ ] ReWrite Digest stuff -
+make a digest list a sublist, allow subscribers to subscribe to either, "list" or "sublist" (or change that in the profile screen)
+digest members not allowed to post to list. For now. Cronjob can be same as Dada Bridge cron, just extra step - time to run the digest?
+What messages get sent out? Make the digest (RFC of format? Different options?), send 'er out.
-[x] "Invite Only" List functionality.
+[ ] Always archive messages, but don't always show the archived message.
+Meaning, there's a new field, Called, "visibility" (or, whatever), that you can set to 1 or 0 -
+If it's 1, it's shown, if it's 0, it's not.
-[x] "You are Subscribed" Message sending to recent subscribed people.
[ ] A truly random pin for subs and unsubs.
+This again, would need a new field in dada_subscribers and probably break compat with the non-SQL backends, which is a bummer.
+Maybe just use a csv format for PlainText? (and only use such functionality, for pins... - not profile fields...)
-[x] - Tracker - track use of "forward to a friend"
- "Live tracking" right in mailing monitor
[ ] - Ability to set a custom Feed URL (ie: Feedburner)
[ ] Ability to have a, "I see your email has changed - want to change it in Dada Mail?" functionality in the list control panel.
+(I don't understand this idea, anymore...)
-[x] Ability to move "selected" list members from one list to another... so from Subscriber to Black or White List, Black List to Subscriber or White list, and White List to Subscriber or Black list
[ ] Ability to NOT distribute messages to users (so for example if I'm using Mail Merge to create labels, I can clear those people I want to NOT print a label for).
@@ -80,9 +86,6 @@ Easier hooks/interface to Dada Mail subscribe
Email address present?
(all the other email validation stuff...)
-[x] set_to_header_to_list_address setting needs to be re-named.
- * The functionality it was supposed to do, it doesn't
- * As it stands, if it's set to, "0", a reply-to header is added (or clobbers an already existing one) with the List Email address set.
[ ] Some ideas from a user:
* Make the List invite be more steamlined - so skip the screen that requires you to
@@ -1028,21 +1031,14 @@ Change the Browser Sig for fetfching.... stuff.
Sort of - encoded in there
Also the nu school unsub url's don't *really* have the email addy in there...
-dada_digest - http://dadamailproject.com/cgi-bin/yabb/YaBB.cgi?board=everything_else;action=display;num=1108658723;start=0#5
-[-] Test for SMTP Sending - Cause that's really annoying....
- How about in its own window?
- Actually, how about in line?!
- How about AJAX this out?
-
+
[] s/\n/<p>/ for physical address, privacy policy.
[-]remove Perl Modules that get d/l'd but, still aren't used? (working on this...)
-BOM ?!
-http://dadamailproject.com/cgi-bin/yabb/YaBB.cgi?board=sending;action=display;num=1109068887;start=0
todo: http://dadamailproject.com/cgi-bin/yabb/YaBB.cgi?board=everything_else;action=display;num=1109103844;start=0#1
@@ -1066,7 +1062,6 @@ http://dadamailproject.com/cgi-bin/yabb/YaBB.cgi?board=everything_else;action=di
delete list should have to use a password too?
-[x] unsub emails should not have complete unsub stuff on them (pin, basically)
----------
View
200 dada/extras/scripts/tracker_add_missing_num_subs.cgi
@@ -0,0 +1,200 @@
+#!/usr/bin/perl
+
+
+my $need_this_many_entries = 5;
+
+
+
+use lib qw(
+ ./
+ ./DADA/perllib
+
+ ../../
+ ../../DADA/perllib
+
+);
+use CGI::Carp qw(fatalsToBrowser);
+use Carp;
+$Carp::Verbose = 1;
+use CGI qw(:standard);
+use DADA::Config;
+use DADA::App::Guts;
+use DADA::Logging::Clickthrough;
+use DADA::App::DBIHandle;
+use Data::Dumper;
+use DADA::MailingList::Archives;
+
+$|++;
+
+my $dbi_obj = DADA::App::DBIHandle->new;
+my $dbh = $dbi_obj->dbh_obj;
+
+print header();
+for my $list(available_lists()){
+
+ print h1($list);
+ my $r = DADA::Logging::Clickthrough->new( { -list => $list } );
+
+ my $query = 'SELECT msg_id FROM ' . $DADA::Config::SQL_PARAMS{mass_mailing_event_log_table} . ' WHERE list = ? GROUP BY msg_id ORDER BY msg_id DESC;';
+ my $msg_ids = $dbh->selectcol_arrayref($query, {}, ($list)); #($statement, \%attr, @bind_values);
+
+
+ for my $mid(@$msg_ids){
+ print '<h2>' . $mid . '</h2>';
+
+ if(!verified_mid($mid)){
+ print p(b('NOT VALID MSG_ID'));
+ }
+ else {
+ my $ah = DADA::MailingList::Archives->new({-list => $list});
+ if($ah->check_if_entry_exists($mid)){
+ print p('ARCHIVE EXISTS');
+ # Do we have a num_subscribers entry?
+ my $num_sub_entry = num_subscriber_entry($list, $mid);
+ if($num_sub_entry > 0){
+ print p("YES NUM_SUB_ENTRY ($num_sub_entry)");
+ }
+ else {
+ print p("NO NUM_SUB_ENTRY");
+ my $num_entries = num_entries($list, $mid);
+ print p(b('ADD A NUM SUB ENTRY! - has ' . $num_entries . ' entries AND an Archive!'));
+ $r->sc_log(
+ {
+ -mid => $mid,
+ -num => 0,
+ }
+ );
+ print p('Added!');
+ }
+ }
+ else {
+ print p('NO ARCHIVE EXISTS');
+ #???print p("NO NUM_SUB_ENTRY");
+ my $num_entries = num_entries($list, $mid);
+ if($num_entries > $need_this_many_entries){
+ print p(b('ADD A NUM SUB ENTRY! - has ' . $num_entries . ' entries!'));
+ $r->sc_log(
+ {
+ -mid => $mid,
+ -num => 0,
+ }
+ );
+ print p('Added!');
+ }
+ else {
+ print p(b('DON\'T ADD A NUM SUB ENTRY! - only has ' . $num_entries . ' entries!'));
+ }
+ }
+ }
+ print hr();
+ }
+}
+
+print p('Done!');
+
+
+sub num_entries {
+ my $list = shift;
+ my $mid = shift;
+ my $query = 'SELECT COUNT(msg_id) FROM ' . $DADA::Config::SQL_PARAMS{mass_mailing_event_log_table} . ' WHERE list = ? AND msg_id = ?';
+ my $msg_id_entries = $dbh->selectcol_arrayref( $query, {}, $list, $mid)->[0];
+ return $msg_id_entries;
+}
+sub num_subscriber_entry {
+ my $list = shift;
+ my $mid = shift;
+ my $query = 'SELECT COUNT(msg_id) FROM ' . $DADA::Config::SQL_PARAMS{mass_mailing_event_log_table} . ' WHERE list = ? AND msg_id = ? AND event = ?';
+ my $c = $dbh->selectcol_arrayref($query, {}, $list, $mid, 'num_subscribers')->[0];
+ #print p(i('num_subscriber_entry ' . $c));
+ return $c;
+}
+sub verified_mid {
+ my $mid = shift;
+ # This could be stronger, but...
+ if ($mid =~ /^\d+$/ && length($mid) == 14) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+=pod
+
+=head1 tracker_add_missing_num_subs.cgi
+
+=head1 Description
+
+Around v5.0.0 to v5.0.3 (the actually version this problem happens is fuzzy), there is/was a problem with the Tracker plugin,
+where it wouldn't successfully track the B<Number of Subscribers> at the time of a mass mailing, or this metric wasn't being tracked, because of a user preference
+(I<Enable Subscriber Count Logging> was B<unchecked>).
+
+Some related bugs:
+
+B<https://github.com/justingit/dada-mail/issues/281>
+
+This leads to a major problem, as Tracker uses this one metric to grab all the mass mailings that it shows in its reports. No "Number of Subscriber" report, no report for anything else.
+
+C<tracker_add_missing_num_subs.cgi> adds that missing entry into the database. You can get a preview of what this plugin will most likely achieve in the Tracker before running this script. In the Tracker Preferences, uncheck the option, B<Clean Up Tracker Reports>. Your missing entries should now be shown, although other, "garbage" entries will probably also be shown, such as Test Mass Mailings.
+
+Since the number of subscribers of a past mass mailing is unknown, it will simply add a new entry and record, C<0> subscribers. (You may later manualy fix this in the SQL table, if you would like.).
+
+This script also makes some assumptions, so not to make a new "Number of Subscribers" entry for every single thing in the Tracker Log:
+
+=over
+
+=item * Doesn't already have a, "num_subscribers" entry
+
+Only mass mailings with missing "num_subscribers" entries will be looked at.
+
+This also means that it's safe to re-run this script multiple times, if you find the desire to do so.
+
+=item * Mass Mailings with an Archived Message but no, "num_subscribers" entry will be given one
+
+=item * Mass Mailings without an Archived Message and too few total Tracker entries will NOT be given a new "num_subscriber" entry
+
+At the moment, this limit is a paltry, B<5>, and you may change this limit on the top of the script, in the variable,
+
+C<$need_this_many_entries>
+
+=back
+
+This plugin also only works with any of the B<SQL> backends, and does not work with the B<Default> (plaintext logs) Backend.
+
+
+=head1 Configuration
+
+No configuration will need to be done in this script itself. The permissions of this script simply need to be set to, C<755>.
+
+=head1 Using
+
+Please fix backup the B<dada_mass_mailing_event_log> table in your SQL database. Although this script will not I<remove> any data from your
+database, it will potentially I<add> data and add quite a bit data.
+
+Visit C<tracker_add_missing_num_subs.cgi> in your web browser, or run the script via the command line. Be aware that
+running the script may potentially take several minutes, depending on how many entries in the database you have, how many lists you have - things like that.
+
+Once the script is finished, visit the Tracker plugin and see if the missing Message entries are now visible.
+The Tracker Summary graph itself will probably have some wildly changing entries, as the actual B<Subscribers> data is not available.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1999 - 2012 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.
+
+=cut
+
+
View
2  dada/mail.cgi
@@ -2393,7 +2393,7 @@ sub amazon_ses_get_stats {
my ($SentLast24Hours, $Max24HourSend, $MaxSendRate) = split(/\s+/, $data);
print $q->header();
- print '<p class="positive">Your current Amazon SES sending limit is: ' . $MaxSendRate . ' message(s)/second with a limit of ' . $Max24HourSend . ' messages every 24 hours.</p>';
+ print '<p class="positive">Your current Amazon SES sending limit is: ' . commify($MaxSendRate) . ' message(s)/second with a limit of ' . commify($Max24HourSend) . ' messages every 24 hours.</p>';
}
}
View
2  dada/plugins/log_viewer.cgi
@@ -334,7 +334,7 @@ sub show_log {
$html .= '<pre>';
for(@$loglines){
$_ =~ s/\t/ /g;
- $html .= convert_to_html_entities($_) . "\n";
+ $html .= encode_html_entities($_, "\200-\377") . "\n";
}
$html .= '</pre>';
return $html;
View
15 dada/plugins/tracker.cgi
@@ -590,8 +590,7 @@ sub domain_breakdown_img {
title => 'Total Subscribers: ' . commify($num_subs),
);
- use HTML::Entities;
- my $enc_chart = encode_entities($chart);
+ my $enc_chart = encode_html_entities($chart);
my $tmpl = domain_breakdown_img_tmpl();
require DADA::Template::Widgets;
@@ -715,8 +714,7 @@ sub subscriber_history_img {
);
- use HTML::Entities;
- my $enc_chart = encode_entities($chart);
+ my $enc_chart = encode_html_entities($chart);
my $tmpl = subscriber_history_img_tmpl();
require DADA::Template::Widgets;
@@ -820,8 +818,7 @@ sub data_ot_img {
chxl => '0:|' . join('|', @$chxl),
);
- use HTML::Entities;
- my $enc_chart = encode_entities($chart);
+ my $enc_chart = encode_html_entities($chart);
if(!exists($ct_ot->[0])) {
$enc_chart = undef;
@@ -1977,8 +1974,7 @@ sub by_domain_img {
title => '',
);
- use HTML::Entities;
- my $enc_chart = encode_entities($chart);
+ my $enc_chart = encode_html_entities($chart);
}
@@ -2086,8 +2082,7 @@ sub country_geoip_data {
chld => $chld,
data => [@number],
);
- use HTML::Entities;
- my $enc_chart = encode_entities($chart);
+ my $enc_chart = encode_html_entities($chart);
require Geography::Countries;
my $ht_report = [];
View
46 dada/t/DADA_App_BounceHandler_MessageParser.t
@@ -318,6 +318,52 @@ undef $entity;
+$msg = dada_test_config::slurp('t/corpus/email_messages/bounce-dsn-user_unknown.eml');
+$entity = $parser->parse_data($msg);
+( $email, $found_list, $diag ) = $bhmp->run_all_parses($entity);
+ok($email eq 'subscriber@example.com');
+ok($found_list eq 'dadatest', "found list ($found_list)");
+$rule = $bhr->find_rule_to_use( $found_list, $email, $diag );
+
+#diag 'email: ' . $email;
+#diag 'list: ' . $list;
+#diag Dumper($diag);
+#diag 'rule: ' . $rule;
+
+ok($rule eq 'delivery_error_550', "rule is: $rule");
+undef $msg;
+undef $email;
+undef $found_list;
+undef $diag;
+undef $entity;
+
+
+
+
+
+$msg = dada_test_config::slurp('t/corpus/email_messages/bounce-dsn-4.4.1.eml');
+$entity = $parser->parse_data($msg);
+( $email, $found_list, $diag ) = $bhmp->run_all_parses($entity);
+ok($email eq 'subscriber@example.com');
+ok($found_list eq 'dadatest', "found list ($found_list)");
+$rule = $bhr->find_rule_to_use( $found_list, $email, $diag );
+
+#diag 'email: ' . $email;
+#diag 'list: ' . $list;
+#diag Dumper($diag);
+#diag 'rule: ' . $rule;
+
+ok($rule eq 'bounce_4dot4dot1_error', "rule is: $rule");
+undef $msg;
+undef $email;
+undef $found_list;
+undef $diag;
+undef $entity;
+
+
+
+
+
View
35 dada/t/DADA_App_FormatMessages.t
@@ -23,6 +23,41 @@ my $ls = DADA::MailingList::Settings->new({-list => $list});
my $li = $ls->get;
my $fm = DADA::App::FormatMessages->new(-yeah_no_list => 1);
+
+# _add_opener_image
+my $c = 'blah blah blah';
+$c = $fm->_add_opener_image($c);
+#diag $c;
+like($c, qr/open_img/);
+undef $c;
+
+my $c = q{
+<html>
+<body>
+ Blah Balh Blah.
+};
+$c = $fm->_add_opener_image($c);
+#diag $c;
+like($c, qr/open_img/);
+undef $c;
+
+
+my $c = q{
+<html>
+<body>
+ Blah Balh Blah.
+</body>
+</html>
+
+};
+$c = $fm->_add_opener_image($c);
+#diag $c;
+like($c, qr/open_img/);
+undef $c;
+
+#/ _add_opener_image
+
+
$filename = 't/corpus/email_messages/simple_template.txt';
#open my $MSG, '<', $filename or die $!;
#my $msg1 = do { local $/; <$MSG> } or die $!;
View
102 dada/t/corpus/email_messages/bounce-dsn-4.4.1.eml
@@ -0,0 +1,102 @@
+Return-path: <simoni@vhost1.example.com>
+Envelope-to: listowner@example.com
+Delivery-date: Thu, 12 Apr 2012 00:00:08 -0400
+Received: from simoni by vhost1.example.com with local (Exim 4.69 (FreeBSD))
+ (envelope-from <simoni@vhost1.example.com>)
+ id 1SIBCa-000H5b-9j
+ for listowner@example.com; Thu, 12 Apr 2012 00:00:08 -0400
+Date: Thu, 12 Apr 2012 00:00:08 -0400
+From: MAILER-DAEMON@vhost1.example.com (Mail Delivery System)
+To: listowner@example.com
+Precedence: list
+Content-type: multipart/report; report-type=delivery-status;
+ boundary="36DA859EF88.1334195469/mx2.zoneedit.com"; charset=UTF-8
+Content-Transfer-Encoding: 7bit
+MIME-Version: 1.0
+Subject: Undelivered Mail Returned to Sender
+Message-Id: <E1SIBCa-000H5b-9j@vhost1.example.com>
+
+This is a MIME-encapsulated message.
+--36DA859EF88.1334195469/mx2.zoneedit.com
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+This is the mail system at host mx2.zoneedit.com.
+
+I'm sorry to have to inform you that your message could not
+be delivered to one or more recipients. It's attached below.
+
+For further assistance, please send mail to postmaster.
+
+If you do so, please include this problem report. You can
+delete your own text from the attached returned message.
+
+ The mail system
+
+<subscriber@example.com>: delivery temporarily suspended: connect to
+ line.example.com[67.18.176.34]: Connection refused
+
+--36DA859EF88.1334195469/mx2.zoneedit.com
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; mx2.zoneedit.com
+X-Postfix-Queue-ID: 36DA859EF88
+X-Postfix-Sender: rfc822; bounces@example.com
+Arrival-Date: Tue, 3 Apr 2012 13:54:03 -0700 (PDT)
+
+Final-Recipient: rfc822; subscriber@example.com
+Original-Recipient: rfc822;subscriber@example.com
+Action: failed
+Status: 4.4.1
+Diagnostic-Code: X-Postfix; delivery temporarily suspended: connect to
+ line.example.com[67.18.176.34]: Connection refused
+
+--36DA859EF88.1334195469/mx2.zoneedit.com
+Content-Description: Undelivered Message Headers
+Content-Type: text/rfc822-headers
+Content-Transfer-Encoding: quoted-printable
+
+Received-SPF: none (example.com: No applicable sender policy availa=
+ble) receiver=3Dmx2.zoneedit.com; identity=3Dmailfrom; envelope-from=3D"bou=
+nces@example.com"; helo=3Dvhost1.example.com; client-ip=3D12.16=
+1.105.151
+Received: from vhost1.example.com (vhost1.example.com [12.161.105.1=
+51])
+ by mx2.zoneedit.com (Postfix) with ESMTP id 36DA859EF88
+ for <subscriber@example.com>; Tue, 3 Apr 2012 13:54:03 -0700 (PDT)
+Received: from simoni by vhost1.example.com with local (Exim 4.69 (Free=
+BSD))
+ (envelope-from <bounces@example.com>)
+ id 1SFAlO-000PTp-6r
+ for subscriber@example.com; Tue, 03 Apr 2012 16:55:38 -0400
+Date: Tue, 03 Apr 2012 16:55:38 -0400
+From: "Dada Mail Announcement List" <listowner@example.com>
+To: "Dada Mail Announcement List Subscriber" <subscriber@example.com>
+X-Priority: 3
+Precedence: list
+List: dadatest
+List-Archive: <http://example.com/cgi-bin/dada/mail.cgi/archive/dad=
+a_announce/>
+List-ID: <dadatest.vhost1.example.com>
+List-Owner: <listowner@example.com>
+List-Post: NO
+List-Subscribe: =3D?UTF-8?Q?=3D3Chttp=3D3A//example=3D2Ecom/cgi-bin=
+/dada/mail=3D2Ecgi/s/dada?=3D
+ =3D?UTF-8?Q?=3D5Fannounce/subscriber/example=3D2Ecom/=3D3E?=3D
+List-Unsubscribe: =3D?UTF-8?Q?=3D3Chttp=3D3A//example=3D2Ecom/cgi-b=
+in/dada/mail=3D2Ecgi/u/dada?=3D
+ =3D?UTF-8?Q?=3D5Fannounce/subscriber/example=3D2Ecom/=3D3E?=3D
+List-URL: <http://example.com/cgi-bin/dada/mail.cgi/list/dada_annou=
+nce/>
+Message-ID: <20120403045348.56269773@example.com>
+X-Mailer: Pro Dada 5.0.1=20
+Content-type: multipart/alternative; boundary=3D"_----------=3D_13334432272=
+83300"; charset=3DUTF-8
+Content-Transfer-Encoding: binary
+MIME-Version: 1.0
+Subject: Dada Mail v5.0.1 Released, Pro Dada Upgrades 25% off until the 25t=
+h, new Upgrade Screencast
+
+
+--36DA859EF88.1334195469/mx2.zoneedit.com--
View
84 dada/t/corpus/email_messages/bounce-dsn-user_unknown.eml
@@ -0,0 +1,84 @@
+Return-path: <simoni@vhost1.example.com>
+Envelope-to: newsletter@example.com
+Delivery-date: Sun, 06 May 2012 00:00:08 -0400
+Received: from simoni by vhost1.example.com with local (Exim 4.69 (FreeBSD))
+ (envelope-from <simoni@vhost1.example.com>)
+ id 1SQsdk-000IIc-6K
+ for newsletter@example.com; Sun, 06 May 2012 00:00:08 -0400
+Date: Sun, 06 May 2012 00:00:08 -0400
+From: MAILER-DAEMON@molosso04.example.com (Mail Delivery System)
+To: newsletter@example.com
+Precedence: list
+Content-type: multipart/report; report-type=delivery-status;
+ boundary="B80621C02FDC.1336215005/molosso04.example.com"; charset=UTF-8
+MIME-Version: 1.0
+Subject: Undelivered Mail Returned to Sender
+Message-Id: <E1SQsdk-000IIc-6K@vhost1.example.com>
+
+This is a MIME-encapsulated message.
+--B80621C02FDC.1336215005/molosso04.example.com
+Content-Description: Notification
+Content-Type: text/plain; charset=us-ascii
+
+This is the mail system at host molosso04.example.com.
+
+I'm sorry to have to inform you that your message could not
+be delivered to one or more recipients. It's attached below.
+
+For further assistance, please send mail to postmaster.
+
+If you do so, please include this problem report. You can
+delete your own text from the attached returned message.
+
+ The mail system
+
+<final.recipient@example.com> (expanded from <subscriber@example.com>): host
+ mail.example.com[81.88.48.107] said: 550 5.1.1 User unknown (in reply
+ to RCPT TO command)
+
+--B80621C02FDC.1336215005/molosso04.example.com
+Content-Description: Delivery report
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; molosso04.example.com
+X-Postfix-Queue-ID: B80621C02FDC
+X-Postfix-Sender: rfc822; bounces@example.com
+Arrival-Date: Sat, 5 May 2012 12:49:48 +0200 (CEST)
+
+Final-Recipient: rfc822; final.recipient@example.com
+Original-Recipient: rfc822;subscriber@example.com
+Action: failed
+Status: 5.1.1
+Remote-MTA: dns; mail.example.com
+Diagnostic-Code: smtp; 550 5.1.1 User unknown
+
+--B80621C02FDC.1336215005/molosso04.example.com
+Content-Description: Undelivered Message Headers
+Content-Type: text/rfc822-headers
+
+Received: from vhost1.example.com (vhost1.example.com [12.161.105.151])
+ by molosso04.example.com (Postfix) with ESMTPS id B80621C02FDC
+ for <subscriber@example.com>; Sat, 5 May 2012 12:49:48 +0200 (CEST)
+Received: from simoni by vhost1.example.com with local (Exim 4.69 (FreeBSD))
+ (envelope-from <bounces@example.com>)
+ id 1SQcY8-0009K1-T8
+ for subscriber@example.com; Sat, 05 May 2012 06:49:16 -0400
+Date: Sat, 05 May 2012 06:49:16 -0400
+From: "Dada Mail Announcement List" <newsletter@example.com>
+To: "Dada Mail Announcement List Subscriber" <subscriber@example.com>
+X-Priority: 3
+Precedence: list
+List: dadatest
+List-Archive: <http://example.com/cgi-bin/dada/mail.cgi/archive/dadatest/>
+List-ID: <dadatest.vhost1.example.com>
+List-Owner: <newsletter@example.com>
+List-Post: NO
+List-Subscribe: =?UTF-8?Q?=3Chttp=3A//dadamailproject=2Ecom/cgi-bin/dada/mail=2Ecgi/s/dadatest/subscriber/example=2Ecom/=3E?=
+List-Unsubscribe: =?UTF-8?Q?=3Chttp=3A//dadamailproject=2Ecom/cgi-bin/dada/mail=2Ecgi/u/dadatest/subscriber/example=2Ecom//=3E?=
+Message-ID: <20120505064916.66382935@example.com>
+X-Mailer: Dada Mail 5.0.2
+Content-type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: quoted-printable
+Subject: Dada Mail Announcement List Mailing List Subscription Confirmation
+
+--B80621C02FDC.1336215005/molosso04.example.com--
Please sign in to comment.
Something went wrong with that request. Please try again.