1 # Copyright (C) 2015, all contributors <meta@public-inbox.org>
2 # License: GPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
3 # based on notmuch, but with no concept of folders, files or flags
4 package PublicInbox::SearchMsg;
8 use Email::Address qw//;
10 use Date::Parse qw/str2time/;
11 use PublicInbox::MID qw/mid_clean mid_compressed/;
12 our $PFX2TERM_RE = undef;
15 my ($class, $mime) = @_;
16 my $doc = Search::Xapian::Document->new;
17 $doc->add_term(PublicInbox::Search::xpfx('type') . 'mail');
19 bless { type => 'mail', doc => $doc, mime => $mime }, $class;
23 my ($class, $doc, $mid) = @_;
24 bless { doc => $doc, mime => undef, mid => $mid }, $class;
28 my ($class, $doc) = @_;
29 my ($mid, $subj, $from, $date) = split(/\n/, $doc->get_data);
41 my $subj = $self->{subject};
42 return $subj if defined $subj;
43 $subj = $self->{mime}->header('Subject');
44 $subj = '' unless defined $subj;
46 $self->{subject} = $subj;
51 my $from = $self->mime->header('From') || '';
55 @from = Email::Address->parse($from);
56 $self->{from} = $from[0];
57 $from = $from[0]->name;
60 $self->{from_name} = $from;
66 my $from_name = $self->{from_name};
67 return $from_name if defined $from_name;
76 $self->{date} = undef;
83 my $date = $self->{date};
84 return $date if $date;
85 my $ts = eval { str2time($self->mime->header('Date')) } || 0;
87 $self->{date} = POSIX::strftime('%Y-%m-%d %H:%M', gmtime($ts));
94 $self->subject . "\n" .
95 $self->from_name . "\n".
101 my $doc = $self->{doc};
102 my $i = $doc->termlist_begin;
103 my $end = $doc->termlist_end;
105 unless (defined $PFX2TERM_RE) {
106 my $or = join('|', keys %PublicInbox::Search::PFX2TERM_RMAP);
107 $PFX2TERM_RE = qr/\A($or)/;
110 for (; $i != $end; $i->inc) {
111 my $val = $i->get_termname;
113 if ($val =~ s/$PFX2TERM_RE//o) {
114 my $field = $PublicInbox::Search::PFX2TERM_RMAP{$1};
115 if ($field eq 'references') {
116 my $refs = $self->{references} ||= [];
119 $self->{$field} = $val;
126 my ($self, $mid) = @_;
131 $self->{mid} ||= $self->_extract_mid;
138 my $mid = $self->mime->header('Message-ID');
139 $mid ? mid_compressed(mid_clean($mid)) : $mid;
143 my ($self, $mime) = @_;
145 $self->{mime} = $mime;
153 my ($self, $doc_id) = @_;
154 if (defined $doc_id) {
155 $self->{doc_id} = $doc_id;
157 # TODO load from xapian
164 my $tid = $self->{thread};
165 return $tid if defined $tid;
166 $self->ensure_metadata;
172 my $path = $self->{path};
173 return $path if defined $path;
174 $self->ensure_metadata;