Skip to content

Commit

Permalink
Sisimai->make, Sisimai->dump receive callback method for each email f…
Browse files Browse the repository at this point in the history
…ile at `c___` argument #399
  • Loading branch information
azumakuniyuki committed Jun 9, 2020
1 parent 1300b7c commit 806e465
Showing 1 changed file with 77 additions and 25 deletions.
102 changes: 77 additions & 25 deletions lib/Sisimai.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ sub make {
# @param [Handle] argv0 or STDIN
# @param [Hash] argv1 Parser options
# @options argv1 [Integer] delivered 1 = Including "delivered" reason
# @options argv1 [Code] hook Code reference to a callback method
# @options argv1 [Code] hook Code reference to a callback method for an email message
# @options argv1 [Code] c___ Code reference to a callback method for each email file
# @return [Array] Parsed objects
# @return [Undef] Undef if the argument was wrong or an empty array
my $class = shift;
Expand All @@ -28,14 +29,21 @@ sub make {

my $list = [];
my $mail = Sisimai::Mail->new($argv0) || return undef;
my $c___ = ref $argv1->{'c___'} eq 'CODE' ? $argv1->{'c___'} : undef;

while( my $r = $mail->data->read ) {
# Read and parse each email file
my $p = { 'data' => $r, 'hook' => $argv1->{'hook'} };
next unless my $mesg = Sisimai::Message->new(%$p);

$p = { 'data' => $mesg, 'delivered' => $argv1->{'delivered'}, 'origin' => $mail->data->path };
my $data = Sisimai::Data->make(%$p);
push @$list, @$data if scalar @$data;
my $args = { 'data' => $r, 'hook' => $argv1->{'hook'} };
my $path = $mail->data->path;
my $sisi = [];

if( my $mesg = Sisimai::Message->new(%$args) ) {
# Sisimai::Message object was created successfull
$args = { 'data' => $mesg, 'delivered' => $argv1->{'delivered'}, 'origin' => $path };
$sisi = Sisimai::Data->make(%$args);
}
$mail->hook($c___, \$r, $sisi) if $c___;
push @$list, @$sisi if scalar @$sisi;
}
return undef unless scalar @$list;
return $list;
Expand Down Expand Up @@ -210,38 +218,82 @@ of dump() and make() method like following command:
=head2 Callback Feature
Beginning from v4.19.0, `hook` argument is available to callback user defined
method like the following codes:
=head3 For email headers and the body
Beginning from v4.19.0, C<hook> argument is available to receive a callback method
for entire email message like the following codes:
my $cmethod = sub {
my $argv = shift;
my $code = sub {
my $argv = shift; # (*Hash)
my $head = $argv->{'head'}; # (*Hash) Email headers
my $body = $argv->{'body'}; # (String) Message body
my $data = {
'queue-id' => '',
'x-mailer' => '',
'queue-id' => '',
'x-mailer' => '',
'precedence' => '',
};
# Header part of the bounced mail
for my $e ( 'x-mailer', 'precedence' ) {
next unless exists $argv->{'headers'}->{ $e };
$data->{ $e } = $argv->{'headers'}->{ $e };
# Read some headers of the bounced mail
next unless exists $head->{ $e };
$data->{ $e } = $head->{ $e };
}
# Message body of the bounced email
if( $argv->{'message'} =~ /^X-Postfix-Queue-ID:\s*(.+)$/m ) {
if( $body =~ /^X-Postfix-Queue-ID:\s*(.+)$/m ) {
# Message body of the bounced email
$data->{'queue-id'} = $1;
}
return $data;
};
my $message = Sisimai::Message->new(
'data' => $mailtxt,
'hook' => $cmethod,
);
print $message->catch->{'x-mailer'}; # Apple Mail (2.1283)
print $message->catch->{'queue-id'}; # 2DAEB222022E
print $message->catch->{'precedence'}; # bulk
my $message = Sisimai::Message->new('data' => $mailtxt, 'hook' => $code);
print $message->catch->{'x-mailer'}; # "Apple Mail (2.1283)"
print $message->catch->{'queue-id'}; # "2DAEB222022E"
print $message->catch->{'precedence'}; # "bulk"
=head3 For each email file
Beginning from v4.25.8, C<c___> argument is available at C<Sisimai->make()> and
C<Sisimai->dump()> meethod for callback feature. The argument C<c___> receives
a callback method for each email file like the following:
my $path = '/path/to/maildir';
my $code = sub {
my $args = shift; # (*Hash)
my $kind = $args->{'kind'}; # (String) Sisimai::Mail->kind
my $mail = $args->{'mail'}; # (*String) Entire email message
my $path = $args->{'path'}; # (String) Sisimai::Mail->path
my $sisi = $args->{'sisi'}; # (*Array) List of Sisimai::Data
for my $e ( @$sisi ) {
# Insert custom fields into the parsed results
$e->{'catch'} ||= {};
$e->{'catch'}->{'size'} = length $$mail;
$e->{'catch'}->{'kind'} = ucfirst $kind;
if( $$mail =~ /^Return-Path: (.+)$/m ) {
# Return-Path: <MAILER-DAEMON>
$e->{'catch'}->{'return-path'} = $1;
}
# Append X-Sisimai-Parsed: header and save into other path
my $a = sprintf("X-Sisimai-Parsed: %d\n", scalar @$sisi);
my $p = sprintf("/path/to/another/directory/sisimai-%s.eml", $e->token);
my $f = IO::File->new($p, 'w');
my $v = $$mail; $v =~ s/^(From:.+)$/$a$1/m;
print $f $v; $f->close;
}
# Remove the email file in Maildir/ after parsed
unlink $path if $kind eq 'maildir';
# Need to not return a value
};
my $list = Sisimai->make($path, 'c___' => $code);
print $list->[0]->{'catch'}->{'size'}; # 2202
print $list->[0]->{'catch'}->{'kind'}; # "Maildir"
print $list->[0]->{'catch'}->{'return-path'}; # "<MAILER-DAEMON>"
=head1 OTHER METHODS
Expand Down

0 comments on commit 806e465

Please sign in to comment.