use v6.d;
unit class MaildirIndexer::Email;
use MaildirIndexer::LogTimelineSchema;
has IO $.path;
has %!headers;
has $!body;
method BUILD(:%!headers,:$!body,:$!path = IO) { }
method message-id(--> Str:D) { split-refs(%!headers<message-id>)[0] // '' }
method refs(--> Iterable) {
return (
|split-refs(%!headers<in-reply-to>),
|split-refs(%!headers<references>).reverse,
);
}
multi split-refs(Any --> Iterable) { return () }
multi split-refs(Str:D $str --> Iterable) {
my @result;
MaildirIndexer::LogTimelineSchema::Parse::Header.log: {
@result = $/<refs>».Str if $str ~~ m{'<' $<refs> = (<-[<>]>+)+ % [ '>' .*? '<' ] '>' };
}
return @result;
}
method addresses (--> Iterable) {
return (
|extract-addresses(%!headers<sender>),
|extract-addresses(%!headers<x-original-sender>),
|extract-addresses(%!headers<from>),
|extract-addresses(%!headers<to>),
|extract-addresses(%!headers<reply-to>),
|extract-addresses(%!headers<mailing-list>),
|extract-addresses(%!headers<x-original-from>),
).unique;
}
my grammar Address {
token CTL { <[ \x00 .. \x1F \x7F ]> }
token special { <[ \( \) \< \> \[ \] \: \; \@ \\ \, \. \" ]> }
token atext { <-CTL> & <-special> & \S }
token dot-atom { <ws> [ [<atext>+]+ % '.' ] <ws> }
token local-part { <-atom> }
token domain { <-atom> }
token addr { <local-part> '@' <domain> }
rule TOP { ^ .*? [ <addr>+ % .+? ] .*? $ }
}
multi sub extract-addresses(Any --> Iterable) { return () }
multi sub extract-addresses(Str:D $str --> Iterable) {
my @result;
MaildirIndexer::LogTimelineSchema::Parse::Header.log: {
with Address.parse($str) {
@result = $_<addr>».Str;
}
}
return @result;
}