#!/usr/bin/perl
# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.

use strict;
use v5.10;

BEGIN {
    require "$ENV{LJHOME}/cgi-bin/ljlib.pl";
}

use Log::Log4perl;
my $log = Log::Log4perl->get_logger(__PACKAGE__);

use Digest::MD5 qw/ md5_hex /;
use DW::Task::IncomingEmail;

my $tempfail = sub {
    my $msg = shift;
    warn "Failure: $msg\n" if $msg;

    # makes postfix do temporary failure:
    exit 75;
};

# below this size, we put in database directly.  if over,
# we put in mogile.
sub IN_MEMORY_THRES () {
    return $ENV{T_MAILINJECT_THRES_SIZE}
        || 768 * 1024;
}

my $msg = '';    # in-memory message
my $len = 0;     # length of message

eval {
    my ( $buf, $rv );
    while ( $rv = sysread STDIN, $buf, 1024 * 64 ) {
        $len += $rv;
        $msg .= $buf;
    }
    $tempfail->("Error reading: $!")
        unless defined $rv;

    if ( should_ignore($msg) ) {
        $log->info("Received probable spam message of $len bytes, dropping");
        exit 0;
    }

    $log->info("Received email of $len bytes, saving for handling");
};
$tempfail->($@) if $@;

if ( $len > IN_MEMORY_THRES ) {
    my $md5 = md5_hex($msg);
    DW::BlobStore->store( temp => "ie:$md5", \$msg );
    $log->info("Storing email in blobstore at key: ie:$md5");

    # Overwrite $msg so that the incoming-email worker knows that this
    # is a key it should look up in the storage system
    $msg = "ie:$md5";
}

my $h = DW::TaskQueue->dispatch( DW::Task::IncomingEmail->new($msg) );
exit 0 if $h;
exit 75;    # temporary error

# it pays to get rid of as many bounces and gibberish now, before we
# have to put it in the database, mogile, allocate ids, run workers,
# move disks around, etc..  so these are just quick & dirty checks.
sub should_ignore {
    my $msg = shift;
    return 0 unless $msg;
    return 1 if $msg =~ /^Return-Path:\s+<>/im;

    my ($subject) = $msg =~ /^Subject: (.+)/im;
    if ($subject) {
        return 1
            if $subject =~ /auto.?(response|reply)/i
            || $subject =~
            /^(Undelive|Mail System Error - |ScanMail Message: |\+\s*SPAM|Norton AntiVirus)/i
            || $subject =~ /^(Mail Delivery Problem|Mail delivery failed)/i
            || $subject =~ /^failure notice$/i
            || $subject =~ /\[BOUNCED SPAM\]/i
            || $subject =~ /^Symantec AVF /i
            || $subject =~ /Attachment block message/i
            || $subject =~ /Use this patch immediately/i
            || $subject =~ /^don\'t be late! ([\w\-]{1,15})$/i
            || $subject =~ /^your account ([\w\-]{1,15})$/i
            || $subject =~ /Message Undeliverable/i;
    }

    return 0;
}
