MIME-tools

 view release on metacpan or  search on metacpan

ChangeLog  view on Meta::CPAN

        Filename, and now accepts Charset as well. *Thanks to Jason Tibbits
        III for the inspirational patch.*

        Documentation fixes. Hopefully we've seen the last of the pod2man
        warnings...

        Better test logging. Now uses ExtUtils::TBone.

Version 4.116   (1998/02/14)
        Bug fix: MIME::Head and MIME::Entity were not downcasing the
        content-type as they claimed. This has now been fixed. *Thanks to
        Rodrigo de Almeida Siqueira for finding this.*

Version 4.114   (1998/02/12)
        Gzip64-encoding has been improved, and turned off as a default,
        since it depends on having gzip installed. See MIME::Decoder::Gzip64
        if you want to activate it in your app. You can now set up the
        gzip/gunzip commands to use, as well. *Thanks to Paul J. Schinder
        for finding this bug.*

Version 4.113   (1998/01/20)

ChangeLog  view on Meta::CPAN

            approximations when 7bit encoding, you'll have to request it
            explicitly. *But use quoted-printable for your 8-bit documents;
            that's what it's there for!*

            7bit and 8bit "encoders" no longer encode. As per RFC-2045,
            these just do a pass-through of the data, but they'll warn you
            if you send bad data through.

            MIME::Entity suggests encoding. Now you can ask MIME::Entity's
            build() method to "suggest" a legal encoding based on the body
            and the content-type. No more guesswork! See the "mimesend"
            example.

            New module structure for MIME::Decoder classes. It should be
            easier for you to see what's happening.

            New MIME decoders! Support added for decoding `x-uuencode', and
            for decoding/encoding `x-gzip64'. You'll need "gzip" to make the
            latter work.

            Quoted-printable back on track... and then some. The 'quoted-

MANIFEST  view on Meta::CPAN

testmsgs/attachment-filename-encoding-UTF8.msg
testmsgs/bluedot-postcard.msg
testmsgs/bluedot-postcard.ref
testmsgs/bluedot-simple.msg
testmsgs/bluedot-simple.ref
testmsgs/double-boundary.msg
testmsgs/double-content-disposition-param.msg
testmsgs/double-content-disposition.msg
testmsgs/double-content-id.msg
testmsgs/double-content-transfer-encoding.msg
testmsgs/double-content-type.msg
testmsgs/double-semicolon.msg
testmsgs/double-semicolon2.msg
testmsgs/dup-names.msg
testmsgs/dup-names.ref
testmsgs/empty-boundary.msg
testmsgs/empty-quoted-boundary.msg
testmsgs/empty-preamble.msg
testmsgs/frag.msg
testmsgs/german-qp.msg
testmsgs/german.msg
testmsgs/german.ref
testmsgs/hdr-fakeout-newmailtools-ref
testmsgs/hdr-fakeout.msg
testmsgs/hdr-fakeout.ref
testmsgs/malformed-content-type-zip.msg
testmsgs/multi-2evil.msg
testmsgs/multi-2evil.ref
testmsgs/multi-2gifs.msg
testmsgs/multi-2gifs.ref
testmsgs/multi-clen.msg
testmsgs/multi-clen.ref
testmsgs/multi-digest.msg
testmsgs/multi-digest.ref
testmsgs/multi-frag.msg
testmsgs/multi-igor.msg

README  view on Meta::CPAN

    what you know about the document's contents (text vs binary), and (2)
    whether you need the resulting message to have a reliable encoding for
    7-bit Internet email transport.

    In general, only `quoted-printable' and `base64' guarantee reliable
    transport of all data; the other three "no-encoding" encodings simply
    pass the data through, and are only reliable if that data is 7bit ASCII
    with under 1000 characters per line, and has no conflicts with the
    multipart boundaries.

    I've considered making it so that the content-type and encoding can be
    automatically inferred from the file's path, but that seems to be asking
    for trouble... or at least, for Mail::Cap...

  Message-logging

    MIME-tools is a large and complex toolkit which tries to deal with a
    wide variety of external input. It's sometimes helpful to see what's
    really going on behind the scenes. There are several kinds of messages
    logged by the toolkit itself:

examples/mimeref  view on Meta::CPAN

    my $head = $ent->head; 
    $head->unfold;
    my $body = $ent->bodyhandle;

    my $sum = {};
    set($sum, From    => c($head->get("From", 0)));
    set($sum, To      => c($head->get("To", 0)));
    set($sum, Subject => c($head->get("Subject", 0)));
    set($sum, Type    => $head->mime_type);
    set($sum, Encoding=> $head->mime_encoding);
    set($sum, Charset => $head->mime_attr("content-type.charset"));
    set($sum, Boundary => $head->multipart_boundary);
    set($sum, Disposition => $head->mime_attr("content-disposition"));
    set($sum, Filename => $head->recommended_filename);
    if ($body and $body->path) {
	set($sum, Size => (-s $body->path));
    }
    $ref->{$name} = $sum;

    my $root = (($name eq 'Msg') ? 'Part' : $name);
    for (1 .. $ent->parts) {

lib/MIME/Entity.pm  view on Meta::CPAN

    $ent = MIME::Entity->build(Path=>"english-msg.txt");

Create a document for a text file with 8-bit (Latin-1) characters:

    $ent = MIME::Entity->build(Path     =>"french-msg.txt",
                               Encoding =>"quoted-printable",
                               From     =>'jean.luc@inria.fr',
                               Subject  =>"C'est bon!");

Create a document for a GIF file (the description is completely optional;
note that we have to specify content-type and encoding since they're
not the default values):

    $ent = MIME::Entity->build(Description => "A pretty picture",
                               Path        => "./docs/mime-sm.gif",
                               Type        => "image/gif",
                               Encoding    => "base64");

Create a document that you already have the text for, using "Data":

    $ent = MIME::Entity->build(Type        => "text/plain",

lib/MIME/Entity.pm  view on Meta::CPAN


If OFFSET is positive, the new part is added at that offset from the
beginning of the array of parts.  If it is negative, it counts from
the end of the array.  (An INDEX of -1 will place the new part at the
very end of the array, -2 will place it as the penultimate item in the
array, etc.)  If OFFSET is not given, the new part is added to the end
of the array.
I<Thanks to Jason L Tibbitts III for providing support for OFFSET.>

B<Warning:> in general, you only want to attach parts to entities
with a content-type of C<multipart/*>).

=cut

sub add_part {
    my ($self, $part, $index) = @_;
    defined($index) or $index = -1;

    ### Make $index count from the end if negative:
    $index = $#{$self->{ME_Parts}} + 2 + $index if ($index < 0);
    splice(@{$self->{ME_Parts}}, $index, 0, $part);

lib/MIME/Entity.pm  view on Meta::CPAN

I<Optional.>
The content-transfer-encoding.
If you don't specify it, a reasonable default is put in.
You can also give the special value '-SUGGEST', to have it chosen for
you in a heavy-duty fashion which scans the data itself.

=item Filename

I<Single-part entities only. Optional.>
The recommended filename.  Overrides any name extracted from C<Path>.
The information is stored both the deprecated (content-type) and
preferred (content-disposition) locations.  If you explicitly want to
I<avoid> a recommended filename (even when Path is used), supply this
as empty or undef.

=item Id

I<Optional.>
Set the content-id.

=item Path

lib/MIME/Entity.pm  view on Meta::CPAN


=item Top

I<Optional.>
Is this a top-level entity?  If so, it must sport a MIME-Version.
The default is true.  (NB: look at how C<attach()> uses it.)

=item Type

I<Optional.>
The basic content-type (C<"text/plain">, etc.).
If you don't specify it, it defaults to C<"text/plain">
as per RFC 2045.  I<Do yourself a favor: put it in.>

=back

=cut

sub build {
    my ($self, @paramlist) = @_;
    my %params = @paramlist;

lib/MIME/Entity.pm  view on Meta::CPAN

    }


    ### MAKE HEAD...

    ### Create head:
    my $head = new MIME::Head;
    $self->head($head);
    $head->modify(1);

    ### Add content-type field:
    $field = new Mail::Field 'Content_type';         ### not a typo :-(
    $field->type($type);
    $field->charset($charset)    if $charset;
    $field->name($filename)      if defined($filename);
    $field->boundary($boundary)  if defined($boundary);
    $head->replace('Content-type', $field->stringify);

    ### Now that both body and content-type are available, we can suggest
    ### content-transfer-encoding (if desired);
    if (!$encoding) {
	$encoding = $self->suggest_encoding_lite;
    }
    elsif (lc($encoding) eq '-suggest') {
	$encoding = $self->suggest_encoding;
    }

    ### Add content-disposition field (if not multipart):
    unless ($is_multipart) {

lib/MIME/Entity.pm  view on Meta::CPAN

This is a read-only data structure: changing its contents will have
no effect.  Its contents are identical to what is printed by
L<print_body()|/print_body>.

Provided for compatibility with Mail::Internet, so that methods
like C<smtpsend()> will work.  Note however that if VALUE is given,
a fatal exception is thrown, since you cannot use this method to
I<set> the lines of the encoded message.

If you want the raw (unencoded) body data, use the L<bodyhandle()|/bodyhandle>
method to get and use a MIME::Body.  The content-type of the entity
will tell you whether that body is best read as text (via getline())
or raw data (via read()).

=cut

sub body {
	my ($self, $value) = @_;
	my $boundary_delimiter = $MIME::Entity::BOUNDARY_DELIMITER || "\n";
	if (@_ > 1) {      ### setting body line(s)...
		croak "you cannot use body() to set the encoded contents\n";

lib/MIME/Entity.pm  view on Meta::CPAN


I<Instance method, override.>
Attempts to remove a user's signature from the body of a message.

It does this by looking for a line matching C</^-- $/> within the last
C<NLINES> of the message.  If found then that line and all lines after
it will be removed. If C<NLINES> is not given, a default value of 10
will be used.  This would be of most use in auto-reply scripts.

For MIME entity, this method is reasonably cautious: it will only
attempt to un-sign a message with a content-type of C<text/*>.

If you send remove_sig() to a multipart entity, it will relay it to
the first part (the others usually being the "attachments").

B<Warning:> currently slurps the whole message-part into core as an
array of lines, so you probably don't want to use this on extremely
long messages.

Returns truth on success, false on error.

lib/MIME/Entity.pm  view on Meta::CPAN

I<MIME-specific; new in this subclass.>

=item File

Use the contents of this file as the signature.
Fatal error if it can't be read.
I<As per superclass method.>

=item Force

Sign it even if the content-type isn't C<text/*>.  Useful for
non-standard types like C<x-foobar>, but be careful!
I<MIME-specific; new in this subclass.>

=item Remove

Normally, we attempt to strip out any existing signature.
If true, this gives us the NLINES parameter of the remove_sig call.
If zero but defined, tells us I<not> to remove any existing signature.
If undefined, removal is done with the default of 10 lines.
I<New in this subclass.>

=item Signature

Use this text as the signature.  You can supply it as either
a scalar, or as a ref to an array of newline-terminated scalars.
I<As per superclass method.>

=back

For MIME messages, this method is reasonably cautious: it will only
attempt to sign a message with a content-type of C<text/*>, unless
C<Force> is specified.

If you send this message to a multipart entity, it will relay it to
the first part (the others usually being the "attachments").

B<Warning:> currently slurps the whole message-part into core as an
array of lines, so you probably don't want to use this on extremely
long messages.

Returns true on success, false otherwise.

lib/MIME/Entity.pm  view on Meta::CPAN


    application/*
    audio/*
    image/*
    text/*
    video/*

=item *

An array of I<parts>, where each part is a MIME::Entity object.
The number of parts will only be nonzero if the content-type
is I<not> one of the "singlepart" types:

    message/*        (should have exactly one part)
    multipart/*      (should have one or more parts)


=back



lib/MIME/Entity.pm  view on Meta::CPAN

B<MIME::Entity:>
The portion of the printed message after the header.


=item How is a message body stored in an entity?

B<Mail::Internet:>
As an array of lines.

B<MIME::Entity:>
It depends on the content-type of the message.
For "container" types (C<multipart/*>, C<message/*>), we store the
contained entities as an array of "parts", accessed via the C<parts()>
method, where each part is a complete MIME::Entity.
For "singlepart" types (C<text/*>, C<image/*>, etc.), the unencoded
body data is referenced via a MIME::Body object, accessed via
the C<bodyhandle()> method:

                      bodyhandle()   parts()
    Content-type:     returns:       returns:
    ------------------------------------------------------------

lib/MIME/Field/ContType.pm  view on Meta::CPAN

Try real hard to determine the content type (e.g., C<"text/plain">,
C<"image/gif">, C<"x-weird-type">, which is returned
in all-lowercase.

A happy thing: the following code will work just as you would want,
even if there's no subtype (as in C<"x-weird-type">)... in such a case,
the $subtype would simply be the empty string:

    ($type, $subtype) = split('/', $head->mime_type);

If the content-type information is missing, it defaults to C<"text/plain">,
as per RFC 2045:

    Default RFC 2822 messages are typed by this protocol as plain text in
    the US-ASCII character set, which can be explicitly specified as
    "Content-type: text/plain; charset=us-ascii".  If no Content-Type is
    specified, this default is assumed.

B<Note:> under the "be liberal in what we accept" principle, this routine
no longer syntax-checks the content type.  If it ain't empty,
just downcase and return it.

lib/MIME/Field/ParamVal.pm  view on Meta::CPAN


use MIME::Words;

=head1 NAME

MIME::Field::ParamVal - subclass of Mail::Field, for structured MIME fields


=head1 SYNOPSIS

    # Create an object for a content-type field:
    $field = new Mail::Field 'Content-type';

    # Set some attributes:
    $field->param('_'        => 'text/html');
    $field->param('charset'  => 'us-ascii');
    $field->param('boundary' => '---ABC---');

    # Same:
    $field->set('_'        => 'text/html',
		'charset'  => 'us-ascii',

lib/MIME/Field/ParamVal.pm  view on Meta::CPAN

I<Class/instance utility method.>
Extract parameter info from a structured field, and return
it as a hash reference.  For example, here is a field with parameters:

    Content-Type: Message/Partial;
	number=2; total=3;
	id="oc=jpbe0M2Yt4s@thumper.bellcore.com"

Here is how you'd extract them:

    $params = $class->parse_params('content-type');
    if ($$params{'_'} eq 'message/partial') {
	$number = $$params{'number'};
	$total  = $$params{'total'};
	$id     = $$params{'id'};
    }

Like field names, parameter names are coerced to lowercase.
The special '_' parameter means the default parameter for the
field.

lib/MIME/Head.pm  view on Meta::CPAN

Before reading further, you should see L<MIME::Tools> to make sure that
you understand where this module fits into the grand scheme of things.
Go on, do it now.  I'll wait.

Ready?  Ok...

=head2 Construction

    ### Create a new, empty header, and populate it manually:
    $head = MIME::Head->new;
    $head->replace('content-type', 'text/plain; charset=US-ASCII');
    $head->replace('content-length', $len);

    ### Parse a new header from a filehandle:
    $head = MIME::Head->read(\*STDIN);

    ### Parse a new header from a file, or a readable pipe:
    $testhead = MIME::Head->from_file("/tmp/test.hdr");
    $a_b_head = MIME::Head->from_file("cat a.hdr b.hdr |");


lib/MIME/Head.pm  view on Meta::CPAN

    ### Get rid of internal newlines in fields:
    $head->unfold;

    ### Decode any Q- or B-encoded-text in fields (DEPRECATED):
    $head->decode;


=head2 Getting high-level MIME information

    ### Get/set a given MIME attribute:
    unless ($charset = $head->mime_attr('content-type.charset')) {
        $head->mime_attr("content-type.charset" => "US-ASCII");
    }

    ### The content type (e.g., "text/html"):
    $mime_type     = $head->mime_type;

    ### The content transfer encoding (e.g., "quoted-printable"):
    $mime_encoding = $head->mime_encoding;

    ### The recommended name when extracted:
    $file_name     = $head->recommended_filename;

lib/MIME/Head.pm  view on Meta::CPAN

use MIME::Field::ContType;

@ISA = qw(Mail::Header);

# The presence of more than one of the following headers
# in a given MIME entity could indicate an ambiguous parse
# and hence a security risk

my $singleton_headers =
    [
     'content-type',
     'content-disposition',
     'content-transfer-encoding',
     'content-id',
    ];

# The presence of a duplicated or empty parameters in one of the following
# headers in a given MIME entity could indicate an ambiguous parse and
# hence a security risk
my $singleton_parameter_headers =
    [
     'content-type',
     'content-disposition',
    ];


#------------------------------
#
# Public globals...
#
#------------------------------

lib/MIME/Head.pm  view on Meta::CPAN

    return MIME::Field::ParamVal->parse_params($self->get($tag,0));
}

#------------------------------

=item mime_attr ATTR,[VALUE]

A quick-and-easy interface to set/get the attributes in structured
MIME fields:

    $head->mime_attr("content-type"         => "text/html");
    $head->mime_attr("content-type.charset" => "US-ASCII");
    $head->mime_attr("content-type.name"    => "homepage.html");

This would cause the final output to look something like this:

    Content-type: text/html; charset=US-ASCII; name="homepage.html"

Note that the special empty sub-field tag indicates the anonymous
first sub-field.

B<Giving VALUE as undefined> will cause the contents of the named subfield
to be deleted:

    $head->mime_attr("content-type.charset" => undef);

B<Supplying no VALUE argument> just returns the attribute's value,
or undefined if it isn't there:

    $type = $head->mime_attr("content-type");      ### text/html
    $name = $head->mime_attr("content-type.name"); ### homepage.html

In all cases, the new/current value is returned.

The special sub-field tag C<@duplicate_parameters> (which can never be
a real tag) returns an arrayref of tags that were duplicated in the header,
or C<undef> if no such tags were found.  For example, given the header:

    Content-Type: multipart/mixed; boundary="foo"; boundary="bar"

Then:

    $head->mime_attr('content-type.@duplicate_parameters')

would return:

    [ 'boundary' ]

Similarly he special sub-field tag C<@empty_parameters> (which can never be
a real tag) returns an arrayref of tags that had an empty parameter value
in the header, or C<undef> if no such tags were found. For example, given
the header:

    Content-Type: multipart/mixed; boundary=;

Then:

    $head->mime_attr('content-type.@emtpy_parameters')

would return:

    [ 'boundary' ]

A duplicate or empty "boundary" tag should be treated as a security risk, as
should duplicate Content-Type headers in a message.  Since such messages
cannot be parsed unambiguously, we strongly recommend that they never be
delivered to end-users.

lib/MIME/Head.pm  view on Meta::CPAN

Unless this is a part of a "multipart/digest", in which case
"message/rfc822" is the default.  Note that you can also I<set> the
default, but you shouldn't: normally only the MIME parser uses this
feature.

=cut

sub mime_type {
    my ($self, $default) = @_;
    $self->{MIH_DefaultType} = $default if @_ > 1;
    my $s = $self->mime_attr('content-type') ||
       $self->{MIH_DefaultType} ||
       'text/plain';
    # avoid [perl #87336] bug, lc laundering tainted data
    return lc($s)  if $] <= 5.008 || $] >= 5.014;
    $s =~ tr/A-Z/a-z/;
    $s;
}

#------------------------------

lib/MIME/Head.pm  view on Meta::CPAN

   If a boundary appears to end with white space, the white space
   must be presumed to have been added by a gateway, and must be deleted.

Returns undef (B<not> the empty string) if either the message is not
multipart or if there is no specified boundary.

=cut

sub multipart_boundary {
    my $self = shift;
    my $value =  $self->mime_attr('content-type.boundary');
    (!defined($value)) ? undef : $value;
}

#------------------------------

=item recommended_filename

I<Instance method.>
Return the recommended external filename.  This is used when
extracting the data from the MIME stream.  The filename is always

lib/MIME/Head.pm  view on Meta::CPAN


=cut

sub recommended_filename
{
	my $self = shift;

	# Try these headers in order, taking the first defined,
	# non-blank one we find.
	my $wd = supported MIME::WordDecoder 'UTF-8';
	foreach my $attr_name ( qw( content-disposition.filename content-type.name ) ) {
		my $value = $self->mime_attr( $attr_name );
		if ( defined $value
		    && $value ne ''
		    && $value =~ /\S/ ) {
			return $wd->decode($value);
		}
	}

	return undef;
}

lib/MIME/Parser.pm  view on Meta::CPAN

    usage "parse_nested_messages() is now extract_nested_messages()";
    shift->extract_nested_messages(@_);
}

#------------------------------

=item extract_uuencode [YESNO]

I<Instance method.>
If set true, then whenever we are confronted with a message
whose effective content-type is "text/plain" and whose encoding
is 7bit/8bit/binary, we scan the encoded body to see if it contains
uuencoded data (generally given away by a "begin XXX" line).

If it does, we explode the uuencoded message into a multipart,
where the text before the first "begin XXX" becomes the first part,
and all "begin...end" sections following become the subsequent parts.
The filename (if given) is accessible through the normal means.

=cut

lib/MIME/Parser.pm  view on Meta::CPAN


#------------------------------
#
# process_part IN, READER, [OPTSHASH...]
#
# I<Instance method.>
# The real back-end engine.
# See the documentation up top for the overview of the algorithm.
# The OPTSHASH can contain:
#
#    Retype => retype this part to the given content-type
#
# Return the entity.
# Fatal exception on failure.  Returns undef if message to complex
#
sub process_part {
    my ($self, $in, $rdr, %p) = @_;

    if ($self->{MP5_MaxParts} > 0) {
	$self->{MP5_NumParts}++;
	if ($self->{MP5_NumParts} > $self->{MP5_MaxParts}) {

lib/MIME/Parser.pm  view on Meta::CPAN

       if (!$self->{MP5_AmbiguousContent}) {
           if ($ent->head->ambiguous_content) {
               $self->{MP5_AmbiguousContent} = 1;
           }
       }
       $self->results->level(-1);
       return $ent;
    }
    $ent->head($head);

    ### Tweak the content-type based on context from our parent...
    ### For example, multipart/digest messages default to type message/rfc822:
    $head->mime_type($p{Retype}) if $p{Retype};

    # We have the header, so that's enough to check for
    # ambiguous content...
    if (!$self->{MP5_AmbiguousContent}) {
        if ($ent->head->ambiguous_content) {
            $self->{MP5_AmbiguousContent} = 1;
        }
    }
    ### Get the MIME type and subtype:
    my ($type, $subtype) = (split('/', $head->mime_type, -1), '');
    $self->debug("type = $type, subtype = $subtype");

    ### Handle, according to the MIME type:
    if ($type eq 'multipart') {
	return undef unless defined($self->process_multipart($in, $rdr, $ent));
    }
    elsif (("$type/$subtype" eq "message/rfc822" ||
	    "$type/$subtype" eq "message/external-body" ||
	    ("$type/$subtype" eq "message/partial" && defined($head->mime_attr("content-type.number")) && $head->mime_attr("content-type.number") == 1)) &&
	    $self->extract_nested_messages) {
	$self->debug("attempting to process a nested message");
	return undef unless defined($self->process_message($in, $rdr, $ent));
    }
    else {
	$self->process_singlepart($in, $rdr, $ent);
    }

    ### Done (we hope!):
    $self->results->level(-1);

lib/MIME/Parser/Filer.pm  view on Meta::CPAN


    ### Return the path where this message's data should be placed:
    $path = $filer->output_path($head);


=head2 Semi-public interface

These methods might be overridden or ignored in some subclasses,
so they don't all make sense in all circumstances:

    ### Tweak the mapping from content-type to extension:
    $emap = $filer->output_extension_map;
    $emap->{"text/html"} = ".htm";




=head1 DESCRIPTION


=head2 How this class is used when parsing

lib/MIME/Parser/Filer.pm  view on Meta::CPAN

### Kit modules:
use MIME::Tools qw(:msgtypes);
use File::Spec;
use File::Path qw(rmtree);
use MIME::WordDecoder;

### Output path uniquifiers:
my $GFileNo = 0;
my $GSubdirNo = 0;

### Map content-type to extension.
### If we can't map "major/minor", we try "major/*", then use "*/*".
my %DefaultTypeToExt =
qw(

application/andrew-inset	.ez
application/octet-stream	.bin
application/oda			.oda
application/pdf			.pdf
application/pgp			.pgp
application/postscript		.ps

lib/MIME/Parser/Filer.pm  view on Meta::CPAN

    $self->{MPF_Prefix} = $prefix if (@_ > 1);
    $self->{MPF_Prefix};
}

#------------------------------

=item output_type_ext

I<Instance method.>
Return a reference to the hash used by the default
L<output_filename()|/output_filename> for mapping from content-types
to extensions when there is no default extension to use.

    $emap = $filer->output_typemap;
    $emap->{'text/plain'} = '.txt';
    $emap->{'text/html'}  = '.html';
    $emap->{'text/*'}     = '.txt';
    $emap->{'*/*'}        = '.dat';

B<Note:> subclasses of MIME::Parser::Filer which override
output_path() or output_filename() might not consult this hash;

lib/MIME/Tools.pm  view on Meta::CPAN

(1) what you know about the document's contents (text vs binary), and
(2) whether you need the resulting message to have a reliable encoding
for 7-bit Internet email transport.

In general, only C<quoted-printable> and C<base64> guarantee reliable
transport of all data; the other three "no-encoding" encodings simply
pass the data through, and are only reliable if that data is 7bit ASCII
with under 1000 characters per line, and has no conflicts with the
multipart boundaries.

I've considered making it so that the content-type and encoding
can be automatically inferred from the file's path, but that seems
to be asking for trouble... or at least, for Mail::Cap...



=head2 Message-logging

MIME-tools is a large and complex toolkit which tries to deal with
a wide variety of external input.  It's sometimes helpful to see
what's really going on behind the scenes.

t/Entity.t  view on Meta::CPAN



#diag("Testing build()");
{local $SIG{__WARN__} = sub { die "caught warning: ",@_ };
 {   
     my $e = MIME::Entity->build(Path     => "./testin/short.txt");
     my $name = 'short.txt';
     my $got;
     
     #-----test------
     $got = $e->head->mime_attr('content-type.name');
     is($got, $name, 'Path: with no Filename, got default content-type.name');
     
     #-----test------
     $got = $e->head->mime_attr('content-disposition.filename');
     is($got, $name, 'Path: with no Filename, got default content-disp.filename');

     #-----test------
     $got = $e->head->recommended_filename;
     is($got, $name, 'Path: with no Filename, got default recommended filename');
 }
 { 
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/short.txt",
				 Filename => undef);
     my $got = $e->head->mime_attr('content-type.name');
     ok(!$got, 'Path: with explicitly undef Filename, got no filename');
     my $x = $e->stringify();
     my $version = $MIME::Entity::VERSION;
     my $desired = "Content-Type: text/plain\nContent-Disposition: inline\nContent-Transfer-Encoding: binary\nMIME-Version: 1.0\nX-Mailer: MIME-tools $version (Entity $version)\n\nDear «François Müller»,\n\nAs you requested, I have rewritten the MIME...
     is($x, $desired, 'Tested stringify');
 }

 { 
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/short.txt",
				 Filename => "foo.txt");
     my $got = $e->head->mime_attr('content-type.name');
     is($got, "foo.txt", "Path: verified explicit 'Filename'" );
 }
 {
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/sig"
				 );
     my $got = $e->head->mime_attr('content-type');
     is($got, 'text/plain', 'Type: default ok');
 }
 {
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/sig",
				 Type     => "text/foo");
     my $got = $e->head->mime_attr('content-type');
     is($got, 'text/foo', 'Type: explicit ok');
 }
 {
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/sig",
				 Encoding => '-SUGGEST');
     my $got = $e->head->mime_attr('content-transfer-encoding');
     is($got, '7bit', 'Encoding: -SUGGEST yields 7bit');
 }
 {

t/Entity.t  view on Meta::CPAN

     my $e = MIME::Entity->build(Type     => 'image/gif',
				 Path     => "./testin/mime-sm.gif",
				 Encoding => '-SUGGEST');
     my $got = $e->head->mime_attr('content-transfer-encoding');
     is($got, 'base64', 'Encoding: -SUGGEST yields base64');
 }
 {
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/short.txt"
				 );
     my $got = $e->head->mime_attr('content-type.charset');
     ok(!$got, 'Charset: default ok');
 }
 {
     #-----test------
     my $e = MIME::Entity->build(Path     => "./testin/short.txt",
				 Charset  => 'iso8859-1');
     my $got = $e->head->mime_attr('content-type.charset');
     is($got, 'iso8859-1', 'Charset: explicit');
 }

 {
     #-----test------
     my $croaked = 1;
     eval {
	     my $e = MIME::Entity->build(Type => 'message/rfc822',
					 Encoding => 'base64',
					 Data => "Subject: phooey\n\nBlat\n");

t/Head.t  view on Meta::CPAN

my @actuals = qw(path
		 from
		 newsgroups
		 subject
		 date
		 organization
		 lines
		 message-id
		 nntp-posting-host
		 mime-version
		 content-type
		 content-transfer-encoding
		 x-mailer
		 x-url
		 );
push(@actuals, "From ");
my $actual = join '|', sort( map {lc($_)} @actuals);
my $parsed = join '|', sort( map {lc($_)} $head->tags);
is($parsed, $actual, 'got all fields we expected?');

#------------------------------------------------------------

t/Ref.t  view on Meta::CPAN

	    }
	    elsif (/^To$/)       { 
		$got  = trim($head->get("To", 0)); 
		$want = trim($want); 
	    }
	    elsif (/^Subject$/)  { 
		$got  = trim($head->get("Subject", 0));
		$want = trim($want); 
	    }
	    elsif (/^Charset$/)  { 
		$got = $head->mime_attr("content-type.charset"); 
	    }
	    elsif (/^Disposition$/) { 
		$got = $head->mime_attr("content-disposition"); 
	    }
	    elsif (/^Type$/)     {
		$got = $head->mime_type;
	    }
	    elsif (/^Encoding$/) {
		$got = $head->mime_encoding;
	    }

t/ambiguous-parse.t  view on Meta::CPAN

use Test::More tests => 32;

use MIME::Entity;
use MIME::Parser;
use lib qw( ./t );

my $parser = MIME::Parser->new();
$parser->output_to_core(1);

my $entity = $parser->parse_open('testmsgs/double-boundary.msg');
my $ans = $entity->head->mime_attr('content-type.@duplicate_parameters');
cmp_deeply($ans, ['boundary'], 'Duplicate "boundary" parameter was detected in bad message');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in bad message');
ok($entity->ambiguous_content(), 'Entity method matches parser method');
$entity = $parser->parse_open('testmsgs/attachment-filename-encoding-UTF8.msg');
$ans  = $entity->head->mime_attr('content-type.@duplicate_parameters');
ok(!defined($ans), 'No duplicate "boundary" parameter was detected in good message');
ok(!$parser->ambiguous_content(), 'Ambiguous content was not detected in good message');
ok(!$entity->ambiguous_content(), 'Entity method matches parser method');

$entity = $parser->parse_open('testmsgs/double-content-type.msg');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with two Content-Type headers');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

$entity = $parser->parse_open('testmsgs/double-content-transfer-encoding.msg');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with two Content-Transfer-Encoding headers');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

$entity = $parser->parse_open('testmsgs/double-content-disposition.msg');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with two Content-Disposition headers');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

t/ambiguous-parse.t  view on Meta::CPAN


### Now create an entity with ambiguous content
$entity = MIME::Entity->build(From => 'x@example.org',
                              To   => 'y@example.org',
                              'Content-Disposition' => 'attachment; filename="foo"; filename="bar"',
                              Type => 'text/plain',
                              Data => ['Hello, world!']);
ok($entity->ambiguous_content(), 'Newly-built entity correctly detects ambiguous content');

$entity = $parser->parse_open('testmsgs/triple-boundary-one-empty.msg');
$ans = $entity->head->mime_attr('content-type.@duplicate_parameters');
cmp_deeply($ans, ['boundary'], 'Duplicate "boundary" parameter was detected in bad message');
$ans = $entity->head->mime_attr('content-type.@empty_parameters');
cmp_deeply($ans, ['boundary'], 'Empty "boundary" parameter value was detected in bad message');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with 3 boundary parameters, one of them empty');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

$entity = $parser->parse_open('testmsgs/empty-boundary.msg');
$ans = $entity->head->mime_attr('content-type.@duplicate_parameters');
ok(!defined($ans), 'No duplicate parameters');
$ans = $entity->head->mime_attr('content-type.@empty_parameters');
cmp_deeply($ans, ['boundary'], 'Empty "boundary" parameter value was detected in bad message');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with empty boundary parameter');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

$entity = $parser->parse_open('testmsgs/empty-quoted-boundary.msg');
$ans = $entity->head->mime_attr('content-type.@duplicate_parameters');
ok(!defined($ans), 'No duplicate parameters');
$ans = $entity->head->mime_attr('content-type.@empty_parameters');
cmp_deeply($ans, ['boundary'], 'Empty "boundary" parameter value was detected in bad message');
ok($parser->ambiguous_content(), 'Ambiguous content was detected in message with "" boundary parameter');
ok($entity->ambiguous_content(), 'Entity method matches parser method');

t/obfuscated-zip.t  view on Meta::CPAN

use warnings;

use Test::More tests => 2;

# Handle a missing type in the Content-Type: header

use MIME::Parser;
my $parser = MIME::Parser->new();
$parser->output_to_core(0);
$parser->output_under("testout");
my $entity = $parser->parse_open("testmsgs/malformed-content-type-zip.msg");

is(scalar($entity->parts), 2, 'Entity has two parts');
is($entity->parts(1)->head->mime_attr('content-type.name'), 'payroll_report_429047_10092013.zip', 'Got expected attachment name');

1;



( run in 3.066 seconds using v1.01-cache-2.11-cpan-524268b4103 )