summaryrefslogtreecommitdiff
path: root/lib/MaildirIndexer/Email.pm6
blob: 4f92106899cefe22cb9e40dc8ca30900671dcc3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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;
    # we should add a hack for info@meetup.com, where we keep the 
    # whole "from", since it's the only way to distinguish between 
    # different groups 
}
 
# subset of the grammar of p5's Email::Address, ignoring comments and 
# quoting 
my grammar Address {
    token CTL { <[ \x00 .. \x1F \x7F ]> }
    token special { <[ \( \) \< \> \[ \] \: \; \@ \\ \, \. \" ]> }
 
    token atext { <-CTL> & <-special> & \S }
    token dot-atom { <ws> [ [<atext>+]+ % '.' ] <ws> }
 
    token local-part { <.dot-atom> }
    token domain { <.dot-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;
}