our
$VERSION
=
'3.017'
;
}
sub
clone(;@)
{
my
$self
=
shift
;
my
$copy
=
ref
(
$self
)->new(
$self
->logSettings);
$copy
->addNoRealize(
$_
->clone)
for
$self
->grepNames(
@_
);
$copy
->modified(1);
$copy
;
}
sub
build(@)
{
my
$class
=
shift
;
my
$self
=
$class
->new;
while
(
@_
)
{
my
$name
=
shift
;
defined
$name
or
next
;
if
(
$name
->isa(
'Mail::Message::Field'
))
{
$self
->add(
$name
);
next
;
}
my
$content
=
shift
;
defined
$content
or
next
;
if
(
ref
$content
&&
$content
->isa(
'Mail::Message::Field'
))
{
$self
->
log
(
WARNING
=>
"Field objects have an implied name ($name)"
);
$self
->add(
$content
);
next
;
}
$self
->add(
$name
,
$content
);
}
$self
;
}
sub
isDelayed() {0}
sub
nrLines() { sum 1,
map
$_
->nrLines,
shift
->orderedFields }
sub
size() { sum 1,
map
$_
->size,
shift
->orderedFields }
sub
wrap($)
{
my
(
$self
,
$length
) =
@_
;
$_
->setWrapLength(
$length
)
for
$self
->orderedFields;
}
sub
add(@)
{
my
$self
=
shift
;
my
$field
=
@_
==1 &&
ref
$_
[0] ?
shift
: (
$self
->{MMH_field_type} ||
'Mail::Message::Field::Fast'
)->new(
@_
);
return
if
!
defined
$field
;
$field
->setWrapLength;
my
$known
=
$self
->{MMH_fields};
my
$name
=
$field
->name;
$self
->addOrderedFields(
$field
);
if
(
defined
$known
->{
$name
})
{
if
(
ref
$known
->{
$name
} eq
'ARRAY'
) {
push
@{
$known
->{
$name
}},
$field
}
else
{
$known
->{
$name
} = [
$known
->{
$name
},
$field
] }
}
else
{
$known
->{
$name
} =
$field
;
}
$self
->{MMH_modified}++;
$field
;
}
sub
count($)
{
my
$known
=
shift
->{MMH_fields};
my
$value
=
$known
->{
lc
shift
};
!
defined
$value
? 0
:
ref
$value
?
@$value
: 1;
}
sub
names() {
shift
->knownNames}
sub
grepNames(@)
{
my
$self
=
shift
;
my
@take
;
push
@take
, (
ref
$_
eq
'ARRAY'
?
@$_
:
$_
)
foreach
@_
;
return
$self
->orderedFields
unless
@take
;
my
$take
;
if
(
@take
==1 &&
ref
$take
[0] eq
'Regexp'
)
{
$take
=
$take
[0];
}
else
{
local
$" =
')|(?:'
;
$take
=
qr/^(?:(?:@take))/
i;
}
grep
{
$_
->name =~
$take
}
$self
->orderedFields;
}
my
@skip_none
=
qw/content-transfer-encoding content-disposition
content-description content-id/
;
my
%skip_none
=
map
+(
$_
=> 1),
@skip_none
;
sub
set(@)
{
my
$self
=
shift
;
@_
!=1 ||
defined
$_
[0] or
return
;
my
$type
=
$self
->{MMH_field_type} ||
'Mail::Message::Field::Fast'
;
$self
->{MMH_modified}++;
my
$field
=
@_
==1 &&
ref
$_
[0] ?
shift
->clone :
$type
->new(
@_
);
my
$name
=
$field
->name;
my
$known
=
$self
->{MMH_fields};
if
(
$skip_none
{
$name
} &&
$field
->body eq
'none'
)
{
delete
$known
->{
$name
};
return
$field
;
}
$field
->setWrapLength;
$known
->{
$name
} =
$field
;
$self
->addOrderedFields(
$field
);
$field
;
}
sub
reset
($@)
{
my
(
$self
,
$name
) = (
shift
,
lc
shift
);
my
$known
=
$self
->{MMH_fields};
if
(
@_
==0)
{
$self
->{MMH_modified}++
if
delete
$known
->{
$name
};
return
();
}
$self
->{MMH_modified}++;
my
@fields
=
map
$_
->clone,
@_
;
if
(
@_
==1) {
$known
->{
$name
} =
$fields
[0] }
else
{
$known
->{
$name
} = [
@fields
] }
$self
->addOrderedFields(
@fields
);
$self
;
}
sub
delete
($) {
$_
[0]->
reset
(
$_
[1]) }
sub
removeField($)
{
my
(
$self
,
$field
) =
@_
;
my
$name
=
$field
->name;
my
$known
=
$self
->{MMH_fields};
if
(!
defined
$known
->{
$name
})
{ ; }
elsif
(
ref
$known
->{
$name
} eq
'ARRAY'
)
{
for
(
my
$i
=0;
$i
< @{
$known
->{
$name
}};
$i
++)
{
return
splice
@{
$known
->{
$name
}},
$i
, 1
if
$known
->{
$name
}[
$i
] eq
$field
;
}
}
elsif
(
$known
->{
$name
} eq
$field
)
{
return
delete
$known
->{
$name
};
}
$self
->
log
(
WARNING
=>
"Cannot remove field $name from header: not found."
);
return
;
}
sub
removeFields(@)
{
my
$self
=
shift
;
(
bless
$self
,
'Mail::Message::Head::Partial'
)->removeFields(
@_
);
}
sub
removeFieldsExcept(@)
{
my
$self
=
shift
;
(
bless
$self
,
'Mail::Message::Head::Partial'
)->removeFieldsExcept(
@_
);
}
sub
removeContentInfo() {
shift
->removeFields(
qr/^Content-/
,
'Lines'
) }
sub
removeResentGroups(@)
{
my
$self
=
shift
;
(
bless
$self
,
'Mail::Message::Head::Partial'
)->removeResentGroups(
@_
);
}
sub
removeListGroup(@)
{
my
$self
=
shift
;
(
bless
$self
,
'Mail::Message::Head::Partial'
)->removeListGroup(
@_
);
}
sub
removeSpamGroups(@)
{
my
$self
=
shift
;
(
bless
$self
,
'Mail::Message::Head::Partial'
)->removeSpamGroups(
@_
);
}
sub
spamDetected()
{
my
$self
=
shift
;
my
@sgs
=
$self
->spamGroups or
return
undef
;
grep
{
$_
->spamDetected }
@sgs
;
}
sub
print
(;$)
{
my
$self
=
shift
;
my
$fh
=
shift
||
select
;
$_
->
print
(
$fh
)
foreach
$self
->orderedFields;
if
(
ref
$fh
eq
'GLOB'
) {
print
$fh
"\n"
}
else
{
$fh
->
print
(
"\n"
) }
$self
;
}
sub
printUndisclosed($)
{
my
(
$self
,
$fh
) =
@_
;
$_
->
print
(
$fh
)
foreach
grep
{
$_
->toDisclose}
$self
->orderedFields;
if
(
ref
$fh
eq
'GLOB'
) {
print
$fh
"\n"
}
else
{
$fh
->
print
(
"\n"
) }
$self
;
}
sub
printSelected($@)
{
my
(
$self
,
$fh
) = (
shift
,
shift
);
foreach
my
$field
(
$self
->orderedFields)
{
my
$Name
=
$field
->Name;
my
$name
=
$field
->name;
my
$found
;
foreach
my
$pattern
(
@_
)
{
$found
=
ref
$pattern
?(
$Name
=~
$pattern
):(
$name
eq
lc
$pattern
);
last
if
$found
;
}
if
(!
$found
) { ; }
elsif
(
ref
$fh
eq
'GLOB'
) {
print
$fh
"\n"
}
else
{
$fh
->
print
(
"\n"
) }
}
$self
;
}
sub
toString() {
shift
->string}
sub
string()
{
my
$self
=
shift
;
my
@lines
=
map
{
$_
->string}
$self
->orderedFields;
push
@lines
,
"\n"
;
wantarray
?
@lines
:
join
(
''
,
@lines
);
}
sub
resentGroups()
{
my
$self
=
shift
;
Mail::Message::Head::ResentGroup->from(
$self
);
}
sub
addResentGroup(@)
{
my
$self
=
shift
;
my
$rg
=
@_
==1 ? (
shift
) : Mail::Message::Head::ResentGroup->new(
@_
);
my
@fields
=
$rg
->orderedFields;
my
$order
=
$self
->{MMH_order};
my
$i
;
for
(
$i
=0;
$i
<
@$order
;
$i
++)
{
next
unless
defined
$order
->[
$i
];
last
if
$rg
->isResentGroupFieldName(
$order
->[
$i
]->name);
}
my
$known
=
$self
->{MMH_fields};
while
(
@fields
)
{
my
$f
=
pop
@fields
;
splice
@$order
,
$i
, 0,
$f
;
weaken(
$order
->[
$i
] );
my
$name
=
$f
->name;
if
(!
defined
$known
->{
$name
}) {
$known
->{
$name
} =
$f
}
elsif
(
ref
$known
->{
$name
} eq
'ARRAY'
){
unshift
@{
$known
->{
$name
}},
$f
}
else
{
$known
->{
$name
} = [
$f
,
$known
->{
$name
}]}
}
$rg
->messageHead(
$self
);
$self
->modified(1);
$rg
;
}
sub
listGroup()
{
my
$self
=
shift
;
eval
"require 'Mail::Message::Head::ListGroup'"
;
Mail::Message::Head::ListGroup->from(
$self
);
}
sub
addListGroup($)
{
my
(
$self
,
$lg
) =
@_
;
$lg
->attach(
$self
);
}
sub
spamGroups(@)
{
my
$self
=
shift
;
my
@types
=
@_
? (
types
=> \
@_
) : ();
my
@sgs
= Mail::Message::Head::SpamGroup->from(
$self
,
@types
);
wantarray
||
@_
!= 1 ?
@sgs
:
$sgs
[0];
}
sub
addSpamGroup($)
{
my
(
$self
,
$sg
) =
@_
;
$sg
->attach(
$self
);
}
sub
timestamp() {
shift
->guessTimestamp ||
time
}
sub
recvstamp()
{
my
$self
=
shift
;
return
$self
->{MMH_recvstamp}
if
exists
$self
->{MMH_recvstamp};
my
$recvd
=
$self
->get(
'received'
, 0) or
return
$self
->{MMH_recvstamp} =
undef
;
my
$stamp
= Mail::Message::Field->dateToTimestamp(
$recvd
->comment);
$self
->{MMH_recvstamp} =
defined
$stamp
&&
$stamp
> 0 ?
$stamp
:
undef
;
}
sub
guessTimestamp()
{
my
$self
=
shift
;
return
$self
->{MMH_timestamp}
if
exists
$self
->{MMH_timestamp};
my
$stamp
;
if
(
my
$date
=
$self
->get(
'date'
))
{
$stamp
= Mail::Message::Field->dateToTimestamp(
$date
);
}
unless
(
$stamp
)
{
foreach
(
reverse
$self
->get(
'received'
))
{
$stamp
= Mail::Message::Field->dateToTimestamp(
$_
->comment);
last
if
$stamp
;
}
}
$self
->{MMH_timestamp} =
defined
$stamp
&&
$stamp
> 0 ?
$stamp
:
undef
;
}
sub
guessBodySize()
{
my
$self
=
shift
;
my
$cl
=
$self
->get(
'Content-Length'
);
return
$1
if
defined
$cl
&&
$cl
=~ m/(\d+)/;
my
$lines
=
$self
->get(
'Lines'
);
return
$1 * 40
if
defined
$lines
&&
$lines
=~ m/(\d+)/;
undef
;
}
sub
createFromLine()
{
my
$self
=
shift
;
my
$sender
=
$self
->message->sender;
my
$stamp
=
$self
->recvstamp ||
$self
->timestamp ||
time
;
my
$addr
=
defined
$sender
?
$sender
->address :
'unknown'
;
"From $addr "
.(
gmtime
$stamp
).
"\n"
}
my
$msgid_creator
;
sub
createMessageId()
{
$msgid_creator
||=
$_
[0]->messageIdPrefix;
$msgid_creator
->(
@_
);
}
sub
messageIdPrefix(;$$)
{
my
$thing
=
shift
;
return
$msgid_creator
unless
@_
|| !
defined
$msgid_creator
;
return
$msgid_creator
=
shift
if
@_
==1 &&
ref
$_
[0] eq
'CODE'
;
my
$prefix
=
shift
||
"mailbox-$$"
;
my
$hostname
=
shift
;
if
(!
defined
$hostname
)
{
eval
"require Net::Domain"
;
$@ or
$hostname
= Net::Domain::hostfqdn();
}
$hostname
||= hostname ||
'localhost'
;
eval
"require Time::HiRes"
;
if
(Time::HiRes->can(
'gettimeofday'
))
{
return
$msgid_creator
=
sub
{
my
(
$sec
,
$micro
) = Time::HiRes::gettimeofday();
"$prefix-$sec-$micro\@$hostname"
;
};
}
my
$unique_id
=
time
;
$msgid_creator
=
sub
{
$unique_id
++;
"$prefix-$unique_id\@$hostname"
;
};
}
1;